十分钟入门前端最佳的语言国际化方案

首先,我们先来介绍一下,什么是语言国际化。i18n(其来源是英文单词 internationalization的首末字符i和n,18为中间的字符数)是“国际化”的简称。在资讯领域,国际化(i18n)指让网站无需做大的改变就能够适应不同的语言和地区的需要。对程序来说,在不修改内部代码的情况下,能根据不同语言及地区显示相应的界面。简单来说,就是你的网站可以有多种语言。

在项目有语言国际化需求的时候,我们通常会选择相应的库,比如使用Vue框架时,我们会选择vue-i18n,当我们使react时,我们也许会使用react-int等,但在具体实践中,往往只是会用这个库还不行,你还得解决如何同步UI框架的组件语言国际化,以及如何处理从浏览器获取默认语言同步问题。总的来说,要充分考虑到这三个环境的语言问题。

现在我就以在Vue项目下,使用vue-i18n整个框架,并且同步更改UI框架Vuetify的组件语言国际化来作为例子,一步一步实现整个项目的语言国际化。

安装

npm

npm install --save vue-i18n@next

yarn

yarn add vue-i18n@next

1.1 定义好语言模版

安装好这个库之后,我们可以先在src目录下新建一个i18n文件夹,然后在messages文件夹下面定义好语言模版(名称没有硬性要求,后面会说到命名方案),如图所示:

1.2 然后,将Vue-i18n引入到Vue项目中

importVuefrom'vue'importVueI18nfrom'vue-i18n'importStorefrom'@/store'importmessagesfrom'./messages/en'//默认语言 Vue.use(VueI18n)newVue({  router,  i18n,  vuetify,  store,render:(h) =>h(App)}).$mount('#app')

这样注入到Vue对象中,我们就可以这样更改语言了,通过

i18n.locale=lang 去更改你需要的语言,就可以自动获取相应的语言了,在模版中使用$t('hello')来翻译。

vue-i18n更多使用姿势看这里:http://kazupon.github.io/vuei18n/introduction.html#sponsors

我就不过多讲解了,我主要说一下与UI框架的同步、异步加载和默认语言处理问题。

这里为了更好的性能,默认只加载一种语言,因为当语言过多时,全部加载存在性能问题,所以采取了异步加载语言模版的方案。

在i18n文件下,新建index.ts入口文件。

异步加载代码如下:

