自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Vue.js 項(xiàng)目前端多語言方案

開發(fā) 前端
前端的國際化是一個(gè)比較常見的需求。但網(wǎng)上關(guān)于這一方面的直接可用的方案卻不多。最近剛做了一版基于Vue.js的多語言實(shí)現(xiàn),在此簡單作一小結(jié)。

  [[412794]]

前端的國際化是一個(gè)比較常見的需求。但網(wǎng)上關(guān)于這一方面的直接可用的方案卻不多。最近剛做了一版基于Vue.js的多語言實(shí)現(xiàn),在此簡單作一小結(jié)。

一、通常有哪些內(nèi)容需要處理

總的來說,一個(gè)Web應(yīng)用中,需要做多語言切換的內(nèi)容常見的包括如下方面:

1、模板中的內(nèi)容,如Vue.js的 <template> 標(biāo)簽中的文字內(nèi)容

2、JS代碼中的文字內(nèi)容

3、圖片中的文案內(nèi)容

4、頁面 title

5、第三方組件中的文案(比如,我的項(xiàng)目中用到了Vux的組件)

6、后端接口中需要展示到前端的數(shù)據(jù)內(nèi)容

7、后端接口返回的錯(cuò)誤提示

二、基本思路

1、首先,需要確定以什么樣的方式來獲取到當(dāng)前應(yīng)該展示何種語言

我采用的是用URL傳遞 ?lang=en 或者 ?lang=zh-CN 這樣的傳遞參數(shù)的形式。這樣做的好處在于可以通過鏈接指定用哪種語言。但是,只依賴于地址欄參數(shù)也是不方便的。比如,在頁面跳轉(zhuǎn)的時(shí)候,這個(gè)地址欄參數(shù)可能就丟失了。這會導(dǎo)致你在頁面跳轉(zhuǎn)之后就不知道該用哪種語言展示了。而理想的的方式應(yīng)該是,進(jìn)入某個(gè)頁面的時(shí)候帶有這個(gè)參數(shù)(這個(gè)時(shí)候就獲取到該使用何種語言了),等再跳轉(zhuǎn)到其它頁面的時(shí)候就不必再帶這個(gè) lang 參數(shù)了,因?yàn)榇藭r(shí)你已經(jīng)知道該用哪種語言了。所以,應(yīng)該在一進(jìn)入第一個(gè)頁面的時(shí)候就把這個(gè)參數(shù)存下來,比如,存在localstorage中,存在vuex的state中。

這里,就引出來一個(gè)語言判斷的優(yōu)先級問題。

因?yàn)榈刂窓诶锟赡苡?nbsp;lang 參數(shù),localstorage中可能也有相關(guān)的存儲字段(因?yàn)樯洗卧L問過本應(yīng)用),你可能還想設(shè)置默認(rèn)的降級語言,等等。其優(yōu)先級應(yīng)該如何處理呢?

正確的優(yōu)先級應(yīng)該是:

先看地址欄參數(shù)中有沒有;

再看localstorage中有沒有;

然后再通過 navigator.language 獲取瀏覽器默認(rèn)語言,看是否是你的應(yīng)用所支持的語言,若是,則采用之;

最后才是使用回退語言(例如,比較通用的英語)。

當(dāng)然,你可以根據(jù)你的需求來做一些簡化。

2、其次,采用什么工具來解決語言轉(zhuǎn)換和打包的問題?

(1)i18n相關(guān)工具的選擇——由誰來提供多語言轉(zhuǎn)換函數(shù)(通常是$t)?

目前國際化通用方式多數(shù)基于i18n,我們也無需再去造輪子了。但就i18n的具體使用上,有很多不同的NPM模塊。比如vuex-i18n、vue-i18n、simplest-i18n等。因?yàn)槎鄶?shù)復(fù)雜一點(diǎn)的項(xiàng)目都會上vuex,所以復(fù)雜一點(diǎn)的項(xiàng)目選擇vuex-i18n會比vue-i18n更方便。

而simplest-i18n這個(gè)很小眾的模塊,其實(shí)也有它的好處。它支持下面這樣的寫法:

在模板中:

  1. <span>$t('真實(shí)姓名''Real Name')</span> 

