第 3 章:多语言国际化(i18n)系统 —— 支持中 / 日 / 英 / 韩四语言并结构化管理
在企业级管理后台或 SaaS 产品中,多语言国际化(i18n)是必须的能力。本章将带你从零构建一个:
-
支持 中、日、英、韩 四语言
-
每种语言独立文件
-
页面级、组件级随时取词
-
自动语言探测(浏览器语言、localStorage)
-
动态切换语言(UI 切换器)
-
完整的 i18next + react-i18next 体系
完成本章后,你将拥有一个正式工程可复用的国际化系统。
3.1 为什么选择 i18next?
enterprise 场景中,i18next 是最成熟的方案,关键优势:
| 特性 | 说明 |
|---|---|
| 自动语言检测 | 自动识别浏览器语言、cookie、localStorage |
| 动态切换语言 | 不刷新页面 |
| 支持复数、日期、多命名空间 | 专业级国际化 |
| react-i18next 针对 React 优化 | hooks 友好 |
相比于简单 JSON 实现,i18next 更适合工程实践。
3.2 安装依赖(上一章已经安装)
如果你已按照前序章节执行,以下依赖已经安装过:
pnpm add react-i18next i18next i18next-browser-languagedetector
如未安装,可执行上述命令。
3.3 目录结构设计(重要)
在 src 下建立 i18n 目录:
src/
└── i18n/
├── index.ts
└── locales/
├── en.ts
├── zh.ts
├── ja.ts
└── ko.ts
每种语言一个文件,便于多人协作与后期 CI 语言缺失检测。
3.4 语言文件内容示例(完整可复制)
3.4.1 en.ts
export default {
common: {
language: "Language",
theme: "Theme",
confirm: "Confirm",
cancel: "Cancel",
submit: "Submit",
},
login: {
title: "Login",
username: "Username",
password: "Password",
button: "Sign In",
},
dashboard: {
title: "Dashboard",
welcome: "Welcome, {{name}}!",
},
errors: {
404: "Page not found",
500: "Server error",
unauthorized: "You do not have permission",
}
};
3.4.2 zh.ts
export default {
common: {
language: "语言",
theme: "主题",
confirm: "确定",
cancel: "取消",
submit: "提交",
},
login: {
title: "登录",
username: "用户名",
password: "密码",
button: "登录",
},
dashboard: {
title: "仪表盘",
welcome: "欢迎你,{{name}}!",
},
errors: {
404: "页面不存在",
500: "服务器错误",
unauthorized: "无权限访问",
}
};
3.4.3 ja.ts
export default {
common: {
language: "言語",
theme: "テーマ",
confirm: "確認",
cancel: "キャンセル",
submit: "送信",
},
login: {
title: "ログイン",
username: "ユーザー名",
password: "パスワード",
button: "ログイン",
},
dashboard: {
title: "ダッシュボード",
welcome: "{{name}} さん、ようこそ!",
},
errors: {
404: "ページが見つかりません",
500: "サーバーエラー",
unauthorized: "アクセス権限がありません",
}
};
3.4.4 ko.ts
export default {
common: {
language: "언어",
theme: "테마",
confirm: "확인",
cancel: "취소",
submit: "제출",
},
login: {
title: "로그인",
username: "아이디",
password: "비밀번호",
button: "로그인",
},
dashboard: {
title: "대시보드",
welcome: "{{name}}님 환영합니다!",
},
errors: {
404: "페이지를 찾을 수 없습니다",
500: "서버 오류",
unauthorized: "접근 권한이 없습니다",
}
};
3.5 初始化 i18next(工程级配置)
在 src/i18n/index.ts:
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import en from "./locales/en";
import zh from "./locales/zh";
import ja from "./locales/ja";
import ko from "./locales/ko";
i18n
.use(LanguageDetector)
.use(initReactI18next)
.init({
resources: {
en: { translation: en },
zh: { translation: zh },
ja: { translation: ja },
ko: { translation: ko },
},
fallbackLng: "zh",
interpolation: {
escapeValue: false,
},
detection: {
order: ["localStorage", "navigator"],
caches: ["localStorage"],
},
});
export default i18n;
语言探测顺序:
-
localStorage 中是否有用户选择的语言
-
浏览器语言
-
fallback:中文
3.6 在 main.tsx 中加载 i18n
import './i18n';
务必在应用渲染之前执行。
3.7 创建语言切换组件(LanguageSwitcher)
src/components/LanguageSwitcher.tsx:
import { useTranslation } from "react-i18next";
const languages = [
{ value: "en", label: "English" },
{ value: "zh", label: "中文" },
{ value: "ja", label: "日本語" },
{ value: "ko", label: "한국어" },
];
export const LanguageSwitcher = () => {
const { i18n } = useTranslation();
return (
<select
className="border px-2 py-1 rounded-md"
value={i18n.language}
onChange={(e) => i18n.changeLanguage(e.target.value)}
>
{languages.map((l) => (
<option key={l.value} value={l.value}>
{l.label}
</option>
))}
</select>
);
};
3.8 在 App 中测试 i18n
src/App.tsx:
import { Button } from "@/components/ui/button"
import { useTranslation } from "react-i18next";
import { LanguageSwitcher } from "./components/LanguageSwitcher";
function App() {
const { t } = useTranslation();
return (
<>
<div className="flex min-h-screen flex-col items-center justify-center p-4 space-x-3 gap-4">
<div>App Initialized</div>
<Button>默认按钮</Button>
<Button size="sm">小</Button>
<Button size="lg">大</Button>
<Button variant="outline">描边按钮</Button>
<LanguageSwitcher />
<h1 className="text-2xl font-bold">{t('dashboard.title')}</h1>
<p>{t('dashboard.welcome', { name: '龙傲天' })}</p>
<div>{t('common.language')}</div>
</div>
</>
)
}
export default App
运行:
pnpm dev
你可以在下拉中切换四种语言。



