使用您最喜欢的AI助手总结文档,并引用此页面和AI提供商
版本历史
- "初始版本"v9.5.102026/9/26
如果您有改善此文档的想法,请随时通过在GitHub上提交拉取请求来贡献。
文档的 GitHub 链接复制文档 Markdown 到剪贴板
2026 年如何使用 Lingui 国际化你的 Next.js 应用
目录
什么是 Lingui?
Lingui 是一个围绕宏(macros)和消息提取(message extraction)构建的 i18n 库。你在组件中编写源文本( t`Hello` 、<Trans>Hello</Trans>),lingui extract 会将每条消息收集到语言目录(默认为 PO 文件)中,然后由加载器将它们编译为紧凑的 JavaScript。消息采用 ICU MessageFormat 语法,并且 Lingui 在 App Router 中支持 React Server Components。
本指南将在 Next.js 16 App Router 项目中配置 Lingui,包含以下内容:
- 通过 SWC 编译宏,确保 Turbopack 保持高速构建。
- 服务端组件与客户端组件共享相同的
Trans和useLinguiAPI。 - 通过
proxy.ts实现语言环境路由:默认语言使用/about,其他语言使用/fr/about,并支持首次访问语言检测。 - 使用
generateStaticParams对每个语言环境进行静态渲染。 - 完整的多语言 SEO 支持:翻译后的
generateMetadata、canonical 规范链接、带x-default的hreflang、Open Graph 本地化标签、JSON-LD、sitemap.ts、robots.ts以及本地化的 404 页面。
想要了解其他国际化库?请参阅 next-intl 指南、next-i18next 指南 或 Next.js + Intlayer 指南。
正在使用 TanStack Start?请参阅 TanStack Start + Lingui 指南。对比不同方案?请阅读 Lingui vs Intlayer 以及 next-i18next vs next-intl vs Intlayer。
Next.js 上 Lingui 的基准测试表现
i18n 基准测试在各大主流库上运行相同的包含 10 个页面和 10 种语言的 Next.js 应用,并测量浏览器实际下载的内容体积。
动态 JSON 加载
在运行时懒加载翻译
有作用域的 JSON (命名空间)
每页翻译命名空间
I18n 性能基准测试
这个指标是什么?
国际化库包的总 gzip 压缩大小。它仅包含 tree-shaking 和压缩(minification)后的提供者(provider)和内容检索逻辑。
为什么这很重要?
较小的库大小可减少初始 JavaScript 负载,从而缩短客户端的下载和执行时间。
视图形式
在 Next.js 16 上测试 @lingui/core@6.6.0 的关键数据,测量日期为 2026-09-26(gzip 压缩):
在弹窗中打开表格以清晰地查看所有数据
| 配置方案 | 库体积 | 每页 JS 体积 | 其他语言泄露率 | 其他页面泄露率 |
|---|---|---|---|---|
| 无 i18n(基础应用) | - | 141.0 KB | 0% | 0% |
| Lingui,每个语言独立目录 | 72.1 KB | 145.4 KB | 2.8% | 89.9% |
@intlayer/lingui(兼容模式) | 10.7 KB | 221.6 KB | 50% | 90% |
next-intlayer(原生 Intlayer) | 4.9 KB | 141.5 KB | 0% | 0% |
核心结论:
- 每个语言使用单一目录仍会将其他页面的消息泄露到客户端 provider。尽量将文本保留在服务端组件中,因为服务端组件发送的是渲染好的 HTML,而不是消息目录。
- Lingui 运行时体积约为 72 KB gzip。
@intlayer/lingui兼容适配器将运行时体积减少到约 11 KB,但在此基准测试中,Next.js 兼容配置仍会将完整的消息目录发送到页面。原生next-intlayerAPI 则是能保持基础应用原始体积的配置方案。
查看完整数据:Next.js 基准测试报告 以及 基准测试仓库。
Next.js 上的功能特性对比
以下是 Next.js App Router 项目常用功能在 Lingui、next-intl 与 Intlayer 之间的对比:
在弹窗中打开表格以清晰地查看所有数据
| 功能特性 | next-intlayer (Intlayer) | Lingui | next-intl |
|---|---|---|---|
| 组件就近存放翻译 | ✅ 内容与每个组件同目录放置 | ⚠️ 组件中编写源文本,语言目录集中管理 | ❌ 集中式 JSON |
| TypeScript 集成 | ✅ 自动生成严格类型 | ⚠️ 宏具有类型,但消息目录没有 | ✅ 优秀,通过 AppConfig 扩展 |
| 缺失翻译检测 | ✅ TypeScript 错误与构建时警告 | ⚠️ 运行时回退到源文本 | ⚠️ 运行时回退 |
| 富文本内容 (JSX, Markdown) | ✅ 直接支持 | ✅ <Trans> 内支持 JSX,不支持 Markdown | ⚠️ 通过 t.rich 支持标签,不支持 Markdown |
| AI 翻译 | ✅ 支持自定义服务商与 API Key,具备应用上下文 | ❌ 不支持 | ❌ 不支持 |
| 可视化编辑器 / CMS | ✅ 本地可视化编辑器 + 可选 CMS | ❌ 仅通过外部平台 | ❌ 仅通过外部平台 |
| 本地化路由 | ✅ 开箱即用 | ❌ 需自行编写 proxy.ts | ✅ 内置 [locale] 路径段 |
| 复数处理 | ✅ 基于枚举规则 | ✅ ICU 语法,<Plural> 宏 | ✅ ICU 语法 |
| 内容格式 | ✅ .ts, .tsx, .js, .json, .md, .yaml | ✅ PO, JSON, CSV | ✅ .json, .js, .ts |
| ICU MessageFormat | ✅ 通过 format: "icu" 支持 | ✅ 原生支持 | ✅ 原生支持 |
| SEO 辅助工具 (hreflang, sitemap) | ✅ 提供元数据、sitemap 与 robots.txt 辅助工具 | ❌ 需手动处理 | ✅ 良好 |
| 服务端组件 (Server Components) | ✅ 在任意服务端组件中直接访问 | ⚠️ 需在每个 layout 和 page 中调用 setI18n | ⚠️ 每个组件需调用 await getTranslations() |
| 按组件进行 Tree-shaking | ✅ 构建时完成 (Babel / SWC) | ⚠️ 每种语言单一目录,按页提取器仍处于实验阶段 | ⚠️ 需手动在每个路由使用 pick() |
| 运行时体积 (gzip, 基准测试) | 4.9 KB | 72.1 KB | 14.7 KB |
| CI 中检测缺失翻译 | ✅ npx intlayer test | ✅ lingui compile --strict | ⚠️ 非内置功能 |
| 生态系统与社区 | ⚠️ 规模较小但增长迅速 | ✅ 成熟 | ✅ 庞大 |
运行时体积来自 Next.js 基准测试。更深入的讨论请阅读 Lingui vs Intlayer。
其他 Next.js 指南:next-intl、next-i18next 和 Intlayer。
你应该遵循的最佳实践
- 在
[locale]布局中的<html>上设置lang和dir。 - 优先在服务端组件中渲染文本:它们在服务端生成 HTML,无需将消息目录发送到客户端。
- 在每个 layout 和 page 中调用
initLingui(locale)。页面跳转时布局不会重新渲染,因此页面不能依赖布局来设置语言环境。 - 为每种语言保留独立 URL,并使用
generateStaticParams预渲染所有语言版本。 - 在
generateMetadata中翻译元数据,并配置canonical、hreflang和x-default。 - 通过
sitemap.ts和robots.ts约定生成多语言站点地图和 robots.txt。 - 语言切换器使用真实的链接元素,以便搜索引擎爬虫发现所有语言版本。
- 在 CI 中运行
lingui extract,确保新消息不会在未翻译的情况下发布。
请参阅我们的国际化与 SEO 指南、hreflang 多语言 SEO 指南以及 Next.js 多语言 SEO 方案对比。
在 Next.js 应用中配置 Lingui 的分步指南
以下是我们将要构建的项目结构:
复制代码到剪贴板
安装依赖
bash复制代码复制代码到剪贴板
- @lingui/core / @lingui/react:运行时、
I18nProvider、用于服务端组件的setI18n以及宏(@lingui/core/macro、@lingui/react/macro)。 - @lingui/swc-plugin:在 Next.js SWC 编译流水线中编译宏。
- @lingui/loader:在导入时编译
.po目录,无需手动执行lingui compile。 - @lingui/cli:通过
lingui extract提取消息到语言目录中。
@lingui/swc-plugin是一个与 Next.js 的 SWC 版本绑定的 WebAssembly 插件。如果在升级 Next.js 后构建失败,请将插件更新到其 README 中注明的兼容版本。- @lingui/core / @lingui/react:运行时、
集中管理语言环境配置
使用单个文件统一定义语言和 URL 辅助函数。路由、元数据、站点地图以及 Lingui 均从中读取配置。
src/i18n/config.ts复制代码复制代码到剪贴板
配置 Lingui 和 Next.js
lingui.config.ts复制代码复制代码到剪贴板
SWC 插件用于编译宏,loader 用于编译
.po文件,同时支持 Turbopack(Next.js 16 默认)与 webpack:next.config.ts复制代码复制代码到剪贴板
添加提取脚本:
package.json复制代码复制代码到剪贴板
加载目录并创建服务端实例
服务端组件没有 React context,因此 Lingui 提供了
setI18n来为当前渲染注册实例。该模块在每个服务端进程中仅加载一次所有目录,并为每个语言环境创建一个I18n实例。它是server-only的:其他语言的目录绝不会进入客户端打包产物中。src/i18n/appRouterI18n.ts复制代码复制代码到剪贴板
src/i18n/initLingui.ts复制代码复制代码到剪贴板
为了让 TypeScript 支持
.po导入,声明一次模块类型:src/i18n/po.d.ts复制代码复制代码到剪贴板
创建客户端 Provider
客户端组件从 React context 中读取翻译。Provider 从服务端布局接收当前活跃语言的目录,并初始化创建一次自身的实例。
src/components/LinguiClientProvider.tsx复制代码复制代码到剪贴板
定义动态语言路由
[locale]路径段包含根布局。generateStaticParams在构建时预渲染每种语言,而dynamicParams = false会对任何其他前缀返回 404。src/app/[locale]/layout.tsx复制代码复制代码到剪贴板
客户端 provider 会接收当前活跃语言的完整目录。这就是基准测试中所衡量的“其他页面泄露”。将文本保留在服务端组件中可以限制客户端实际所需的内容。对于大型应用,Lingui 的实验性按页面提取器(
lingui.config.ts中的experimental.extractor)可以按入口点拆分消息目录。在服务端组件中使用翻译
服务端组件使用与客户端组件相同的宏。由于在同一布局下的页面间导航时布局不会重新渲染,因此在页面中也必须调用
initLingui。src/app/[locale]/about/page.tsx复制代码复制代码到剪贴板
在客户端组件中使用翻译
客户端组件使用相同的导入方式。宏会直接从
LinguiClientProvider中读取实例。src/components/Counter.tsx复制代码复制代码到剪贴板
提取并翻译你的消息
运行提取命令。Lingui 会将
src中找到的每条消息写入各个语言目录:bash复制代码复制代码到剪贴板
然后翻译每个条目的
msgstr:src/locales/fr/messages.po复制代码复制代码到剪贴板
src/locales/es/messages.po复制代码复制代码到剪贴板
<0>占位符保留了<Trans>中的 JSX 元素位置,使翻译人员可以在不改动代码结构的情况下调整它们的位置。配置用于语言路由的 Proxy
可选Next.js 16 将
middleware.ts重命名为proxy.ts。Proxy 实现了“按需添加前缀”策略:/fr/about按原样响应;/en/about重定向至/about,确保默认语言拥有唯一的 URL;/about在内部重写为/en/about,URL 保持不变;- 首次访问
/时重定向至首选语言(先检测 Cookie,再检测Accept-Language)。
src/i18n/negotiateLocale.ts复制代码复制代码到剪贴板
src/proxy.ts复制代码复制代码到剪贴板
切换内容语言
可选usePathname返回浏览器当前看到的 URL(如/about或/fr/about)。去除语言前缀后,构建每种语言对应的链接。切换器渲染真实的链接标签,以便搜索引擎爬虫发现所有语言版本,同时 Cookie 会持久化保存用户的显式选择。src/components/LocaleSwitcher.tsx复制代码复制代码到剪贴板
构建本地化链接组件
可选src/components/LocalizedLink.tsx复制代码复制代码到剪贴板
该组件在服务端组件中也能正常工作,因为它是在
LinguiClientProvider内部渲染的:tsx复制代码复制代码到剪贴板
国际化你的元数据
可选只要每个页面提供以下信息,各语言版本都能独立获得搜索引擎排名:
- 已翻译的
title和description; - 指向自身的 canonical 规范链接;
- 每个语言环境一个
hreflang备用链接,外加x-default; - Open Graph 的
locale、alternateLocale和url; - 带有
inLanguage的 JSON-LD 数据。
generateMetadata在 React 组件树之外执行,因此它使用msg宏直接操作服务端实例:src/i18n/metadata.ts复制代码复制代码到剪贴板
src/app/[locale]/about/page.tsx复制代码复制代码到剪贴板
JSON-LD 由页面本身渲染。页面文件只能导出 Next.js 约定的字段,因此请将该组件保存在独立文件中:
src/components/WebPageJsonLd.tsx复制代码复制代码到剪贴板
src/app/[locale]/about/page.tsx复制代码复制代码到剪贴板
- 已翻译的
国际化你的站点地图
可选Next.js 的
sitemap.ts约定支持alternates.languages,Next.js 会将其渲染为xhtml:link备用链接。列出每种语言的每个 URL:src/app/sitemap.ts复制代码复制代码到剪贴板
国际化你的 robots.txt
可选私有路由在每种语言中均存在,因此
disallow规则必须覆盖所有本地化路径:src/app/robots.ts复制代码复制代码到剪贴板
处理本地化 404 页面
可选not-found.tsx在[locale]布局内部渲染,因此它可以正常访问客户端 provider。通配路由将语言内部的未知路径分发给它。Next.js 会自动向 404 响应添加noindex。src/app/[locale]/not-found.tsx复制代码复制代码到剪贴板
src/app/[locale]/[...rest]/page.tsx复制代码复制代码到剪贴板
在 Server Actions 中获取语言环境
可选Server Actions 不会直接接收路由参数。最可靠的做法是在已知语言环境的页面中随表单一同提交该语言信息:
src/app/[locale]/contact/page.tsx复制代码复制代码到剪贴板
src/app/actions/sendContactMessage.ts复制代码复制代码到剪贴板
保留宏定义,使用 Intlayer 缩减运行时体积
可选@intlayer/lingui兼容适配器允许你保持源代码不变:宏照常编译,编译生成的i18n._()、useLingui()和<Trans>调用由 Intlayer 字典提供支持。在 Next.js 基准测试中,运行时体积从约 72.1 KB 下降至约 10.7 KB gzip。在 Next.js 中,通过在
next.config.ts(webpack 与 Turbopack)中将@lingui/core和@lingui/react别名指向@intlayer/lingui,并使用next-intlayer/server中的withIntlayer包装配置即可启用适配器。保留@lingui/swc-plugin以便宏能够先行编译。完整配置请参阅 Lingui 兼容指南。正如基准测试表格所示,该适配器缩减了运行时体积,但在 Next.js 上尚未减少发送到每个页面的目录体积。它最适合作为迁移桥梁:一旦运行稳定,即可逐个组件迁移至原生
useIntlayerAPI,从而仅打包每个组件实际渲染的内容。请参阅 Next.js + Intlayer 指南、Lingui vs @intlayer/lingui 以及所有兼容适配器。
常见问题解答
支持。@lingui/react 支持 React Server Components。服务端组件通过 @lingui/react/server 中的 setI18n 注册实例,客户端组件从 I18nProvider 中读取实例,两者共用相同的 Trans 和 useLingui 宏。
服务端组件没有 React context,因此实例是按次渲染注册的。布局在跨页面导航时会被保留且不会重新渲染,因此页面不能依赖布局来设置语言环境。在每个布局和页面的顶部调用 initLingui(locale) 可以保持它们的独立性。
请使用 @lingui/swc-plugin。它能保留 SWC 流水线与 Turbopack 的极速构建能力。引入 Babel 配置会禁用 Next.js 的 SWC 从而拖慢构建速度。唯一的约束是需要保持插件版本与当前 Next.js 版本的 SWC 保持兼容。
使用 getI18nInstance(locale) 获取服务端实例,并翻译通过 msg 宏声明的描述符:i18n._(msg`About us`)。返回 alternates.canonical、带 x-default 的 alternates.languages 以及 openGraph.locale。步骤 13 提供了一个可复用的辅助函数。
基准测试测得运行时体积约为 72 KB gzip。每个语言使用独立目录时,页面体积约为 145 KB(无 i18n 基础应用为 141 KB),但每个页面仍会通过客户端 provider 接收到其他页面的消息。
Lingui 适合喜欢在组件中编写源文本、并与 PO 文件及翻译人员协作的团队。next-intl 适合偏好 JSON 目录结构以及与 Next.js 深度集成的 t("key") API 的团队。next-i18next 则带来了丰富的 i18next 插件生态。详情请参阅 next-i18next vs next-intl vs Intlayer 以及 Next.js 基准测试。
评论
暂无评论。成为第一个分享您想法的人吧。
