最近非常惊讶,工作过程中发现很多做国际化项目的同事,居然没有用过任何国际化管理插件...
实在不能容忍大家还停留在"农耕时代",于是特意花时间详细整理了一下过去的笔记,配上大量gif动态图。
以后抓到一个"农民",直接链接贴脸!
应用场景
针对所有需要引入国际化插件的项目,如vue-i18n
国际化后新增的开发难点
1,变量替换文本后,可读性极差
login.loginText 这种规范命名还能勉强猜测到文本内容,但是对于不熟悉的词汇、长提示语等几乎无法猜测,后续定位问题时难度增加
2,翻译文本较难管理
- "登录" 文本 的英文、德语等等版本是否已翻译完成?内容是什么样?
- 我现在需要修改内容,其他N个版本要怎样才能快速修改?
- 如何查看本项目整体翻译状况,翻译进度是怎么样?是否有遗漏?
- 如何自动翻译?
在语种、语言内容逐渐增多时,会越发难以查阅和管理文本的翻译情况。
3,添加新文本时难以查重和管理
- 新的文本是否已经翻译过?
- 如何快速找到已翻译过的
tag和文本?
当语种增多、内容增多、文本模块增多、多人合作时,以上问题会越发严重
推荐使用 i18n Ally 插件,都能解决以上问题。
展示一下最终效果
变量文本可视化
快速添加文本标志
自动检查已有翻译并快捷录入
同时查看和管理所有语言版本
全局管理翻译情况
(以源语言为基础)自动翻译
这里可能需要梯子,否则 google 翻译无法正常运行!
(项目)全局翻译
i18n Ally 插件
All in one i18n extension for VS Code
只需要安装这一个插件,可以看到我的 Vuei18n 插件是没有安装的!
修改 .vscode/settings.json
{
"i18n-ally.localesPaths": ["src/lang"], // 翻译文件项目路径
"i18n-ally.keystyle": "nested", // 翻译路径格式 ( nested:嵌套式 flat:扁平式)
"i18n-ally.sortKeys": true,
"i18n-ally.namespace": true,
"i18n-ally.enabledParsers": ["json"], // 翻译文件可允许的格式,默认json。
"i18n-ally.sourceLanguage": "zh-CN", // 翻译源语言 (源文件)
"i18n-ally.displayLanguage": "zh-CN", // 显示语言 (显示文件/翻译文件)
"i18n-ally.translate.engines": ["deepl", "google"], // 翻译器
"i18n-ally.extract.keygenStyle": "camelCase", // 翻译字段命名样式采用驼峰
"i18n-ally.enabledFrameworks": [
"vue"
],
"workbench.activityBar.visible": true,
}
localesPaths和sourceLanguage,需要根据项目语言文件路径,语言标识情况修改。enabledParsers只推荐json
以一个vue3项目为例
vue-i18n -- 这是一个项目插件,跟vscode 插件无关。
文件结构
注意:最好提前将对应语言的
json文件都创建好,方便后续步骤。
lang/index.ts
import { createI18n, I18nOptions } from 'vue-i18n';
import type { App } from 'vue';
const zhModules = import.meta.glob('./zh/*.json', { eager: true });
const enModules = import.meta.glob('./en/*.json', { eager: true });
const zhObj = getLangByModules(zhModules);
const enObj = getLangByModules(enModules);
const messages = {
...zhObj,
...enObj,
} as I18nOptions['messages'];
/**
* 获取当前系统使用语言字符串
*
* @returns zh|en ...
*/
export const getLanguage = () => {
// 浏览器使用语言
const language = localStorage.getItem('language') || navigator.language;
// const language = 'en';
const locales = Object.keys(messages as any);
for (const locale of locales) {
if (language.indexOf(locale) > -1) {
return locale;
}
}
return 'zh';
};
const i18n = createI18n({
legacy: false,
locale: getLanguage(),
messages: messages,
globalInjection: true,
});
export function setupI18n(app: App<Element>) {
app.use(i18n);
}
export default i18n;
// ---------------- function --------------------------
/**
* 需要保证文件夹内至少有一个json文件,方便获取到文件名
* 注意:当对应文件夹内匹配不到json文件时, 会连整个语言类型都不会注册,即 enObj 为 {} 而不是 { en: {} }
* @returns
*/
function getLangByModules(modules: any) {
const moduleArr = Object.keys(modules);
const langMsgObj = moduleArr.reduce((obj: any, key) => {
const content = (modules[key] as any).default || {};
const langType = key.split('/')[1];
const moduleName = key.split('/')[2].split('.')[0];
if (obj[langType] === undefined) {
obj[langType] = {};
}
obj[langType][moduleName] = content;
return obj;
}, {});
return langMsgObj;
}
使用过程种遇到的坑点总结
坑点1: i18n侧边栏没有出现
情况:如果i18n能正常工作,但是侧边栏没出现,
原因:可能是因为当前版本的侧边栏图标是默认隐藏的
解决方案:右键侧边栏 --- 勾选 i18n 即可
坑点2:批量翻译异常,居然反过来把原本的语言改了
情况:点击批量翻译时,没有看到新的文件被创建,反而是原本的中文被替换成英文了
原因:可能是对应翻译版本的文件没有创建。 比如中译英, zh-CN/form.json 存在,但是 en/form.json 不存在,就会出现这个问题。
解决方案:提前创建好对应语言版本的json文件