Web accessibility glyph color icon. Silhouette symbol on white background with no outline. Universal access. Negative space. Vector illustration
目次

多言語・多文化サイトのアクセシビリティ完全ガイド:言語切替・読み上げ・表記ゆれ・フォーム入力までやさしく設計する

概要サマリー(先に要点)

  • 言語スイッチャーはどこからでも辿れること、かつ現在言語と次に選べる言語が明確であることが第一歩です。
  • ページ/部分ごとの**lang属性文字方向(dirの正確な指定は、スクリーンリーダーの発音・読み上げ速度**に直結します。
  • 名前順序・住所・日付・通貨・数字などのローカライズ規則をUIとバリデーションに織り込み、**“書き方の間違い”ではなく“文化差”**として扱います。
  • CJKのルビ(ふりがな)/読み、略語、固有名詞、借用語の読み上げ配慮で理解コストを下げます。
  • RTL(右→左)言語対応、翻訳の遅延・欠落時のフォールバック、多言語の代替テキスト・字幕検索・ソートのロケール整合まで、実務で“詰まりやすい所”を丸ごと整理しました。

対象読者(具体)
多言語サイトを運営するプロダクトマネージャー、UI/UXデザイナー、フロントエンドエンジニア、テクニカルライター/ローカライズ担当、QA・CS、広報・採用のWeb運用担当者

アクセシビリティレベルWCAG 2.1 AA 準拠を基本に、可能箇所はAAA(読みの支援・コントラスト強化・明快な説明)も志向


1. はじめに:多言語対応=翻訳ではなく「理解の最短距離」を作ること

多言語・多文化のユーザーに同じ価値を届けるには、単に文言を翻訳するだけでは足りません。読み上げの発音入力様式日付や通貨の書き方名前の順序など、「文化が前提にしているルール」をUIに織り込む必要があります。さらに、視覚・聴覚・運動・認知特性の違いが加わると、配慮すべきポイントは掛け算で増えるのです。
本ガイドでは、言語と文化に起因する障壁を構造・セマンティクス・インタラクションで解消し、誰もが同じ理解に到達できる多言語アクセシビリティの実装手順を、サンプルコードとチェックリストを交えて丁寧に解説しますね。


2. 言語切替の原則:いつでも・どこでも・迷わず

2.1 位置と名前の一貫性

  • ヘッダー右上など、全ページで同じ位置に配置。
  • ボタン名は可視テキストで(例:日本語 / English)。国旗アイコンだけはNG(言語=国ではありません)。
<nav aria-label="言語切替">
  <ul class="lang-switcher">
    <li><a href="/ja/" hreflang="ja" lang="ja" aria-current="page">日本語</a></li>
    <li><a href="/en/" hreflang="en" lang="en">English</a></li>
    <li><a href="/fr/" hreflang="fr" lang="fr">Français</a></li>
  </ul>
</nav>

2.2 現在言語の明示と状態露出

  • 現在の言語には**aria-current="page"**や視覚的強調を。
  • 切替後は同一コンテンツの別言語版に遷移できるよう、URL設計(/ja/, /en/)を揃えます。

2.3 キーボードと読み上げ

  • 言語スイッチャーはTabで到達Enter/Spaceで選択できる構造(<button><a>)。
  • ショートカットは過度に設けず、ユーザー定義機能(OS/AT)の邪魔をしないように。

3. langと文字方向:正しい「発音」と「並び」を支援技術に渡す

3.1 ページ全体の既定言語

<html lang="ja">
  • ページの主要言語を必ず宣言。スクリーンリーダーはこの情報を基準に音声エンジン読み上げ規則を選びます。

3.2 部分的な言語切替

  • 外来語・引用・製品名などは、部分的にlangを切替して正しく発音。
<p>当社は <span lang="en">Accessibility</span> と <span lang="fr">Inclusivité</span> を重視します。</p>

3.3 右→左(RTL)言語

  • アラビア語・ヘブライ語などは、**dir="rtl"を適用。混在文では双方向テキスト(BiDi)**の崩れを避けるため、句読点・数字・略語の塊ごとにdirを適用します。
<p lang="ar" dir="rtl">هذا مثال <span dir="ltr">2025-10-06</span>.</p>

3.4 画面レイアウト

  • RTL対応では、ナビゲーションの並び・矢印方向・アイコンも反転に留意。CSSの**logical properties**(margin-inline-start など)で左右依存を減らします。

4. 代替テキスト・字幕・音声説明:多言語で“同じ理解”を届ける

4.1 画像の代替テキスト

  • 言語ごとに要約の文体を合わせ、専門用語は現地語訳の有無を方針化。
  • 装飾はaltで沈黙、情報画像は要点を短く
<img src="chart.png" alt="2025年上期の売上推移。3月が最大。">

4.2 動画の字幕/キャプション

  • クローズドキャプション(効果音・話者も表記)を多言語提供。
  • track要素で複数言語のVTTを切替可能に。
<video controls>
  <source src="promo.mp4" type="video/mp4">
  <track kind="captions" srclang="ja" src="captions.ja.vtt" label="日本語" default>
  <track kind="captions" srclang="en" src="captions.en.vtt" label="English">
</video>

4.3 オーディオディスクリプション

  • 視覚情報の多い動画は言語別ADを用意。UIはキーボード操作で切替できるように。

5. 名前・住所・日付・通貨:フォームの国際化=「相手の普通」に合わせる

5.1 名前(氏名)の順序とフィールド分割

  • 姓→名 or 名→姓は文化で異なります。ユーザーのロケールに応じてラベルを出し分け、内部では独立フィールドで保持。
<!-- 日本語ロケール例 -->
<label for="family-name">姓</label>
<input id="family-name" name="familyName" autocomplete="family-name">

<label for="given-name">名</label>
<input id="given-name" name="givenName" autocomplete="given-name">

5.2 住所の構造

  • 国際郵便に耐えるよう、自由入力の余地を残しつつ、主要国では**住所コンポーネント(都道府県/州/郵便番号等)**をローカライズ。
  • バリデーションは**“正誤”ではなく“確認を促す”**文体(地名は揺れます)。

5.3 日付・時間・タイムゾーン

  • 入力はISO形式(YYYY-MM-DD)を許可しつつ、表示はロケールに合わせてフォーマット。
  • 予約・配信など時間が重要な導線では、ユーザーのタイムゾーンを明示し、変更も可能に。
<label for="date">Date</label>
<input id="date" name="date" type="date" inputmode="numeric" aria-describedby="date-hint">
<small id="date-hint" lang="en">Format: YYYY-MM-DD</small>

5.4 数字・通貨・桁区切り

  • 3桁区切りや小数点記号(, / .)は言語で異なります。入力は寛容に、保存はISO/通貨コードで正規化。
  • 金額は通貨記号税の扱いを近接表記し、読み上げでは単位を明言します。

6. CJK固有の配慮:ふりがな/読み/略語・外来語の扱い

6.1 ルビ(ふりがな)

  • 人名・地名・専門用語など、読みの誤解がUXに影響する箇所は**<ruby>**で提供します。
<p><ruby>山科<rt>やましな</rt></ruby>駅までのご案内</p>
  • ルビは視覚的にも読み上げ的にも冗長になり得るため、必要箇所に限定します。

6.2 略語・頭字語

  • <abbr title="…">で正式名を提供し、スクリーンリーダーに読み方のヒントを渡します。
<abbr title="User Experience">UX</abbr>

6.3 外来語の発音

  • 読みが難しい製品名等は、スクリーンリーダー専用テキストsr-only)で補助を。

