國(guó)際化完全指南:多語(yǔ)言配置、vue-i18n 兼容與源碼級(jí)原理解析)
Element UIVue 2.x國(guó)際化完全指南多語(yǔ)言配置、vue-i18n 兼容與源碼級(jí)原理解析【免費(fèi)下載鏈接】elementA Vue.js 2.0 UI Toolkit for Web項(xiàng)目地址: https://gitcode.com/gh_mirrors/eleme/elementElement 組件庫(kù)默認(rèn)內(nèi)置簡(jiǎn)體中文但在國(guó)際化產(chǎn)品中你需要將其切換為英文、日文、法文等數(shù)十種語(yǔ)言并與vue-i18n深度整合以支持運(yùn)行時(shí)語(yǔ)言切換。本文以官方 i18n 文檔為主線完整覆蓋 Element 多語(yǔ)言配置的三種引入方式、vue-i18n5.x與6.x的兼容方案、CDN 加載語(yǔ)言包等全部實(shí)戰(zhàn)步驟并結(jié)合本倉(cāng)庫(kù) locale 模塊源碼 剖析use/t/i18n三個(gè)核心 API 的底層實(shí)現(xiàn)幫助你徹底理解 Element 的國(guó)際化機(jī)制并能夠自行定制、擴(kuò)展語(yǔ)言包。一、Element 國(guó)際化機(jī)制總覽Element 的組件文案如分頁(yè)器、日期選擇器、消息彈框的按鈕文字統(tǒng)一通過(guò)一套語(yǔ)言包locale管理。語(yǔ)言包的默認(rèn)文件為 src/locale/lang/zh-CN.js其結(jié)構(gòu)是el命名空間下按組件分組的鍵值對(duì)象例如export default { el: { pagination: { goto: 前往, pagesize: 條/頁(yè), total: 共 {total} 條, pageClassifier: 頁(yè) }, // colorpicker / datepicker / select / cascader / ... 每個(gè)組件一組 } }組件內(nèi)部并不直接書(shū)寫(xiě)文案而是通過(guò) src/mixins/locale.js 混入的t方法讀取當(dāng)前語(yǔ)言包import { t } from element-ui/src/locale; export default { methods: { t(...args) { return t.apply(this, args); } } };最終所有文案的查詢、解析與切換都匯聚到 src/locale/index.js 這一核心模塊。它對(duì)外暴露三個(gè) APIAPI作用對(duì)應(yīng)源碼use(lang)切換當(dāng)前語(yǔ)言包src/locale/index.js#L40-L42t(path, options)按點(diǎn)路徑取文案支持{name}占位符插值src/locale/index.js#L23-L38i18n(fn)注入自定義翻譯處理器對(duì)接 vue-i18n 等src/locale/index.js#L44-L46其中t的查找邏輯是先用自定義的i18nHandler嘗試翻譯若返回空則回退到內(nèi)置語(yǔ)言包按路徑逐級(jí)取值最后調(diào)用 src/locale/format.js 中的模板函數(shù)完成{total}、{checked}等占位符替換。format內(nèi)部使用正則/(%|)\{([0-9a-zA-Z_])\}/g匹配占位符并從參數(shù)對(duì)象中取值替換參見(jiàn) src/locale/format.js#L3-L43。二、基本用法為 Element 設(shè)置語(yǔ)言Element 組件內(nèi)部默認(rèn)使用中文若希望使用其他語(yǔ)言則需要進(jìn)行多語(yǔ)言設(shè)置。以英文為例在main.js中2.1 完整引入 Element// 完整引入 Element import Vue from vue import ElementUI from element-ui import locale from element-ui/lib/locale/lang/en Vue.use(ElementUI, { locale })Vue.use(ElementUI, opts)時(shí)opts.locale會(huì)被傳入插件的install函數(shù)進(jìn)而調(diào)用locale.use(opts.locale)完成語(yǔ)言包切換該調(diào)用鏈在 src/index.js#L183-L185 中有明確體現(xiàn)const install function(Vue, opts {}) { locale.use(opts.locale); locale.i18n(opts.i18n); // ... 注冊(cè)所有組件 };2.2 按需引入 Element// 按需引入 Element import Vue from vue import { Button, Select } from element-ui import lang from element-ui/lib/locale/lang/en import locale from element-ui/lib/locale // 設(shè)置語(yǔ)言 locale.use(lang) // 引入組件 Vue.component(Button.name, Button) Vue.component(Select.name, Select)注意這里的element-ui/lib/locale即構(gòu)建產(chǎn)物中的 locale 模塊其默認(rèn)導(dǎo)出對(duì)象包含use、t、i18n三個(gè)方法對(duì)應(yīng) src/locale/index.js#L48 的export default { use, t, i18n }所以可以在按需注冊(cè)組件前手動(dòng)調(diào)用locale.use(lang)完成切換。三、用 webpack 替換默認(rèn)語(yǔ)言包NormalModuleReplacementPlugin如果使用其它語(yǔ)言默認(rèn)情況下中文語(yǔ)言包依舊是被引入的。這是因?yàn)?locale 模塊在源碼層面直接import defaultLang from element-ui/src/locale/lang/zh-CN見(jiàn) src/locale/index.js#L1構(gòu)建產(chǎn)物同樣保留了這一默認(rèn)依賴。你可以使用 webpack 的NormalModuleReplacementPlugin把默認(rèn)語(yǔ)言包直接替換為目標(biāo)語(yǔ)言從而避免多打包一份中文包webpack.config.js{ plugins: [ new webpack.NormalModuleReplacementPlugin(/element-ui[\/\\]lib[\/\\]locale[\/\\]lang[\/\\]zh-CN/, element-ui/lib/locale/lang/en) ] }該正則同時(shí)匹配/與\兩種路徑分隔符兼容 Windows 與 Linux/macOS 下的打包環(huán)境。替換后整個(gè)構(gòu)建產(chǎn)物將不再攜帶中文語(yǔ)言包包體積更小。四、兼容vue-i18n5.xElement 兼容vue-i18n5.x搭配使用能更方便地實(shí)現(xiàn)多語(yǔ)言切換——切換應(yīng)用語(yǔ)言時(shí)Element 組件文案會(huì)跟隨vue-i18n同步變化import Vue from vue import VueI18n from vue-i18n import Element from element-ui import enLocale from element-ui/lib/locale/lang/en import zhLocale from element-ui/lib/locale/lang/zh-CN Vue.use(VueI18n) Vue.use(Element) Vue.config.lang zh-cn Vue.locale(zh-cn, zhLocale) Vue.locale(en, enLocale)這種兼容能力來(lái)自 src/locale/index.js#L9-L21 的i18nHandler默認(rèn)實(shí)現(xiàn)它會(huì)探測(cè)原型上的$t方法以及Vue.locale若檢測(cè)到 5.x 的vue-i18n環(huán)境則首次使用時(shí)通過(guò)deepmerge把 Element 語(yǔ)言包與 vue-i18n 的 messages 深度合并Vue.locale(Vue.config.lang, deepmerge(lang, Vue.locale(Vue.config.lang) || {}, { clone: true }))隨后委托$t進(jìn)行翻譯從而讓兩套文案共用同一個(gè)翻譯管線。五、兼容其他 i18n 插件如果不使用vue-i18n5.x而是用其他的 i18n 插件Element 將無(wú)法自動(dòng)兼容但是可以自定義 Element 的 i18n 處理方法——通過(guò)i18n選項(xiàng)注入你自己的翻譯函數(shù)import Vue from vue import Element from element-ui import enLocale from element-ui/lib/locale/lang/en import zhLocale from element-ui/lib/locale/lang/zh-CN Vue.use(Element, { i18n: function (path, options) { // path 形如 el.datepicker.todayoptions 為插值參數(shù)對(duì)象 // 在這里調(diào)用你自定義 i18n 插件的翻譯方法并返回結(jié)果 } })傳入的i18n函數(shù)會(huì)通過(guò)locale.i18n(opts.i18n)src/index.js#L185覆蓋默認(rèn)的i18nHandler對(duì)應(yīng) src/locale/index.js#L44-L46此后每次組件調(diào)用t都會(huì)優(yōu)先進(jìn)入你的翻譯函數(shù)。若你的函數(shù)返回null或undefinedt會(huì)回退到內(nèi)置語(yǔ)言包繼續(xù)查找src/locale/index.js#L23-L26這一設(shè)計(jì)保證了自定義翻譯與內(nèi)置語(yǔ)言的平滑共存。六、兼容vue-i18n6.x默認(rèn)不支持 6.x 的vue-i18n6.x 移除了Vue.locale全局 API改為實(shí)例化VueI18n你需要手動(dòng)處理——把 Element 語(yǔ)言包展開(kāi)合并進(jìn)VueI18n的messages再把實(shí)例的t方法注入給 Elementimport Vue from vue import Element from element-ui import VueI18n from vue-i18n import enLocale from element-ui/lib/locale/lang/en import zhLocale from element-ui/lib/locale/lang/zh-CN Vue.use(VueI18n) const messages { en: { message: hello, ...enLocale // 或者用 Object.assign({ message: hello }, enLocale) }, zh: { message: 你好, ...zhLocale // 或者用 Object.assign({ message: 你好 }, zhLocale) } } // Create VueI18n instance with options const i18n new VueI18n({ locale: en, // set locale messages, // set locale messages }) Vue.use(Element, { i18n: (key, value) i18n.t(key, value) }) new Vue({ i18n }).$mount(#app)要點(diǎn)說(shuō)明...enLocale與Object.assign兩種寫(xiě)法等價(jià)Element 語(yǔ)言包本身就是{ el: { ... } }結(jié)構(gòu)的普通對(duì)象可以直接展開(kāi)進(jìn) messages通過(guò)i18n: (key, value) i18n.t(key, value)把VueI18n實(shí)例的t包裝后注入 Element組件文案便與VueI18n實(shí)例的locale狀態(tài)完全聯(lián)動(dòng)new Vue({ i18n })將實(shí)例掛載到根組件運(yùn)行時(shí)切換i18n.locale即可全局切換語(yǔ)言。七、按需加載里定制 i18n按需引入組件時(shí)同樣可以接入vue-i18n6.x區(qū)別在于不能通過(guò)Vue.use(Element, ...)傳參而要直接調(diào)用 locale 模塊的i18n方法import Vue from vue import DatePicker from element/lib/date-picker import VueI18n from vue-i18n import enLocale from element-ui/lib/locale/lang/en import zhLocale from element-ui/lib/locale/lang/zh-CN import ElementLocale from element-ui/lib/locale Vue.use(VueI18n) Vue.use(DatePicker) const messages { en: { message: hello, ...enLocale }, zh: { message: 你好, ...zhLocale } } // Create VueI18n instance with options const i18n new VueI18n({ locale: en, // set locale messages, // set locale messages }) ElementLocale.i18n((key, value) i18n.t(key, value))這里的ElementLocale.i18n(...)與完整引入時(shí)Vue.use(Element, { i18n })內(nèi)部執(zhí)行的locale.i18n(opts.i18n)src/index.js#L185是同一個(gè)入口因此按需引入時(shí)只要手動(dòng)調(diào)用一次即可讓已注冊(cè)組件的t走自定義翻譯。八、通過(guò) CDN 的方式加載語(yǔ)言文件在非模塊化直接script標(biāo)簽場(chǎng)景下Element 提供 UMD 格式的語(yǔ)言包文件通過(guò)全局變量ELEMENT操作script src//unpkg.com/vue2/script script src//unpkg.com/element-ui/script script src//unpkg.com/element-ui/lib/umd/locale/en.js/script script ELEMENT.locale(ELEMENT.lang.en) /script搭配vue-i18n使用此時(shí)用的是vue-i18n的全局版本與Vue.localeAPI即 5.x 風(fēng)格的全局注冊(cè)方式script src//unpkg.com/vue2/script script src//unpkg.com/vue-i18n/dist/vue-i18n.js/script script src//unpkg.com/element-ui/script script src//unpkg.com/element-ui/lib/umd/locale/zh-CN.js/script script src//unpkg.com/element-ui/lib/umd/locale/en.js/script script Vue.locale(en, ELEMENT.lang.en) Vue.locale(zh-cn, ELEMENT.lang.zhCN) /script注意 UMD 語(yǔ)言包掛載到全局后ELEMENT.lang.zhCN對(duì)應(yīng)中文語(yǔ)言包、ELEMENT.lang.en對(duì)應(yīng)英文語(yǔ)言包而ELEMENT.locale(...)等價(jià)于源碼中的locale.use(...)方法src/index.js#L216 將locale.use作為Element.locale暴露。九、Element 內(nèi)置語(yǔ)言一覽目前 Element 內(nèi)置了以下語(yǔ)言對(duì)應(yīng)本倉(cāng)庫(kù) src/locale/lang 目錄下的語(yǔ)言包文件該目錄實(shí)際已包含超過(guò) 60 個(gè)語(yǔ)言的配置文件除下表外還有阿塞拜疆語(yǔ) az、孟加拉語(yǔ) bn、冰島語(yǔ) is、老撾語(yǔ) lo-LA、馬來(lái)語(yǔ) ms、僧伽羅語(yǔ) si、塞爾維亞拉丁文 sr-Latn、斯瓦希里語(yǔ) sw、烏茲別克語(yǔ) uz-UZ、亞美尼亞語(yǔ) hy-AM 等語(yǔ)言locale 標(biāo)識(shí)語(yǔ)言locale 標(biāo)識(shí)簡(jiǎn)體中文zh-CN英語(yǔ)en德語(yǔ)de葡萄牙語(yǔ)pt西班牙語(yǔ)es丹麥語(yǔ)da法語(yǔ)fr挪威語(yǔ)nb-NO繁體中文zh-TW意大利語(yǔ)it韓語(yǔ)ko日語(yǔ)ja荷蘭語(yǔ)nl越南語(yǔ)vi俄語(yǔ)ru-RU土耳其語(yǔ)tr-TR巴西葡萄牙語(yǔ)pt-br波斯語(yǔ)fa泰語(yǔ)th印尼語(yǔ)id保加利亞語(yǔ)bg波蘭語(yǔ)pl芬蘭語(yǔ)fi瑞典語(yǔ)sv-SE希臘語(yǔ)el斯洛伐克語(yǔ)sk加泰羅尼亞語(yǔ)ca捷克語(yǔ)cs-CZ烏克蘭語(yǔ)ua土庫(kù)曼語(yǔ)tk泰米爾語(yǔ)ta拉脫維亞語(yǔ)lv南非荷蘭語(yǔ)af-ZA愛(ài)沙尼亞語(yǔ)ee斯洛文尼亞語(yǔ)sl阿拉伯語(yǔ)ar希伯來(lái)語(yǔ)he立陶宛語(yǔ)lt蒙古語(yǔ)mn哈薩克斯坦語(yǔ)kz匈牙利語(yǔ)hu羅馬尼亞語(yǔ)ro庫(kù)爾德語(yǔ)ku維吾爾語(yǔ)ug-CN高棉語(yǔ)km塞爾維亞語(yǔ)sr巴斯克語(yǔ)eu吉爾吉斯語(yǔ)kg亞美尼亞語(yǔ)hy克羅地亞hr世界語(yǔ)eo十、擴(kuò)展與貢獻(xiàn)新的語(yǔ)言包如果你需要使用列表之外的語(yǔ)言可以為本倉(cāng)庫(kù)貢獻(xiàn)語(yǔ)言文件只需在 src/locale/lang 目錄下新增一個(gè)語(yǔ)言配置文件即可。新語(yǔ)言包需遵循統(tǒng)一的結(jié)構(gòu)約定——頂層導(dǎo)出{ el: { 組件名: { 文案鍵: 值 } } }可參照 src/locale/lang/en.js 或 src/locale/lang/zh-CN.js 的完整結(jié)構(gòu)覆蓋 colorpicker、datepicker、select、cascader、pagination、messagebox、upload、table、tree、transfer、image、pageHeader、popconfirm、empty 等全部組件的文案含{total}、{checked}等占位符需一并保留。需要特別說(shuō)明的是use切換語(yǔ)言包時(shí)并不做深校驗(yàn)語(yǔ)言包結(jié)構(gòu)越接近默認(rèn)語(yǔ)言包組件文案的命中率越高未命中的鍵會(huì)回退為空字符串見(jiàn) src/locale/index.js#L34-L37 的if (!value) return 分支因此在新增語(yǔ)言包時(shí)建議以 zh-CN 或 en 為模板逐組補(bǔ)齊避免界面出現(xiàn)空白文案。十一、總結(jié)Element 國(guó)際化的三條路線怎么選僅切換靜態(tài)語(yǔ)言用Vue.use(ElementUI, { locale })或按需場(chǎng)景下的locale.use(lang)最簡(jiǎn)單直接需要運(yùn)行時(shí)動(dòng)態(tài)切換語(yǔ)言接入vue-i18n5.x 自動(dòng)兼容6.x 按第六、七節(jié)手動(dòng)接線讓 Element 與業(yè)務(wù)文案共享同一翻譯管線深度定制翻譯邏輯通過(guò)Vue.use(Element, { i18n: fn })或locale.i18n(fn)注入自定義處理器Element 會(huì)在自定義翻譯返回空時(shí)自動(dòng)回退內(nèi)置語(yǔ)言包追求極致包體積用 webpackNormalModuleReplacementPlugin在構(gòu)建期替換掉默認(rèn)中文語(yǔ)言包。理解 src/locale/index.js 中use/t/i18n三者的協(xié)作關(guān)系——先自定義翻譯、再內(nèi)置語(yǔ)言包回退、最后占位符插值——你就能在任何構(gòu)建方式完整引入、按需引入、CDN下從容完成 Element 的多語(yǔ)言適配?!久赓M(fèi)下載鏈接】elementA Vue.js 2.0 UI Toolkit for Web項(xiàng)目地址: https://gitcode.com/gh_mirrors/eleme/element創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考