コンテンツにスキップ

多言語対応と言語切り替え

EpoCanvas Docs にはコンテンツレベルの多言語対応が組み込まれています。ナビゲーションバー、サイドバー、検索の案内などの UI 文字列も、各ドキュメントの本文も、10 言語それぞれの独立したバージョンが用意されています。読者がページ右上で言語を選ぶと、同じ記事の対象言語版へ移動し、本文と UI がまとめて切り替わります。


対応言語の一覧

サイトは現在 10 言語を提供しており、そのうち簡体字中国語がデフォルト言語です。

言語言語名称URL プレフィックスUI 略称
简体中文簡体字中国語(デフォルト)プレフィックスなしZH
繁體中文繁体字中国語/zh-tw/TW
English英語/en/EN
日本語日本語/ja/JA
한국어韓国語/ko/KO
Españolスペイン語/es/ES
Françaisフランス語/fr/FR
Deutschドイツ語/de/DE
Русскийロシア語/ru/RU
Portuguêsポルトガル語/pt/PT

言語の一覧は src/utils/i18n.ts の SUPPORTED_LANGUAGES で定義され、言語ルーティングは astro.config.mjs の locales 設定に登録されています。両者は一致させておく必要があります。


言語の切り替え方法

  1. ページ上部ナビゲーションバーの右側にある言語ボタンを探します(現在の言語の略称、例:ZH が表示されています)。
  2. ボタンをクリックすると、ドロップダウンメニューに 10 言語すべてが表示されます。
  3. 対象の言語(例:English や 日本語)をクリックします。
  4. ブラウザーが現在の記事の対象言語版へ移動し、ナビゲーション、サイドバー、目次、本文がまとめて対象言語に変わります。

言語切り替えドロップダウンを展開したときの実際の注釈画面:① 言語ボタン ② 言語リスト ③ 現在の言語

図:「多言語対応と言語切り替え」ページで言語ボタンをクリックしたときの実際の注釈画面。① トップバー右側の言語切り替えボタン、② 展開されたドロップダウンメニュー(10 言語すべてを表示、リストはスクロール可能)、③ 現在有効な言語(チェックマーク付き)。

言語切り替えの仕組みの模式図

図:言語切り替えの実行フロー。ビルド時に言語ごとに一式の静的ページが生成され、言語ボタンをクリックすると対応言語の同じ記事へ移動します。一部のページに翻訳がない場合は、自動的に簡体字中国語でフォールバック表示されます。


URL の規則

各言語のページには独立した URL プレフィックスがあり、同じ記事は言語が違ってもプレフィックスしか違いません。

/canvas/i18n/ → 簡体字中国語(デフォルト言語、プレフィックスなし)
/en/canvas/i18n/ → 英語
/ja/canvas/i18n/ → 日本語
/zh-tw/canvas/i18n/ → 繁体字中国語
  • 言語情報は URL に直接エンコードされているため、切り替え後のページをそのままブックマークや共有でき、検索エンジンも言語ごとに別々にインデックスできます。
  • ページ内のサイト内リンク(ナビゲーション、サイドバー、本文中のおすすめリンク)にはすべて現在の言語のプレフィックスが自動的に付くため、ある言語で読み続けている間に簡体字中国語のページへ戻されることはありません。
  • 各言語版はビルド時に生成される独立した静的ページで、ページの <html lang> 属性は言語と一致するため、スクリーンリーダーや翻訳ツールが正しく認識できます。

翻訳が不足している場合

システムは「デフォルト言語へのフォールバック」という方針で不足している翻訳を処理します。あるドキュメントにまだある言語の翻訳がない場合、その言語のページにアクセスするとデフォルトの簡体字中国語の内容が表示され、ページの残りの部分(ナビゲーション、サイドバー、UI 文字列)は対象言語のままです。404 エラーや空白ページにはなりません。

この方針の利点は、新しいドキュメントを追加するときに全言語の翻訳が揃うのを待つ必要がなく、まず簡体字中国語版を公開し、翻訳を揃えてから再ビルドすればよいことです。


実装の仕組み