7. 検索・ソート・ハイライト:ロケールで“意味の順番”が変わる

  • ソート:辞書式/音読み/訓読み/アクセント記号の無視など、ロケールごとに期待が違います。フロント/バックいずれもロケール対応の比較関数を採用(たとえばJavaScriptのIntl.Collator)。
  • 検索:全角半角・ひらがな/カタカナ/ローマ字、ダイヤクリティカルマークの有無を正規化
  • ハイライト:合致箇所を色だけに頼らず、太字や背景板で重複伝達(1.4.1)。
// ソート例:日本語の五十音順
const collator = new Intl.Collator('ja', { sensitivity: 'base', numeric: true });
items.sort((a,b)=> collator.compare(a.label, b.label));

8. 翻訳の遅延・欠落に備える:フォールバックとラベルの一貫性

  • フォールバック言語(例:en)を定義し、未翻訳のキーは意味が通る文で出す。
  • ラベルの粒度UI単位で固定(「保存」「保存する」を混在させない)。
  • テストでは、片言語だけ差し替えてUI崩れ・改行の溢れを検知。

9. コンポーネント設計:最小ARIA+ネイティブ優先で“言語を跨いで”壊れない

9.1 言語スイッチャー(ディスクロージャ)

<div class="i18n" aria-labelledby="lang-label">
  <h2 id="lang-label" class="sr-only">言語切替</h2>
  <button aria-expanded="false" aria-controls="lang-list" aria-haspopup="listbox">日本語</button>
  <ul id="lang-list" role="listbox" hidden>
    <li role="option" aria-selected="true"><a lang="ja" hreflang="ja" href="/ja/">日本語</a></li>
    <li role="option"><a lang="en" hreflang="en" href="/en/">English</a></li>
    <li role="option"><a lang="ar" hreflang="ar" dir="rtl" href="/ar/">العربية</a></li>
  </ul>
