Next.js i18n 字典與提供者(nextjs-i18n-usage)
用於在 React 伺服器元件、客戶端元件、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. 雙向 (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