公司动环系统功能越来越强大,但不支持多国语言,国际化提上议事日程。我对公司绝大多数前端项目做了多国语言方案调研并在部门内部做了一次分享,特意记录一下。
背景介绍
公司目前前端框架主要采用 Vue,经过比较充分地调研,我强烈推荐使用 Vue I18n + localStorage+ element-ui 组件 I18n 来作为解决该系统多国语言的解决方案。以下是 Demo 工程 最终效果。
Why Vue I18n
Vue I18n 是 Vue.js 的国际化插件,具有以下的特性:
- 开源,Vue.js 官方推荐;
- Github 6.4K Star;
- 文档丰富;
- 简单:API 简单,使用方便;
- 强大:除了简单的翻译外,还支持复数,数字,日期时间等本地化处理;
- 面向组件,你可以在单文件组件上管理。
Why localStorage
相比 Cookie 等浏览器端本地存储,有以下优势:
- 简单:原生 API 简单
- 友好:安全限制少
具体实现
- 导入 Vue 和 VueI18n ,然后调用 Vue.use(VueI18n);
import Vue from "vue";
import VueI18n from "vue-i18n";
Vue.use(VueI18n);
- 准备翻译的语言环境信息,可使用对象变量的方式,但通常情况下推荐使用全局 lang 配置文件。Demo 工程 目前配置了英文和中文两种语言。
lang/en.js
export default {
app: {
ACTIVITY_NAME: "Name",
ACTIVITY_REGION: "Region",
...
ACTIVITY_TIME: "Time",
TODAY: "Today",
YESTERDAY: "Yesterday",
ADD: "Add",
UPDATE: "Update",
DELETE: "Delete",
RESET: "RESET",
SUBMIT: "Submit",
SUCCEED: " succeed",
UNKNOWN: "Unknown error",
REQUIRED_ERROR: "{0} is required"
}
};
lang/zh-CN.js 源码:
export default {
app: {
ACTIVITY_NAME: "活动名称",
ACTIVITY_REGION: "活动区域",
...
ACTIVITY_TIME: "活动时间",
TODAY: "今天",
YESTERDAY: "昨天",
ONE_WEEK_AGO: "一周前",
ADD: "新增",
UPDATE: "修改",
DELETE: "删除",
RESET: "重置",
SUBMIT: "提交",
REQUIRED_ERROR: "{0}不能为空",
SUCCEED: "成功",
UNKNOWN: "未知错误"
}
};
- 通过选项创建 VueI18n 实例, 并设置 Vue 实例 i18n 选项。
mport i18n from "./i18n";
import App from "./App.vue";
new Vue({
i18n,
render: (h) => h(App)
}).$mount("#app");
- 兼容 UI 库。本项目 UI 库使用了 element-ui,所以国际化的同时也要将其国际化。本系统中已经实现国际化的 element-ui 组件有:Datepicker、Select、Pagination、Messagebox、TableTree。完整代码查 看这里 。element-ui 默认不支持 >= 6.x 的 vue-i18n,需要手动处理。
import zhLocale from "element-ui/lib/locale/lang/zh-CN";
import enLocale from "element-ui/lib/locale/lang/en";
import zhBMS from "./lang/zh-CN";
import enBMS from "./lang/en";
Vue.use(VueI18n);
const DEFAULT_LANG = "zh";
const LOCALE_KEY = "LOCALE";
const messages = {
zh: { ...zhLocale, ...zhBMS },
en: { ...enLocale, ...enBMS }
};
- 模块化
该模块提供了一个 setup()
的方法,给使用者修改当前使用语种的能力。同时,我们在 setup
里还做了三件事:
- 将当前语种存到
localStorage
中,保存用户的使用习惯; - 将给
body
添加语种相关的class
,因为不同语言可能导致排版出现差异,我们需要适配; - 将将当前语种存到 Vue 的全局配置中,以便未来可能的使用;
- 将 $i18n 绑定到
window
,这样方便 JavaScript 模块直接用 $i18n 对象。
点击此处查看完整代码。
使用案例
- Vue 模板中使用 $t,如下实例:
<el-form-item
:label="$t('app.ACTIVITY_REGION')"
:rules="[
{
required: true,
message: $t('app.REQUIRED_ERROR', [$t('app.ACTIVITY_REGION')]),
},
]"
prop="region"
>
- Vue 脚本中使用 this.$t,如下实例:
this.$refs.ruleForm.validate((valid) => {
if (valid) {
this.$confirm(this.$t("app.SUBMIT_FAILED"), {
type: "warning",
})
.then(() => {
this.resetForm();
})
.catch(() => {});
}
});
- JavaScrit 模块中使用全局 $i18n.t,如下实例:
// request.js
function getAction(config) {
...
if(method === 'post') {
const url = config.url.toLocaleLowerCase()
if(/$\/?add/.test(url)){
action = $i18n.t('app.ADD')
}
} else if(method === 'put') {
action = i18n.t('app.UPDATE')
} else if(method === 'delete') {
action = i18n.t('app.DELETE')
}
return action
- 模板使用占位或参数
语言环境信息如下
export default {
app: {
REQUIRED_ERROR: "{0}不能为空"
}
};
模板如下:
<el-form-item
:label="$t('app.ACTIVITY_NAME')"
:rules="[
{
required: true,
message: $t('app.REQUIRED_ERROR', [$t('app.ACTIVITY_NAME')]),
},
]"
prop="name"
class="region-name"
>
- 使用 element-ui 中的语言环境信息
<el-button type="primary" @click="submitForm">
{{ $t("el.colorpicker.confirm") }}
</el-button>
- 配合 v-for 灵活使用
语言环境信息如下:
export default {
app: {
REGION_BG: "北京",
REGION_SH: "上海",
REGION_GZ: "广州",
REGION_SZ: "深圳",
}
}
模板如下:
<el-select v-model="form.region" clearable class="region-select">
<el-option
v-for="item in regionOptions"
:key="item"
:label="$t('app.REGION_' + item)"
:value="item"
/>
</el-select>
- 更多高级用法
复数、日期时间本地化、数字本地化等, 点击此处查看 。
评论 (0)