</div>
<script>
const btn = document.querySelector('.i18n button');
const list = document.getElementById('lang-list');
btn.addEventListener('click', ()=>{
  const open = btn.getAttribute('aria-expanded')==='true';
  btn.setAttribute('aria-expanded', String(!open));
  list.hidden = open;
  if(!open) list.querySelector('a')?.focus();
});
document.addEventListener('keydown', e=>{
  if(e.key==='Escape'){ btn.setAttribute('aria-expanded','false'); list.hidden = true; btn.focus(); }
});
</script>

9.2 右→左対応のCSS

:root { --space: 1rem; }
html[dir="ltr"] .nav li { margin-inline-end: var(--space); }
html[dir="rtl"] .nav li { margin-inline-start: var(--space); }

9.3 スクリーンリーダー専用テキスト

.sr-only{
  position:absolute!important;width:1px;height:1px;margin:-1px;padding:0;border:0;
  clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden;white-space:nowrap
}

10. マイクロコピーの国際化:理解の“つまずき”を言葉で減らす

  • 直接的で簡潔な文体(受動態を避け、行動の動詞を先頭へ)。
  • 否定形の連続は避ける(文化差で誤解されやすい)。
  • 数・単位・日付例示で補足し、**“直し方”**を短く示す。
  • 翻訳メモリを使う場合は、文脈タグ(場面・UI種別・性数一致など)を付与し、再利用で誤訳を防止。

11. パフォーマンス×アクセシビリティ:フォント・幅・行間

  • Webフォント:CJKは容量が大きいので、サブセット化表示フォールバックfont-display: swap)でFOITを回避。
  • 行間と文字サイズ:ロケールによって平均単語長禁則処理が異なるため、行間1.6前後・文中改行に余裕を。
  • 長い単語(ドイツ語など)にはoverflow-wrap: anywhere;はみ出しを防ぐ。
html { font-size: 100%; line-height: 1.6; }
p { overflow-wrap: anywhere; }

12. ユーザーテスト:当事者の“普通”を基準にする

  • 参加者の多様性:スクリーンリーダー利用、キーボード操作中心、色覚多様性、複数言語話者、RTL言語話者。
  • タスク設計:言語切替→検索→フォーム入力→確認メール(時刻・通貨の確認)。
  • 観察ポイント
    1. 言語切替が迷わずできるか。
    2. アナウンスの言語が突然混ざらないか。
    3. 入力エラーが文化差ではなく誤入力として適切に指摘できているか。
    4. 日付・通貨・単位が意図通りに理解・表示できているか。

13. よくある落とし穴と回避策

落とし穴 何が起きる? 回避策
国旗で言語切替 国=言語ではない/政治的配慮不足 言語名のテキストを表示、hreflang/lang付与
lang未設定 読み上げの発音が不自然 ページ・部分ともにlang明示
RTLに未対応 ナビの方向・アイコンが逆 dir="rtl"論理プロパティで左右依存を解消
翻訳欠落で[MISSING_KEY] 利用不能・不信感 フォールバック言語監視テスト
住所・氏名の固定様式 文化差を誤入力扱い ローカライズと柔軟バリデーション
色だけで状態説明 伝わらない テキスト+形で重複伝達
動画が単一言語 情報格差 多言語字幕・ADの提供
検索が全半角・濁点で不一致 見つからない 正規化とロケールソート

14. 手動テスト(5分ルーティン)

  1. 言語切替:Tab→言語スイッチャー→別言語同一ページに遷移できる。
  2. lang切替:本文中の英語箇所などが正しく発音される。
  3. RTLdir="rtl"でナビ・パンくず・矢印・フォーカス順が自然。
  4. フォーム:氏名・住所・日付・通貨がロケールに沿って入力・保存・表示できる。
  5. 字幕:動画で字幕言語が切替可能、キーボード操作に追随。
  6. ソート・検索:ロケールに従った結果とハイライトの重複伝達

15. デザインシステムへの落とし込み

  • トークン:言語・方向(dir)・日付/通貨・数字フォーマット・長い単語折返し設定。
  • コンポーネント仕様:言語スイッチャー、字幕トグル、住所入力、日付・時間ピッカー、通貨フィールド。
  • ドキュメント
    • 名前・役割・値(ARIA)
    • キー操作(Tab/矢印/Enter/Esc)
    • 視覚・音声の重複伝達
    • ローカライズ方針(丁寧語・口調・数の表記)

16. サンプル:国際化対応のミニフォーム(完成度高め)

