如何在 React Router v7 中设置文档语言

为浏览器和屏幕阅读器声明页面语言

问题

网页需要向浏览器和辅助技术声明其主要语言。如果没有明确声明语言,屏幕阅读器会默认使用用户的系统语言,这会导致内容语言不一致时发音错误。浏览器无法准确提供翻译功能,因为它们必须猜测源语言。搜索引擎也难以将页面正确地索引到对应语言的受众,从而降低了该语言用户的可发现性。

解决方案

在根 <html> 元素上设置 lang 属性,以声明文档的主要语言。该属性接受有效的语言代码,告知浏览器、屏幕阅读器和搜索引擎内容所使用的语言。明确声明语言后,辅助技术可以应用正确的发音规则,浏览器可以提供合适的翻译选项,搜索引擎也能将页面索引到正确的语言受众。

步骤

1. 确定当前的 locale

app/root.tsx 中,根路由负责渲染根 HTML 文档。如果你的应用使用基于 locale 的路由(如 /:locale/... 模式),请从路由参数中提取 locale。否则,使用默认 locale。

import { useParams } from "react-router";

export default function Root() {
  const params = useParams();
  const locale = params.locale || "en";

  return (
    <html lang={locale}>
      <head>
        <meta charSet="utf-8" />
      </head>
      <body>
        <h1>Content</h1>
      </body>
    </html>
  );
}

这段代码会从 URL 中读取 locale,如果没有 locale 参数,则回退到英文。

2. 将 locale 代码映射为语言标签

如果你的应用使用了与标准语言标签不同的自定义 locale 标识符,请创建一个映射函数,将其转换为有效的 BCP 47 语言代码。

function getLanguageTag(locale: string): string {
  const languageMap: Record<string, string> = {
    en: "en",
    "en-US": "en-US",
    es: "es",
    fr: "fr",
    de: "de",
    ja: "ja",
    "zh-CN": "zh-Hans",
    "zh-TW": "zh-Hant",
  };

  return languageMap[locale] || "en";
}

这样可以确保 lang 属性即使在你的路由使用简化语言代码时,也能获得有效的语言标签。

3. 将语言标签应用到 HTML 元素

在根组件的 <html> 元素上,将映射后的语言标签作为 lang 属性的值。

import { useParams } from "react-router";

function getLanguageTag(locale: string): string {
  const languageMap: Record<string, string> = {
    en: "en",
    es: "es",
    fr: "fr",
    de: "de",
  };
  return languageMap[locale] || "en";
}

export default function Root() {
  const params = useParams();
  const locale = params.locale || "en";
  const lang = getLanguageTag(locale);

  return (
    <html lang={lang}>
      <head>
        <meta charSet="utf-8" />
      </head>
      <body>
        <h1>Content</h1>
      </body>
    </html>
  );
}

lang 属性现在会反映当前的 locale,并在用户切换不同语言路由时自动更新。