或者在JS中:

  1. this.$t('真實(shí)姓名''Real Name'

即將語言寫在一起,$t函數(shù)的每一個(gè)參數(shù)都是一種語言,一目了然,還是比較方便閱讀的。對小項(xiàng)目來說,不失為一種選擇。

其基本使用如下:

t.js文件:

  1. import i18n from 'simplest-i18n'
  2. import getLang from '../../getLang'
  3.  
  4. const t = i18n({ 
  5.   locale: getLang.lang, // 當(dāng)前語言 
  6.   locales: getLang.langs // 支持的語言列表 
  7. }); 
  8. export default t; 

然后在應(yīng)用的入口文件中對Vue.js進(jìn)行擴(kuò)展:

  1. import t from './t'
  2. Vue.$t = Vue.prototype.$t = t; 

這樣就把 $t 這個(gè)方法掛載到了Vue.js的全局。Vue實(shí)例中也可以通過 this.$t 訪問到,使用上還是非常簡單的。

但是,對于大項(xiàng)目來說,把語言包都寫在代碼里面,對維護(hù)并不友好。而且,靠它也解決不了我所用到的Vux組件的多語言化的問題。

所以最終,我選擇了vuex-i18n作為基礎(chǔ)。

(2)組織和處理語言包的工具——語言包怎么組織,怎么打包處理?

對于這個(gè)問題,我首先需要解決Vux第三方組件的多語言化問題。

首先,在語言包的組織方面,比較常見的是寫成JSON配置文件。不過,我最終采用了Yaml這種格式,它支持將多語言字段寫在一起。比如:

config.yml

  1. confirm: 
  2.   zh-CN: 確認(rèn) 
  3.   en: confirm 

而不是像下面那樣將一個(gè)字段的多語言拆成幾處,比如:

  1. confirm: 確認(rèn) 


  1. confirm: confirm 

這樣帶來的好處就是,可以方便地對照一個(gè)字段的不同語言版本,而且要修改或刪除某一個(gè)字段時(shí),也可以在一處完成,無需切換。況且,Yaml文件的語法也更加簡單明了,省去了JSON文件必須寫雙引號、不可以出現(xiàn)注釋等諸多麻煩。

其次,在語言包的打包方面,我找到了vux-loader。它可以和現(xiàn)有的webpack配置結(jié)合,不僅能完成Vux組件多語言配置的打包,還允許在自定義的Vue組件中使用 <i18n> 標(biāo)簽。比如,在自定義組件中我可以這么寫:

  1. <i18n> 
  2. confirm: 
  3.   zh-CN: 確認(rèn) 
  4.   en: confirm 
  5. <i18n> 

打包時(shí),vux-loader會將 <i18n> 標(biāo)簽中的多語言配置信息導(dǎo)出至我們所配置的一個(gè)Yaml文件中,而把 <i18n> 標(biāo)簽從我們的自定義組件中移除。

那么,對于Yaml文件如何處理呢?可以用json-loader和yaml-loader。它們可以將Yaml文件轉(zhuǎn)換成我們所需要的json格式,方便在JS函數(shù)中使用,就像這樣:

  1. const componentsLocales = require('json-loader!yaml-loader!../../locales/components.yml'); // 這就得到了一個(gè)語言包的json格式 

3、如何通知后端接口返回何種語言的數(shù)據(jù)?

因?yàn)樯婕暗皆S多接口都要通知后端采用哪種語言,所以,我選擇了使用header頭的方式。在axios的interceptor中給請求統(tǒng)一添加了header頭: Accept-Language , 并把這個(gè)值的內(nèi)容設(shè)置成前端所獲得應(yīng)使用的語言(如,zh-CN 或 en 等)。這樣,就集中在一處把這個(gè)問題處理掉了。

三、具體實(shí)踐中的一些細(xì)節(jié)