多言語機能は Astro と Starlight の国際化の仕組みによって実現されており、ビルドの流れは次のとおりです。

  1. コンテンツディレクトリを言語別に分ける:デフォルト言語のドキュメントは src/content/docs/(簡体字中国語)に置き、他の言語は src/content/docs/<言語>/ の下に置きます。ディレクトリ構造は簡体字中国語版と完全に対応しており、たとえば英語版の「多言語対応と言語切り替え」は src/content/docs/en/canvas/i18n.md です。
  2. ビルド時に全言語のページを生成:astro build は astro.config.mjs の locales 設定を読み込み、言語ごとに一式の完全な静的ページを生成します。
  3. UI 文字列を言語別にレンダリング:トップバーのナビゲーション、検索の案内、目次の見出しなどの UI 文字列は、各コンポーネントが getTranslation(key, lang) を呼び出してビルド時に対応言語を直接出力します。ページ内に実行時の差し替えスクリプトはありません。
  4. 本文内の内部リンクを自動ローカライズ:ビルドパイプラインの rehypeLocalizeInternalLinks プラグインが、翻訳本文中の /canvas/xxx 内部リンクに現在の言語のプレフィックスを自動的に付けます。
  5. 全文検索を言語別に分離:Pagefind は言語ごとに独立したインデックスを構築し、英語のページでの検索は英語の結果だけを返します。
  6. 本文中の画像は言語単位で自動フォールバック:rehypeLocalizeDiagramImages プラグインが訳文本文の /images/canvas/<ファイル名> を /images/canvas/<言語>/<ファイル名> に書き換えます。各言語の画像は public/images/canvas/<言語>/ に置きます。同名ファイルがなければ元の画像のまま使うため、新しい画像を 10 言語すべて同時に用意する必要はありません;
  7. 吹き出しと脚注もページの言語に追従:rehypeLocalizeAsides と rehypeLocalizeFootnotes はソースファイルのある言語ディレクトリに基づき吹き出しタイトルと脚注文言を書き換えます。Starlight は remark 段階で絶対パスから言語を推定しますが、ローカルビルドでは相対パスが渡されるため、この処理がないとすべて中国語にフォールバックします;
  8. hreflang と 404 ページ:hreflangXDefault() はビルド後に各ページへ hreflang="x-default" を 1 本追加し、簡体字中国語版を指します。src/pages/404.astro は同じ辞書を使い、ブラウザ言語で案内文を出し、言語メニューは各言語のトップページへ飛びます。

開発者向け:新しい言語を追加するには?

イタリア語(Italiano、コード it)を追加する場合を例にします。

  1. 言語ルーティングを登録:astro.config.mjs の locales に it: { label: 'Italiano', lang: 'it' } を追加します。
  2. サイドバーの文案を追加:同じファイルの SIDEBAR_I18N で、すべてのグループと項目に it の翻訳を追加します。
  3. UI 文字列を追加:src/utils/i18n.ts の SUPPORTED_LANGUAGES に言語の一覧(コード、名称、略称、URL プレフィックス)を登録し、UI_TRANSLATIONS にその言語の UI 文字列を揃えます。
  4. ドキュメント本文を翻訳:src/content/docs/it/ ディレクトリを新規作成し、簡体字中国語版と同じディレクトリ構造で翻訳を置きます。未翻訳のページは一旦簡体字中国語でフォールバック表示されるため、少しずつ揃えていけます画面スクリーンショットや構成図を翻訳する場合は public/images/canvas/it/ を作って同名ファイルを置けば、ページ側で自動参照されます。
  5. 再ビルド:pnpm run build を実行すると、新しい言語のページと検索インデックスが生成されます。ビルド後に node scripts/audit-i18n.mjs と node scripts/check-localized-images.mjs を実行して訳文の構造と画像参照を点検します。両方とも CI で必須のチェックです。

開発者向け:UI 文字列を追加・変更するには?

新しい UI 要素を追加するときは、src/utils/i18n.ts の UI_TRANSLATIONS に文字列を追加します。

src/utils/i18n.ts
// 辞書は「言語 → キー」の 2 階層で構成され、getTranslation の読み取り順序と一致しています
export const UI_TRANSLATIONS: Record<string, Record<string, string>> = {
// ステップ 1: デフォルト言語 zh-CN に文字列を追加する(欠けている場合は UI にキー名が fallback 表示される)
'zh-CN': {
'nav.plugins': '插件生态',
// ...その他の既存の文字列
},
// ステップ 2: 他の言語に同じキー名の翻訳を追加する。未追加の言語は自動的に簡体字中国語へ fallback する
en: {
'nav.plugins': 'Plugins',
},
ja: {
'nav.plugins': 'プラグイン',
},
};

次に、コンポーネント内で getTranslation を呼び出し、現在の言語を渡します。

---
import { getLangFromLocale, getTranslation } from '../../utils/i18n';
const lang = getLangFromLocale(Astro.currentLocale);
---
<a href={localizedHref('/plugins/', lang)}>{getTranslation('nav.plugins', lang)}</a>

文字列はビルド時に対応言語の静的なテキストとしてレンダリングされ、実行時のオーバーヘッドはありません。