作者:
    Creation:2026-01-10Last update:2026-06-23

    如何将现有的 Next.js 应用程序多语言化 (i18n) (i18n 指南 2026)

    www.youtube.com
    ide.intlayer.org

    在 GitHub 上查看应用程序模板

    目录

    为什么对现有应用程序进行国际化会很困难?

    如果您曾经尝试向仅为单语言构建的应用程序中添加多种语言,您就会明白其中的痛苦。这不仅仅是“困难”,而是非常繁琐。您必须检查每个文件,找出每一个文本字符串,并将它们移动到单独的字典文件中。

    接下来才是冒险的部分:用代码钩子替换所有文本,同时保证不破坏布局或逻辑。这类工作往往会让新功能的开发停滞数周,感觉像是一场无止境的重构。

    什么是 Intlayer 编译器?

    Intlayer 编译器旨在规避这种繁琐的手动工作。您无需手动提取字符串,编译器会为您完成。它会扫描您的代码,找到文本,并使用 AI 在后台生成字典。 然后,在构建步骤期间,它会修改您的源代码以注入必要的 i18n 钩子。基本上,您可以像写单语言应用一样继续编写您的应用,而编译器会自动原生处理多语言转换。

    编译器文档:/zh/doc/compiler

    限制

    由于编译器在编译时执行代码分析和转换(注入钩子和生成字典),因此它可能会减慢应用程序的构建时间

    为了限制在活跃开发过程(dev 模式)中的影响,您可以将编译器设置为 'build-only' 模式,或在不需要时将其禁用。


    在 Next.js 应用程序中设置 Intlayer 的分步指南

    1. 安装依赖项

      使用您偏好的包管理器安装必要的包:

      bash
      npx intlayer init --interactive
      
      --interactive 标志是可选的。如果您是 AI 代理,请使用 intlayer-cli init
      该命令将检测您的环境并安装所需的软件包。例如:
      bash
      npm install intlayer next-intlayer
      npm install @intlayer/babel --save-dev
      
      • intlayer

        核心包,提供用于配置管理、翻译、内容声明、转译和 CLI 命令的国际化工具。

      • next-intlayer

        将 Intlayer 与 Next.js 集成的包。它为 Next.js 国际化提供上下文提供程序和钩子。此外,它还包括用于将 Intlayer 与 WebpackTurbopack 集成的 Next.js 插件,以及用于检测用户首选语言环境、管理 cookie 和处理 URL 重定向的中间件。

    2. 配置您的项目

      创建一个配置文件来定义应用程序的语言:

      intlayer.config.ts
      import { Locales, type IntlayerConfig } from "intlayer";
      
      const config: IntlayerConfig = {
        internationalization: {
          locales: [Locales.ENGLISH, Locales.CHINESE],
          defaultLocale: Locales.CHINESE,
        },
        routing: {
          mode: "search-params",
        },
        compiler: {
          /**
           * 指示是否应启用编译器。
           */
          enabled: true,
      
          /**
           * 优化字典的输出目录。
           */
          output: ({ locale, key }) => `compiler/${locale}/${key}.json`,
      
          /**
           * 仅在生成的文件中插入内容,不含键。
           */
          noMetadata: false,
      
          /**
           * 字典键前缀
           */
          dictionaryKeyPrefix: "", // Remove base prefix
      
          /**
           * 指示转换后是否应保存组件。
           * 这样,编译器只需运行一次即可转换应用程序,然后即可将其删除。
           */
          saveComponents: false,
        },
        ai: {
          provider: "openai",
          model: "gpt-5-mini",
          apiKey: process.env.OPEN_AI_API_KEY,
          applicationContext: "这是一个简单的地图应用程序示例",
        },
      };
      
      export default config;
      
      注意:请确保您在环境变量中设置了 OPEN_AI_API_KEY
      通过此配置文件,您可以设置本地化的 URL、代理重定向、cookie 映射、内容声明的位置和扩展名、在控制台中禁用 Intlayer 日志等等。有关可用参数的完整列表,请参阅配置文档
    3. 将 Intlayer 集成到 Next.js 配置中

      配置您的 Next.js 设置以使用 Intlayer:

      next.config.ts
      import type { NextConfig } from "next";
      import { withIntlayer } from "next-intlayer/server";
      
      const nextConfig: NextConfig = {/* 这里可选填写额外的 Next.js 配置 */};
      
      export default withIntlayer(nextConfig);
      

      Next.js 插件 withIntlayer() 用于将 Intlayer 与 Next.js 集成。它确保字典文件的构建,并在开发模式下监视它们。它在 WebpackTurbopack 环境中定义 Intlayer 环境变量。此外,它还提供别名以优化性能,并保留与服务器组件的兼容性。

    4. </Step>

    5. 配置 Babel

      Intlayer 编译器需要 Babel 来提取和优化您的内容。更新您的 babel.config.js(或 babel.config.json)以包含 Intlayer 插件:

      babel.config.js
      const {
        intlayerExtractBabelPlugin,
        intlayerOptimizeBabelPlugin,
        getExtractPluginOptions,
        getOptimizePluginOptions,
      } = require("@intlayer/babel");
      
      module.exports = {
        presets: ["next/babel"],
        plugins: [
          [intlayerExtractBabelPlugin, getExtractPluginOptions()],
          [intlayerOptimizeBabelPlugin, getOptimizePluginOptions()],
        ],
      };
      
    6. 页面中的语言环境检测

      清空 RootLayout 的内容,并将其替换为以下示例:

      src/app/layout.tsx
      import type { Metadata } from "next";
      import type { ReactNode } from "react";
      import "./globals.css";
      import { IntlayerProvider, LocalPromiseParams } from "next-intlayer";
      import { getHTMLTextDir, getIntlayer } from "intlayer";
      import { getLocale } from "next-intlayer/server";
      export { generateStaticParams } from "next-intlayer";
      
      export const generateMetadata = async (): Promise<Metadata> => {
        const locale = await getLocale();
        const { title, description, keywords } = getIntlayer("metadata", locale);
      
        return {
          title,
          description,
          keywords,
        };
      };
      
      const RootLayout = async ({
        children,
      }: Readonly<{
        children: ReactNode;
      }>) => {
        const locale = await getLocale();
      
        return (
          <html lang={locale} dir={getHTMLTextDir(locale)}>
            <body>
              <IntlayerProvider defaultLocale={locale}>{children}</IntlayerProvider>
            </body>
          </html>
        );
      };
      
      export default RootLayout;
      
    7. 声明您的内容(自动)

      启用编译器后,您不再需要手动声明内容字典(例如 .content.ts 文件)。

      相反,您只需在代码中以硬编码字符串的形式写入您的内容。Intlayer 会扫描源代码,使用配置的 AI 提供商生成翻译,并在构建编译期间自动将这些字符串替换为本地化内容。这一切都是完全自动化的。

      只需在组件中使用默认语言环境的硬编码字符串,让 Intlayer 编译器处理剩下的工作。

      page.tsx 可能看起来像这样:

      src/app/page.tsx
      import type { FC } from "react";
      import { IntlayerServerProvider } from "next-intlayer/server";
      import { getLocale } from "next-intlayer/server";
      
      const PageContent: FC = () => {
        return (
          <>
            <p>开始编辑吧!</p>
            <code>src/app/page.tsx</code>
          </>
        );
      };
      
      export default async function Page() {
        const locale = await getLocale();
      
        return (
          <IntlayerServerProvider locale={locale}>
            <PageContent />
          </IntlayerServerProvider>
        );
      }
      
      i18n/page-content.content.tsx
      {
        key: "page-content",
        content: {
          nodeType: "translation",
          translation: {
            en: {
              getStartedByEditingThis: "Get started by editing this!",
            },
            fr: {
              getStartedByEditingThis: "Commencez par éditer ceci !",
            },
            zh: {
              getStartedByEditingThis: "开始编辑吧!",
            },
          }
        }
      }
      
      src/app/page.tsx
      import { type FC } from "react";
      import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server";
      import { getLocale } from "next-intlayer/server";
      
      const PageContent: FC = () => {
        const content = useIntlayer("page-content");
      
        return (
          <>
            <p>{content.getStartedByEditing}</p>
            <code>src/app/page.tsx</code>
          </>
        );
      };
      
      export default async function Page() {
        const locale = await getLocale();
      
        return (
          <IntlayerServerProvider locale={locale}>
            <PageContent />
          </IntlayerServerProvider>
        );
      }
      
      • IntlayerClientProvider 用于在客户端向子组件提供语言环境。
      • IntlayerServerProvider 用于在服务器端向子组件提供语言环境。

        Layout and page cannot share a common server context because the server context system is based on a per-request data store (via React's cache mechanism), causing each "context" to be re-created for different segments of the application. Placing the provider in a shared layout would break this isolation, preventing the correct propagation of the server context values to your server components.

    8. </Tab>

      </Tabs>

      </Step>

    9. 填写缺失的翻译

      可选

      Intlayer 提供了一个 CLI 工具来帮助您填写缺失的翻译。您可以使用 intlayer 命令来测试并从您的代码中填写缺失的翻译。

      bash
      npx intlayer test         # 测试是否有缺失的翻译
      
      bash
      npx intlayer fill         # 填写缺失的翻译
      
      有关更多详细信息,请参阅 CLI 文档
    10. 本地化路由代理中间件

      可选

      如果您希望自动将用户重定向到其偏好的语言环境,请建立代理解析中间件:

      src/proxy.ts
      export { intlayerProxy as proxy } from "next-intlayer/proxy";
      
      export const config = {
        matcher:
          "/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",
      };
      

      intlayerProxy 用于检测用户的首选语言环境,并根据 配置文件设置 将其重定向到适当的 URL。此外,它还支持将用户的首选语言环境保存在 cookie 中。

    11. 自 Intlayer v9 起,此中间件遵守 routing.enableProxy 选项(默认为 true)。在您的配置中设置 routing.enableProxy: false 以将其转换为直通,而无需删除此文件。请参阅 v9 发布说明

      </Step>

    12. 更改内容语言环境

      可选

      在 Next.js 中更改内容语言环境的最推荐方法是使用 Link 组件将用户重定向到包含相应语言环境的路由。这将利用 Next.js 的预取功能,并避免页面强制刷新。

      src/components/localeSwitcher/LocaleSwitcher.tsx
      "use client";
      
      import type { FC } from "react";
      import { Locales, getHTMLTextDir, getLocaleName } from "intlayer";
      import { useLocale } from "next-intlayer";
      
      export const LocaleSwitcher: FC = () => {
        const { locale, availableLocales, setLocale } = useLocale();
      
        return (
          <div>
            <button popoverTarget="localePopover">{getLocaleName(locale)}</button>
            <div id="localePopover" popover="auto">
              {availableLocales.map((localeItem) => (
                <button
                  key={localeItem}
                  aria-current={locale === localeItem ? "page" : undefined}
                  onClick={() => setLocale(localeItem)}
                >
                  <span>
                    {/* 语言环境 - 例如:ZH */}
                    {localeItem}
                  </span>
                  <span>
                    {/* 语言环境自身的名称 - 例如:中文 */}
                    {getLocaleName(localeItem, locale)}
                  </span>
                  <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
                    {/* 当前语言环境下的名称 - 例如:Francés(当当前语言环境为 Locales.SPANISH 时) */}
                    {getLocaleName(localeItem)}
                  </span>
                  <span dir="ltr" lang={Locales.ENGLISH}>
                    {/* 英语下的名称 - 例如:Chinese */}
                    {getLocaleName(localeItem, Locales.ENGLISH)}
                  </span>
                </button>
              ))}
            </div>
          </div>
        );
      };
      
      另一种方法是使用 useLocale 钩子提供的 setLocale 函数。该函数不支持页面预取。有关更多详细信息,请查看 useLocale 钩子文档
    13. 优化包体积

      可选

      使用 next-intlayer 时,字典默认会包含在每个页面的包中。为了优化包体积,Intlayer 提供了一个可选的 SWC 插件,它利用宏智能地优化 useIntlayer 调用。这确保了字典仅包含在实际使用它们的页面的包中。

      @intlayer/babel 插件已经集成了打包优化(见 babel.config.js)。但是 @intlayer/swc 插件性能更好。如果你移除 @intlayer/babel 插件,你可以使用 @intlayer/swc 插件。

      要启用此优化,请安装 @intlayer/swc 包。安装后,next-intlayer 会自动检测并使用该插件:

      bash
      npm install @intlayer/swc --save-dev
      
      注意:此优化仅适用于 Next.js 13 及以上版本。
      注意:由于 Next.js SWC 插件仍处于试验阶段,该包默认未安装。未来可能会有所改变。
      注意:如果您设置了 importMode: 'dynamic'importMode: 'fetch'(在字典配置中),它将依赖于 Suspense,因此您需要将 useIntlayer 调用包裹在 Suspense 边界内。这意味着您无法直接在页面/布局组件的顶层使用 useIntlayer
    14. 提取组件内容

      可选

      如果您有现有的代码库,转换数千个文件可能会非常耗时。

      为了简化此过程,Intlayer 提出了 编译器 / 提取器 来转换您的组件并提取内容。

      要进行设置,您可以在 intlayer.config.ts 文件中添加 compiler 部分:

      intlayer.config.ts
      import { type IntlayerConfig } from "intlayer";
      
      const config: IntlayerConfig = {
        // ... 您的其他配置
        compiler: {
          /**
           * 指示是否应启用编译器。
           */
          enabled: true,
      
          /**
           * 定义输出文件路径
           */
          output: ({ fileName, extension }) => `./${fileName}${extension}`,
      
          /**
           * 指示在转换后是否应保存组件。这样,编译器只需运行一次即可转换应用程序,然后即可将其删除。
           */
          saveComponents: false,
      
          /**
           * 字典键前缀
           */
          dictionaryKeyPrefix: "",
        },
      };
      
      export default config;
      

      运行提取器以转换组件并提取内容

      bash
      npx intlayer extract
      
      Since v9, the intlayerCompiler is included in the intlayer plugin. So you don't need to add it manually.
      bash
      npm install @intlayer/babel --save-dev
      
      babel.config.js
      const {
        intlayerExtractBabelPlugin,
        getExtractPluginOptions,
      } = require("@intlayer/babel");
      
      module.exports = {
        presets: ["next/babel"],
        plugins: [
          // 将组件内容提取到字典中
          [intlayerExtractBabelPlugin, getExtractPluginOptions()],
        ],
      };
      
      bash
      npm run build # 或 npm run dev
      

    TypeScript 配置

    Intlayer 使用模块扩展 (module augmentation) 来利用 TypeScript 的优势并使您的代码库更加健壮。

    自动补全

    翻译错误

    确保您的 TypeScript 配置包含自动生成的类型。

    tsconfig.json
    {
      // ... 您的现有 TypeScript 配置
      "include": [
        // ... 您的现有 TypeScript 配置
        ".intlayer/**/*.ts", // 包含自动生成的类型
      ],
    }
    

    Git 配置

    建议忽略 Intlayer 生成的文件。这可以避免将它们提交到您的 Git 存储库中。

    为此,您可以在 .gitignore 文件中添加以下指令:

    .gitignore
    # 忽略 Intlayer 生成的文件
    .intlayer
    

    VS Code 扩展

    为了提升使用 Intlayer 的开发体验,您可以安装官方 Intlayer VS Code 扩展

    从 VS Code Marketplace 安装

    该扩展提供:

    • 翻译键的自动补全
    • 缺失翻译的实时错误检测
    • 翻译内容的内联预览
    • 轻松创建和更新翻译的快速操作 (Quick actions)

    阅读 Intlayer VS Code 扩展文档 以了解更多关于扩展使用的详细说明。

    进一步深入

    您可以实现 可视化编辑器 或使用 CMS 来实现内容的外部管理。