在给Vue项目添加i18n支持(一)中我们介绍了如何给Vue项目添加国际化支持,但是在真实的项目中,将所有翻译写在一个文件中通常会带来一些问题,比如容易引起代码冲突,也不方便维护。
我们期望的i18n配置大概长这样,
| 12
 3
 4
 5
 6
 7
 8
 
 | |--src/|  |--locales/
 |  |  |--index.js
 |  |  |--app.js
 |  |  |--common.js
 |  |  |--module/
 |  |  |  |--sys-user.js
 |  |  |  |--sys-role.js
 
 | 
app.js用来存放与整个应用相关的一些翻译,比如应用标题,slogan等等。
common.js用来存放公共翻译。
module下则是各个模块单独的翻译。
各个模块的翻译配置可能是多层级的,例如公共翻译:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | export default {dialog: {
 delete: {
 title: { en: "Delete", zhcn: "删除" },
 message: {
 en: "Deleted items cannot be retrieved, do you want to continue?",
 zhcn: "删除的条目将无法找回,是否继续?"
 },
 yes: { en: "Delete", zhcn: "删除" },
 no: { en: "Cancel", zhcn: "取消" }
 }
 }
 };
 
 | 
接下来我们来实现它。
locales
locales目录下用来存放所有翻译配置,它最终导出的数据应该是这样:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | {_: {
 dialog: {
 delete: {
 message: { en: "", zhcn: ""}
 }
 }
 },
 app: {
 name: { en: "", zhcn: "" }
 },
 user: {
 username: { en: "", zhcn: "" }
 }
 }
 
 | 
像这个示例中的一样。
.env
在.env中定义语言列表
vue-i18n
我们需要在引入vue-i18n的地方将上面的数据结构进行转换,转换的结果符合vue-i18n的预期。
i18n.js
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 
 | import Vue from "vue";import VueI18n from "vue-i18n";
 import i18nConf from "@/locales";
 
 Vue.use(VueI18n);
 
 const langs = process.env.VUE_APP_LANGS.split(",");
 
 function load(conf, lang, result) {
 for (let k in conf) {
 if (
 langs.every(item => Object.prototype.hasOwnProperty.call(conf[k], item))
 ) {
 result[k] = conf[k][lang];
 } else {
 result[k] = {};
 load(conf[k], lang, result[k]);
 }
 }
 }
 
 function loadLocaleMessages() {
 const messages = {};
 langs.forEach(lang => {
 messages[lang] = {};
 load(i18nConf, lang, messages[lang]);
 });
 return messages;
 }
 
 export default new VueI18n({
 locale: process.env.VUE_APP_I18N_LOCALE || "en",
 fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || "en",
 messages: loadLocaleMessages()
 });
 
 | 
main.js
引入就好了
| 12
 3
 4
 5
 6
 7
 8
 
 | import i18n from "./i18n";
 new Vue({
 router,
 store,
 i18n,
 render: h => h(App)
 }).$mount("#app");
 
 |