Next.js i18n 辞書とプロバイダ (nextjs-i18n-usage)
React Server Components、Client Components、Storybook ストーリー、テストハーネス全体で next-intl 翻訳を利用するためのエンジニアリング標準、フック、プロバイダパターン。
[!TIP] 実装パターン:
references/examples.mdを参照して完全なコード例(RSC、クライアントフォーム、言語スイッチャー、Storybook デコレーター、テストラッパー)を確認してください。 高速実行: 辞書の検証やキーの同期は軽量なサブエージェント(Model: 'flash')に委任してください。
1. ゼロハードコーディング契約
- テキストのハードコーディング禁止: ユーザーに表示されるラベル、プレースホルダー、フォールバック文字列を JSX に直接記述しないでください。
- モックオブジェクト禁止: ファイル内にモック辞書(例:
const DEFAULT_CONTENT = {...})を作成することは禁止です。 - 同期同期: UI コピーを追加・更新する場合、JSX を記述する前に、
messages/[locale].json(例:messages/en.jsonとmessages/fa.json)内のすべてのロケールファイルに正しい翻訳を挿入してください。
2. API とフックのクイックリファレンス
| 環境 / ターゲット | フック / API | 構文例 |
|---|---|---|
| サーバーコンポーネント (RSC) | getTranslations | const t = await getTranslations('namespace'); |
| サーバーフォーマッター | getFormatter | const format = await getFormatter(); format.dateTime(...) |
| 動的メタデータ | getTranslations | export async function generateMetadata({ params }) { ... } |
| クライアントコンポーネント | useTranslations | const t = useTranslations('namespace'); |
| クライアントフォーマッター | useFormatter | const format = useFormatter(); format.number(...) |
| リッチテキスト (クライアント) | t.rich | t.rich('terms', { link: (c) => <Link href="/t">{c}</Link> }) |
| ナビゲーション | @/i18n/navigation | import { Link, useRouter, usePathname } from '@/i18n/navigation'; |
| Storybook プレビュー | NextIntlClientProvider | <NextIntlClientProvider locale="en" messages={enMessages}> でプレビューデコレーターをラップ |
| ユニットテスト (Jest) | renderWithIntl | <NextIntlClientProvider locale="en" messages={messages}> でレンダリングをラップ |
3. BiDi (LTR / RTL) とスタイリングの標準
- Tailwind 論理プロパティのみ:
- 禁止:
ml-*,mr-*,pl-*,pr-*,left-*,right-*,text-left,text-right - 必須:
ms-*,me-*,ps-*,pe-*,start-*,end-*,text-start,text-end
- 禁止:
- 動的な方向指定:
fa/arの場合は動的に<html dir="rtl">、enの場合はdir="ltr"を設定します。
4. アンチパターンと落とし穴
| 誤り | 根本原因 | 解決策 |
|---|---|---|
RSC での useTranslations | フックは非同期サーバーコンポーネントでは実行不可 | await getTranslations('ns') を使用する |
クライアントでの getTranslations | サーバー専用の非同期関数 | "use client" で useTranslations('ns') を使用する |
| 「intl コンテキストが見つかりません」 | Storybook/テストでプロバイダが不足 | ストーリー/テストを <NextIntlClientProvider> でラップ |
| ハードコードされたフォールバック | 例:`t('btn') | |
素の next/link | ルート変更時にロケールプレフィックスが失われる | @/i18n/navigation から Link を使用する |
5. パリティ検証
辞書のパリティチェックを実行します:
pwsh .agents/skills/nextjs-i18n-usage/scripts/verify-dictionaries.ps1