在Vue.js
項目中舷蟀,vue-i18n
是一個比較流行的多語言方案固蛾。常規(guī)用法是在項目入口文件里氏淑,將它作為插件引入届宠,然后在 .vue
文件或者組件模板里按照 API 來調用就行。插件會自動往組件實例中注入$t
方法鹏倘。
const messages = {
en: {
message: {
hello: 'hello world'
}
},
cn: {
message: {
hello: '你好世界'
}
}
}
// Create VueI18n instance with options
const i18n = new VueI18n({
locale: 'cn', // set locale
messages, // set locale messages
})
new Vue({ i18n }).$mount('#app')
//App.vue
<div id="app">
<p>{{ $t("message.hello") }}</p>
</div>
問題來了,如果不在組件模板里怎么辦?比如一些工具函數(shù)旋圆,請求攔截器等跟視圖無關的JS代碼中如何使用呢?官方文檔里貌似沒有直接的API麸恍。摸索了一段時間終于解決灵巧,在此記錄下。
import VueI18n from 'vue-i18n';
const messages = {
en: {
message: {
hello: 'hello world'
}
},
cn: {
message: {
hello: '你好世界'
}
}
}
const i18n = new VueI18n({
locale: 'cn', // set locale
messages: messages , // set locale messages
});
console.log(i18n.tc('message.hello')) // 你好世界
搭配 VS Code 插件
隨著項目規(guī)模的擴大抹沪,文本標簽會越來越多刻肄,手動維護非常麻煩。同時融欧,模板里用a.b.c
這樣的屬性字符串來引用文本敏弃,在源碼層面非常不易閱讀。這些問題噪馏,都應該由工具來解決麦到。之前想過自己開發(fā)一個 VS Code 插件來解決這些問題,沒想到早就有人做好了欠肾。開源社區(qū)就是這么強大瓶颠,你能想到的,早就有人做了刺桃。這個插件就叫 Vue i18n粹淋。
早期版本不怎么好用,本人還提過 PR 修過缺陷÷采觯現(xiàn)在比較完善了廓啊,功能齊全,操作便捷封豪∏绰郑可以選中文本一鍵生成中英文,鍵名默認是組件路徑加隨機串吹埠,省去了命名的煩惱第步。還能在編輯器里直接看到對應的中文疮装,鼠標懸浮顯示英文≌扯迹總之比較方便廓推,推薦使用。
前面介紹了vue-i18n
在 Vue 組件外部使用的方法翩隧,但是對于這個 VS Code 插件有點小問題要解決樊展。插件是根據(jù)源碼的字符串來匹配,然后在編輯器顯示出對應的文本堆生。因此专缠,源碼里一定要有 $t('xxx)
字樣才行。
改成這樣就能顯示出來了:
看起來沒問題淑仆,但實際上運行會報錯:
這是為什么呢涝婉?點擊錯誤信息的調用棧進去看源碼,發(fā)現(xiàn)原來i18n.tc
這個方法是綁定到this
(運行時指向VueI18n
對象)上去執(zhí)行的蔗怠,而這里的代碼執(zhí)行的時候并沒有this
墩弯,所以是undefined
。
VueI18n.prototype.tc = function tc (key, choice) {
var ref;
var values = [], len = arguments.length - 2;
while ( len-- > 0 ) values[ len ] = arguments[ len + 2 ];
return (ref = this)._tc.apply(ref, [ key, this.locale, this._getMessages(), null, choice ].concat( values ))
};
所以寞射,這里不能直接拿來調用渔工,需要改變執(zhí)行上下文。重新封裝下這個方法:
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import i18nLabels from '@/i18n';
Vue.use(VueI18n);
export const i18n = new VueI18n({
locale: 'zh', // set locale
messages: i18nLabels, // set locale messages
});
// 重新封裝方法
export function $t(args) {
return i18n.tc.call(i18n, args);
}
使用的時候導入這個方法就行了桥温。