如何在 Next.js(Pages Router)v16 中翻译页面元数据
为搜索和社交平台翻译元数据
问题
页面元数据(标题和描述)显示在页面内容之外,例如浏览器标签、书签、搜索引擎结果和社交媒体预览中。如果元数据与页面语言不一致,用户在看到内容前就会感受到突兀的不协调。例如,西班牙语页面却显示英文标题,会让访问者感到困惑,并且反映出较差的本地化质量。
搜索引擎会将语言不匹配视为本地化质量低的信号,可能导致在特定语言的搜索结果中排名下降。社交媒体平台在链接预览中显示错误的语言,也会降低国际用户的参与度。确保所有触点(包括元数据)的一致翻译,是实现专业多语言体验的关键。
解决方案
使用与页面内容相同的翻译资源来翻译页面元数据。通过 react-intl 的 useIntl hook 获取翻译字符串,并将其放入页面的 <Head> 组件中。这样可以确保标题和描述在浏览器标签、搜索结果和社交媒体预览中与当前语言环境一致。
将元数据与可见内容共用同一消息目录,可以保持一致性,避免重复翻译工作。该方法适用于静态页面和依赖页面数据的动态路由。
步骤
1. 将元数据消息添加到翻译文件
在翻译目录中为页面标题和描述定义消息描述符,结构与其他翻译内容保持一致。
{
"home.title": "Welcome to Our Store",
"home.description": "Discover amazing products at great prices",
"products.title": "Our Products",
"products.description": "Browse our full catalog of items"
}
每个需要翻译元数据的页面都应有对应的标题和描述消息 ID。
2. 创建可翻译的元数据组件
使用 useIntl hook 获取 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"。