如何翻译 React Router v7 中的页面元数据
为搜索和社交翻译元数据
问题
页面元数据(标题和描述)显示在页面本身之外,例如浏览器标签、书签、搜索结果和社交媒体预览中。当这些元数据与页面的语言不匹配时,会造成令人不适的一致性问题。例如,一个西班牙语页面却有一个英文标题,这会在用户看到内容之前就让他们感到困惑。搜索引擎将这种不匹配视为页面本地化不佳或质量较低的信号,可能会降低其在特定语言搜索结果中的排名。用户可能会在页面加载之前就放弃,认为页面不是他们的语言。
解决方案
通过从路由模块中导出一个 meta 函数,将页面元数据翻译为当前语言。使用 react-intl 的 formatMessage API 和消息描述符(Message Descriptors)来翻译标题和描述字符串,确保元数据使用与页面内容相同的翻译资源。这可以保持浏览器标签、搜索结果和页面本身之间的一致性。
步骤
1. 创建一个帮助程序以在组件外部访问 intl
intl 对象提供 formatMessage 方法,可以通过组件中的 useIntl 钩子访问,或者在非 React 环境中直接使用 createIntl 创建。由于 meta 函数运行在 React 组件树之外,因此需要创建一个帮助程序,从消息中构建一个 intl 实例。
import { createIntl, createIntlCache } from "react-intl";
const cache = createIntlCache();
export function createIntlForLocale(
locale: string,
messages: Record<string, string>,
) {
return createIntl(
{
locale,
messages,
},
cache,
);
}
这个帮助程序创建了一个 intl 实例,可以在任何函数中格式化消息,而不仅限于 React 组件。
2. 在父路由加载器中加载消息
路由加载器返回组件通过 loaderData 属性访问的数据。在父路由中加载翻译消息,以便子路由可以使用这些消息。
import type { Route } from "./+types/root";
export async function loader({ request }: Route.LoaderArgs) {
const url = new URL(request.url);
const locale = url.pathname.split("/")[1] || "en";
const messages = await import(`../translations/${locale}.json`);
return {
locale,
messages: messages.default,
};
}
meta 函数接收一个 matches 参数,其中包含所有匹配路由的加载器数据,使得父加载器数据可以被子路由的 meta 函数访问。
3. 导出一个翻译元数据的 meta 函数
从路由模块中导出一个 meta 函数,该函数返回一个元描述符对象数组。从 matches 中访问父加载器数据,并使用您的 intl 助手翻译字符串。
import type { Route } from "./+types/product";
import { createIntlForLocale } from "~/utils/intl";
export function meta({ matches }: Route.MetaArgs) {
const rootMatch = matches.find((match) => match.id === "root");
const { locale, messages } = rootMatch?.data || {
locale: "en",
messages: {},
};
const intl = createIntlForLocale(locale, messages);
return [
{
title: intl.formatMessage({
id: "product.meta.title",
defaultMessage: "Product Details",
}),
},
{
name: "description",
content: intl.formatMessage({
id: "product.meta.description",
defaultMessage: "View detailed information about this product",
}),
},
];
}
formatMessage 函数接受一个包含 id 和 defaultMessage 的消息描述符,并返回当前语言环境的翻译字符串。
4. 将翻译后的元数据字符串添加到您的消息文件中
将元数据翻译键添加到每个语言环境的消息文件中,以便 formatMessage 可以找到它们。
{
"product.meta.title": "产品详情",
"product.meta.description": "查看此产品的详细信息"
}
当用户导航到此路由时,根布局中的 Meta 组件会渲染所有由路由 meta 导出创建的 meta 标签,显示与页面语言匹配的翻译标题和描述。