一、安装
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);
-
命名空间(Namespace) :拆分大型项目的翻译文件(如
common.json、user.json),使用时指定ns参数:javascriptconst { t } = useTranslation('user'); // 只加载 user 命名空间 t('name'); // 对应 locales/zh-CN/user.json 中的 name -
动态加载语言 :避免一次性加载所有语言包,
i18next-http-backend已默认支持按需加载; -
自定义语言检测 :比如从 URL 参数(
?lng=en)切换语言,插件已默认支持。 -
若是在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 的错误回调,你可以自定义兜底逻辑:
javascripti18n.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,实现多语言的自动适配。
插件的本质是「多源语言读取器 + 优先级排序器 + 缓存管理器」,工作流程如下:
- 读取多维度语言来源:从浏览器 / Electron 环境的不同位置读取语言信息;
- 按优先级筛选:按你配置的优先级,从多个来源中选出「最高优先级」的语言;
- 缓存(可选):将用户手动切换的语言缓存到本地(如 localStorage);
- 注入 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.language→zh-CN; - 当系统语言是「英文」(比如英语 - 美国):
navigator.language→en-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'],
},
// 其他配置...
});