<form id="profile" lang="ja" novalidate aria-describedby="note">
  <p id="note">*は必須です。入力規則はお住まいの地域に合わせています。</p>

  <fieldset>
    <legend>氏名 <span aria-hidden="true">*</span></legend>
    <div class="field">
      <label for="family-name">姓</label>
      <input id="family-name" name="familyName" autocomplete="family-name" required>
    </div>
    <div class="field">
      <label for="given-name">名</label>
      <input id="given-name" name="givenName" autocomplete="given-name" required>
    </div>
    <div class="field">
      <label for="name-kana">ふりがな</label>
      <input id="name-kana" name="nameKana" aria-describedby="kana-hint">
      <small id="kana-hint">読みを伝える必要がある場合のみ。</small>
    </div>
  </fieldset>

  <fieldset>
    <legend>住所</legend>
    <div class="field">
      <label for="country">国</label>
      <select id="country" name="country" autocomplete="country-name">
        <option value="JP" selected>日本</option>
        <option value="US">United States</option>
        <option value="DE">Deutschland</option>
        <option value="AE" dir="rtl" lang="ar">الإمارات العربية المتحدة</option>
      </select>
    </div>

    <div class="field">
      <label for="postal">郵便番号</label>
      <input id="postal" name="postal" inputmode="numeric" autocomplete="postal-code">
    </div>

    <div class="field">
      <label for="line1">住所1</label>
      <input id="line1" name="address1" autocomplete="address-line1">
    </div>

    <div class="field">
      <label for="city">市区町村</label>
      <input id="city" name="city" autocomplete="address-level2">
    </div>
  </fieldset>

  <fieldset>
    <legend>連絡先</legend>
    <div class="field">
      <label for="email">Email</label>
      <input id="email" name="email" type="email" autocomplete="email" lang="en" aria-describedby="email-hint">
      <small id="email-hint" lang="en">Example: user@example.com</small>
    </div>
    <div class="field">
      <label for="tel">電話番号</label>
      <input id="tel" name="tel" type="tel" inputmode="tel" autocomplete="tel">
    </div>
  </fieldset>

  <button type="submit">保存</button>

  <div id="status" role="status" aria-atomic="true" class="sr-only"></div>
</form>
<script>
const form = document.getElementById('profile');
const country = document.getElementById('country');
country.addEventListener('change', ()=>{
  const html = document.documentElement;
  // RTL切替(簡易例)
  html.setAttribute('dir', country.value==='AE' ? 'rtl' : 'ltr');
  // 郵便番号のヒント・入力モード等を国別で調整(実務では辞書化)
  const postal = document.getElementById('postal');
  if(country.value==='US'){ postal.placeholder='ZIP (e.g., 94105)'; postal.setAttribute('inputmode','numeric'); }
  if(country.value==='JP'){ postal.placeholder='例:1000001'; }
});
form.addEventListener('submit', e=>{
  e.preventDefault();
  document.getElementById('status').textContent='保存しました。';
});
</script>

17. 組織運用:翻訳とUIを“別物にしない”ために

  • リリースブランチと翻訳ブランチの同期を自動化(未翻訳キーのアラート)。
  • PRテンプレに**lang/dir/字幕/代替テキスト**のチェック項目を追加。
  • 地域ごとのCSナレッジ(住所・郵便・敬称・休日)をWiki化し、マイクロコピーの一貫性を担保。
  • 四半期レビューで、検索・ソート・フォームの実地データ(エラー率・離脱)を確認し改善。

18. 誰に、どう効くの?(具体的インパクト)

  • スクリーンリーダー利用者:正しいlang自然な発音、字幕・ADで同じ理解
  • キーボード/音声操作ユーザー:言語切替・字幕切替が同じキー操作で完結。
  • 高齢者・学習者:CJKのルビや略語の補足で理解が滑らかに。
  • 国外ユーザー:住所・氏名・日付・通貨が**自分の“普通”**で入力・確認でき、エラーが減少。
  • 運用チーム:翻訳欠落・方向性崩れ・ソート不整合などの事故が激減
  • ビジネス:離脱率低下、問い合わせ削減、現地化の信頼によるCVR改善。

19. まとめ:言語の数だけ、やさしさの形が増える

  1. 言語切替は“いつでも・同じ場所で”、状態を正しく露出。
  2. **langdir**をページ/部分で適切に設定し、発音と方向を支援技術へ。
  3. 住所・氏名・日付・通貨はロケールの“普通”に合わせ、柔らかなバリデーションで支える。
  4. 字幕・代替テキストを多言語で提供し、同じ理解へ導く。
  5. 検索・ソートはロケール対応の比較と正規化、色だけに頼らない伝達
  6. RTL・長文・フォントまで含めて、見やすさ・読みやすさ・操作しやすさを整える。
  7. デザインシステムと運用を整え、翻訳とUIを一体で育てる。

世界中のユーザーが、あなたの言葉で、あなたの意図どおりに、安心して理解できる。そんな多言語サイトを一緒に作っていきましょう。わたしも心を込めて応援していますわ。


投稿者 greeden

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)