/**

* @functin setLang - 设置应用语言

* @param {string} lang - 要设置语言的名称

* @return {string} lang - 语言名称

*/function_set(lang: string):string{  i18n.locale = lang// i18n.fallbackLocale = langAxios.defaults.headers.common['Accept-Language'] = lang  Store.__s('app.language', lang)returnlang}/**

* @functin loadLangAsync - 异步加载语言模版

* @param {string} lang - 需要加载的语言名称

* @return {string} lang - 加载好的语言名称

*/exportfunctionsetLang(lang: string):Promise{if(__LOCALE__ !== __LANGS__) {// ___LOCALE__  是本地已经加载好的语言模版数组if(!__LANGS__.includes(lang)) {// 本地没有,则加载returnimport(/* webpackChunkName: "lang-[request]" */`@/i18n/messages/${lang}`).then(msgs=>{        i18n.setLocaleMessage(lang, msgs.default[lang])        __LANGS__.push(lang)return_set(lang)      })    }returnPromise.resolve(_set(lang))  }returnPromise.resolve(lang)}

1.3 持久化和默认语言问题

const__LANGS__ = ['enUS']// 默认语言let__LOCALE__ = Store.state.app.language// 获取本地存储的语言// 首次加载没有存储的语言,则默认使用浏览器的语言if(!__LOCALE__) {  __LOCALE__ =window.navigator.language.split('-').join('')  Store.commit('SETLANG', __LOCALE__)}

设置好语言应该添加到vuex的store里面,并且同步到localstorage,做好语言持久化处理。

这时候,异步加载和默认语言处理问题已经解决好了,现在我们再来说同步Vuetify组件国际化问题。

1.4 同步UI组件国际化

不同UI框架都有自己的组件国际化API,vuetify提供的是

this.$vuetify.lang.current = lang

因此,我们只要调用vue-i18n的setLang方法时,同步调用这个方法就好了。

lang() {      setLang(this.d_language)this.setVuetifyLang(this.d_language) }

这时,又有一个命名的问题,我们的vue-i18n这个插件可以自己命名语言模版名,但是vuetify的语言名已经命名好了,无法更改的,如下:

因此,这里需要我们的模版名称应该和这里的命名一致,如简体中文的模版名应该为zhHans,但是我们默认语言处理是以浏览器的语言来处理的,浏览器的语言名使用SO 639-1标准 为各种语言定义了缩略词,就是以一种简称代替某种语言,如英文用en,中文用zh,部分列表如下:

因为名称不一致,为了统一命名,我们还应该添加一个翻译表,以浏览器的语言为标准,建立语言模版名,并且将与vutify组件不一致的名称翻译过来,如浏览器的enUS对应vuetify的en,部分翻译如下:

/**

*  使 I18n and vuetify 保持一致

*/exportconstTranslateTable: TranslateItem = {enUS:'en',zhCN:'zhHans',zhTW:'zhHant',ja:'ja',ko:'ko'}

当然,vuetify的模版语言可以使可以按需加载的

/**

* the vuetify-i18n language list

* see more :  https://vuetifyjs.com/en/customization/internationalization/

*/constlocalList = ['zhHans','en','ko','zhHant','ja']//加载自己需要的语言// webpack的api,自动模块化加载constfiles =require.context('vuetify/lib/locale/',true, /\.js$/)constlocales:Array = []files.keys().forEach(key=>{constlanguageName = key    .replace('./','')    .replace('.js','')    .replace('-','')if(localList.includes(languageName)) {    locales.push({ [languageName]: files(key).default })  }})

Tips:这里有个小技巧,当默认语言为英语时,我们可以在默认不添加翻译,如this.$t("hello"),当没有对应翻译时,会翻译成hello,这样是不是很方便呢?

所以我的项目中,都是以英文作为翻译的key,就不用添加英文的翻译了,懒人必备。

至此,我们就完成所有的语言国际化工作了,是不是很简单呢?

赶快Get吧,10分钟就可以轻松入门。

完整的封装如下:

/**

* vue-i18n

* see more : https://kazupon.github.io/vue-i18n/zh/guide/lazy-loading.html

*/importVuefrom'vue'importVueI18nfrom'vue-i18n'importAxiosfrom'axios'importStorefrom'@/store'importmessagesfrom'./messages/en'Vue.use(VueI18n)const__LANGS__ = ['enUS']let__LOCALE__ = Store.__s('app.language')if(!__LOCALE__) {  __LOCALE__ =window.navigator.language.split('-').join('')  Store.__s('app.language', __LOCALE__)}consti18n =newVueI18n({locale: __LOCALE__,fallbackLocale:'enUS',silentTranslationWarn:false,  messages})/**

* @functin setLang - set the app's language

* @param {string} lang - the language will be setted

* @return {string} lang - langguage name

*/function_set(lang: string):string{  i18n.locale = lang// i18n.fallbackLocale = langAxios.defaults.headers.common['Accept-Language'] = lang  Store.__s('app.language', lang)returnlang}/**

* @functin loadLangAsync - load language asynchronous

* @param {string} lang - the language will be loading

* @return {string} lang - loaded language name

*/exportfunctionsetLang(lang: string):Promise{if(__LOCALE__ !== __LANGS__) {if(!__LANGS__.includes(lang)) {returnimport(/* webpackChunkName: "lang-[request]" */`@/i18n/messages/${lang}`).then(msgs=>{        i18n.setLocaleMessage(lang, msgs.default[lang])        __LANGS__.push(lang)return_set(lang)      })    }returnPromise.resolve(_set(lang))  }returnPromise.resolve(lang)}setLang(__LOCALE__)// initializationexportdefaulti18n

如果需要源码的话,请关注wx公众号「前端攻城之路」,回复“语言国际化”,将自动获取到源码链接。

支持

如果这篇文章对你有帮助或者有启发的话,我想请你关注我,让我们一起在前端攻城路上进阶。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容