i18n ally 是一款轻量且功能强大的可视化编辑插件,提供了增删改查、视图审阅、在线翻译等功能,极大地提高了开发者翻译多语言的效率。
本文分享如何使用该插件、附带其常用配置,并带大家实现简易的 $t()
方法,有需要的可以收藏以便查阅。
项目文件配置
文件格式
文件格式一览表:
格式 | 可读 | 可编辑 | 支持注释 | 说明 |
---|---|---|---|---|
JSON | ✅ | ✅ | ✅ | |
YAML | ✅ | ✅ | ✅ | 注释不会被保留 |
JSON5 | ✅ | ✅ | ❌ | 注释不会被保留 |
INI | ✅ | ✅ | ❌ | 注释不会被保留 |
properties | ✅ | ✅ | ❌ | 注释不会被保留 |
POT | ✅ | ✅ | ❌ | |
JavaScript | ✅ | ❌ | ❌ | 只读 |
TypeScript | ✅ | ❌ | ❌ | 只读 |
PHP | ✅ | ❌ | ❌ | 只读 |
💡请注意,从 v2.0 开始,推荐使用 YAML
和 JSON
格式,其他格式将默认禁用。当然,你也可以手动选择启用的格式:
json
// .vscode/settings.json
{
"i18n-ally.enabledParsers": ["js", "ts", "pot"]
}
属性名样式
i18n 支持嵌套对象(nested)和路径平铺(flat)两种书写格式:
json
{
// 嵌套对象
"user": {
"name": "张三"
},
// 路径平铺
"user.name": "张三"
}
所以,对于 i18n ally 插件而言,同样可以配置 nested
和 flat
两种属性名的风格:
json
// .vscode/settings.json
{
"i18n-ally.keystyle": "nested" // 或 "flat"
}
文件读取路径
不管你用的是 vue-i18n
还是 react-i18next
,项目中都会有一个 locales
或 language
的文件夹,里面存有本地的各种语言,以及一个导出 i18n
的 index
文件,它的结构可能长这样:
json
locales
├─ en.json
├─ zh-CN.json
├─ ja.json
├─ ko.json
├─ ....
└─ index.js
我们启用 i18n ally 时,需要给插件配置该文件夹的路径,让插件读取到多语言文件。
💡请注意,该路径是相对于项目根目录而言的。
json
// .vscode/settings.json
{
"i18n-ally.localesPaths": "src/locales"
}
此时,点击 VSCode 侧边栏的 i18n ally,就能看到对应的多语言以及翻译进度了。
插件功能
显示语言
设置 displayLanguage
可以让 $t('xxx.xxx)
中的引用显示成自己想要的语言
json
// .vscode/settings.json
{
"i18n-ally.displayLanguage": "zh-CN"
}
这样就对开发者很友好了,一目了然,尽收眼底有木有?😝
增删改查
我们可以直接在侧边栏面板中对语言进行编辑操作。
如果想对某一个字段的所有语言进行编辑,可以直接点击"在编辑器中打开"。
这样就可以直接在编辑器中批量修改所有语言,不用在侧边栏中挨个儿点一遍了。
当然,如果想禁用翻译和编辑功能,可以将 i18n-ally.readonly
设置成 false。这样。插件就会进入只读模式。
在线翻译
json
{
// 翻译时的源语言
"i18n-ally.sourceLanguage": "zh-CN",
// 翻译引擎
"i18n-ally.translate.engines": [
"google-cn",
"google",
"deepl"
],
}
sourceLanguage
:设置项目的主语言,也是翻译时的源语言;
translate.engines
:指定翻译服务,默认是 ['google'],当提供多个引擎时,它会尝试从左到右使用,直到一个成功。
接下来便可在侧边栏或编辑器中进行翻译了。
常用配置
总结下常用配置:
配置项 | 说明 | 默认值 |
---|---|---|
enabledParsers | 指定文件格式 | |
localesPaths | 多语言目录的路径(相对于项目的根目录)也支持路径数组 | auto |
keystyle | 多语言文件的属性名风格,可以是嵌套的 nested 或 平铺的 flat |
auto |
sourceLanguage | 项目的主语言,也是翻译时的源语言 | en |
displayLanguage | 注释和模板中显示的语言 | en |
keepFulfilled | 始终保持所有键都用空字符串填充 | false |
enabledFrameworks | 指定要使用的框架。 如果未设置值,扩展将自动检测框架 | auto |
translate.engines | 指定翻译引擎 | |
sortKeys | 保存时,按字母顺序排序(仅对 json 和 yaml 格式有用) | |
namespace | 对于支持命名空间的 i18n 框架。可以启用该项,将语言文件的文件名映射到 i18n 的根目录上。 | false |
readonly | 只读模式,会禁用编辑和翻译功能 | false |
贴份我的常用配置,以供参考:
json
// .vscode/setting.json
{
"i18n-ally.keystyle": "nested", // 对象嵌套或平铺
"i18n-ally.sourceLanguage": "zh-CN", // 翻译时的源语言
"i18n-ally.displayLanguage": "zh-CN", // 注释和树视图中的显示语言
"i18n-ally.translate.engines": [
"google-cn",
"google",
"deepl"
],
"i18n-ally.sortKeys": true, // 字母顺序排序
"i18n-ally.namespace": true, // 开启命名空间
"i18n-ally.keepFulfilled": true, // 始终用空字符串填充所有的键
"i18n-ally.enabledParsers": [ // 指定文件格式
"yaml",
"json"
],
"i18n-ally.enabledFrameworks": [ // 指定框架
"vue"
]
}
在模板外实现简易的 i18n
拿 Vue 举例,在模板外用不了 this.$t()
方法时,我们可以自己实现一个简易的 $t()
方法,让其拥有以下功能:
- 根据传入的路径,自动查找对应的语言;
- 支持具名格式,也就是占位符替换。如需在翻译时传入数据,可以先使用
[xxx]
进行占位。
js
// locale/lang.js
const locales = {
'zh-CN': {
app: {
title: '标题',
userName: '我的名字叫[name]',
},
},
en: {
app: {
title: 'APP Title',
userName: 'My name is [name]',
},
}
}
export default locales;
ts
import locales from '@/locale/lang.js';
import get from 'lodash/get';
class GetLang {
private readonly currLocale: { [key: string]: any };
constructor(private readonly lang = 'en') {
this.currLocale = locales[this.lang];
}
$t(path: string, template?: { [key: string]: any }) {
let value = get(this.currLocale, path);
if (!value) return path;
// 模板字符串替换
if (template) {
Object.keys(template).forEach((t) => {
const regxp = new RegExp(`\\[${t}\\]`);
value = value.replace(regxp, template[t]);
});
}
return value;
}
}
export default new GetLang(window.navigator.language);
我们使用 lodash/get 轻松实现了第一个需求,然后通过正则进行字符串的匹配,实现了模板的替换。
接着,我们在 js 文件中也能直接使用多语言翻译了:
ts
// demo.ts
import getLang from '@/utils/lang'
getLang.$t('app.userName', { name: '鱼翅' });
// output => 我的名字叫鱼翅
国际化多语言标准
多语言的文件名应当遵循国际化语言版本规范。错误的文件名可能导致插件无法正常工作,比如韩语叫 ko
,你要是写成 kr
,就不好使了。在参考资料中也给出了目前的多语言的标准,大家可以参考一下。
常用语言附录
Language string | Description |
---|---|
zh-CN | 中文(简体) |
zh-TW | 中文(繁体) |
en | 英语 |
en-us | 英语(美国) |
ja | 日语 |
ko | 韩语 |
pt | 葡萄牙语 |
th | 泰国语 |