定義
Locale-aware routing(ロケール対応ルーティング)とは、ユーザーが選んだ言語(ko/en/ja)がすべての内部 URL とクライアントナビゲーションに一貫して反映されるルーティング方式です。
next-intl で localePrefix: "always" を使うと、URL は常に /ko/til、/en/knowledge/... の形になり、プレフィックスのない /til のようなパスはミドルウェアがデフォルト locale(例: /ko/til)へ 301 リダイレクトします。
なぜ必要か
コンテンツは en/ja に増えたのに、ヘッダー・サイトマップ・カードが plain な next/link で /til を指していると、/en からクリックするたびにミドルウェアが /ko/til に送り、言語選択が毎回リセットされます。翻訳品質の問題ではなく、ルーティング契約の違反です。
逆に @/i18n/navigation の Link・useRouter は現在の locale を href に自動で含めます。SSR HTML の href をサンプリングすれば、bare path の回帰を素早く検出できます。
動作の仕組み
- ミドルウェア:
localePrefix: "always"→ bare pathname 検出時に default locale へ redirect。 - i18n Link:
href="/til"→ レンダー時/en/til(現在 locale 基準)。 - plain next/link:
href="/til"のまま → ミドルウェア 301 →/ko/til。 - 言語選択 UI:
routing.localesを単一ソースに Dropdown・sitemap・メッセージキーを同期。 - programmatic nav:
router.push、replaceも i18n router を使用。startTransition・view transition と併用可能。 - Markdown 本文リンク: remark 段階で locale prefix 変換(アプリ shell の Link とは別パイプライン)。
実務での適用
- content-nav・footer・リストカード・パンくずを grep し、
next/linkの内部利用を除去する。 - detail の未翻訳 fallback はページごとのコピペではなく
getLocalizedDocumentOrRedirectヘルパー + テスト。 - prod
next start後curlで/en/...HTML の internal href が en-prefixed かカウント(bare 0 件を目標)。 - load-more・relations API にアクティブ locale のクエリパラメータまたはヘッダーを渡す。
- ESLint カスタムルールまたは codemod で
src/内のfrom "next/link"新規利用をレビュー。
トレードオフ
| 選択 | 利点 | 欠点 |
|---|---|---|
| localePrefix always | URL だけで言語識別、キャッシュ・共有が明確 | すべての内部リンクで i18n API が必須 |
| localePrefix as-needed | default locale の URL が短い | en/ja と ko で URL 形が不一致 |
| plain Link + 手動 prefix | 慣れている | 漏れで 301・ロケール喪失 |
| redirect fallback(ko) | 読めるコンテンツを保証 | URL の locale が変わる |
使うべきでない場合
- 外部サイト・
mailto:・絶対 URL — plain<a>または full URL 付きnext/linkは locale と無関係。 - API route・静的 asset — locale segment なし。
localePrefix: "never"ポリシー — この文書の always 前提と異なる。
よくある間違い
- ヘッダーだけ i18n
Linkに変え、content-nav 12 箇所は plainnext/linkのまま。 - クライアントだけ locale prefix を付け、SSR HTML は bare → SEO・no-JS 環境で ko に飛ぶ。
router.back()に view transition を期待 — popstate は同期のため VT 非対応(明示 URL のpushが必要)。- markdown 本文の
../knowledge/...リンクを locale 変換パイプラインなしでデプロイ。
関連概念
- multilingual-content-locale-suffix — コンテンツ locale 軸
- hierarchical-document-navigation — 一覧→詳細の depth
- ssr-hydration-mismatch — SSR HTML とクライアント href の一致