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>;
}
このコンポーネントは言語コードを受け取り、その子要素を lang 属性を持つ span でラップします。これにより、スクリーンリーダーは囲まれたテキストの発音ルールを切り替えることができます。
2. インライン外国語テキストをマークするためにコンポーネントを使用する
コンテンツ内の外国語の単語やフレーズを ForeignText コンポーネントで囲みます。
export default function ArticlePage() {
return (
<article>
<h1>国際料理</h1>
<p>
レストランの看板料理は{" "}
<ForeignText lang="fr">coq au vin</ForeignText>で、この古典的なフランス料理は
彼らのハウスワインと完璧に合います。
</p>
<p>
デザートメニューには{" "}
<ForeignText lang="es">tres leches</ForeignText>と{" "}
<ForeignText lang="it">tiramisu</ForeignText>があります。
</p>
</article>
);
}
これにより、スクリーンリーダーは「coq au vin」をフランス語の発音で、「tres leches」をスペイン語の発音で、「tiramisu」をイタリア語の発音で読み上げるようになり、周囲の英語テキストは英語の発音で読み上げられます。
3. より長い外国語の段落をマークする
複数の文からなる外国語コンテンツには、ブロックレベル要素に直接 lang 属性を適用します。
export default function QuotePage() {
return (
<article>
<h1>世界人権宣言</h1>
<h2>第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>
);
}
blockquote要素にlangを適用することで、引用全体をフランス語としてマークし、段落全体の正しい発音とタイポグラフィを確保します。
4. 翻訳されたUIテキストと組み合わせる
翻訳されたインターフェイステキストと外国語コンテンツを一緒に表示する場合は、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を通じてユーザーのロケールに適応し、書籍のタイトルはアクセシビリティのための適切な言語マーキングで元のドイツ語を保持します。