i18n-nextjs

TotalClaw 作者 totalclaw

使用 App Router 的 Next.js / Node.js Web 应用程序的国际化 (i18n) 指南。 涵盖翻译文件结构、区域设置路由、每个区域设置的 SEO 元数据、hreflang、结构化 JSON-LD 数据、UI 组件翻译和多语言站点地图生成。 当用户要求执行以下操作时使用:添加 i18n 支持、添加新语言、翻译页面或组件、 为多个区域设置添加 SEO 元数据,实施 hreflang,更新新区域设置的站点地图, 或者在 Next.js 项目中遵循 i18n 最佳实践。

安装 / 下载方式

TotalClaw CLI推荐
totalclaw install totalclaw:totalclaw~javainthinking-web-i18n-nextjs
cURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/totalclaw%3Atotalclaw~javainthinking-web-i18n-nextjs/file -o javainthinking-web-i18n-nextjs.md
# i18n for Next.js — Implementation Guide

## Core Principles

- All user-facing features **must** implement i18n — no hardcoded strings in components.
- Translations must be **natural and idiomatic** — never use scripts or machine translation; treat quality the same as English copywriting.
- SEO metadata, JSON-LD structured data, and sitemaps must all be locale-aware.
- Default locale (English) uses **clean URLs** with no prefix (`/products`); other locales use a prefix (`/es/products`).

## Supported Locales

Locale list lives in `src/lib/i18n/locales.ts`. Keep the sitemap script's `locales` array in sync with this file.

```typescript
export const locales = ['en', 'es', 'fr', 'de', 'ja', 'zh-CN', /* ... add as needed */]
export const defaultLocale = 'en'
export type Locale = typeof locales[number]
```

## Directory Structure

```
src/app/[lang]/
├── dictionaries/       ← One JSON file per locale
│   ├── en.json
│   ├── es.json
│   └── ...
├── dictionaries.ts     ← getDictionary(locale) server helper
├── layout.tsx          ← Root layout: generateMetadata + hreflang + JSON-LD
└── <page>/
    └── page.tsx        ← generateMetadata + page content
```

## Translation Files

See **[references/translation-files.md](references/translation-files.md)** for:
- JSON key hierarchy conventions (`page.section.key`)
- Server-side `getDictionary()` usage
- Client-side `useDictionary()` hook usage
- Template variable pattern (`{count}` substitution)
- Fallback pattern for missing keys

## Routing & Middleware

See **[references/routing.md](references/routing.md)** for:
- `src/middleware.ts` — locale detection, redirect `/en/*` → `/*`, rewrite for default locale
- `LocalizedLink` component — automatically prefixes non-default locales
- `useLocale()` hook — reads locale from URL params → pathname → localStorage → default
- `getLocalizedPath()` / `removeLocalePrefix()` utilities

## SEO Metadata

See **[references/seo-metadata.md](references/seo-metadata.md)** for:
- `generateMetadata()` pattern in layout/page files
- `generateAlternatesMetadata()` from `src/lib/i18n/seo.ts`
- Full hreflang `alternates.languages` output (all locales + `x-default`)
- OpenGraph `locale` / `alternateLocale` fields
- `html lang` attribute and `LangSetter` client component

## Structured JSON-LD Data

See **[references/structured-data.md](references/structured-data.md)** for:
- WebApplication schema with translated `featureList`, `description`
- BlogPosting schema with `inLanguage` field
- FAQ schema with translated `acceptedAnswer`
- BreadcrumbList schema with localized URLs
- Rendering via `<Script>` or `<script>` tags

## Multi-language Sitemap

See **[references/sitemap.md](references/sitemap.md)** for:
- Sitemap structure: one `<url>` entry per page with `<xhtml:link>` alternates for every locale
- `<loc>` uses the default-locale (clean) URL; `x-default` also points there
- Full XML example with static and dynamic pages
- Next.js App Router `sitemap.ts` implementation pattern
- What to include vs. exclude (admin/API routes excluded)
- Hreflang language code format rules

## Quick Checklist — Adding a New Feature with i18n

1. **Add translation keys** to all locale JSON files in `src/app/[lang]/dictionaries/`
   - Add English first, then translate to all other languages naturally
2. **Server components**: `const dict = await getDictionary(locale)` → `dict?.page?.section?.key || 'fallback'`
3. **Client components**: `const dict = useDictionary()` → same fallback pattern
4. **Add `generateMetadata()`** to the page file, calling `generateAlternatesMetadata()`
5. **Add JSON-LD** structured data script tag with translated fields and `inLanguage`
6. **Update sitemap** if the page is new: add it to the sitemap source (see [references/sitemap.md](references/sitemap.md))
7. **Use `<LocalizedLink>`** for internal links and `getLocalizedPath()` for programmatic navigation

## Quick Checklist — Adding a New Locale

1. Add locale code to `locales` array in `src/lib/i18n/locales.ts`
2. Add locale entry to `dictionaries/` as `<code>.json` (full translation of `en.json`)
3. Add entry in `src/app/[lang]/dictionaries.ts` import map
4. Add display name in `LanguageSwitcher` `languageNames` map
5. Sync the sitemap locale list with the app's `locales` array
6. Regenerate / redeploy the sitemap

