作者:
    Creation:2025-09-04Last update:2026-10-08

    使用 Intlayer 翻译您的 React Router v7 网站

    本指南演示了如何在 React Router v7 项目中集成 Intlayer,实现无缝国际化,支持基于语言环境的路由、TypeScript 支持以及现代开发实践。

    本指南同时涵盖基于配置的路由(routes.ts)和基于文件系统的路由(@react-router/fs-routes)。

    目录

    为什么选择 Intlayer 而不是其他方案?

    与 react-i18next 或 i18next 等主流解决方案相比,Intlayer 是一个自带多项集成的优化方案,例如:

    Intlayer 经过深度优化,可与 React Router 完美配合,提供语言环境感知路由、用于语言环境检测的中间件以及扩展国际化 (i18n) 所需的全部功能。

    您无需在页面中加载庞大的 JSON 文件,而是只加载所需的内容。Intlayer 可以帮助 将您的打包产物和页面体积减少多达 50%。

    将应用程序内容与组件就近维护在相应作用域内,极大提升了大体量应用的可维护性。您可以直接复制或删除单个功能目录,而无需承担检查整个全局内容代码库的认知负担。此外,Intlayer 提供 完整的 TypeScript 类型支持,确保内容的准确性与安全性。

    内容就近组织 (Co-location) 显著减少了大型语言模型 (LLM) 所需的上下文。Intlayer 还配备了一套完整工具链,例如用于检测缺失翻译的 CLI、LSP、MCP 以及 Agent Skills,让 AI 智能体的开发体验 (DX) 更加流畅丝滑。

    在 CI/CD 流水线中,使用您自选的 LLM(直接基于您自有的 AI 提供商 API 计费)实现自动化翻译。Intlayer 还提供了可自动提取内容的 编译器,并配备了 Web 平台 / CMS 以便在后台管理系统中执行翻译。

    将大型 JSON 文件全局挂载到各个组件容易导致渲染性能下降与响应迟滞。Intlayer 会在构建阶段自动优化内容加载。

    Intlayer 不仅仅是一个简单的 i18n 解决方案。它还提供了 支持自托管的可视化编辑器 以及 完整的 CMS。借此,您可以 实时 管理多语言内容,让译者、文案及团队其他成员实现无缝协作。内容可存储在本地和/或远程服务器上。

    在 React Router v7 应用中设置 Intlayer 的分步指南

    youtube.com
    ide.intlayer.org
    ide.intlayer.org
    intlayer-react-router-v7.vercel.app

    See the Config-Based Routing Template or File-System Routes Template on GitHub.

    1. 安装依赖

      使用您首选的包管理器安装必要的包:

      bash
      npx intlayer init --interactive
      
      --interactive 标志是可选的。如果您是 AI agent,请使用 intlayer-cli init。
      此命令将检测您的环境并安装所需的包。例如:
      bash
      npm install intlayer react-intlayer
      npm install vite-intlayer --save-dev
      
      • intlayer

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

      • react-intlayer 将 Intlayer 与 React 应用集成的包。它为 React 国际化提供了上下文 Provider 和 Hook。

      • vite-intlayer 包括用于将 Intlayer 与 Vite bundler 集成的 Vite 插件,以及用于检测用户首选区域设置、管理 cookie 和处理 URL 重定向的中间件。

    2. 配置您的项目

      架构

      在此架构中,路由在 app/routes.ts 中以编程方式定义,并带有可选的 /:locale? 动态段。本地化页面、布局和内容声明都组织在 app/ 目录下:

      bash
      .
      ├── app
      │   ├── components
      │   │   ├── locale-switcher.content.ts
      │   │   ├── locale-switcher.tsx
      │   │   ├── localized-link.tsx
      │   │   ├── navbar.content.ts
      │   │   └── navbar.tsx
      │   ├── hooks
      │   │   ├── useI18nHTMLAttributes.tsx
      │   │   └── useLocalizedNavigate.tsx
      │   ├── routes
      │   │   ├── about
      │   │   │   ├── page.content.ts
      │   │   │   └── page.tsx
      │   │   ├── layout.tsx
      │   │   ├── page.content.ts
      │   │   └── page.tsx
      │   ├── root.tsx                      # Root layout for IntlayerProvider
      │   └── routes.ts                     # Route definition file
      ├── intlayer.config.ts
      ├── package.json
      ├── react-router.config.ts
      ├── tsconfig.json
      └── vite.config.ts
      

      配置

      创建 intlayer.config.ts 配置文件以声明应用程序支持的语言:

      intlayer.config.ts
      import { type IntlayerConfig, Locales } from "intlayer";
      
      const config: IntlayerConfig = {
        internationalization: {
          defaultLocale: Locales.ENGLISH,
          locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
        },
      };
      
      export default config;
      

      架构

      在此架构中,路由遵循使用 flatRoutes 的 React Router v7 文件系统路由规范,其中点(.)代表 URL 段,($locale) 表示可选的本地化段:

      bash
      .
      ├── app
      │   ├── components
      │   │   ├── locale-switcher.content.ts
      │   │   ├── locale-switcher.tsx
      │   │   ├── localized-link.tsx
      │   │   ├── navbar.content.ts
      │   │   └── navbar.tsx
      │   ├── hooks
      │   │   ├── useI18nHTMLAttributes.tsx
      │   │   └── useLocalizedNavigate.tsx
      │   ├── routes
      │   │   ├── ($locale)._index.content.ts
      │   │   ├── ($locale)._index.tsx
      │   │   ├── ($locale).about.content.ts
      │   │   └── ($locale).about.tsx
      │   ├── root.tsx                      # Root layout for IntlayerProvider
      │   └── routes.ts                     # Route definition file using flatRoutes
      ├── intlayer.config.ts
      ├── package.json
      ├── react-router.config.ts
      ├── tsconfig.json
      └── vite.config.ts
      

      配置

      创建 intlayer.config.ts 配置文件以声明应用程序支持的语言:

      intlayer.config.ts
      import { type IntlayerConfig, Locales } from "intlayer";
      
      const config: IntlayerConfig = {
        internationalization: {
          defaultLocale: Locales.ENGLISH,
          locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
        },
      };
      
      export default config;
      
      通过此配置文件,您可以设置本地化的 URL、中间件重定向、cookie 名称、内容声明的位置和扩展名,禁用控制台中的 Intlayer 日志等。有关可用参数的完整列表,请参阅配置文档。
    3. 在您的 Vite 配置中集成 Intlayer

      将 intlayer 插件添加到您的配置中:

      vite.config.ts
      import { reactRouter } from "@react-router/dev/vite";
      import { defineConfig } from "vite";
      import { intlayer } from "vite-intlayer";
      
      export default defineConfig({
        plugins: [reactRouter(), intlayer()],
      });
      
      intlayer() Vite 插件用于将 Intlayer 与 Vite 集成。它确保构建内容声明文件并在开发模式下监控它们。它在 Vite 应用程序中定义 Intlayer 环境变量。此外,它提供别名以优化性能。
    4. 配置 React Router v7 Routes

      使用本地化感知路由设置您的路由配置:

      app/routes.ts
      import { layout, route, type RouteConfig } from "@react-router/dev/routes";
      
      export default [
        route("/:locale?", "routes/page.tsx"), // 本地化主页
        route("/:locale?/about", "routes/about/page.tsx"), // 本地化关于页面
      ] satisfies RouteConfig;
      

      Set up your routing configuration to use file-system based routes with flatRoutes:

      app/routes.ts
      import type { RouteConfig } from "@react-router/dev/routes";
      import { flatRoutes } from "@react-router/fs-routes";
      import { configuration } from "intlayer";
      
      const routes: RouteConfig = flatRoutes({
        // Ignore content declaration files from being treated as routes
        ignoredRouteFiles: configuration.content.fileExtensions.map(
          (fileExtension) => `**/*${fileExtension}`
        ),
      });
      
      export default routes;
      
      The flatRoutes function from @react-router/fs-routes enables file-system based routing, where the file structure in the routes/ directory determines your application's routes. The ignoredRouteFiles option ensures that Intlayer content declaration files (.content.ts, etc.) are not treated as route files.
    5. 创建根布局

      设置您的根布局和特定于语言的布局:

      根布局

      app/root.tsx
      import { getLocaleFromPath } from "intlayer";
      import { IntlayerProvider } from "react-intlayer";
      import {
        data,
        Meta,
        Scripts,
        ScrollRestoration,
        useLoaderData,
      } from "react-router";
      import type { Route } from "./+types/root";
      
      // ... Unchanged App, links and ErrorBoundary code
      
      export async function loader({ request }: Route.LoaderArgs) {
        const locale = getLocaleFromPath(request.url);
      
        if (!locale) {
          throw data("Language not supported", { status: 404 });
        }
      
        return { locale };
      }
      
      export function Layout({
        children,
      }: { children: React.ReactNode } & Route.ComponentProps) {
        const data = useLoaderData<typeof loader>();
        const { locale } = data ?? {};
      
        return (
          <html lang={locale}>
            <head>
              <meta charSet="utf-8" />
              <meta content="width=device-width, initial-scale=1" name="viewport" />
              <Meta />
              <Links />
            </head>
            <body>
              <IntlayerProvider locale={locale}>{children}</IntlayerProvider>
              <ScrollRestoration />
              <Scripts />
            </body>
          </html>
        );
      }
      
    6. 声明您的内容

      创建并管理您的内容声明以存储翻译:

      app/routes/[lang]/page.content.ts
      import { t, type Dictionary } from "intlayer";
      
      const pageContent = {
        key: "page",
        content: {
          title: t({
            zh: "欢迎来到 React Router v7 + Intlayer",
            en: "Welcome to React Router v7 + Intlayer",
            es: "Bienvenido a React Router v7 + Intlayer",
            fr: "Bienvenue sur React Router v7 + Intlayer",
          }),
          description: t({
            zh: "使用 React Router v7 和 Intlayer 轻松构建多语言应用程序。",
            en: "Build multilingual applications with ease using React Router v7 and Intlayer.",
            es: "Cree aplicaciones multilingües fácilmente usando React Router v7 y Intlayer.",
            fr: "Créez des applications multilingues facilement avec React Router v7 et Intlayer.",
          }),
          aboutLink: t({
            zh: "了解我们",
            en: "Learn About Us",
            es: "Aprender Sobre Nosotros",
            fr: "En savoir plus sur nous",
          }),
          homeLink: t({
            zh: "首页",
            en: "Home",
            es: "Inicio",
            fr: "Accueil",
          }),
        },
      } satisfies Dictionary;
      
      export default pageContent;
      
      您的内容声明可以在应用程序的任何地方定义,只要它们被包含在 contentDir 目录中(默认为 ./app)。并且匹配内容声明文件扩展名(默认为 .content.{json,ts,tsx,js,jsx,mjs,cjs,md,mdx,yaml,yml})。
      如果使用基于文件系统的路由,可以放置在 app/routes/($locale)._index.content.ts。
      有关更多详细信息,请参阅content 声明文档。
    7. 创建本地化感知的组件

      为区域感知导航创建一个 LocalizedLink 组件:

      app/components/localized-link.tsx
      import type { FC } from "react";
      
      import { getLocalizedUrl, type LocalesValues } from "intlayer";
      import { useLocale } from "react-intlayer";
      import { Link, type LinkProps, type To } from "react-router";
      
      // 检查是否为外部链接
      const isExternalLink = (to: string) => /^(https?:)?\/\//.test(to);
      
      // 将链接本地化
      export const locacalizeTo = (to: To, locale: LocalesValues): To => {
        if (typeof to === "string") {
          if (isExternalLink(to)) {
            return to;
          }
      
          return getLocalizedUrl(to, locale);
        }
      
        if (isExternalLink(to.pathname ?? "")) {
          return to;
        }
      
        return {
          ...to,
          pathname: getLocalizedUrl(to.pathname ?? "", locale),
        };
      };
      
      // 本地化链接组件
      export const LocalizedLink: FC<LinkProps> = (props) => {
        const { locale } = useLocale();
      
        return <Link {...props} to={locacalizeTo(props.to, locale)} />;
      };
      

      如果您想导航到本地化的路由,您可以使用 useLocalizedNavigate hook:

      app/hooks/useLocalizedNavigate.ts
      import { useLocale } from "react-intlayer";
      import { type NavigateOptions, type To, useNavigate } from "react-router";
      
      import { locacalizeTo } from "~/components/localized-link";
      
      export const useLocalizedNavigate = () => {
        // 获取导航函数
        const navigate = useNavigate();
        // 获取当前语言环境
        const { locale } = useLocale();
      
        // 创建本地化导航函数
        const localizedNavigate = (to: To, options?: NavigateOptions) => {
          // 将路径本地化到当前语言
          const localedTo = locacalizeTo(to, locale);
      
          navigate(localedTo, options);
        };
      
        return localizedNavigate;
      };
      
    8. 在你的页面中使用 Intlayer

      在整个应用程序中访问您的内容字典:

      本地化主页

      app/routes/page.tsx
      import { getIntlayer, validatePrefix } from "intlayer";
      import { useIntlayer } from "react-intlayer";
      import { data } from "react-router";
      
      import { LocaleSwitcher } from "~/components/locale-switcher";
      
      import { Navbar } from "~/components/navbar";
      import type { Route } from "./+types/page";
      
      export const loader = ({ params }: Route.LoaderArgs) => {
        const { locale } = params;
      
        const { isValid } = validatePrefix(locale);
      
        if (!isValid) {
          throw data("Locale not supported", { status: 404 });
        }
      };
      
      export const meta: Route.MetaFunction = ({ params }) => {
        const content = getIntlayer("page", params.locale);
      
        return [
          { title: content.title },
          { content: content.description, name: "description" },
        ];
      };
      
      export default function Page() {
        const { title, description, aboutLink } = useIntlayer("page");
      
        return (
          <div>
            <h1>{title}</h1>
            <p>{description}</p>
            <nav>
              <LocalizedLink to="/about">{aboutLink}</LocalizedLink>
            </nav>
          </div>
        );
      }
      
      app/routes/($locale)._index.tsx
      import { getIntlayer, validatePrefix } from "intlayer";
      import { useIntlayer } from "react-intlayer";
      import { data } from "react-router";
      
      import { LocaleSwitcher } from "~/components/locale-switcher";
      
      import { Navbar } from "~/components/navbar";
      import type { Route } from "./+types/($locale)._index";
      
      export const loader = ({ params }: Route.LoaderArgs) => {
        const { locale } = params;
      
        const { isValid } = validatePrefix(locale);
      
        if (!isValid) {
          throw data("Locale not supported", { status: 404 });
        }
      };
      
      export const meta: Route.MetaFunction = ({ params }) => {
        const content = getIntlayer("page", params.locale);
      
        return [
          { title: content.title },
          { content: content.description, name: "description" },
        ];
      };
      
      export default function Page() {
        const { title, description, aboutLink } = useIntlayer("page");
      
        return (
          <div>
            <h1>{title}</h1>
            <p>{description}</p>
            <nav>
              <LocalizedLink to="/about">{aboutLink}</LocalizedLink>
            </nav>
          </div>
        );
      }
      
      了解更多关于 useIntlayer hook 的信息,请参考文档。
      如果你的应用已经存在,你可以使用 Intlayer 编译器以及提取命令,在一秒内转换数千个组件。
    9. 创建语言切换器组件

      创建一个组件以允许用户更改语言:

      app/components/locale-switcher.tsx
      import type { FC } from "react";
      
      import {
        getHTMLTextDir,
        getLocaleName,
        getLocalizedUrl,
        getPathWithoutLocale,
      } from "intlayer";
      import { useIntlayer, useLocale } from "react-intlayer";
      import { Link, useLocation } from "react-router";
      
      export const LocaleSwitcher: FC = () => {
        const { localeSwitcherLabel } = useIntlayer("locale-switcher");
        const { pathname } = useLocation();
      
        const { availableLocales, locale, setLocale } = useLocale();
      
        const pathWithoutLocale = getPathWithoutLocale(pathname);
      
        return (
          <ol>
            {availableLocales.map((localeItem) => (
              <li key={localeItem}>
                <Link
                  aria-current={localeItem === locale ? "page" : undefined}
                  aria-label={`${localeSwitcherLabel.value} ${getLocaleName(localeItem)}`}
                  onClick={() => setLocale(localeItem)}
                  reloadDocument // Reload the page to apply the new locale
                  to={getLocalizedUrl(pathWithoutLocale, localeItem)}
                >
                  <span>
                    {/* 语言环境代码 - 例如 FR */}
                    {localeItem}
                  </span>
                  <span>
                    {/* 用其自身语言环境表示的语言 - 例如 Français */}
                    {getLocaleName(localeItem, locale)}
                  </span>
                  <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
                    {/* 用当前语言环境表示的语言 - 例如当前语言环境设置为 Locales.SPANISH 时的 Francés */}
                    {getLocaleName(localeItem)}
                  </span>
                  <span dir="ltr" lang={defaultLocale}>
                    {/* 用英文表示的语言 - 例如 French */}
                    {getLocaleName(localeItem, defaultLocale)}
                  </span>
                </Link>
              </li>
            ))}
          </ol>
        );
      };
      
      app/components/locale-switcher.tsx
      import type { FC } from "react";
      
      import {
        getHTMLTextDir,
        getLocaleName,
        getLocalizedUrl,
        getPathWithoutLocale,
        defaultLocale,
      } from "intlayer";
      import { useIntlayer, useLocale } from "react-intlayer";
      import { Link, useLocation } from "react-router";
      
      export const LocaleSwitcher: FC = () => {
        const { localeSwitcherLabel } = useIntlayer("locale-switcher");
        const { pathname } = useLocation();
      
        const { availableLocales, locale, setLocale } = useLocale();
      
        const pathWithoutLocale = getPathWithoutLocale(pathname);
      
        return (
          <ol>
            {availableLocales.map((localeItem) => (
              <li key={localeItem}>
                <Link
                  aria-current={localeItem === locale ? "page" : undefined}
                  aria-label={`${localeSwitcherLabel.value} ${getLocaleName(localeItem)}`}
                  onClick={() => setLocale(localeItem)}
                  reloadDocument // Reload the page to apply the new locale
                  to={getLocalizedUrl(pathWithoutLocale, localeItem)}
                >
                  <span>
                    {/* Locale - e.g. FR */}
                    {localeItem}
                  </span>
                  <span>
                    {/* Language in its own Locale - e.g. Français */}
                    {getLocaleName(localeItem, locale)}
                  </span>
                  <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
                    {/* Language in current Locale - e.g. Francés with current locale set to Locales.SPANISH */}
                    {getLocaleName(localeItem)}
                  </span>
                  <span dir="ltr" lang={defaultLocale}>
                    {/* Language in English - e.g. French */}
                    {getLocaleName(localeItem, defaultLocale)}
                  </span>
                </Link>
              </li>
            ))}
          </ol>
        );
      };
      
      了解更多关于 useLocale hook 的信息,请参考文档。
    10. 添加 HTML 属性管理

      创建一个 hook 来管理 HTML lang 和 dir 属性:

      app/hooks/useI18nHTMLAttributes.tsx
      import { getHTMLTextDir } from "intlayer";
      import { useEffect } from "react";
      import { useLocale } from "react-intlayer";
      
      export const useI18nHTMLAttributes = () => {
        const { locale } = useLocale();
      
        useEffect(() => {
          document.documentElement.lang = locale;
          document.documentElement.dir = getHTMLTextDir(locale);
        }, [locale]);
      };
      

      然后在你的根组件中使用它:

      app/routes/layout.tsx
      import { Outlet } from "react-router";
      import { IntlayerProvider } from "react-intlayer";
      
      import { useI18nHTMLAttributes } from "app/hooks/useI18nHTMLAttributes"; // 导入 hook
      
      export default function RootLayout() {
        useI18nHTMLAttributes(); // 调用 hook
      
        return (
          <IntlayerProvider>
            <Outlet />
          </IntlayerProvider>
        );
      }
      
    11. 添加中间件

      你也可以使用 intlayerProxy 来为你的应用添加服务器端路由。这个插件将自动根据 URL 检测当前语言环境并设置适当的语言 cookie。如果未指定语言环境,该插件将根据用户的浏览器语言偏好确定最合适的语言环境。如果未检测到语言环境,它将重定向到默认语言环境。

      注意,要在生产环境中使用 intlayerProxy,你需要将 vite-intlayer 包从 devDependencies 切换到 dependencies。
      自 Intlayer v9 起,intlayerProxy() 直接内置在 intlayer() 插件中,并通过 routing.enableProxy 选项(默认为 true)默认启用。如下所示单独注册它现在是可选的,它保留用于向后兼容性和需要控制插件顺序的设置。设置 routing.enableProxy: false 以选择退出。查看 v9 发布说明。
      vite.config.ts
      import { defineConfig } from "vite";
      import react from "@vitejs/plugin-react-swc";
      import { intlayer } from "vite-intlayer";
      
      // https://vitejs.dev/config/
      export default defineConfig({
        plugins: [
          react(),
          intlayer({
            proxy: {
              ignore: (req) => req.url?.startsWith("/api"),
            },
          }),
        ],
      });
      
    12. 提取组件的内容

      可选

      如果你有一个现有的代码库,转换数千个文件可能很耗时。

      为了简化这个过程,Intlayer 提供了一个编译器 / 提取器来转换你的组件并提取内容。

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

      intlayer.config.ts
      import { type IntlayerConfig } from "intlayer";
      
      const config: IntlayerConfig = {
        // ... 其余配置
        compiler: {
          /**
           * 指示编译器是否应该被启用。
           */
          enabled: true,
      
          /**
           * 定义输出文件路径
           */
          output: ({ fileName, extension }) => `./${fileName}${extension}`,
      
          /**
           * 指示组件在转换后是否应该被保存。
           *
           * - 如果为 `true`,编译器将重新将组件文件写入磁盘。因此转换将是永久的,编译器将跳过下一个过程的转换。这样,编译器可以转换应用,然后可以删除它。
           *
           * - 如果为 `false`,编译器仅在构建输出中注入 `useIntlayer()` 函数调用,并保持基础代码库完整。转换仅在内存中完成。
           */
          saveComponents: false,
      
          /**
           * 词典键前缀
           */
          dictionaryKeyPrefix: "",
        },
      };
      
      export default config;
      

      运行提取器来转换你的组件并提取内容

      bash
      npx intlayer extract
      
      自 v9 起,intlayerCompiler 已包含在 intlayer 插件中。因此你不需要手动添加它。

      更新你的 vite.config.ts 以包含 intlayerCompiler 插件:

      vite.config.ts
      import { defineConfig } from "vite";
      import { intlayer, intlayerCompiler } from "vite-intlayer";
      
      export default defineConfig({
        plugins: [
          intlayer(),
          intlayerCompiler(), // 添加编译器插件
        ],
      });
      

      构建你的应用程序来转换你的组件并提取内容

      bash
      npm run build # 或 npm run dev
      

    Configure TypeScript

    Intlayer uses module augmentation to get benefits of TypeScript and make your codebase stronger.

    Ensure your TypeScript configuration includes the autogenerated types:

    tsconfig.json
    {
      // ... your existing configurations
      include: [
        // ... your existing includes
        ".intlayer/**/*.ts", // Include the auto-generated types
      ],
    }
    

    Git 配置

    建议忽略 Intlayer 自动生成的文件,避免将它们提交到 Git 仓库中。

    为此,您可以将以下规则添加到 .gitignore 文件中:

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

    VS Code 插件

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

    该插件提供以下特性:

    • 翻译键的自动补全。
    • 缺失翻译的实时错误检测。
    • 翻译内容的行内悬停预览。
    • 轻松创建和更新翻译的快速修复操作。

    有关如何使用该插件的更多详细信息,请参阅 Intlayer VS Code 插件文档。

    深入了解

    要深入了解,您可以实现 可视化编辑器 或使用 CMS 将内容外部化。

    文档参考

    本综合指南提供了将 Intlayer 与 React Router v7 集成所需的全部内容,帮助您构建具备支持语言环境的路由与 TypeScript 支持的完整国际化应用。

    常见问题

    React Router v7 本身不包含消息管理层,因此需要将其与 i18n 库搭配使用:

    • react-i18next / i18next:在运行时加载 JSON 命名空间,需要单独编写语言检测器接入路由。
    • react-intl 和 Lingui:基于提取步骤的 ICU 消息方案。
    • Intlayer:最先进的解决方案。内容可以在代码库中的任何位置声明(靠近每个组件或集中管理),在构建时编译,全链路类型安全,提供支持语言环境的路由辅助函数、AI 翻译、可视化编辑器和 CMS。

    请参阅 为什么选择 Intlayer 和 性能基准。

    远少于基于命名空间的方案,因为页面永远不会下载它不渲染的语言目录。服务端渲染的标记在服务端直接解析内容,构建时编译器将 useIntlayer 调用替换为组件使用的确切字典条目,因此未使用的键和未使用的语言都会被自动丢弃,并且 动态字典 会按语言环境拆分剩余内容。与常规替代方案相比,Intlayer 可将 bundle 和页面体积减少高达 50%。请参阅 Bundle 体积优化 和 性能基准。

    可以,有两条迁移路径。您可以使用 react-i18next 迁移指南 或 i18next 迁移指南 逐步迁移内容。或者,您可以完全保留当前的 API:兼容性适配器 公开与 react-i18next、react-intl 和 i18next 完全相同的 API,但底层由 Intlayer 字典驱动,因此只需更改导入语句,组件代码完全无需修改。

    可以。JSON 同步插件 将您的 /messages/{locale}/{namespace}.json 文件作为单一真实来源(source of truth),并双向生成 Intlayer 字典。PO 同步插件 对 gettext 目录执行相同的操作,而 按语言环境组织的文件 允许您按语言拆分内容,而不是将所有语言打包到一个文件中。

    不需要。运行 npx intlayer extract,Intlayer 会读取您的组件,提取面向用户的字符串,并在每个组件旁边生成 .content 文件,这样您只需审查 diff,而无需手动逐一复制字符串到语言目录中。本指南的第 12 步详细介绍了此过程。

    如需全自动流程,Intlayer Compiler 可在构建时执行相同操作:它在每次更改时扫描您的 JSX、TSX、Vue 和 Svelte 源代码,生成字典并通过模块热替换 (HMR) 保持同步,因此完全无需手动维护键名。

    开启编译器前有两个限制值得了解:它通过静态分析工作,因此仅在运行时存在的字符串(如 API 错误代码或 CMS 字段)无法被捕获;此外它需要区分用户文本和应用程序逻辑(如 className="active" 或状态代码),在大型代码库中需要少量注解。而 extract 命令 则通过让您参与审查避免了这两个问题。

    共有 5 个工具,均为可选:

    • VS Code 扩展:从 useIntlayer 键跳转到声明它的内容文件,从组件中提取内容,并从命令面板或专属的 Intlayer 选项卡运行 build、fill、test、push 和 pull。
    • LSP 服务器:在任何支持 LSP 的编辑器中提供相同的感知能力,支持跳转到定义、查找所有引用、悬停预览翻译值、键和字段的自动补全,以及在键未声明时发出警告。它还可以解析 i18next、react-i18next、next-intl 和 use-intl 调用,助力平滑迁移。
    • MCP 服务器:向 Cursor、VS Code、Claude Desktop、Claude Code 和 ChatGPT 公开 Intlayer 文档与 CLI,使 AI 助手能够基于最新文档进行准确回答,并能自行运行 intlayer fill 等命令。
    • Agent Skills:针对特定领域的技能(如 intlayer-config、intlayer-cli 和 intlayer-content,以及每个框架对应的专属技能),教导 AI 代理您的路由配置和内容节点类型。
    • ESLint 插件:no-raw-text 规则标记硬编码字符串,并提供针对静态字典键和未使用内容的额外规则。