Next.js 项目中 i18n 多语言实现详解
date
Jul 13, 2025
AI 摘要
slug
nextjs-i18n-implementation-guide
status
Published
tags
front-end
summary
在现代 Web 开发中,国际化(i18n)已成为构建全球化应用不可或缺的一部分。
Next.js 相关架构下,一般可以基于 next-intl 的国际化实现方式,本文将从代码结构、配置方式到实际使用场景,全面介绍 i18n的使用,包括语言配置、翻译消息加载、路由支持、组件使用等核心知识点。
type
Post
在现代 Web 开发中,国际化(i18n)已成为构建全球化应用不可或缺的一部分。
Next.js 相关架构下,一般可以基于 next-intl 的国际化实现方式,本文将从代码结构、配置方式到实际使用场景,全面介绍 i18n的使用,包括语言配置、翻译消息加载、路由支持、组件使用等核心知识点。
一、i18n 实现基础
1.1 使用 next-intl 库实现国际化
用 next-intl 库来实现国际化功能。该库为 Next.js 提供了完整的国际化解决方案,包括翻译、日期格式化、数字格式化等功能。
1.2 安装与依赖管理
项目使用
pnpm
作为包管理器,安装 next-intl 及其相关依赖非常简单:1.3 语言配置文件
语言配置主要定义在
/src/config/website.tsx
文件中,包含默认语言和所有支持的语言列表:此配置不仅用于控制应用的默认语言,还被多个组件引用,如语言切换器、页面标题生成等。
二、翻译消息文件
2.1 翻译消息文件结构
翻译消息存储在
/messages/<locale>.json
文件中,按模块划分,例如 "Common"、"PricingPage" 等:2.2 在客户端组件中使用翻译
在客户端组件中,使用
useTranslations
钩子获取翻译内容:2.3 在服务端组件中使用翻译
在服务器端组件中,使用
getTranslations
获取翻译内容:三、路由国际化配置
3.1 动态路由 [locale]
支持
Next.js 的 App Router 支持通过动态路由
[locale]
来处理不同语言版本的页面请求。路由配置文件位于 /src/i18n/routing.ts
,定义了支持的语言列表和默认语言:3.2 自动检测语言与 Cookie 记忆
设置
localeDetection: false
禁用浏览器自动检测语言的功能。用户语言偏好通过 cookie (NEXT_LOCALE
) 记忆。四、语言切换组件与导航链接
4.1 语言切换组件
可以实现多个语言切换组件,如
LocaleSwitcher
和 LocaleSelector
,允许用户手动切换语言:4.2 带翻译的导航链接
使用自定义的
LocaleLink
组件生成带语言前缀的链接:五、TypeScript 类型定义与类型安全
为了确保类型安全并提供更好的开发体验,项目中使用全局类型定义文件
global.d.ts
扩展 AppConfig
接口,提供 Locale
和 Messages
类型定义:该类型定义文件通常位于项目根目录,并需在
tsconfig.json
中显式包含以确保被识别。此外,还可以通过 fumadocs-ui 提供的 i18n 工具自动生成
Translations
类型定义,确保类型安全和自动补全支持。六、新增语言的正确做法
当你需要扩展新的语言或新增翻译字段时,应遵循以下步骤:
- 添加新语言 JSON 文件 到
/messages/
目录,如es.json
。
- 在
website.tsx
中添加该语言配置,提供国旗、名称等元信息。
- 在
routing.ts
中添加语言支持,同步更新语言列表。
- 页面中使用
useTranslations('Namespace.key')
即可生效。
这样可以保证国际化系统的一致性和可维护性。
七、国际化布局与上下文注入机制
7.1 LocaleLayout 组件的作用
在 Next.js 的 App Router 中,
[locale]
路由下的 LocaleLayout
是整个国际化的根布局组件。它的主要职责包括:- 加载当前语言的翻译消息文件(如
/messages/en.json
或/messages/zh.json
)
- 注入国际化上下文,通过
NextIntlClientProvider
- 设置 HTML 标签的语言属性,确保 SEO 和无障碍支持
- 包裹页面内容,使所有子组件都能基于正确的语言环境渲染
示例代码片段:
⚠️ 注意:虽然目前项目中未显式导入消息文件,但 NextIntlClientProvider 默认会从 /messages/<locale>.json 自动加载翻译消息。
7.2 NextIntlClientProvider 的作用
NextIntlClientProvider
是 next-intl
提供的核心组件之一,它通过 React Context 将翻译数据传递给所有客户端组件。主要功能:
功能 | 描述 |
翻译注入 | 将 messages 注入 React 上下文,使 useTranslations 可用 |
客户端支持 | 所有使用 useTranslations 的组件均可访问翻译键值 |
本地化格式化 | 支持日期、时间、数字等本地化格式输出 |
示例用法:
📌 提示:如果你希望手动控制消息加载方式,可以显式传入 messages 属性给 NextIntlClientProvider。
7.3 整体流程图解
4. 最佳实践建议
- ✅ 新增语言时只需添加
/messages/<new-locale>.json
文件即可生效
- ✅ 在 website.tsx 中注册语言元信息
- ✅ 在 routing.ts 中同步更新语言列表
- ❗ 不建议修改
LocaleLayout
的结构,除非你有特殊需求
通过以上机制,可以实现了简洁、可维护且高效的国际化系统,适合大型 SaaS 应用的多语言需求。
八、翻译消息加载机制详解
8.1 为什么没有显式导入翻译消息?
在
/src/app/[locale]/layout.tsx
中,你不会看到类似 import messages from '@/messages/zh.json'
的代码片段,这是因为 next-intl 提供了自动加载翻译消息的能力。✅ 自动加载机制
NextIntlClientProvider
默认会从 /messages/<locale>.json
路径加载对应语言的消息文件。只要项目结构符合预期(如 /messages/en.json
和 /messages/zh.json
存在),就可以无需手动导入。示例代码如下:
📌 注意:这里并没有传入 messages 属性,表示使用默认的自动加载方式。
⚠️ 手动加载的适用场景
如果你需要自定义路径、延迟加载或调试,可以显式导入并传入
messages
属性:
但目前项目中不推荐这样做,因为结构和配置已完全符合自动加载的要求。
8.2 翻译消息文件路径约定
- 消息文件必须存放在
/messages/<locale>.json
。
- 示例:
- /messages/en.json
- /messages/zh.json
💡 建议:新增语言时只需添加对应的 JSON 文件即可生效,无需修改 layout.tsx。
8.3 加载方式对比
方式 | 是否需要手动导入 | 使用场景 |
✅ 自动加载 | 否 | 标准项目结构、消息文件在 /messages/<locale>.json |
🔁 手动加载 | 是 | 自定义消息路径、动态加载、服务器渲染等高级用法 |
8.4 最佳实践建议
- ✅ 新增语言时只需添加
/messages/<new-locale>.json
文件即可生效
- ✅ 在 website.tsx 中注册语言元信息
- ✅ 在 routing.ts 中同步更新语言列表
- ❗ 不建议修改
LocaleLayout
的结构,除非你有特殊需求
通过以上机制,MkSaaS 模板实现了简洁、可维护且高效的国际化系统,适合大型 SaaS 应用的多语言需求。
九、语言配置的职责划分:website.tsx 与 routing.ts 的作用解析
在 MkSaaS 模板中,国际化(i18n)的语言配置分别定义在两个文件中:
- website.tsx:用于提供语言元信息和 UI 显示;
- routing.ts:用于控制路由系统中的多语言行为。
9.1 website.tsx:UI 层语言配置
路径: /src/config/website.tsx
示例代码:
作用:
- 定义网站支持的语言列表及默认语言;
- 提供语言元信息(如国旗、名称),用于 UI 显示;
- 被多个组件引用,例如语言切换器、页面标题生成等。
📌 这是面向前端 UI 的语言配置,主要用于控制语言选择器、显示标签等。
9.2 routing.ts:框架层语言路由配置
路径: /src/i18n/routing.ts
示例代码:
作用:
- 配置 App Router 中的国际化路由规则;
- 控制 URL 是否添加语言前缀(如
/en/about
vs/about
);
- 设置语言检测方式(浏览器自动检测 or cookie);
- 定义多语言 Cookie 名称(如
NEXT_LOCALE
)。
📌 这是面向 Next.js 路由系统的语言配置,主要用于控制语言感知的路由行为和请求处理。
9.3 为什么不统一到一个地方?
虽然从表面上看将语言配置合并到一个文件中似乎更简洁,但实际原因如下:
维度 | website.tsx | routing.ts |
用途 | 提供语言元信息(UI 层) | 控制路由行为(框架层) |
使用者 | 前端组件、翻译钩子 | Next.js App Router、中间件 |
功能 | 显示语言选项、翻译内容 | 多语言 URL、Cookie 存储、路由匹配 |
是否可合并? | ❌ 不建议 | ❌ 不建议 |
✅ 正确做法:同步更新两处配置
当你新增一种语言(如西班牙语
es
)时,应执行以下步骤:1、 在 website.tsx 添加语言配置
2、 在 routing.ts 更新语言列表
3、 创建对应语言的消息文件
/messages/es.json
✅ 总结
问题 | 回答 |
为什么要分开配置? | 因为 website.tsx 提供 UI 元信息,routing.ts 控制路由行为,二者职责不同。 |
能否统一? | 不建议,违反单一职责原则且可能导致类型冲突。 |
新增语言应怎么做? | 在 website.tsx 添加语言元信息,在 routing.ts 同步更新,并创建对应 JSON 消息文件。 |
这样设计确保了国际化系统的灵活性和可维护性,是符合最佳实践的结构.