引入vue-i18n
vue-i18n 是一個vue插件,主要作用就是讓項目支持國際化多語言。首先我們引入這個插件:
import Vue from 'vue' import Vue18n from 'vue-i18n' Vue.use(Vuei18n);
vue插件的使用方法,通過全局方法Vue.use()使用插件。
插件通常會為Vue添加全局功能。插件的范圍沒有限制-一般有下面幾種:添加全局方法或者屬性;添加全局資源;指令/過濾器/過渡等;通過全局mixin方法添加一些組件選項;添加Vue實例方法,通過把它們添加到Vue.prototype上實現。
Vue.js的插件應當有一個公開方法install,通過代碼可以更直觀的看出插件提供的功能:
//1 添加全局方法或者屬性 Vue.myGlobalMethod=function(){} //2 添加全局資源 Vue.directive('my-directive',{ bind(el,binding,vnode,oldVnode){} }); //3 注入組件 Vue.mixin({ created(){} }); //4 添加實例發方法 Vue.prototype.$myMethods=function(methodOptions){}
使用vue-i18n
<div id="app">{{$t("message.hello")}}</div> import Vue from 'vue' import VueI18n from 'vue-i18n'
const messages={ en:{message:{hello:'hello world'}}, cn:{message:{hello:'您好世界'}} }; const i18n=new VueI18n({ locale:'en', messages:messages }); new Vue({i18n}).$mount("#app");
//output
<div id="app">hello world</div>
可以看到,我們再實例化Vue的時候,將i18n當作一個options傳了進去。之后我們就可以在vue的組件里使用i18n了,使用方法主要是兩種:
1 在組件的template中,使用$t()方法
2 在組件的script中,使用this.$i18n.$t()
添加locales文件夾
messages是一個包含了多語言的對象,它就像哦我們的字典。可以新建一個locales文件夾,存放作於跟我們語言相關的代碼。目前包含三個文件:index.js en.js cn.js
en.js 和cn.js是我們的語言包,是一個json形式。
index.js
import Vue form 'vue' import VueI18n from 'vue-i18n' import EN from './en.js' import CN from './cn.js'
const DEFAULT_LANG='cn'; const LOCALE_KEY='localeLanguage'; const locales={ en:EN, cn:CN }; const i18n=new VueI18n({ locale:DEFAULT_LANG, messages:locales });
export const setup=(lang)=>{ if(lang==undefiend){ lang=window.getStorage(LOCALE_KEY) if(locales[lang]==undefined){lang=DEFAULT_LANG} } window.localstorage.setItem(LOCALE_KEY,lang); Object.keys(locales).forEach(function(lang){ document.body.classList.remove(`lang-${lang}`); }); document.body.classList.add(`lang-${lang}`); document.body.setAttribute('lang',lang); i18n.locale=lange; Vue.config.lang=lang; } setup(); export default I18n;
我們對外提供一個setup的方法,給使用者修改當前使用語種的能力。同時,我們在setup里還做了三件事:
將當前語種存在localStorage中,保存用戶的使用習慣;給body添加語種相關的class,因為不同語言可能導致排版出現差異,我們還需要配置,將當前語種存在
Vue的全局配置中,以便未來可能的使用。
最后在main.js中引入這個index.js就可以了
import Vue from ‘vue’ import App from './app.vue' import router from './router' import store from './store' ... import i18n from '@/locales' new Vue({router,store,i18n,render:h=>h(App)}).$mount('#app');
vue實例外的js代碼中的額文本怎么替換?
vue實例中我們可以使用this.$i18n.t,這里的this是vue的實例,那項目中的很多js代碼在vue的實例之外。最簡單的方法就是咋需要
使用的地方手動直接import i18n
這樣在vue實例中使用this.$i18n.t,如果不是就先import ,使用i18n.t,這樣顯然復雜了。
為了解決這個問題,最直接的辦法就是把i18n直接掛載在window下,變成全局變量。我們就不需要import了,直接使用i18n.t就可以了;
在main.js:
import Vue from 'vue' import App from './app.vue' import store from './store' import router from './router' ... import i18n from '@crm/locales' ... window.i18n = i18n new Vue({ i18n, router, store, render: h => h(App), }).$mount('#app')
然而我們將組件中的import i18n全去掉,並將this.$i18n.t改成i18n.t.項目跑起來之后就報錯了:i18n is not defined
顯然是組件在調用i18n的時候,i18n還沒有掛載到window上,所以執行順序出了問題:
//假設webpack的入口文件是```main.js``` //main.js import moduleA from 'moduleA' console.log(1) import moduleB from 'moduleB' console.log(2) //moduleA.js console.log(3) //moduleB.js console.log(4) //最終在瀏覽器中打印出的數字順序是: 3 4 1 2
跟ES6 module的機制有關系。import命令具有提升效果,會提升到整個模塊的頭部,首先執行,這種行為的本質是,import命令是編譯階段執行的,在代碼運行之前。
這樣我們就找到之前報錯的原因了,我們先import app router這些視圖,然后import i18n並掛載在window,所有組件的script中的代碼都先執行,而此時i18n掛載到
window的代碼還沒有執行。import中的script代碼執行完之后才到main.js中其他的js代碼,我們首先將window.i18n=i18n移到locales/index中,然后調整main.js中的import的順序:
//locales/index ... setup() window.i18n = i18n export default i18n //main.js import Vue from 'vue' import i18n from '@crm/locales' import App from './app.vue' import store from './store' import router from './router' ...
參考:https://segmentfault.com/a/1190000015008808