# 言語の指定がなく、誤った発音で読まれる別の言語の箇所

Source: https://easeweb.dev/learn/language-of-parts
Topics: ページの構造 > 別の言語の箇所に、その言語が指定されている (WCAG 3.1.2)
The fix: 別の言語の箇所それぞれに、その箇所を囲む要素でlangを指定します。言語の切り替えの各言語名のような決まった文言にはマークアップに書き、顧客のレビューのようにデータから来る内容には保存された言語から出力します。
Test with: screen reader
References: https://www.w3.org/WAI/WCAG22/Understanding/language-of-parts.html https://www.w3.org/WAI/WCAG22/Techniques/html/H58 https://www.w3.org/International/questions/qa-lang-why https://www.w3.org/International/questions/qa-choosing-language-tags https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/lang https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a#hreflang https://dequeuniversity.com/rules/axe/4.10/valid-lang

よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。

## 場面

アウトドア用品店がホーローのキャンプ用マグを販売しています。英語の商品ページには、顧客のレビューが並んでいます。ほとんどは英語ですが、リヨンの顧客のレビューはフランス語です。「<span lang="fr">Parfaite pour le café du matin au camping.</span>」。スクリーンリーダー利用者が、買うかどうか決めるためにレビューを読みます。英語のレビューは問題ありません。フランス語のレビューは「パーフェイト・プア・リー・キャフェイ・ドゥー・マティン・オー・キャンピング」のように、フランス語の単語が英語の音で読まれます。利用者はフランス語が分かりますが、聞き取れません。ページの下にある言語の切り替えの「<span lang="fr">Français</span>」「<span lang="de">Deutsch</span>」「<span lang="es">Español</span>」も、同じ英語の声で読まれます。

## 確認できる問題

ページには `lang="en"` が指定されています。ページとしては正しく、中の要素は、別の指定がない限りこの言語を受け継ぎます。レビューは店のレビューのデータから表示されています。データはこのレビューがフランス語だと知っていますが、テンプレートがそれを出力しないため、レビューは英語を受け継ぎます。言語の切り替えのリンクには `hreflang="fr"` がありますが、これはリンク先のページの言語を示すもので、リンク自体のテキストの言語ではありません。スクリーンリーダー、読み上げツール、点字翻訳は、各テキストの言語を `lang` から判断するため、すべてを英語として読みます。WCAG 3.1.2は、各箇所や語句の言語をプログラムで判定できることを求めています。この例では、フランス語のレビューと三つの言語名が、英語だと示しています。

## 利用者への影響

この問題はテンプレートではなく内容に現れます。英語のページは、顧客が別の言語で書くまでは、見た目も読み上げも正しいままです。自分たちのレビューでテストするチームは、気づかないかもしれません。ブラウザーも `lang` を使って、フォント、ハイフネーション、スペルチェック、翻訳の提案を決めることがあります。誤った言語の箇所は、表示やハイフネーションが崩れることもあります。

## 自動チェックとAIの限界

axeの `valid-lang` のルールは、ページにある `lang` の値を確認します。`lang="francais"` は報告され、`lang="fr"` は合格します。この問題でよくある、`lang` がまったくない箇所は対象外です。EaseWebの診断は、言語名に独自の `lang` がない言語の切り替えを報告し、英語のページの日本語の文や、日本語のページの英語の文のように、別の文字で書かれたテキストを確認の対象として挙げます。英語のページのフランス語のレビューは周りと同じ文字を使うため、ここでのどのチェックにも見つかりません。AIツールは箇所の言語をおおむね推測できますが、その語が名前、専門用語、ページの言語に取り込まれた語のどれか（いずれも指定は不要）を決めるのは人です。

## 修正前：langのないフランス語のレビューと言語の切り替え

```html
<html lang="en">
…
<h1>Enamel camping mug</h1>
…
<ul class="reviews">  <!-- rendered from the reviews feed -->
  <li>
    <p class="review-text">Light, tough, and keeps tea hot.</p>
    <p class="reviewer">Sam, Leeds</p>
  </li>
  <li>
    <p class="review-text">Parfaite pour le café du matin au camping.</p>
    <p class="reviewer">Camille, Lyon</p>
  </li>
</ul>
…
<footer>
  <nav aria-label="Language">
    <a href="/en/" aria-current="true">English</a>
    <a href="/fr/" hreflang="fr">Français</a>
    <a href="/de/" hreflang="de">Deutsch</a>
    <a href="/es/" hreflang="es">Español</a>
  </nav>
</footer>
```

フランス語のレビューと三つの言語名は、ページの `lang="en"` を受け継ぐため、英語の発音で読まれます。`hreflang` はリンク先を示すもので、テキストの読まれ方は何も変えません。

## 修正後：各箇所にlangを指定

