Next.js i18n 사전 및 Provider (nextjs-i18n-usage)
next-intl 번역을 React Server Components, Client Components, Storybook 스토리 및 테스트 환경에서 사용하기 위한 엔지니어링 표준, 훅, Provider 패턴입니다.
[!TIP] 구현 패턴:
references/examples.md에서 전체 코드 예제(RSC, Client 양식, 언어 전환기, Storybook 데코레이터, 테스트 래퍼)를 참조하세요. 빠른 실행: 사전 검증이나 키 동기화는 경량 서브 에이전트(Model: 'flash')에 위임하세요.
1. 하드코딩 금지 계약
- 텍스트 하드코딩 금지: JSX에서 사용자에게 표시되는 레이블, 플레이스홀더, 폴백 문자열을 절대 직접 작성하지 마세요.
- 모의 객체 금지: 파일 내 모의 사전(예:
const DEFAULT_CONTENT = {...})은 금지됩니다. - 동기화 필수: UI 복사본을 추가/수정할 때는 JSX를 작성하기 전에
messages/[locale].json의 모든 로케일 파일(예:messages/en.json,messages/fa.json)에 실제 번역을 삽입하세요.
2. API 및 훅 빠른 참조
| 환경 / 대상 | 훅 / API | 예제 구문 |
|---|---|---|
| Server Component (RSC) | getTranslations | const t = await getTranslations('namespace'); |
| Server Formatter | getFormatter | const format = await getFormatter(); format.dateTime(...) |
| 동적 메타데이터 | getTranslations | export async function generateMetadata({ params }) { ... } |
| Client Component | useTranslations | const t = useTranslations('namespace'); |
| Client Formatter | useFormatter | const format = useFormatter(); format.number(...) |
| 리치 텍스트 (Client) | 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 Logical Properties만 사용:
- 금지:
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 사용 | 훅은 비동기 Server Components에서 실행 불가 | await getTranslations('ns') 사용 |
Client에서 getTranslations 사용 | 서버 전용 비동기 함수 | "use client"와 함께 useTranslations('ns') 사용 |
| "intl 컨텍스트를 찾을 수 없음" | Storybook/테스트에 Provider 누락 | 스토리/테스트를 <NextIntlClientProvider>로 감쌉니다. |
| 하드코딩된 폴백 | 예: `t('btn') | |
원시 next/link 사용 | 경로 변경 시 로케일 접두사가 사라짐 | @/i18n/navigation에서 Link를 사용하세요. |
5. 일관성 검증
사전 일관성 검사를 실행합니다:
pwsh .agents/skills/nextjs-i18n-usage/scripts/verify-dictionaries.ps1