如何在 React Router v7 中标记混合语言内容

为不同语言的文本添加可访问性标记

问题

当页面包含多种语言的文本时,浏览器和辅助技术会假定所有内容都使用页面声明的语言。例如,配置为英语的屏幕阅读器会尝试用英语发音规则朗读法语短语、西班牙语书名或德语姓名,导致依赖音频的用户听到难以理解的内容。浏览器会根据页面语言应用拼写检查和排版规则,错误地将外语单词标记为拼写错误,并错误处理特定语言的标点符号。搜索引擎和翻译工具如果没有明确的语言标记,也无法准确处理混合语言内容。

这不仅影响屏幕阅读器用户,也影响所有依赖语言检测的浏览器功能,包括自动翻译、文本转语音和阅读模式等。

解决方案

将外语文本包裹在带有 lang 属性且设置为正确语言代码的 HTML 元素中。lang 属性会指示浏览器和辅助技术针对该内容切换到相应的语言规则,从而确保屏幕阅读器正确发音,浏览器正确拼写检查和排版。

使用 <span><i> 等语义化 HTML 元素包裹内联外语文本,不会影响页面布局。lang 属性接受 ISO 639-1 语言代码(如 fr 表示法语,es 表示西班牙语),也可选填地区代码以处理方言。

步骤

1. 创建用于标记外语文本的组件

构建一个可复用组件,将文本包裹在带有相应 lang 属性的 span 元素中。

type ForeignTextProps = {
  lang: string;
  children: React.ReactNode;
};

export function ForeignText({ lang, children }: ForeignTextProps) {
  return <span lang={lang}>{children}</span>;
}

该组件接受一个语言代码,并将其子元素包裹在 span 中,并带有 lang 属性,使屏幕阅读器能够根据所包裹文本切换发音规则。

2. 使用组件标记内联外语文本

在内容中使用 ForeignText 组件包裹外语单词或短语。

export default function ArticlePage() {
  return (
    <article>
      <h1>International Cuisine</h1>
      <p>
        The restaurant's signature dish is{" "}
        <ForeignText lang="fr">coq au vin</ForeignText>, a classic French
        preparation that pairs perfectly with their house wine.
      </p>
      <p>
        Their dessert menu features{" "}
        <ForeignText lang="es">tres leches</ForeignText> and{" "}
        <ForeignText lang="it">tiramisu</ForeignText>.
      </p>
    </article>
  );
}

现在,屏幕阅读器会用法语发音 "coq au vin",用西班牙语发音 "tres leches",用意大利语发音 "tiramisu",而周围的英文文本则使用英语发音。

3. 标记较长的外语段落

对于多句的外语内容,请直接在块级元素上应用 lang 属性。

export default function QuotePage() {
  return (
    <article>
      <h1>Universal Declaration of Human Rights</h1>
      <h2>Article 1</h2>
      <blockquote lang="fr">
        <p>
          Tous les êtres humains naissent libres et égaux en dignité et en
          droits. Ils sont doués de raison et de conscience et doivent agir les
          uns envers les autres dans un esprit de fraternité.
        </p>
      </blockquote>
    </article>
  );
}

lang 应用于 blockquote 元素,可以将整段引用标记为法语,确保整段内容的发音和排版都正确。

4. 与已翻译的界面文本结合使用

在显示外语内容和已翻译界面文本时,UI 元素使用 react-intl,用户生成或引用的内容使用 lang 属性。

import { FormattedMessage } from "react-intl";
import { ForeignText } from "~/components/ForeignText";

export default function BookReview() {
  return (
    <article>
      <h1>
        <FormattedMessage id="review.title" defaultMessage="Book Review" />
      </h1>
      <p>
        <FormattedMessage
          id="review.intro"
          defaultMessage="The novel {title} explores themes of identity and belonging."
          values={{
            title: <ForeignText lang="de">Der Steppenwolf</ForeignText>,
          }}
        />
      </p>
    </article>
  );
}

界面文本会通过 react-intl 根据用户的语言环境自动适配,而书名则保留原始德语,并通过正确的语言标记提升无障碍体验。