作者:
    Creation:2025-09-04Last update:2026-06-23

    使用Intlayer翻译您的React Router v7 | 国际化(i18n)

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

    目录

    为什么选择 Inlayer 而不是替代品?

    与“react-i18next”或“i18next”等主要解决方案相比,Intlayer是一个具有集成优化的解决方案,例如:

    完整的 React Router 覆盖

    Intlayer 经过优化,可与 React Router 完美配合,提供区域设置感知路由用于区域设置检测的中间件以及扩展国际化 (i18n) 所需的所有功能。

    捆绑尺寸

    不要将大量 JSON 文件加载到页面中,而只需加载必要的内容。 Intlayer 有助于将捆绑包和页面大小减少多达 50%

    可维护性

    确定应用程序内容的范围有利于大型应用程序的维护。您可以复制或删除单个功能文件夹,而无需承担检查整个内容代码库的精神负担。此外,Intlayer 具有完全类型化 (fully typed),以确保您的内容的准确性。

    人工智能代理

    共置内容减少大型语言模型 (LLM) 所需的上下文。 Intlayer 还附带了一套工具,例如用于测试缺失翻译的 CLILSPMCPagent技能,使 AI 代理的开发者体验 (DX) 更加流畅。

    自动化

    使用您选择的法学硕士,通过自动化在 CI/CD 管道中进行翻译,而费用由您的 AI 提供商承担。 Intlayer 还提供了一个编译器来自动提取内容,以及一个网络平台来帮助在后台翻译

    表现

    将大量 JSON 文件连接到组件可能会导致性能和反应性问题。 Intlayer 可在构建时 (build time)优化您的内容加载。

    无需开发即可扩展

    Intlayer 不仅仅是一个 i18n 解决方案,还提供了一个自托管的可视化编辑器和一个完整的 CMS 来帮助您管理多语言内容实时,与译员、文案人员和其他团队成员无缝协作。内容可以本地和/或远程存储。


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

    1. 安装依赖

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

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

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

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

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

    2. 配置您的项目

    在 React Router v7 应用程序中使用基于文件系统的路由设置 Intlayer 的分步指南

    www.youtube.com

    See Application Template on GitHub.

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

    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 日志等。有关可用参数的完整列表,请参阅配置文档
    1. 创建根布局

      根布局

      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 codeexport 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>  );}

      本地化主页

      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>  );}
      了解更多关于 useIntlayer hook 的信息,请参考文档
      如果你的应用已经存在,你可以使用 Intlayer 编译器以及提取命令,在一秒内转换数千个组件。
    2. 创建语言切换器组件

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

      app/components/locale-switcher.tsx
      import type { FC } from "react";import {  getHTMLTextDir,  getLocaleName,  getLocalizedUrl,  getPathWithoutLocale,} from "intlayer";import { setLocaleInStorage, 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 } = 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)}            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={Locales.ENGLISH}>              {/* 用英文表示的语言 - 例如 French */}              {getLocaleName(localeItem, Locales.ENGLISH)}            </span>          </Link>        </li>      ))}    </ol>  );};
      了解更多关于 useLocale hook 的信息,请参考文档
    3. 添加 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"; // 导入 hookexport default function RootLayout() {  useI18nHTMLAttributes(); // 调用 hook  return (    <IntlayerProvider>      <Outlet />    </IntlayerProvider>  );}
    4. 添加中间件

      你也可以使用 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"),      },    }),  ],});
    5. 提取组件的内容

      可选

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

      为了简化这个过程,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

    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 Configuration

    It is recommended to ignore the files generated by Intlayer. This allows you to avoid committing them to your Git repository.

    To do this, you can add the following instructions to your .gitignore file:

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

    VS Code Extension

    To improve your development experience with Intlayer, you can install the official Intlayer VS Code Extension.

    Install from the VS Code Marketplace

    This extension provides:

    • Autocompletion for translation keys.
    • Real-time error detection for missing translations.
    • Inline previews of translated content.
    • Quick actions to easily create and update translations.

    For more details on how to use the extension, refer to the Intlayer VS Code Extension documentation.


    Go Further

    To go further, you can implement the visual editor or externalize your content using the CMS.


    Documentation References

    This comprehensive guide provides everything you need to integrate Intlayer with React Router v7 for a fully internationalized application with locale-aware routing and TypeScript support.