3.9 语言持久化(localStorage)
i18next-browser-languagedetector 自动处理:
localStorage.setItem("i18nextLng", "zh")
用户下次进入仍保持中文。
3.10 将 i18n 注入 UI 组件体系
在任意组件使用:
const { t } = useTranslation();
例如:
<Button>{t('common.submit')}</Button>
即可获得多语言按钮。
3.11 常见问题(高级工程经验)
1)为什么不用 JSON?
JSON 不支持注释,不利于多人协作。
2)是否要拆分语言文件?
大型项目可按模块拆分,本教程保持单文件便于学习。
3)为什么暂时不使用命名空间?
命名空间适用于超大型项目,会在高级章节介绍。
3.12 安装与配置 i18n Ally(VS Code 强力推荐)
为了提升多语言开发效率,我们推荐安装 VS Code 上的国际化辅助插件 i18n Ally。
它可以在编码过程中做到:
✔ 自动识别 i18next 词条
✔ 在代码中即时预览翻译内容
✔ 快速跳转到语言文件
✔ 检测缺失翻译(Missing Keys)
✔ 支持 TypeScript 语言包、支持多语言目录结构
在大型项目中非常重要。
① 安装插件
打开 VS Code → Extensions → 搜索:
i18n Ally
选择 i18n Ally(publisher:Lokalise) → 点击安装。

② 配置 .vscode/settings.json
在项目根目录创建或修改 .vscode/settings.json:
官方配置说明:
https://github.com/lokalise/i18n-ally/wiki/Configurations
{
// 指定语言文件目录
"i18n-ally.localesPaths": ["src/i18n/locales"],
// 明确告诉插件启用 i18next 规则
"i18n-ally.enabledFrameworks": ["react", "i18next"],
// 键风格:嵌套式
"i18n-ally.keystyle": "nested",
// 源语言(你的 i18n fallback)
"i18n-ally.sourceLanguage": "en",
// VS Code 翻译面板显示中文
"i18n-ally.displayLanguage": "zh",
// 支持 TS 文件作为语言资源
"i18n-ally.enabledParsers": ["ts"],
}
解释如下:
| 配置项 | 作用 |
|---|---|
localesPaths | 语言包目录(指向我们刚构建的 src/i18n/locales) |
enabledFrameworks | 使用 i18next 框架 |
keystyle: nested | 将 dashboard.title 识别为嵌套词条 |
sourceLanguage | 默认源语言为英文 |
displayLanguage | 控制插件 UI 的显示语言 |
enabledParsers | 告诉 i18n Ally 我们语言包是 TypeScript 文件 |
⚠️ 注意
i18n Ally 默认只识别 JSON,需要enabledParsers才能识别我们使用的.ts语言文件格式。
③ 使用方式展示(开发体验提升巨大)
✓ 在代码中悬停鼠标
t("dashboard.title")
悬停 → 自动显示四语言的实际翻译。

✓ 快速跳转到语言来源
悬停 → 点击 "Go to definition" 或者 按住ctrl + 鼠标左键点击

直接进入对应语言文件(如 zh.ts)。

✓ 自动检测缺失翻译(蓝色波浪线)
如果你写了:
t("dashboard.aaa")

但 zh/en/ja/ko 没有该词条,
插件会自动给你标蓝色波浪线。
你也可以自己配置主题颜色
"i18n-ally.theme.annotation": "rgba(153, 153, 153, .8)"
"i18n-ally.theme.annotationBorder": "rgba(153, 153, 153, .8)",
"i18n-ally.theme.annotationMissing": "#d37070",
"i18n-ally.theme.annotationMissingBorder": "#d37070",
✓ 自动从 TS 文件读写词条
因为我们配置了:
"i18n-ally.enabledParsers": ["ts"],
插件可以正常读写 .ts 多语言文件,而不是仅限 JSON。
④ 多语言自动翻译(可选)
https://github.com/lokalise/i18n-ally/wiki/Machine-Translation
i18n Ally 支持自动调用 DeepL / Google 翻译:
但需要配置 API key。
"i18n-ally.translate.apiKey": "YOUR_KEY"
如果不配置,也不影响使用。
3.13 本章小结
本章完成:
✔ 完整 i18n 目录结构
✔ 四种语言独立文件
✔ i18next 自动探测 + 持久化
✔ UI 语言切换器
✔ 页面级多语言演示
✔ 工程化的国际化体系

269

被折叠的 条评论
为什么被折叠?