```html
<html lang="en">
…
<h1>Enamel camping mug</h1>
…
<ul class="reviews">  <!-- each li takes the language stored with its review -->
  <li lang="en">
    <p class="review-text">Light, tough, and keeps tea hot.</p>
    <p class="reviewer">Sam, Leeds</p>
  </li>
  <li lang="fr">
    <p class="review-text">Parfaite pour le café du matin au camping.</p>
    <p class="reviewer">Camille, Lyon</p>
  </li>
</ul>
…
<footer>
  <nav aria-label="Language">
    <a href="/en/" aria-current="true">English</a>
    <a href="/fr/" hreflang="fr" lang="fr">Français</a>
    <a href="/de/" hreflang="de" lang="de">Deutsch</a>
    <a href="/es/" hreflang="es" lang="es">Español</a>
  </nav>
</footer>
```

各レビューを、一緒に保存された言語を持つ要素で囲んでいます。フランス語のレビューはフランス語の規則で読まれ、その後の英語は英語に戻ります。英語のレビューにも `lang` を付けているため、フランス語版のページに表示しても英語のまま読まれます。各言語名には、その言語の `lang` をリンク自体に付け、リンク先を示す `hreflang` と並べています。

## 実装の判断

`lang` は箇所全体を囲む要素に付けます。レビューのリスト項目、`blockquote`、`p` などです。文の中の数語なら `span lang="…"` で囲みます。リンクやボタンでは、できれば要素自体に付けます。コントロールの名前はプレーンテキストとして求められるため、名前の一部に付けた `lang` は支援技術に届く途中で失われることがあります。W3Cの例のように、リンクの中で独自の `lang` を持つspanで囲んでも、3.1.2は満たします。同じ理由で、言語の切り替えのリンクに「<span lang="en">Switch to French</span>」のような `aria-label` を付けないでください。名前が英語になり、リンクの `lang="fr"` でそれをフランス語の規則で読むことになります。表示されている言語名を、そのまま名前にします。

自分で書かない内容は、言語をどこかから得る必要があります。方法によって確かさが違います。

- 投稿した人が使っていた言語：サイトのフランス語版から投稿されたレビューは、おそらくフランス語です。投稿時にそのロケールをレビューと一緒に保存します。
- 届いたときの判定：言語判定のライブラリや、ブラウザーに言語判定の機能があればそれを使います。一文以上ならよく当たりますが、二、三語ではよく外れます。結果を保存し、モデレーターが直せるようにします。
- フォームの項目：レビューを書いた言語を投稿者に選んでもらいます。初期値はサイトの現在の言語にします。

言語が分からないときは、推測せずに `lang` なしで表示し、埋めるべき穴として扱います。誤った `lang` は、ないのと同じく基準を満たしません。

別の言語でも、指定がいらない語があります。WCAG 3.1.2は、固有名詞、専門用語、言語を特定できない語、周りの言語の一部になった語を除いています。「Camille」や「Lyon」、英語の文の中の「café」、ブランド名などです。目安は、ページの言語を話す人が同じように発音するかどうかです。日本語のページでは、カタカナの外来語は日本語ですが、スローガンやレビューのような英語の文はひとまとまりの箇所なので `lang="en"` が必要です。日本語を正しく指定することは見た目にも関わります。ブラウザーは `lang` から漢字の字形を選ぶことがあるため、中国語と指定された箇所の日本語は、中国語の字形で表示されることがあります。

レビューをページの言語に翻訳して表示するのは、別の機能です。翻訳はページの言語なので `lang` はいりませんが、原文は、どこに表示するにしても `lang` が必要です。

ページ自体の言語は3.1.1で、[読み上げの発音が崩れる、誤ったページの言語指定](/ja/learn/page-language)で扱っています。タグはそちらと同じく有効なものを使います。`fr`、`de`、`es`、`zh-Hant` などで、`french` や `jp` は使いません。

## 修正の確認

1. ページの言語ではない箇所（レビュー、引用、名前ではない商品名など）をすべて探し、それぞれを囲む要素にその言語の `lang` があるか確認する。
2. 言語の切り替えで、各リンクに、テキストの言語と一致する `lang` がリンク自体か内側のテキストにあり、別の言語の `aria-label` がないか確認する。
3. 実際のフォームから別の言語のレビューを投稿するか取り込み、正しい `lang` で表示されるか確認する。次に、ページの言語で書かれたレビューを、別の言語版のページで確認する。
4. スクリーンリーダーでレビューと言語の切り替えを読み、それぞれがその言語の声で読まれ、その後のテキストでページの声に戻るか確認する。
5. axeの `valid-lang` のルールを実行するか、各 `lang` の値を有効なタグの一覧と照らし合わせる。

OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。新しい出どころの内容や新しい言語を追加した際は、再度確認します。

## 制限

このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。スクリーンリーダーが声を切り替えるのは、その言語の声がインストールされている場合だけで、利用者が自動の言語切り替えをオフにしている場合もあります。これは制御できませんが、マークアップは正しくしておく必要があります。テキストから言語を推測するスクリーンリーダーもありますが、ページと同じ文字で書かれた短い箇所ほど推測は当たりにくく、推測しないものもあるため、`lang` の代わりにはなりません。指定が必要な語かどうかは判断が分かれることもあります。大切な箇所は、できればその言語を読める人と一緒に確認してください。

---

このガイドをコーディングエージェントで使う: MCP https://easeweb.dev/mcp（設定は https://easeweb.dev/ja/services/developers）
