--- name: i18n-patterns description: Internationalization (i18n) patterns for server and client components using getTranslations and useTranslations. Use when working with translations, locales, multilingual content, translation files, TranslationContextProvider, locale switching, or when the user mentions i18n, translations, getTranslations, useTranslations, or translation.json files. --- # Internationalization Patterns ## Overview This project supports internationalization (i18n) with separate patterns for server and client components. ## Supported Locales Routes use the `[locale]` parameter to support: - `en` - English - `zh` - Chinese ## Routing ### URL Structure All routes include the locale parameter: ``` /en/about /zh/about ``` ### Generating Localized URLs Use `getLocalePath()` to create locale-aware URLs: ```tsx import { getLocalePath } from "@/utils/locale"; // Current locale: "en" const aboutPath = getLocalePath("/about"); // Returns "/en/about" // Switching locale const zhAboutPath = getLocalePath("/about", "zh"); // Returns "/zh/about" ``` ## Translation File Structure ### Server Component Translations Location: `translations.json` files in component and route folders ``` src/ components/ Header/ translations.json app/ [locale]/ about/ translations.json ``` Example `translations.json`: ```json { "en": { "title": "About Us", "description": "Learn more about our company" }, "zh": { "title": "关于我们", "description": "了解更多关于我们公司的信息" } } ``` ### Client Component Translations Location: `[ComponentName].translations.json` (component-specific for tree shaking) ``` src/ components/ Button/ Button.tsx Button.translations.json ``` Example `Button.translations.json`: ```json { "en": { "submit": "Submit", "cancel": "Cancel" }, "zh": { "submit": "提交", "cancel": "取消" } } ``` Component-specific translation files enable tree shaking. ## Server Components Server components use the `getTranslations` utility to obtain translated texts. ```tsx import { getTranslations } from "@/utils/translations"; async function ServerComponent({ params }) { const t = await getTranslations(params.locale); return (

{t.title}

{t.description}

); } ``` Use `getTranslations(locale)` - async function that returns translation object. ## Client Components Client components use the `useTranslations()` hook which reads translations from context. ```tsx "use client"; import { useTranslations } from "@/hooks/useTranslations"; function ClientComponent() { const t = useTranslations(); return ; } ``` ### Providing Translations to Client Components A server component parent must render `` with the translation content. ```tsx // Server component (parent) import { TranslationContextProvider } from "@/contexts/TranslationContext"; import buttonTranslations from "@/components/Button/Button.translations.json"; import ClientComponent from "./ClientComponent"; async function ServerParent({ params }) { const locale = params.locale; return ( ); } ``` Server component parent must provide `` with component-specific translations imported from JSON. ## Complete Example ### Scenario: Button component with translations **1. Translation file** (`Button.translations.json`): ```json { "en": { "submit": "Submit", "cancel": "Cancel", "loading": "Loading..." }, "zh": { "submit": "提交", "cancel": "取消", "loading": "加载中..." } } ``` **2. Client component** (`Button.tsx`): ```tsx "use client"; import { useTranslations } from "@/hooks/useTranslations"; export function Button({ isLoading, onSubmit, onCancel }) { const t = useTranslations(); return (
); } ``` **3. Server component parent** (`Form.tsx`): ```tsx import { TranslationContextProvider } from "@/contexts/TranslationContext"; import buttonTranslations from "@/components/Button/Button.translations.json"; import { Button } from "@/components/Button/Button"; export async function Form({ params }) { const locale = params.locale; return (