i18n
前言
what is i18?
i18n 全称 Internationalization,也就是国际化的意思,因为单词太长,所以中间的 18 个字母被缩写为 18,再加上开头和结尾的字母,就组成了 i18n。
why i18n?
英语是世界上使用最广泛的语言,但只有七分之一的人会说英语。它是 3.79 亿人的第一(母语)语言,但有 9.17 亿人说中文普通话,4.6 亿人说西班牙语,3.41 亿人说印地语。
在互联网呈指数级增长的新兴市场,存在大量非英语用户。如果你的网站可以在全球范围内进行翻译,那么你的潜在目标市场可能会增加 700%!
项目
安装
npm install vue-i18n --save
—> “vue-i18n”: “^9.2.2”,
这里由于我创建的Vue2的项目,无法正常安装新版的I18n包,亲测可用版本 “vue-i18n”: “^8.1.0”
配置及使用
配置
在src目录新建i18n目录,en.js为英文语言包,zh.js为中文语言包(建议目录名)
【此处只做轻快上手i18n
, 对所需的配置项可参考官网,主打的是一个轻快便捷】
- i18n 下index.js文件
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import enLocale from './en' // 导入项目中用到的英文语言包
import zhLocale from './zh'// 导入项目中用到的中文语言包
Vue.use(VueI18n)
const messages = {
en: {
...enLocale,
},
zh: {
...zhLocale,
},
}
const i18n = new VueI18n({
locale: localStorage.getItem('language') || 'zh', // 设置语种
fallbackLocale: 'en', // 默认语言设置,当其他语言没有的情况下,使用en作为默认语言
messages, // 设置全局当地语言包,
})
export default i18n
messages : 一般会将项目中的静态语言分成产品所需要的各个语种,包括中文,英文,法文等… 此上对静态语言做了模块化处理,再使用展开运算符。这样项目不仅结构变得更简洁明了,在维护开发阶段也节省很多时间。
- i18n 下zh.js文件
export default {
common: {
username: '张三',
password: '密码',
save: '保存',
edit: '编辑',
update: '更新',
delete: '删除',
forever: '永久',
expired: '过期'
}
}
- i18n 下en.js文件
export default {
common: {
username: 'zhangsan',
password: 'password',
save: 'Save',
edit: 'Edit',
update: 'Update',
delete: 'Delete',
forever: 'Forever',
expired: 'Expired'
}
}
- main.js
import Vue from 'vue'
import App from './App.vue'
//导入配置好的国际化语言包
import i18n from './i18n'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
i18n,//注入配置好的国际化语言配置
}).$mount('#app')
使用
在vue中注册i18n之后,我们便可以在组件中通过this.$i18n
获取到我们配置好的这个i18n对象
说明:i18n == this.$18n
—> true
常用配置信息
- locale 主要是用来设置语种包
//在组件中
import i18n from "@/i18n" //根据项目对应真实路径
i18n.locale="en" // 改变为中文
localStorage.setItem('language',"en")//在localStorage中存入设置
- $t 的使用(格式化)
简单来说就是拿到messages
中的某个数据,参数是字符串,代表着所要获取的某一条数据
$t 是扩展的Vue实例方法
[优点] 在模板中灵活使用小胡子语法(mustash)语法{{}},也可以在Vue实例中灵活地使用计算道具和方法。
[缺点] 每次重新渲染时都会执行,因此它比较消耗性能。
简单使用
//template 需要使用 {{}} 将$t取出的内容包装起来
{{$t('save')}}
// js
this.$t('save')
命名格式化
命名格式化,可以区域格式化信息。 这种情况下$t
的第二参数是一个对象,就代表了所有需要动态添加的内容,注意是所有在message
中所需要动态添加的变量都在第二个参数中。
const messages = {
en: {
message: {
title: 'hello, {name}'
}
}
}
//组件中使用
<p>{{ $t('message.title', { name: 'Kite' }) }}</p>
//输出
<p>hello, Kite</p>
如果未传第二个参数,那么将会都以按照字符串的形式展示.
输出 : <p>hello, {name}</p>
遇到的问题
点击en切换为英文的效果如下,使用{{}}语法的内容在切换语言时可以自行切换,但是放在data中的数据不会更换。
data如下:
控制台输出如下,可见this.$t(‘common.name’)数据已经更新,但是data中的person[0].name并没有更新
解决方案一:刷新页面,可重新加载data中的数据,从而获得最新的this.$t(‘common.name’)
解决方案二:既然原因是data引起的,那么重置data中的数据不就好了吗
//重置data中的所有数据
Object.assign(this._data, this.$options.data.call(this));
//this._data == this.$data --> true
Object.assign():方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象
用法: Object.assign(target, …sources)
第一个参数是目标对象,第二个参数是源对象,就是将源对象属性复制到目标对象,返回目标对象
this.$data 获取的是当前状态下的data对象
this.$options.data() 获取该组件初始状态下的data
Object.assign 则可以将一个对象赋值给另一个对象
所以,下面就可以将初始状态的data复制到当前状态的data,实现重置效果:
Object.assign(this.$data, this.$options.data.call(this))
这样有存在一个问题,data中其他数据也会被重置成初始状态的值。解决如下,只重置使用了i18n的数据
this.person = this.$options.data.call(this).person
持久化保留当前语言信息(刷新页面任然保留原来的语言),可以使用Storage存储当前语种,若有bug请在相应的生命周期函数中重置一下跟i18n相关的数据。【按理来说刷新页面能实现切换语言,但是data中的person并没有改变】
解决方案三: 放在data中的静态数据 国际化需要放到computed中,切换时才会有响应式
//使用
{{ computedPerson[0].name}}
computed: {
computedPerson() {
return [{ name: this.$t("common.username") }]; //这里不能直接 return this.person
},
},
TODO:异步加载语言包
方案三:放在data中的静态数据 国际化需要放到computed中,切换时才会有响应式
//使用
{{ computedPerson[0].name}}
computed: {
computedPerson() {
return [{ name: this.$t("common.username") }]; //这里不能直接 return this.person
},
},
TODO:异步加载语言包