react-i18next+i18next使用

一、安装

bash 复制代码
# npm 安装
npm install i18next react-i18next i18next-http-backend i18next-browser-languagedetector

# yarn 安装
yarn add i18next react-i18next i18next-http-backend i18next-browser-languagedetector

其中以下可选:

  • i18next-http-backend:用于从本地文件加载语言包(通过http请求按需加载);
  • i18next-browser-languagedetector:自动检测浏览器的默认语言(可选,但推荐)。

二、核心配置

1、初始化
javascript 复制代码
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';

// import en_US from './locals/en_US'
// import zh_CN from './locals/zh_CN'
// const resources = {
//   [LOCALE.ZH_CN]: {
//     translation: zh_CN
//   },
//   [LOCALE.EN_US]: {
//     translation: en_US
//   }
// }


//可以单独处理,如放在locals文件夹下:en_US.ts、zh_CN.ts
// 定义多语言资源
const resources = {
  en: {
    translation: {
      welcome: 'Welcome to our <1>website</1>',
    },
  },
  zh: {
    translation: {
      welcome: '欢迎访问我们的<1>网站</1>',
    },
  },
};

i18n
  .use(initReactI18next)
  .init({
    resources,
    lng: 'en', // 默认语言,使用自动检测就不需要此配置
    //fallbackLng: "en",
    interpolation: {
      escapeValue: false, // React 已经处理了 XSS,所以关闭即可
    },
  });

export default i18n;

使用i18next-http-backend和i18next-browser-languagedetector

bash 复制代码
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import Backend from 'i18next-http-backend'; // 加载语言文件
import LanguageDetector from 'i18next-browser-languagedetector'; // 检测浏览器语言

// 初始化 i18n
i18n
  // 加载语言文件的插件
  .use(Backend)
  // 自动检测语言的插件
  .use(LanguageDetector)
  // 绑定 react-i18next
  .use(initReactI18next)
  // 核心配置
  .init({
    fallbackLng: 'zh-CN', // 兜底语言(检测不到时用)
    debug: process.env.NODE_ENV === 'development', // 开发环境开启调试
    interpolation: {
      escapeValue: false, // React 已自带 XSS 防护,关闭即可
    },
    // 语言检测的优先级(可选,默认已有合理配置)
    detection: {
      order: ['querystring', 'cookie', 'localStorage', 'navigator'],
      caches: ['localStorage', 'cookie'], // 缓存语言到本地
    },
    react: {
      useSuspense: false, // 关闭 Suspense(新手避免异步加载报错,暂时没遇到)
    },
    //supportedLngs: ['de', 'en', 'fr'],  //支持的语言列表
  });

export default i18n;

使用i18next-http-backend需要把翻译文件放到public目录下(不参与打包的目录,如public,内部语言目录随意写的,可以根据项目中语言key命名,默认中英文可以zh和en),不参与打包,如:

测试项目中只有两种语言:语言key为zh-CN和en-US,正常匹配(默认路径loadPath: '/locales/{{lng}}/{{ns}}.json'),也可以显示配置语言包位置:

javascript 复制代码
i18next
  .use(Backend)
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    fallbackLng: LOCALE.ZH_CN,
    debug: import.meta.env.DEV,
    interpolation: {
      escapeValue: false 
    },
    // Backend 配置 - 指定语言包加载路径
    backend: {
      loadPath: '/locales/{{lng}}/{{ns}}.json', // 语言包路径(Electron 渲染进程中的 public 目录)
      addPath: '/locales/{{lng}}/{{ns}}.missing.json' // 缺失翻译的保存路径(可选)
    },
   //...其他配置
  })
问题:控制台看到如下请求
javascript 复制代码
// 中文请求
http://localhost:8000/locales/zh-CN/translation.json  //精确语言
http://localhost:8000/locales/zh/translation.json  //基础语言

// 英文请求
http://localhost:8000/locales/en-US/translation.json

中文会有两个请求,多个请求属于语言回退机制 导致的,属于正常行为,可以不解决,也可以按如下修复( load: 'currentOnly'就可以解决):

javascript 复制代码
i18next.init({
  fallbackLng: LOCALE.ZH_CN,
  supportedLngs: ['zh-CN', 'en-US'],
  nonExplicitSupportedLngs: false,
  load: 'currentOnly',
})

关键配置说明:

配置 作用
load: 'currentOnly' 只加载当前语言,不加载基础语言
supportedLngs 限定合法语言
nonExplicitSupportedLngs: false 禁止 zh → zh-CN 的反向映射

