指南 · 进阶
版本基线 i18next v23+。把 i18next 用进真实项目:语言检测插件、HTTP 懒加载、动态注入翻译、
fallbackLng高级形式、load策略、事件系统、自定义格式器。只讲核心引擎与官方插件。
一、语言检测:i18next-browser-languagedetector
浏览器里自动识别用户语言(cookie / localStorage / navigator.language 等):
import i18next from "i18next";
import LanguageDetector from "i18next-browser-languagedetector";
await i18next.use(LanguageDetector).init({
fallbackLng: "en",
detection: {
order: ["cookie", "localStorage", "navigator"], // 检测优先级
caches: ["localStorage"], // 把检测结果缓存到哪
},
});⚠️ 用检测器时不要再硬写
lng——lng会覆盖语言检测。
二、HTTP 懒加载:i18next-http-backend
不把翻译打进 bundle,运行时按需从服务器拉 JSON:
import i18next from "i18next";
import HttpBackend from "i18next-http-backend";
await i18next.use(HttpBackend).init({
fallbackLng: "en",
ns: ["translation", "common"],
backend: {
loadPath: "/locales/{{lng}}/{{ns}}.json", // {{lng}}/{{ns}} 会被替换
},
});loadPath里的{{lng}}、{{ns}}会替换成实际语言与命名空间去请求。- Node 端从文件系统读用
i18next-fs-backend;想用import()动态导入用i18next-resources-to-backend。
内联 resources 与 backend 不互为 fallback
官方明确:直接同时给 resources 和 backend,二者不会自动拿一方当兜底。要链式回退请用 i18next-chained-backend。
三、检测 + 加载 + 回退:组合配置
import i18next from "i18next";
import HttpBackend from "i18next-http-backend";
import LanguageDetector from "i18next-browser-languagedetector";
await i18next
.use(HttpBackend)
.use(LanguageDetector)
.init({
fallbackLng: "en",
supportedLngs: ["en", "de", "fr", "zh"],
ns: ["translation", "common"],
defaultNS: "translation",
fallbackNS: "common",
backend: { loadPath: "/locales/{{lng}}/{{ns}}.json" },
detection: { order: ["localStorage", "navigator"], caches: ["localStorage"] },
});.use() 可链式串联多个插件,最后 .init()。每类插件靠自身 type 字段(backend / languageDetector / postProcessor 等)声明角色。
四、fallbackLng 的高级形式
fallbackLng 支持 string / array / object / function 四种:
// 数组:依次尝试
fallbackLng: ["fr", "en"];
// 对象:按语言定制回退链,default 兜底
fallbackLng: {
"zh-Hant": ["zh-Hans", "en"],
"de-CH": ["fr", "it"],
default: ["en"],
};
// 函数:动态决定回退链
fallbackLng: (code) => (code === "zh-TW" ? ["zh-CN", "en"] : ["en"]);五、load 策略:要不要带地区
await i18next.init({
load: "languageOnly", // 把 en-US 当 en 加载,忽略地区
// load: 'all' // 默认:加载 en-US / en / dev
// load: 'currentOnly'// 只加当前精确码
});load: 'languageOnly' 适合「不想为每个地区单独维护文件」的项目。
六、动态注入翻译
代码分割时,把某模块的翻译运行时合并进来:
i18next.addResourceBundle(
"en", // 语言
"moduleA", // 命名空间
{ title: "Module A" }, // 一批 key
true, // deep:深度合并
true // overwrite:覆盖已有
);
// 单条:
i18next.addResource("en", "moduleA", "subtitle", "Hello");也可用 i18next.loadNamespaces('moduleA') 触发某命名空间的(backend)加载。
七、事件系统
i18next.on("initialized", (options) => {});
i18next.on("loaded", (loaded) => {}); // 资源加载完成
i18next.on("languageChanged", (lng) => {}); // 语言切换完成 → 刷新 UI
i18next.on("missingKey", (lngs, ns, key, res) => {}); // 命中缺失 key
i18next.off("languageChanged", handler); // 取消监听i18next 用
on/off,不是 DOM 的addEventListener。绑定层(如 react-i18next)正是监听languageChanged来自动重渲染。
八、自定义格式器
// 普通:每次调用都跑
i18next.services.formatter.add("uppercase", (value, lng, options) => value.toUpperCase());
// 缓存版:适合 Intl 这类构造开销大的
i18next.services.formatter.addCached("eur", (lng, options) => {
const f = new Intl.NumberFormat(lng, { style: "currency", currency: "EUR", ...options });
return (val) => f.format(val);
});文案里即可写 {{name, uppercase}} / {{price, eur}}。
进入 指南 · 专家:v3→v4 复数迁移、序数复数、skipOnVariables 安全、多实例与 SSR、TypeScript 类型安全、saveMissing 工作流。