---

## 中文说明

# Next.js 的 i18n —— 实现指南

## 核心原则

- 所有面向用户的功能**必须**实现 i18n —— 组件中不得有硬编码字符串。
- 翻译必须**自然且地道** —— 切勿使用脚本或机器翻译;其质量要求与英文文案撰写相同。
- SEO 元数据、JSON-LD 结构化数据和站点地图都必须支持区域设置(locale-aware)。
- 默认区域设置(英语)使用**干净的 URL**,无前缀(`/products`);其他区域设置使用前缀(`/es/products`)。

## 支持的区域设置

区域设置列表位于 `src/lib/i18n/locales.ts`。保持站点地图脚本的 `locales` 数组与此文件同步。

```typescript
export const locales = ['en', 'es', 'fr', 'de', 'ja', 'zh-CN', /* ... add as needed */]
export const defaultLocale = 'en'
export type Locale = typeof locales[number]
```

## 目录结构

```
src/app/[lang]/
├── dictionaries/       ← One JSON file per locale
│   ├── en.json
│   ├── es.json
│   └── ...
├── dictionaries.ts     ← getDictionary(locale) server helper
├── layout.tsx          ← Root layout: generateMetadata + hreflang + JSON-LD
└── <page>/
    └── page.tsx        ← generateMetadata + page content
```

## 翻译文件

参见 **[references/translation-files.md](references/translation-files.md)**,了解:
- JSON 键层级约定(`page.section.key`)
- 服务端 `getDictionary()` 用法
- 客户端 `useDictionary()` hook 用法
- 模板变量模式(`{count}` 替换)
- 缺失键的兜底模式

## 路由与中间件

参见 **[references/routing.md](references/routing.md)**,了解:
- `src/middleware.ts` —— 区域设置检测、重定向 `/en/*` → `/*`、为默认区域设置进行重写
- `LocalizedLink` 组件 —— 自动为非默认区域设置添加前缀
- `useLocale()` hook —— 从 URL params → pathname → localStorage → default 读取区域设置
- `getLocalizedPath()` / `removeLocalePrefix()` 工具函数

## SEO 元数据

参见 **[references/seo-metadata.md](references/seo-metadata.md)**,了解:
- layout/page 文件中的 `generateMetadata()` 模式
- 来自 `src/lib/i18n/seo.ts` 的 `generateAlternatesMetadata()`
- 完整的 hreflang `alternates.languages` 输出(所有区域设置 + `x-default`)
- OpenGraph `locale` / `alternateLocale` 字段
- `html lang` 属性和 `LangSetter` 客户端组件

## 结构化 JSON-LD 数据

参见 **[references/structured-data.md](references/structured-data.md)**,了解:
- 带翻译后 `featureList`、`description` 的 WebApplication schema
- 带 `inLanguage` 字段的 BlogPosting schema
- 带翻译后 `acceptedAnswer` 的 FAQ schema
- 带本地化 URL 的 BreadcrumbList schema
- 通过 `<Script>` 或 `<script>` 标签渲染

## 多语言站点地图

参见 **[references/sitemap.md](references/sitemap.md)**,了解:
- 站点地图结构:每个页面一个 `<url>` 条目,并为每个区域设置带有 `<xhtml:link>` 替代项
- `<loc>` 使用默认区域设置(干净)的 URL;`x-default` 也指向该处
- 包含静态和动态页面的完整 XML 示例
- Next.js App Router `sitemap.ts` 实现模式
- 应包含 vs. 排除的内容(排除 admin/API 路由)
- Hreflang 语言代码格式规则

## 快速清单 —— 添加带 i18n 的新功能

1. **添加翻译键**到 `src/app/[lang]/dictionaries/` 中的所有区域设置 JSON 文件
   - 先添加英语,然后自然地翻译为所有其他语言
2. **服务端组件**:`const dict = await getDictionary(locale)` → `dict?.page?.section?.key || 'fallback'`
3. **客户端组件**:`const dict = useDictionary()` → 相同的兜底模式
4. **添加 `generateMetadata()`** 到页面文件,调用 `generateAlternatesMetadata()`
5. **添加 JSON-LD** 结构化数据 script 标签,带翻译后的字段和 `inLanguage`
6. **更新站点地图**,如果页面是新的:将其添加到站点地图源(参见 [references/sitemap.md](references/sitemap.md))
7. **使用 `<LocalizedLink>`** 用于内部链接,使用 `getLocalizedPath()` 用于编程式导航

## 快速清单 —— 添加新区域设置

1. 将区域设置代码添加到 `src/lib/i18n/locales.ts` 中的 `locales` 数组
2. 在 `dictionaries/` 中添加区域设置条目,命名为 `<code>.json`(`en.json` 的完整翻译)
3. 在 `src/app/[lang]/dictionaries.ts` 的 import map 中添加条目
4. 在 `LanguageSwitcher` 的 `languageNames` map 中添加显示名称
5. 将站点地图区域设置列表与应用的 `locales` 数组同步
6. 重新生成 / 重新部署站点地图