国际化
平台的国际化由下面两个库提供支持:
IDE 插件
国际化默认使用的是 JSON 文件,这会导致调试和书写非常困难。利用 VSCode 的 lokalise.i18n-ally
插件可以获得良好的编写体验和类型提示。
项目已添加如下内容到 vscode/settings.json
文件中,你可以修改自定义任何字段:
{
"i18n-ally.localesPaths": "src/locales",
// https://github.com/lokalise/i18n-ally/wiki/Path-Matcher
"i18n-ally.namespace": true,
"i18n-ally.pathMatcher": "{locale}/{namespaces}.json",
"i18n-ally.sourceLanguage": "zh-CN",
"i18n-ally.displayLanguage": "zh-CN",
"i18n-ally.enabledFrameworks": ["react-i18next"],
"i18n-ally.keystyle": "nested"
}
正确配置之后,将会看到如下友好的页面,代码中被翻译的文字,以及侧边栏中构建的翻译字典树:
翻译目录
国际化文件默认存储在 src/locales
文件夹下面,打开之后,将会看到两个文件夹,默认支持中英文两种语言:
- zh-CN(中文)
- en-US(英文)
如果需要新增语言支持,确保文件名是 ISO 639-1 规范里面的,而不是自己随便写。
以英语为例子,这个语言下包含的文件结构如下所示:
├── locales
│ ├── README.md
│ ├── en-US
│ │ ├── access.json # 演示访问权限相关
│ │ ├── authority.json # 权限相关,例如登录页面等
│ │ ├── common.json # 通用字段,例如菜单、按钮文字、信息提示等
│ │ ├── form.json # 表单相关,例如表单字段、校验信息等
│ │ ├── preferences.json # 偏好设置相关,例如主题、字体大小等
│ │ ├── widgets.json # 偏好设置里的控件,例如系统更新等
│ │ ├── ----------- # 以下为页面级别的翻译文件
│ │ ├── system.json # 系统管理页面
│ │ ├── home.json # 首页
│ │ ├── about.json # 关于页面
│ │ └── personal-center.json # 个人中心
如果新建一个路由,只需要新建一个对应的 JSON 文件即可。
根据实践,存放翻译的 JSON 文件最好不超过一层,下面两种都是友好的。
国际化 Key 的规范
本项目翻译文件 JSON 的 key 优先使用嵌套风格,而不是扁平风格,例如:
{
"a": {
"b": {
"c": "..."
}
}
}
当然你也可以随意修改成扁平风格。
如何使用
在 JSX 中使用
import { useTranslation } from "react-i18next";
export default function About() {
const { t } = useTranslation();
return (
<div>
{t("about.aboutProject")}
</div>
);
}
在纯 JS 或 TS 文件中使用
不推荐在纯 JS 或 TS 文件中使用 react-i18next,因为切换语言之后,不会自动改变语言,无论是使用 i18n.t
还是 Trans
。
It does ONLY interpolation. It does not rerender on language change or load any translations needed. Check useTranslation hook or withTranslation HOC for those cases.—— Trans Component
如果需要使用,请使用下面的方式:
直接传递一个 t 函数
import type { TFunction } from "react-i18next";
import { useTranslation } from "react-i18next";
function getMessage(t: TFunction<"translation", undefined>): string {
return t("about.aboutProject");
}
function About() {
const { t } = useTranslation();
return <div>{getMessage(t)}</div>;
}
内容是动态的
// 例如:common.json 文件内容如下:
// {
// "sendText": "{{ second }} 秒后重新获取",
// }
import { useTranslation } from "react-i18next";
export default function Login() {
const { t } = useTranslation();
return (
<div>
{t("common.sendText", { second: 60 })}
</div>
);
}
Trans Component
Trans 组件特别适合自定义 HTML 标签,例如:
// 例如:authority.json 文件内容如下:
// {
// "agree": "我已阅读并同意《<0>隐私政策</0>》和《<1>服务条款</1>》",
// }
import { Trans } from "react-i18next";
export default function Login() {
return (
<Trans
i18nKey="authority.agree"
components={[
<Link key={0} to="/terms-of-service" target="_blank" />,
<Link key={1} to="/privacy-policy" target="_blank" />,
]}
/>
);
}
$t
是干什么的?
/**
* 获取路径字符串
*
* @param path 路径字符串
* @returns 返回传入的路径字符串
*/
export function $t(path: string) {
return path;
}
可以看到 $t
就是简单的返回传入的路径字符串,本函数主要用于 lokalise.i18n-ally
插件提供类型提示。
import { $t } from "#src/locales";
const title = $t("common.menu.about");
// 在 VSCode 中,`$t("common.menu.about")` 渲染为 $t(关于),