1、獲取當(dāng)前應(yīng)該采用何種語言的getLang模塊的實(shí)現(xiàn)

  1. import { getQueryObj } from '../utils/url'
  2. import { setItem, getItem } from '../utils/storage'
  3.  
  4. const langs = ['zh-CN''en']; // 支持哪些語言 
  5. const defaultLang = 'en'// 默認(rèn)語言,暫時(shí)并沒有對外拋出 
  6.  
  7. function getLang() { 
  8.   let queries = getQueryObj(); 
  9.   let storeLang = getItem('lang'); 
  10.   let rawLang; 
  11.   let flag = false
  12.  
  13.   if (queries && queries['lang']) { 
  14.     rawLang = queries['lang']; 
  15.     setItem('lang', rawLang); 
  16.   } else { 
  17.     rawLang = storeLang || navigator.language; 
  18.   } 
  19.  
  20.   langs.map(item => { 
  21.     if (item === rawLang) { 
  22.       flag = true
  23.     } 
  24.   }); 
  25.   return flag ? rawLang : defaultLang; 
  26.  
  27. const lang = getLang(langs, defaultLang); 
  28.  
  29. export default { 
  30.     lang, // 獲取到當(dāng)前語言 
  31.     langs // 所支持的語言列表 

2、Vux組件的多語言包的配置

可以從Vux的官方github中找到 src/locales/all.yml 拷貝過來(同一目錄下的 src/locales/zh-CN.yml 、 src/locales/en.yml 分別是其中文部分和英文部分),根據(jù)你自己的需要略作修改即可。

然后在你的應(yīng)用的應(yīng)用的入口文件中引入:

  1. const vuxLocales = require('json-loader!yaml-loader!../../locales/all.yml'); 

3、vux-loader的配置

webpack.dev.conf.js 中:

  1. resolve(vuxLoader.merge(devWebpackConfig, { 
  2.     plugins_dir: [ 
  3.         'vux-ui'
  4.         { 
  5.             name: 'i18n'
  6.             vuxStaticReplace: false
  7.             staticReplace: false
  8.             extractToFiles: 'src/locales/components.yml'
  9.             localeList: ['en','zh-CN'
  10.         } 
  11.     ] 
  12. })) 

webpack.prod.conf.js中:

  1. resolve(vuxLoader.merge(buildWebpackConfig, { 
  2.     plugins_dir: [ 
  3.         'vux-ui'
  4.         { 
  5.             name: 'i18n'
  6.             vuxStaticReplace: false
  7.             staticReplace: false
  8.             extractToFiles: 'src/locales/components.yml'
  9.             localeList: ['en','zh-CN'
  10.         } 
  11.     ] 
  12. })) 

其中的 localeList: ['en','zh-CN'] 就是指定你的應(yīng)用支持哪幾種語言。

而 extractToFiles: 'src/locales/components.yml' 就是指定你的自定義組件中所用到的那些 <i18n> 標(biāo)簽中的語言包信息,應(yīng)該導(dǎo)出到哪個(gè)Yaml文件中。也就是說,你在各個(gè)自定義組件中使用的 <i18n> 標(biāo)簽中的語言包信息都會被vux-loader集中抽取到這個(gè)文件中。

然后在應(yīng)用的入口文件中引入這個(gè)語言包文件:

  1. const componentsLocales = require('json-loader!yaml-loader!../../locales/components.yml'); 

4、自定義組件內(nèi)外文案的多語言化

(1)對于自定義組件內(nèi)部的文案的多語言化信息,寫在組件的 <i18n> 標(biāo)簽中即可。同時(shí),為了避免不同的自定義組件中多語言字段的命名沖突,在每個(gè)字段的名字前面加上以組件名-式的前綴。

(2)對于頁面的標(biāo)題、一些錯(cuò)誤提示等文案,它們是出現(xiàn)在組件之外的,因此不適合寫在組件的 <i18n> 標(biāo)簽中,所以我們單獨(dú)新建一個(gè) global.yml 來存放這些全局性的多語言信息。這些內(nèi)容直接寫在 global.yml 中即可,并且,為了表面與其它的語言包字段相沖突,我們在每個(gè)字段的前面加上 global- 前綴。

然后在應(yīng)用的入口文件中引入這個(gè)語言包文件:

  1. const componentsLocales = require('json-loader!yaml-loader!../../locales/global.yml'); 

5、vuex-i18n的實(shí)現(xiàn)

在src/store/index.js文件中:

  1. import VuexI18n from 'vuex-i18n'

export default new Vuex.Store 中增加:

  1. i18n: VuexI18n.store 

在應(yīng)用的入口文件中:

  1. import VuexI18n from 'vuex-i18n'
  2. import getLang from '../../getLang'
  3.  
  4. Vue.use(VuexI18n.plugin, store); 
  5.  
  6. const vuxLocales = require('json-loader!yaml-loader!../../locales/all.yml'); 
  7. const componentsLocales = require('json-loader!yaml-loader!../../locales/components.yml'); 
  8.  
  9. const finalLocales = { 
  10.   'en': Object.assign(vuxLocales['en'], componentsLocales['en']), 
  11.   'zh-CN': Object.assign(vuxLocales['zh-CN'], componentsLocales['zh-CN']) 
  12.  
  13. for (let i in finalLocales) { 
  14.   Vue.i18n.add(i, finalLocales[i]) 
  15.  
  16. Vue.i18n.set(globalVars.lang); 

6、圖片的多語言化

對于圖片中的文案信息,多語言化主要有這么兩種方式:一是根據(jù)不同的語言展示不同的圖片;二是盡將文字從圖片背景中分離出來,采用文字層加背景圖片層的方式,這樣文字層就可以作為普通文本來實(shí)現(xiàn)多語言化了。都比較簡單,不再贅述。

7、在當(dāng)前頁面通過按鈕切換當(dāng)前語言后,如何更新當(dāng)前頁面的內(nèi)容?

如果你的應(yīng)用并不需要在頁面內(nèi)部切換語言版本,那么直接通過URL中傳入不同的 lang 參數(shù)就可以了,并不涉及到此問題。

第一種方式:刷新頁面

  1. <button @click="changeLang('zh-CN')">中文</button> 
  2. <button @click="changeLang('en')">英文</button> 
  1. changeLang(lang){ 
  2.     location.href = this.$utils.url.replaceParam(this.$router.history.current.path, 'lang', lang); 
  3. }, 

第二種方式:watch當(dāng)前頁data中 lang 字段的變化,通過 v-if 局部刷新某些相關(guān)組件:

  1. data(){ 
  2.     return { 
  3.         lang: this.$i18n.locale() 
  4.     } 
  5.  
  6. changeLang(lang){ 
  7.     this.$i18n.set(lang); 
  8.     this.lang = this.$i18n.locale(); 
  9. }, 
  10.  
  11. watch: { 
  12.     lang(newVal, oldVal) { 
  13.         if(newVal === oldVal) { 
  14.             return
  15.         } 
  16.  
  17.         // 在這里通過改變某個(gè)標(biāo)志位 結(jié)合 v-if 來觸發(fā)某個(gè)局部組件的重新渲染 
  18.     } 

第三種方式:結(jié)合vuex派發(fā)全局的語言狀態(tài),接收到狀態(tài)變化時(shí)進(jìn)行更新,或者自己簡單地改寫vuex-i18n的實(shí)現(xiàn)。這種方式相對復(fù)雜一些。

具體根據(jù)自己的業(yè)務(wù)需求選擇。

8、Yaml中特殊字符的轉(zhuǎn)義

對于一些包含特殊字符的yaml鍵值,比如 [、] 等,需要進(jìn)行轉(zhuǎn)義。轉(zhuǎn)的方式是給鍵值加上單引號引起來。

如果你的語言包信息中有單引號,則必須連續(xù)使用兩個(gè)單引號轉(zhuǎn)義。例如:

  • str: 'labor''s day' 

 

 

責(zé)任編輯:張燕妮 來源: Vue中文社區(qū)
相關(guān)推薦

2020-09-16 14:01:10

Vue.js項(xiàng)目語言

2016-11-02 18:43:02

javascripthtml5vue.js

2017-12-15 10:00:46

前端框架Vue.js

2016-11-01 19:10:33

vue.js前端前端框架

2020-11-06 07:30:36

JS文件

2014-04-16 14:50:20

Spark

2022-10-27 22:11:40

react擴(kuò)展庫語言

2020-04-14 09:50:02

2012-04-19 11:40:21

Titanium

2011-08-05 17:54:33

Cocoa Touch 多語言

2009-08-25 10:44:50

C#實(shí)現(xiàn)多語言

2014-07-09 09:20:06

WPFWPF應(yīng)用

2017-09-27 16:44:23

前端

2023-04-27 08:23:38

JavaScriptVue.jsMVVC

2024-05-09 08:14:09

系統(tǒng)設(shè)計(jì)語言多語言

2013-10-16 15:50:01

iOS優(yōu)化本地化

2022-08-09 07:22:15

語言數(shù)據(jù)庫程序

2023-08-04 10:18:15

2021-09-07 10:17:35

iOS多語言適配設(shè)計(jì)

2021-06-29 21:48:32

開源語言架構(gòu)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號