如何翻译 Next.js(页面路由)v16 中的页面元数据
为搜索和社交翻译元数据
问题
页面元数据(标题和描述)位于页面内容之外。它显示在浏览器标签、书签、搜索引擎结果和社交媒体预览中。当元数据与页面的语言不匹配时,用户在看到内容之前就会遇到令人不适的一致性问题。例如,一个西班牙语页面却有一个英文标题,这会让访问者感到困惑,并传递出糟糕的本地化质量信号。
搜索引擎将语言不匹配视为低质量本地化的标志,这可能会降低在特定语言搜索结果中的排名。社交媒体平台在链接预览中显示错误的语言,降低了国际受众的参与度。在所有接触点(包括元数据)中保持一致的翻译,对于提供专业的多语言体验至关重要。
解决方案
使用与页面内容相同的翻译资源翻译页面元数据。使用 react-intl 的 useIntl 钩子访问翻译后的字符串,并将它们放置在页面的 <Head> 组件中。这确保了标题和描述在浏览器标签、搜索结果和社交媒体预览中与当前语言环境一致。
通过从与可见内容相同的消息目录中获取元数据,可以保持一致性并避免重复翻译工作。此方法适用于静态页面和元数据依赖于页面特定数据的动态路由。
步骤
1. 将元数据消息添加到翻译文件中
在翻译目录中为页面标题和描述定义消息描述符,使用与其他翻译内容相同的结构。
{
"home.title": "欢迎光临我们的商店",
"home.description": "发现超值的优质商品",
"products.title": "我们的产品",
"products.description": "浏览我们完整的商品目录"
}
每个需要翻译元数据的页面都应有对应的标题和描述的消息 ID。
2. 创建一个翻译后的元数据组件
使用 useIntl 钩子访问 formatMessage 函数,然后在 Head 组件中渲染翻译后的字符串。
import Head from "next/head";
import { useIntl } from "react-intl";
export default function HomePage() {
const intl = useIntl();
return (
<>
<Head>
<title>{intl.formatMessage({ id: "home.title" })}</title>
<meta
name="description"
content={intl.formatMessage({ id: "home.description" })}
/>
</Head>
<main>
<h1>{intl.formatMessage({ id: "home.title" })}</h1>
</main>
</>
);
}
Head 组件是 Next.js 内置的一个 React 组件,用于修改页面的 <head> 部分。formatMessage 函数会根据当前语言环境返回翻译后的字符串。
3. 添加 Open Graph 和社交元数据
扩展模式以包含用于社交媒体预览的 Open Graph 和 Twitter Card 元数据。
import Head from "next/head";
import { useIntl } from "react-intl";
export default function ProductsPage() {
const intl = useIntl();
const title = intl.formatMessage({ id: "products.title" });
const description = intl.formatMessage({ id: "products.description" });
return (
<>
<Head>
<title>{title}</title>
<meta name="description" content={description} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
</Head>
<main>
<h1>{title}</h1>
</main>
</>
);
}
将格式化后的消息存储在变量中可以避免多次调用 formatMessage 来获取相同的翻译,并使 JSX 更加简洁。
4. 处理参数化页面的动态元数据
对于具有动态路由的页面,将路由参数与翻译后的字符串结合起来,创建上下文相关的元数据。
import Head from "next/head";
import { useIntl } from "react-intl";
import { useRouter } from "next/router";
export default function ProductDetailPage() {
const intl = useIntl();
const router = useRouter();
const { id } = router.query;
const title = intl.formatMessage(
{ id: "product.detail.title" },
{ productId: id },
);
return (
<>
<Head>
<title>{title}</title>
</Head>
<main>
<h1>{title}</h1>
</main>
</>
);
}
消息描述符支持变量插值,允许您将动态值(如产品 ID 或名称)注入到翻译后的元数据字符串中。对应的消息可能是 "Product {productId} - Our Store"。