或者:

2、react中集成:

javascript 复制代码
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './i18n'; // 引入 i18n 配置
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

3、项目中使用:

javascript 复制代码
import React from 'react';
import { useTranslation } from 'react-i18next';

function App() {
  // t 是翻译函数,i18n 是实例(用于切换语言)
  const { t, i18n } = useTranslation();

  // 切换语言的方法
  const changeLanguage = (lng) => {
    i18n.changeLanguage(lng);
  };

  return (
    <div style={{ padding: '20px' }}>
      <h1>{t('welcome')}</h1>
      
      {/* 基础翻译 */}
      <button onClick={() => changeLanguage('zh-CN')}>
        {t('button.switchLang')}(中文)
      </button>
      <button onClick={() => changeLanguage('en')} style={{ marginLeft: '10px' }}>
        {t('button.switchLang')}(English)
      </button>

      {/* 带变量的翻译 */}
      <div style={{ marginTop: '20px' }}>
        {t('user.greet', { name: '张三', age: 25 })}
      </div>
    </div>
  );
}

export default App;

如果翻译文本中需要嵌入 React 元素(如 <b><a>),用 Trans 组件更方便:

javascript 复制代码
import React from 'react';
import { Trans } from 'react-i18next';

function TransComponent() {
  return (
    <div>
      {/* 翻译文本中嵌入加粗标签 */}
      <Trans i18nKey="welcome">
        Welcome to <b>React i18n</b>
      </Trans>

      {/* 带变量的 Trans 组件 */}
      <Trans i18nKey="user.greet" values={{ name: '李四', age: 30 }}>
        Hello, <span>{{name}}</span>! You are <span>{{age}}</span> years old
      </Trans>
    </div>
  );
}

export default TransComponent;

class组件使用HOC:withTranslation

javascript 复制代码
import React from "react";
import { withTranslation } from "react-i18next";

class App extends React.Component {

  render() {
	const { t, i18n } = this.props;  //i18n.changeLanguage("en")
	return (<div className="App">
	  {t("title")}
	</div>);
  }
}

export default withTranslation()(App);
  1. 命名空间(Namespace) :拆分大型项目的翻译文件(如 common.jsonuser.json),使用时指定 ns 参数:

    javascript 复制代码
    const { t } = useTranslation('user'); // 只加载 user 命名空间
    t('name'); // 对应 locales/zh-CN/user.json 中的 name
  2. 动态加载语言 :避免一次性加载所有语言包,i18next-http-backend 已默认支持按需加载;

  3. 自定义语言检测 :比如从 URL 参数(?lng=en)切换语言,插件已默认支持。

  4. 若是在store中的地方使用可以用i18nnext.t("langKey")

三、i18next-http-backend

1、语言包位置:

使用 i18next-http-backend 后,只需要把翻译文本存在独立的 JSON 文件里,插件会自动根据规则发起 HTTP 请求去读取这些文件, 也不用通过resources设置语言了**。**

2、自动适配 i18next 的「语言 / 命名空间」规则,简化加载逻辑

插件内置了一套默认的请求路径规则,会根据你使用的语言(lng)和命名空间(ns)自动拼接请求 URL,无需你手动写请求:

  • 默认规则:/locales/{``{lng}}/{``{ns}}.json
    • 比如调用 useTranslation('user') 且当前语言是 zh-CN,插件会自动请求:/locales/zh-CN/user.json
    • 比如默认命名空间 translation + 语言 en,请求:/locales/en/translation.json

你也可以自定义这个路径规则,适配你的项目结构:

javascript 复制代码
// 在 i18n 初始化时配置 backend
i18n.use(Backend).init({
  backend: {
    // 自定义请求路径(比如把文件放在 /static/lang 下)
    loadPath: '/static/lang/{{lng}}/{{ns}}.json',
    // 其他配置:请求超时、自定义请求头(比如带 token)等
    requestOptions: {
      timeout: 5000, // 请求超时 5 秒
      headers: { 'X-Custom-Header': 'xxx' } // 自定义请求头(对接后端接口时有用)
    }
  }
});
3. 支持「远程加载」(不止本地文件)

这个插件的「HTTP 请求」能力不局限于加载本地静态 JSON 文件,还能加载后端接口返回的翻译文本 ------ 这是它的重要扩展作用。比如你的翻译文本存在服务器数据库里,后端提供接口 https://api.xxx.com/lang/{``{lng}},只需修改 loadPath 即可:

javascript 复制代码
backend: {
  loadPath: 'https://api.xxx.com/lang/{{lng}}', // 从后端接口加载翻译文本
}
4. 内置缓存与错误处理,提升稳定性

插件自带了基础的请求缓存和错误处理逻辑,无需你手动写:

  • 缓存:同一个语言 / 命名空间的文件,不会重复发起请求(减少网络开销);

  • 错误处理:如果请求失败(比如文件不存在),会触发 i18next 的错误回调,你可以自定义兜底逻辑:

    javascript 复制代码
    i18n.init({
      backend: {
        // 请求失败的回调
        readFailed: (error) => {
          console.error('翻译文件加载失败:', error);
        }
      }
    });
5. 「按需加载」:减少首屏体积(最直观的优势)
  • 没有插件时,所有语言包会被打包进前端代码(比如 zh-CN/en/ja 都在代码里),首屏加载体积大;
  • 有插件时,首屏只加载当前语言(比如浏览器默认是中文,只加载 zh-CN/translation.json),切换到英文时才加载 en/translation.json,大幅减少首屏资源体积。

总结:

方式 静态导入(src 目录,无 backend) HTTP 加载(public 目录,用 backend)
加载方式 打包时整合到 JS 包中 运行时 HTTP 请求加载
首屏体积 包含所有语言包,体积较大 只加载当前语言,体积较小
翻译文本修改 需重新打包部署 直接修改 public 文件 / 后端接口即可
TypeScript 支持 天然支持(类型推导、语法提示) 需额外配置类型(JSON 无类型)
适用场景 小型项目、翻译文本少、需类型提示 大型项目、多语言包、需动态更新翻译

四、i18next-browser-languagedetector

核心作用是:在浏览器 / 基于浏览器内核的环境(如 Electron 渲染进程)中,自动检测用户的语言偏好,并将检测结果传给 i18next,实现多语言的自动适配

插件的本质是「多源语言读取器 + 优先级排序器 + 缓存管理器」,工作流程如下:

  1. 读取多维度语言来源:从浏览器 / Electron 环境的不同位置读取语言信息;
  2. 按优先级筛选:按你配置的优先级,从多个来源中选出「最高优先级」的语言;
  3. 缓存(可选):将用户手动切换的语言缓存到本地(如 localStorage);
  4. 注入 i18next:将最终检测到的语言传给 i18next,作为初始化 / 切换的语言。

插件内置了 9 种常见的语言检测源(还有hash),开箱即用,你可通过 order 配置优先级:

检测源 说明 适用场景
querystring 读取 URL 查询参数(如 ?lng=en-US 测试 / 调试、链接跳转传语言
cookie 读取浏览器 Cookie 中的语言值 服务端渲染(SSR)、跨域名共享
localStorage 读取 localStorage 中的语言值 浏览器 / Electron 持久化缓存
sessionStorage 读取 sessionStorage 中的语言值(会话级缓存) 临时语言切换,关闭页面失效
navigator 读取 navigator.language(浏览器 / Electron 系统默认语言) 自动适配系统语言
path 读取 URL 路径(如 /en-US/home 路由级多语言(如 Next.js)
subdomain 读取子域名(如 en.xxx.com 多语言子域名场景
htmlTag 读取 <html lang="zh-CN"> 中的 lang 属性 手动设置 html 语言标签
常用的配置:

插件的所有配置都放在 i18next 初始化的 **detection**字段中

javascript 复制代码
{
  // order and from where user language should be detected
  order: ['querystring', 'hash', 'cookie', 'localStorage', 'sessionStorage', 'navigator', 'htmlTag', 'path', 'subdomain'],

  // keys or params to lookup language from
  lookupQuerystring: 'lng',
  lookupCookie: 'i18next',
  lookupLocalStorage: 'i18nextLng',
  lookupSessionStorage: 'i18nextLng',
  lookupFromPathIndex: 0,
  lookupFromSubdomainIndex: 0,
  lookupHash: 'lng', // #lng=pt or #something&lng=en
  lookupFromHashIndex: 0, // #/de

  // cache user language on
  caches: ['localStorage', 'cookie'],
  excludeCacheFor: ['cimode'], // languages to not persist (cookie, localStorage)

  // optional expiry and domain for set cookie
  cookieMinutes: 10,
  cookieDomain: 'myDomain',

  // optional htmlTag with lang attribute, the default is:
  htmlTag: document.documentElement,

  // optional set cookie options, reference:[MDN Set-Cookie docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie)
  cookieOptions: { path: '/', sameSite: 'strict' },

  // optional conversion function used to modify the detected language code
  convertDetectedLanguage: 'Iso15897',
  convertDetectedLanguage: (lng) => lng.replace('-', '_')
}
javascript 复制代码
// src/i18n/index.ts
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import resources from '@/language'; // 你的静态翻译资源

i18n
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    resources,
    fallbackLng: 'zh-CN',
    debug: !import.meta.env.PROD,
    interpolation: { escapeValue: false },
    // 定制 Electron 下的检测规则
    detection: {
      // 检测优先级:先读缓存(用户手动选的),再读系统语言,最后读 URL(querystring url中的查询参数)
      order: ['localStorage', 'navigator', 'querystring'],
      // 缓存到 localStorage,切换语言时会自动写入
      caches: ['localStorage'],
      // 自定义 localStorage 的 key
      lookupLocalStorage: 'app-locale', //默认的 i18nextLng
      //lookupQuerystring: 'lang',        // 替换默认的 lng(如 ?lang=en-US)
      //lookupCookie: 'app-lang',         // 自定义 Cookie key
      
      // 可选:忽略检测源的大小写(如 En-US → en-US)
      //convertDetectedLanguage: (lng) => lng.toLowerCase(),
    },
    react: { useSuspense: false },
  });

export default i18n;
自定义存储

如electron环境下使用electron-store存储:

javascript 复制代码
// 自定义语言检测器
import Store from 'electron-store';
const store = new Store();

LanguageDetector.addDetector({
  name: 'electron-store',
  lookup: () => store.get('app-locale') || app.getLocale(), // 先读缓存,再读系统语言
  cacheUserLanguage: (lng) => store.set('app-locale', lng), // 缓存用户选择的语言
});

// 然后在 detection.order 中加入 'electron-store'
detection: {
  order: ['electron-store', 'navigator'],
  caches: ['electron-store'], // 缓存到 electron-store
}
自定义适配格式:

i18next-browser-languagedetector 在 Electron 渲染进程中,本质是读取 navigator.language(和浏览器一致),而 Electron 的 navigator.language精准映射你的系统默认语言

  • 当系统语言是「简体中文」(Windows/macOS):navigator.languagezh-CN
  • 当系统语言是「英文」(比如英语 - 美国):navigator.languageen-US

因此插件检测返回的是:zh-CN/en-US,而你的翻译文件假如是:zh_CN/en_US,需提前做格式适配,否则会导致「检测到语言但匹配不到翻译资源」:

javascript 复制代码
// 适配语言格式的示例(初始化 i18n 时)
import { LOCALE } from '@/utils/storage';

// 定义格式转换函数
const normalizeLang = (lng: string) => {
  return lng.replace('-', '_').toUpperCase(); // zh-CN → ZH_CN,en-US → EN_US
};

// 初始化时手动适配检测结果
i18n.use(LanguageDetector).init({
  detection: {
    // 检测后自动适配格式(自定义检测逻辑)
    lookupNavigator: () => {
      const rawLng = navigator.language || 'zh-CN';
      return normalizeLang(rawLng); // 转换为和 LOCALE 一致的格式
    },
    order: ['localStorage', 'navigator'], // 优先读用户缓存,再读系统语言
    caches: ['localStorage'],
  },
  // 其他配置...
});
相关推荐
汐泽学园2 小时前
基于Vue的幼儿绘本阅读启蒙网站设计与实现
前端·javascript·vue.js
mikan2 小时前
详解把老旧的vue2+vue-cli+node-sass项目升级为vite
前端·javascript
七宝三叔2 小时前
C# 上位机开发中的动态绑定与虚拟化
前端
安卓程序员_谢伟光2 小时前
如何监听System.exit(0)的调用栈
java·服务器·前端
爱上妖精的尾巴3 小时前
7-2 WPS JS宏 Object对象属性的查、改、增、删
前端·javascript·vue.js
小哀23 小时前
2025年总结: 我还在往前走
前端·后端·全栈
0思必得03 小时前
[Web自动化] Requests模块基本使用
运维·前端·python·自动化·html·web自动化
change_fate3 小时前
vue模板数组不要直接使用reverse方法
前端·javascript·vue.js
一 乐3 小时前
健康管理|基于springboot + vue健康管理系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·后端·学习