言語切り替えLanguage switcher
地球儀のアイコンといま表示中の言語名を並べたボタン。押すと、各言語をその言語自身の文字で書いた一覧が開き、同じページの別の言語版へ移れる。
表示例
アイコン: Font Awesome 7 Free(fa-solid / fa-regular)
別名・英語表記
- ランゲージセレクター
- 言語選択
- 多言語メニュー
- 言語メニュー
- Language ボタン
- Language switcher
実装例
<nav class="x-language-switcher" aria-label="言語の切り替え">
<button class="x-language-switcher__b" type="button" aria-expanded="true" aria-controls="x-language-switcher-l">
<i class="fa-solid fa-globe" aria-hidden="true"></i>
<span class="x-language-switcher__vh">言語: </span>日本語
<i class="fa-solid fa-chevron-down x-language-switcher__arrow" aria-hidden="true"></i>
</button>
<!-- 見本なので開いた状態。閉じるときは hidden 属性を付け、aria-expanded を false にする -->
<ul role="list" class="x-language-switcher__l" id="x-language-switcher-l">
<li><a href="/ja/pricing/" hreflang="ja" lang="ja" aria-current="page">日本語<i class="fa-solid fa-check" aria-hidden="true"></i></a></li>
<li><a href="/en/pricing/" hreflang="en" lang="en">English</a></li>
<li><a href="/zh-hans/pricing/" hreflang="zh-Hans" lang="zh-Hans">简体中文</a></li>
<li><a href="/ko/pricing/" hreflang="ko" lang="ko">한국어</a></li>
<li><a href="/es/pricing/" hreflang="es" lang="es">Español</a></li>
</ul>
</nav>
/* 貼った先のリセットに頼らないよう、この部品の中だけ border-box にする */
.x-language-switcher,
.x-language-switcher *:not([class*="fa-"]),
.x-language-switcher *:not([class*="fa-"])::before,
.x-language-switcher *:not([class*="fa-"])::after {
box-sizing: border-box;
/* 貼った先の既定の書体に引きずられないようにする。書体が変わると
文字の幅と高さが変わり、枠のサイズまでずれる */
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Hiragino Sans", "Noto Sans JP", "Yu Gothic UI", Meiryo, sans-serif;
}
.x-language-switcher {
width: 180px;
color: #1b2028;
}
.x-language-switcher__b {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
min-height: 36px;
padding: 0 12px;
border: 1px solid #7f8a99;
border-radius: 8px;
background: #fff;
color: #1b2028;
font: inherit;
font-size: 13px;
cursor: pointer;
}
.x-language-switcher__b .fa-globe {
color: #1d4ed8;
}
.x-language-switcher__arrow {
margin-left: auto;
font-size: 10px;
transition: transform 0.15s;
}
.x-language-switcher__b[aria-expanded="true"] .x-language-switcher__arrow {
transform: rotate(180deg);
}
.x-language-switcher__b:hover {
background: #f1f3f6;
}
.x-language-switcher__l {
margin: 6px 0 0;
padding: 5px;
border: 1px solid #e3e6ea;
border-radius: 8px;
background: #fff;
box-shadow: 0 6px 14px rgba(27, 32, 40, 0.1);
list-style: none;
}
.x-language-switcher__l[hidden] {
display: none;
}
.x-language-switcher__l a {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 30px;
padding: 0 10px;
border-radius: 6px;
color: #1b2028;
font-size: 13px;
text-decoration: none;
}
.x-language-switcher__l a:hover {
background: #f1f3f6;
}
/* 選んでいる言語は、色だけでなく太字とチェックの形でも示す */
.x-language-switcher__l a[aria-current="true"] {
color: #1d4ed8;
font-weight: 700;
}
.x-language-switcher__b:focus-visible,
.x-language-switcher__l a:focus-visible {
outline: 2px solid #1d4ed8;
outline-offset: 2px;
}
/* 画面には出さず、読み上げにだけ渡す文字 */
.x-language-switcher__vh {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
border: 0;
}
@media (prefers-reduced-motion: reduce) {
.x-language-switcher__arrow {
transition: none;
}
}
AIへの指示文
「言語切り替え(Language switcher)」を実装してください。
## これは何か
地球儀のアイコンといま表示中の言語名を並べたボタン。押すと、各言語をその言語自身の文字で書いた一覧が開き、同じページの別の言語版へ移れる。
## 使いどころ
- 同じ内容を複数の言語で用意したサイトで、読む人が自分で言語を選び直せるようにしたいとき
- ブラウザの言語設定や地域で自動的に振り分けた結果が、本人の読みたい言語と違う場合の逃げ道を用意したいとき
## 実装の要件
- nav[aria-label] > button[aria-expanded][aria-controls] + ul > li > a[hreflang][lang] の構成にする
- リンクの href は同じページの別言語版(/en/pricing/ など)にする
- 検索エンジン向けには、各言語版の head に link rel="alternate" hreflang="…" を相互に書く。画面の切り替えボタンだけでは言語版どうしの対応が検索エンジンに伝わらない
- 一覧に display を指定したら、一覧のクラスに絞って .一覧[hidden] { display: none; } も書く([hidden] 全体に書くと hidden="until-found" が検索で開かなくなる)
- 国旗で言語を表さない。国旗は国の印で、英語やスペイン語のように複数の国で使われる言語や、複数の言語を使う国に対応しない(W3C の国際化の指針も、言語の表示には国旗ではなく文字を使うよう勧めている)
- 言語名は、その言語自身の書き方で並べる(English・한국어・Español)。日本語で「英語」「韓国語」と書くと、日本語を読めない人がいちばん探せない
- 切り替えたら、トップページではなく同じページの別の言語版へ移す。対応するページが無い言語は、その旨を書いてから移す
- IP アドレスやブラウザの言語設定で自動的に別の言語版へ転送し、手で戻れないようにしない。選んだ言語は Cookie などに覚えておき、次から優先する
- ヘッダーの端かフッターのように、どのページでも同じ場所に置く
## アクセシビリティの要件
- 開閉は button に aria-expanded と aria-controls を付けて行う。中身は行き先のリンクなので role="menu" にしない(WAI-ARIA APG の Disclosure の形)
- 各言語のリンクに lang 属性を付け、読み上げがその言語の発音で読めるようにする(WCAG 3.1.2 一部分の言語)
- ボタンの名前は「言語: 日本語」のように、何のボタンかといまの言語が両方伝わるようにする。見えている文字(日本語)は名前に含める(WCAG 2.5.3 ラベルを含む名前)
- 選んでいる言語は色だけで示さず、チェックの形や太字を添え、aria-current で伝える
- Esc キーで一覧を閉じ、ボタンへフォーカスを戻す
## 参考にする実装
この形を出発点にして、プロジェクトの命名規則・色・余白に合わせて調整してください。
```html
<nav class="x-language-switcher" aria-label="言語の切り替え">
<button class="x-language-switcher__b" type="button" aria-expanded="true" aria-controls="x-language-switcher-l">
<i class="fa-solid fa-globe" aria-hidden="true"></i>
<span class="x-language-switcher__vh">言語: </span>日本語
<i class="fa-solid fa-chevron-down x-language-switcher__arrow" aria-hidden="true"></i>
</button>
<!-- 見本なので開いた状態。閉じるときは hidden 属性を付け、aria-expanded を false にする -->
<ul role="list" class="x-language-switcher__l" id="x-language-switcher-l">
<li><a href="/ja/pricing/" hreflang="ja" lang="ja" aria-current="page">日本語<i class="fa-solid fa-check" aria-hidden="true"></i></a></li>
<li><a href="/en/pricing/" hreflang="en" lang="en">English</a></li>
<li><a href="/zh-hans/pricing/" hreflang="zh-Hans" lang="zh-Hans">简体中文</a></li>
<li><a href="/ko/pricing/" hreflang="ko" lang="ko">한국어</a></li>
<li><a href="/es/pricing/" hreflang="es" lang="es">Español</a></li>
</ul>
</nav>
```
```css
/* 貼った先のリセットに頼らないよう、この部品の中だけ border-box にする */
.x-language-switcher,
.x-language-switcher *:not([class*="fa-"]),
.x-language-switcher *:not([class*="fa-"])::before,
.x-language-switcher *:not([class*="fa-"])::after {
box-sizing: border-box;
/* 貼った先の既定の書体に引きずられないようにする。書体が変わると
文字の幅と高さが変わり、枠のサイズまでずれる */
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Hiragino Sans", "Noto Sans JP", "Yu Gothic UI", Meiryo, sans-serif;
}
.x-language-switcher {
width: 180px;
color: #1b2028;
}
.x-language-switcher__b {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
min-height: 36px;
padding: 0 12px;
border: 1px solid #7f8a99;
border-radius: 8px;
background: #fff;
color: #1b2028;
font: inherit;
font-size: 13px;
cursor: pointer;
}
.x-language-switcher__b .fa-globe {
color: #1d4ed8;
}
.x-language-switcher__arrow {
margin-left: auto;
font-size: 10px;
transition: transform 0.15s;
}
.x-language-switcher__b[aria-expanded="true"] .x-language-switcher__arrow {
transform: rotate(180deg);
}
.x-language-switcher__b:hover {
background: #f1f3f6;
}
.x-language-switcher__l {
margin: 6px 0 0;
padding: 5px;
border: 1px solid #e3e6ea;
border-radius: 8px;
background: #fff;
box-shadow: 0 6px 14px rgba(27, 32, 40, 0.1);
list-style: none;
}
.x-language-switcher__l[hidden] {
display: none;
}
.x-language-switcher__l a {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 30px;
padding: 0 10px;
border-radius: 6px;
color: #1b2028;
font-size: 13px;
text-decoration: none;
}
.x-language-switcher__l a:hover {
background: #f1f3f6;
}
/* 選んでいる言語は、色だけでなく太字とチェックの形でも示す */
.x-language-switcher__l a[aria-current="true"] {
color: #1d4ed8;
font-weight: 700;
}
.x-language-switcher__b:focus-visible,
.x-language-switcher__l a:focus-visible {
outline: 2px solid #1d4ed8;
outline-offset: 2px;
}
/* 画面には出さず、読み上げにだけ渡す文字 */
.x-language-switcher__vh {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
border: 0;
}
@media (prefers-reduced-motion: reduce) {
.x-language-switcher__arrow {
transition: none;
}
}
```
## 出力の約束
- HTML と CSS を分けて出す。JavaScript が要るときは素の JavaScript で書き、UIフレームワークは使わない。
- 参考実装がアイコンに Font Awesome のクラスを使っている場合は、プロジェクトで使っているアイコンかインライン SVG に置き換えてよい。
- 上のアクセシビリティ要件を満たす。満たせない箇所があるときは、理由を添えて先に知らせる。
- 色・角丸・余白は既存のデザイントークンがあればそれを使う。無ければ CSS 変数として切り出す。
使いどころ
- 同じ内容を複数の言語で用意したサイトで、読む人が自分で言語を選び直せるようにしたいとき
- ブラウザの言語設定や地域で自動的に振り分けた結果が、本人の読みたい言語と違う場合の逃げ道を用意したいとき
注意点
- 国旗で言語を表さない。国旗は国の印で、英語やスペイン語のように複数の国で使われる言語や、複数の言語を使う国に対応しない(W3C の国際化の指針も、言語の表示には国旗ではなく文字を使うよう勧めている)
- 言語名は、その言語自身の書き方で並べる(English・한국어・Español)。日本語で「英語」「韓国語」と書くと、日本語を読めない人がいちばん探せない
- 切り替えたら、トップページではなく同じページの別の言語版へ移す。対応するページが無い言語は、その旨を書いてから移す
- IP アドレスやブラウザの言語設定で自動的に別の言語版へ転送し、手で戻れないようにしない。選んだ言語は Cookie などに覚えておき、次から優先する
- ヘッダーの端かフッターのように、どのページでも同じ場所に置く
アクセシビリティの要点
- 開閉は button に aria-expanded と aria-controls を付けて行う。中身は行き先のリンクなので role="menu" にしない(WAI-ARIA APG の Disclosure の形)
- 各言語のリンクに lang 属性を付け、読み上げがその言語の発音で読めるようにする(WCAG 3.1.2 一部分の言語)
- ボタンの名前は「言語: 日本語」のように、何のボタンかといまの言語が両方伝わるようにする。見えている文字(日本語)は名前に含める(WCAG 2.5.3 ラベルを含む名前)
- 選んでいる言語は色だけで示さず、チェックの形や太字を添え、aria-current で伝える
- Esc キーで一覧を閉じ、ボタンへフォーカスを戻す