介绍
vue-i18n
是一个适用于Vue项目的国际化库,借助这个库可以方便地在一个项目中支持多国语言。在现成的项目中添加vue-i18n
是非常方便的,本文假设你已经有了自己的Vue项目,如果你想新建一个,我推荐使用Vue的官方命令行工具Vue CLI,关于如何使用Vue CLI创建新项目,可以参考我的另外一篇文章Vue CLI 3 快速搭建项目。
安装
npm install --save vue-i18n
初始配置
我们需要将一个i18n
组件挂载到Vue实例上,为了让我们的项目组件化,我们在/src
目录下新建一个.js
文件,命名为i18n.js
,在这个js文件中加入如下代码:
import Vue from 'vue';
import VueI18n from 'vue-i18n';
Vue.use(VueI18n);
以上代码只是引入了i18n
这个库,并没有任何实质性的操作,接下来我们就要建立几个静态的语言文件,作为用户使用不同语言时出现在网页上的文本内容。
由于这些语言文件是静态文件,在/src/assets
目录下新建一个名为i18n
的文件夹,为了方便,我这里只设置两种语言,中文和英文,在实际操作时可以用同样的方法设置多种语言。
建立zh.js
文件,作为中文语言文件,再建立en.js
文件,作为英文语言文件,文件名没有硬性要求,这里为了表意清楚选择了这样的命名方式,读者可以根据自己的需求自由命名。现在我们的文件结构应该是这样的:
接下来让我们给语言文件加一些内容,由于这些语言文件最后是要导出给i18n的主配置文件使用的,我们就直接写成一个JavaScript对象的形式,并默认导出。
// zh.js
export default {
greeting: '欢迎',
numbers: ['一', '二', '三'],
buttons: {
change: '切换语言',
}
}
// en.js
export default {
greeting: 'Welcome',
numbers: ['One', 'Two', 'Three'],
buttons: {
change: 'Change language',
}
}
两个JavaScript对象应当有相同的结构和键名,但是值应当不同,相当于是同样内容在不同语言中的呈现。
接下来让我们把这两个语言文件导入到i18n的配置文件中,并实例化一个i18n组件,在/src/i18n.js
文件中添加内容,添加后文件内容如下:
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import zh from '../assets/i18n/zh';
import en from '../assets/i18n/en';
Vue.use(VueI18n);
const messages = {
zh, // 这是zh: zh的简写,后面同理
en,
};
export default new VueI18n({
locale: 'zh',
messages,
});
我们先创建了一个messages
对象,这个对象的键表示语言,值为一个静态JavaScript对象,表示语言的配置。以中文为例,键zh
表示中文,值zh
是在文件开头引入的,我们刚刚写的语言文件。这里键和值不必同名,键名也没有硬性规定,我这样写是为了操作方便。
在文件最后我们创建了了一个VueI18n
的实例,这个类的构造器需要一个对象作为参数,对象的locale
值是一个字符串,表示默认语言,需要与messages
里面的键统一,我这里填了'zh'
,与上面的代码统一,表示默认语言为中文。对象的messages
值是一个对象,需要传入我们已经配置好的多语言对象,这里我们直接把上面的messages
对象传入,由于键值同名,这里使用了JavaScript ES6的简写语法。
最后我们需要把这个实例挂载到Vue的根实例上,在/src/main.js
中:
import Vue from 'vue';
import App from './App.vue';
import i18n from './i18n';
Vue.config.productionTip = false;
new Vue({
i18n,
render: function (h) {
return h(App);
},
}).$mount('#app');
在Vue实例中应用
配置完毕,我们现在可以在Vue实例中使用了,这里为了方便,我直接把所有的内容都放在根组件App.vue
中,不创建子组件了,在实际开发过程中,绝大多数情况我们都应该再创建一个子组件,这符合组件化开发的模式。
先展示一下最终App.vue
中的代码:
<template>
<div id="app">
<button @click="changeLanguage">{{$t('buttons.change')}}</button>
<h1>{{$t('greeting')}}</h1>
<p>
<span v-for="num in $t('numbers')">
{{num}}
</span>
</p>
</div>
</template>
<script>
export default {
name: 'app',
methods: {
changeLanguage() {
this.$i18n.locale = this.$i18n.locale === 'zh' ? 'en' : 'zh';
}
},
created() {
console.log(this.$t('greeting'));
}
};
</script>
<style>
</style>
如果要在模板中访问多语言内容,首先将该内容用{{}}
双花括号括起来,然后在其中使用$t(key)
的方法来访问内容,其中key
是语言对象中的一个键名或者按顺序层层深入的一串键名,需要注意的是,这个键名必须以字符串形式传入。如上面的例子所示,我想访问buttons.change
的内容,在模板中就可以用{{$t('buttons.change')}}
或者是{{$t('buttons["change"]')}}
。
多语言内容也可以用在Vue的模板渲染或者条件渲染等情况,由于v-for
或者v-if
后面的内容默认已经是JavaScript代码了,所以不需要花括号,如上面例子中的v-for="num in $t('numbers')"
。
在Vue的模板中,this
是自动绑定的,但是在Vue组件中,我们想要访问多语言内容,还是需要加上this
关键字的,也就是以this.$t(key)
的方式来访问,在上面例子中,由于默认语言被设置成了中文,所以在实例被创建时会在控制台中打印出'欢迎'
。
我们还可以通过设置this.$i18n.locale
的值来更换语言,在我的初始化阶段,VueI18n
实例的messages
属性中有zh
和en
两个属性,所以我们可以通过将this.$i18n.locale
设置成zh
或en
来切换语言。
运行效果:
点击“切换语言”后的效果:
动态设置初始语言
我们并不知道用户的语言偏好是什么,所以写死默认语言并不是很好的做法,一个更好的选择是根据用户浏览器的语言偏好来动态地设置初始语言,让我们对i18n.js
文件做一个小小的修改。
BOM对象navigator
的language
属性可以告诉我们用户的语言偏好,鉴于我们目前只有中文和英文两种语言,我们做如下设置:如果用户偏好中文,我们就把默认语言设置成中文,否则就把默认语言设置成英文。
我们保持i18n.js
文件其他的部分不变,只修改最后一部分代码:
const isChinese = navigator.language.indexOf('zh') > -1;
export default new VueI18n({
locale: isChinese ? 'zh' : 'en',
messages,
});
我先解释一下第一行的运行原理,语言偏好一般是采用语言-地区的格式,例如中文-大陆就是zh-CN
,中文-台湾就是zh-TW
,有的用户干脆直接设置成中文,这时候navigator.language
的值就是zh
,所以我们通过在navigator.language
中寻找子字符串zh
来判断用户是否偏好中文,当然你也可以通过枚举的方式更严谨地设置默认语言。
当判断完用户的语言偏好后,我们就可以在初始化VueI18n
实例时动态设置语言了。
源代码
文章中所用示例的源代码已经上传到GitHub,点击这里查看或下载。