Intermediatei18n25 分2026年4月18日

静的サイトの i18n —— 5 ロケール

CMS なしのスラッシュルート多言語化:辞書、動的 [locale] パス、hreflang、5 言語の同期維持。

アーキテクチャ

/en/blog/hello    ← デフォルトロケール、それでもプレフィックス付き(特例よりすっきり)
/ru/blog/hello
/zh/blog/hello
/ja/blog/hello
/de/blog/hello

動く部品は3つ:

  1. 辞書 —— ロケールごとに1つの JSON。形は同一で、Record<Locale, typeof en> と型付けすることでキーがずれたら TypeScript が叫ぶ。
  2. 動的ルート —— src/pages/[locale]/... に getStaticPaths() で全ロケールを返す。
  3. コンテンツのフォールバック —— 記事は en/ に一度だけ書き、翻訳が来るまですべてのロケールで描画する。

あなたを救う型の小技

export type Locale = "en" | "ru" | "zh" | "ja" | "de";
const dictionaries: Record<Locale, typeof en> = { en, ru, zh, ja, de };

typeof en がスキーマ。en.json にキーを追加すると、残り4つの辞書が追いつくまでビルドが失敗する。

head を忘れるな

全ロケール分の <link rel="alternate" hreflang="..."> に加えて x-default、ページごとの canonical、そして Astro.url 由来のパス。検索エンジンは地味な配管工事を評価する。