作者:
    Creation:2025-06-18Last update:2026-06-25

    翻译您的 Expo and React Native 应用 | 国际化(i18n)

    ide.intlayer.org

    目录

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

    react-native-localizei18next 等主流方案相比,Intlayer 是一个集成了以下优化功能的解决方案:

    Intlayer 经过优化,可与 React Native 和 Expo 完美配合,提供组件级内容作用域TypeScript 支持以及在移动应用中扩展国际化 (i18n) 所需的所有功能。

    将应用内容限定作用域有助于维护大规模应用程序。您可以复制或删除单个功能文件夹,而无需承受审查整个内容代码库的心理负担。此外,Intlayer 具有完整的类型支持,确保内容的准确性。

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

    使用您选择的 LLM,以 AI 提供商的成本在 CI/CD 管道中自动进行翻译。Intlayer 还提供编译器来自动提取内容,以及网络平台来帮助在后台进行翻译

    将大型 JSON 文件连接到组件可能会导致性能和响应性问题。Intlayer 在构建时优化内容加载。

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

    无需将大型 JSON 文件加载到页面中,只需加载必要的内容。Intlayer 帮助将包体积和视图大小减少多达 50%

    1. 安装依赖

      请参阅 GitHub 上的应用模板

      在您的 React Native 项目中,安装以下包:

      bash
      npx intlayer@canary init --interactive    # v9# npx intlayer init                       # v8
      --interactive 标志是可选的。如果您是 AI 代理,请使用 intlayer-cli init
      该命令将检测您的环境并安装所需的软件包。例如:
      bash
      npm install intlayer react-native-intlayer

      套餐

      • intlayer
        用于配置、字典内容、类型生成和 CLI 命令的核心 i18n 工具包。

      • react-native-intlayer
        React Native 集成,提供您将用于获取和切换语言环境的上下文 provider 和 React hook、React Native polyfill,以及将 Intlayer 与 React Native 打包器集成的 Metro 插件。它重新导出 react-intlayer 的所有内容,因此在 React Native 应用中只需要这一个包。


    2. 创建 Intlayer 配置

      在您的项目根目录(或任何方便的位置)创建一个 Intlayer 配置文件。它可能如下所示:

      intlayer.config.ts
      /**
       * 如果 Locales 类型不可用,请尝试在 tsconfig.json 中将 moduleResolution 设置为 "bundler"
       */
      import { Locales, type IntlayerConfig } from "intlayer";
      
      const config: IntlayerConfig = {
        internationalization: {
          locales: [
            Locales.ENGLISH,
            Locales.FRENCH,
            Locales.SPANISH,
            // ... 添加您需要的其他语言环境
          ],
          defaultLocale: Locales.ENGLISH,
        },
      };
      
      export default config;

      在此配置中,您可以:

      • 配置支持的语言环境列表
      • 设置默认语言环境。
      • 以后,您可以添加更多高级选项(例如日志、自定义内容目录等)。
      • 请参阅 Intlayer 配置文档 了解更多信息。
    3. 添加 Metro 插件

      Metro 是 React Native 的打包器。它是使用 react-native init 命令创建的 React Native 项目的默认打包器。要在 Metro 中使用 Intlayer,您需要将插件添加到 metro.config.js 文件中:

      metro.config.js
      const { getDefaultConfig } = require("expo/metro-config");const { configMetroIntlayer } = require("react-native-intlayer/metro");module.exports = (async () => {  const defaultConfig = getDefaultConfig(__dirname);  return await configMetroIntlayer(defaultConfig);})();

      注意:configMetroIntlayer 是一个 Promise 函数。如果您想同步使用它,请改用 configMetroIntlayerSync,或避免使用 IFFE(立即调用函数表达式)。 注意:configMetroIntlayerSync 不允许在服务器启动时构建 intlayer 字典

    4. 添加 Intlayer provider

      为了在您的应用程序中保持用户语言的同步,您需要使用来自 react-native-intlayerIntlayerProvider 组件包裹您的根组件。

      始终从 react-native-intlayer 导入。其 IntlayerProvider 包含 Intlayer 使用的 web API 的 polyfill,该包重新导出了 react-intlayer 中的所有 hook 和工具。

      此外,您需要在 index.js 文件中添加 intlayerPolyfill 函数,以确保 Intlayer 能够正常工作。

      app/_layout.tsx
      import { Stack } from "expo-router";
      import { getLocales } from "expo-localization";
      import { IntlayerProvider } from "react-native-intlayer";
      import { type FC } from "react";
      
      const getDeviceLocale = () => getLocales()[0]?.languageTag;
      
      const RootLayout: FC = () => {
        return (
          <IntlayerProvider defaultLocale={getDeviceLocale()}>
            <Stack>
              <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
            </Stack>
          </IntlayerProvider>
        );
      };
      
      export default RootLayout;
    5. 声明您的内容

      在项目中任意位置(通常在 src/ 目录中)创建内容声明文件,使用 Intlayer 支持的任何扩展格式:

      • .content.json
      • .content.jsonc
      • .content.json5
      • .content.ts
      • .content.tsx
      • .content.js
      • .content.jsx
      • .content.mjs
      • .content.mjx
      • .content.cjs
      • .content.md
      • .content.mdx
      • .content.yaml
      • .content.yml
      • 等等

      Expo Router (web): 请将 .content.* 文件保留在 app/ 目录之外。 Expo Router 会将 app/ 内的每个 JavaScript/TypeScript 文件视为一个路由。在 web 上,它的路由发现会直接扫描文件系统,并且 遵循 Metro 的 resolver.blockList,因此同位置的 *.content.ts 会被注册为一个路由。像 app/(tabs)/_layout.content.ts 这样的文件甚至会被解析为布局(.content 部分被读取为平台后缀),这会与实际的 _layout.tsx 发生冲突并抛出错误:

      plaintext
      The layouts "./(tabs)/_layout.content.ts" and "./(tabs)/_layout.tsx" conflict on the route "/(tabs)/_layout.content". Remove or rename one of these files.

      请将您的声明放置在 app/ 之外的目录中(例如 content/src/content/)。Intlayer 会发现项目中任意位置的 .content.* 文件,字典通过它们的 key 进行引用,因此不需要进行任何导入更改。在原生端这不是必需的(Metro 的 blockList 已经隐藏了它们),但使用非 app/ 目录可确保这两个平台都能正常工作。

      示例(带有 React Native TSX 节点的 TypeScript):

      src/app.content.tsx
      import { t, type Dictionary } from "intlayer";
      import type { ReactNode } from "react";
      
      /**
       * 我们"app"域的内容字典
       */
      import { t, type Dictionary } from "intlayer";
      
      const homeScreenContent = {
        key: "home-screen",
        content: {
          title: t({
            en: "Welcome!",
            fr: "Bienvenue!",
            es: "¡Bienvenido!",
          }),
        },
      } satisfies Dictionary;
      
      export default homeScreenContent;
      有关内容声明的详细信息,请参阅 Intlayer 内容文档

    6. 在组件中使用 Intlayer

      在子组件中使用 useIntlayer hook 获取本地化内容。

      示例

      app/(tabs)/index.tsx
      import { Image, StyleSheet, Platform } from "react-native";
      import { useIntlayer } from "react-native-intlayer";
      import { HelloWave } from "@/components/HelloWave";
      import ParallaxScrollView from "@/components/ParallaxScrollView";
      import { ThemedText } from "@/components/ThemedText";
      import { ThemedView } from "@/components/ThemedView";
      import { type FC } from "react";
      
      const HomeScreen = (): FC => {
        const { title, steps } = useIntlayer("home-screen");
      
        return (
          <ParallaxScrollView
            headerBackgroundColor={{ light: "#A1CEDC", dark: "#1D3D47" }}
            headerImage={
              <Image
                source={require("@/assets/images/partial-react-logo.png")}
                style={styles.reactLogo}
              />
            }
          >
            <ThemedView style={styles.titleContainer}>
              <ThemedText type="title">{title}</ThemedText>
              <HelloWave />
            </ThemedView>
          </ParallaxScrollView>
        );
      };
      
      const styles = StyleSheet.create({
        titleContainer: {
          flexDirection: "row",
          alignItems: "center",
          gap: 8,
        },
      });
      
      export default HomeScreen;
      当在基于字符串的属性中使用 content.someKey(例如按钮的 titleText 组件的 children)时,请调用 content.someKey.value 来获取实际的字符串。
      如果您的应用程序已经存在,您可以结合使用 Intlayer 编译器提取命令 在一秒钟内转换数千个组件。

    7. 更改应用程序语言环境

      可选

      要在组件内部切换语言环境,可以使用 useLocale hook 的 setLocale 方法:

      src/components/LocaleSwitcher.tsx
      import { type FC } from "react";
      import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
      import { getLocaleName } from "intlayer";
      import { useLocale } from "react-native-intlayer";
      
      export const LocaleSwitcher: FC = () => {
        const { setLocale, availableLocales } = useLocale();
      
        return (
          <View style={styles.container}>
            {availableLocales.map((locale) => (
              <TouchableOpacity
                key={locale}
                style={styles.button}
                onPress={() => setLocale(locale)}
              >
                <Text style={styles.text}>{getLocaleName(locale)}</Text>
              </TouchableOpacity>
            ))}
          </View>
        );
      };
      
      const styles = StyleSheet.create({
        container: {
          flexDirection: "row",
          justifyContent: "center",
          alignItems: "center",
          gap: 8,
        },
        button: {
          paddingVertical: 6,
          paddingHorizontal: 12,
          borderRadius: 6,
          backgroundColor: "#ddd",
        },
        text: {
          fontSize: 14,
          fontWeight: "500",
          color: "#333",
        },
      });

      这会触发所有使用 Intlayer 内容的组件重新渲染,现在显示新语言环境的翻译内容。

      详情请参见 useLocale 文档

    配置 TypeScript(如果您使用 TypeScript)

    Intlayer 会在一个隐藏文件夹中(默认是 .intlayer)生成类型定义,以提升自动补全功能并捕获翻译错误:

    json5
    // tsconfig.json{  // ... 您现有的 TS 配置  "include": [    "src", // 您的源代码    ".intlayer/types/**/*.ts", // <-- 确保包含自动生成的类型    // ... 您已经包含的其他内容  ],}

    这使得以下功能成为可能:

    • 自动补全 您的字典键。
    • 类型检查,如果访问不存在的键或类型不匹配,会发出警告。

    Git 配置

    为了避免提交 Intlayer 自动生成的文件,请将以下内容添加到您的 .gitignore 文件中:

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

    VS Code 扩展

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

    从 VS Code 市场安装

    此扩展提供:

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

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


    深入了解

    • 可视化编辑器:使用Intlayer 可视化编辑器来可视化管理翻译。
    • CMS 集成:您还可以将词典内容外部化,并从 CMS 中获取。
    • CLI 命令:探索 Intlayer CLI,用于执行诸如提取翻译检查缺失键等任务。

    享受通过 Intlayer 为您的 React Native 应用构建强大国际化支持的乐趣!


    调试

    React Native 的稳定性不如 React Web,因此要特别注意版本对齐。

    Intlayer 主要针对 Web Intl API;在 React Native 上,你必须包含适当的 polyfill。

    检查清单:

    • 使用最新版本的 intlayerreact-native-intlayer
    • 启用 Intlayer polyfill。
    • 如果你使用 getLocaleName 或其他基于 Intl-API 的工具,请提前导入这些 polyfill(例如在 index.jsApp.tsx 中):
    ts
    import "intl";import "@formatjs/intl-getcanonicallocales/polyfill";import "@formatjs/intl-locale/polyfill";import "@formatjs/intl-pluralrules/polyfill";import "@formatjs/intl-displaynames/polyfill";import "@formatjs/intl-listformat/polyfill";import "@formatjs/intl-numberformat/polyfill";import "@formatjs/intl-relativetimeformat/polyfill";import "@formatjs/intl-datetimeformat/polyfill";
    • 如果模块无法解析,请验证你的 Metro 配置(resolver 别名、asset 插件、tsconfig 路径)。