前言
本文是使用vue2.x + ant-design-vue 搭建的项目,对于框架使用不会做过多的说明
以下是需要思考的问题
1、如何使用vue-i18n ?
2、翻译的字段数据存放在哪里合适 ?
3、ant-design-vue如何国际化 ?
4、如何全局监听切换了语言 ?
5、语言的不同如何兼容样式 ?
使用vue-i18n
1. 安装 注意:vue2.x要安装第8版本,vue3.x安装第9版本
npm install vue-i18n@8
2. 引入 + 挂载 + 使用
我这边是新建了个plugin/vuei18n文件夹去管理该插件的内容
// vuei18n/index.js
import Vue from 'vue'
import Vuei18n from 'vue-i18n'
Vue.use(Vuei18n)
很多人在将翻译的字段都是放在本地由前端去维护,这里我推荐是在后台系统有个地方专门管理语言互译的字典管理的,这样做的好处哪怕以后翻译的文案不正确直接在后台修改即可,不需要前端修改后又要重新发版上线
// vuei18n/index.js
// 模拟从后台获取中英互译数据
/*
假设数据结构
{
dictType: "common", // 分类
dictLabel: "user", // 描述
dictZhValue: "大栗子", // 中文值
dictEnValue: "lily" // 英文值
}
*/
const i18nData = () => {
return [{
dictType: 'link',
dictLabel: 'homeLink',
dictZhValue: '首页',
dictEnValue: 'Home'
}, {
dictType: 'link',
dictLabel: 'detailLink',
dictZhValue: '详情',
dictEnValue: 'Detail'
}, {
dictType: 'home',
dictLabel: 'username',
dictZhValue: '姓名',
dictEnValue: 'username'
}, {
dictType: 'home',
dictLabel: 'password',
dictZhValue: '密码',
dictEnValue: 'password'
}, {
dictType: 'home',
dictLabel: 'email',
dictZhValue: '邮箱',
dictEnValue: 'email'
}, {
dictType: 'detail',
dictLabel: 'desc',
dictZhValue: '这是详情页',
dictEnValue: 'This is a detail page'
}]
}
const geti18nData = () => {
const res = i18nData()
const zh = {} // 存储中文
const en = {} // 存储英文
for (const item of res) {
if (!zh[item.dictType]) {
zh[item.dictType] = {}
en[item.dictType] = {}
}
zh[item.dictType][item.dictLabel] = item.dictZhValue // 中文
en[item.dictType][item.dictLabel] = item.dictEnValue // 英文
}
return {
zh,
en
}
}
打印的结果
3. 初始化i18n
// vuei18n/index.js
const initVuei18n = () => {
const { zh, en } = geti18nData()
return new Vuei18n({
locale: 'zh-CN', // 默认为中文
messages: {
'zh-CN': zh,
'en-US': en
}
})
}
const i18n = initVuei18n()
export default i18n
4. 挂载
// main.js
...
import i18n from './plugin/vuei18n/index'
new Vue({
router,
store,
i18n, // 挂载到全局
render: h => h(App)
}).$mount('#app')
5. 使用
i18n挂载到全局之后,内部会把i18n合并到Vue实例上,新加属性$i18n, $t 等属性方法
// 在模板上直接使用
<a-button type="link">{
{ $t('link.homeLink') }}</a-button>
<a-button type="link">{
{ $t('link.detailLink') }}</a-button>
// 切换语言
methods: {
// 切换语言
switchLanguage (type) {
this.$i18n.locale = type
}
}
Ant-Design-Vue 国际化的支持
在app.vue文件中使用ConfigProvider组件包裹住router-view,引入ant-design-vue多语言文件
注意:LocaleProvider 已经废弃了 换成 ConfigProvider
// app.vue
<template>
<div id="app">
<a-config-provider :locale="locale">
<router-view/>
</a-config-provider>
</div>
</template>
<script>
// 引入antdesignvue的语言包
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN'
import enUS from 'ant-design-vue/lib/locale-provider/en_US'
export default {
data () {
return {
locale: zhCN,
lang: {
'zh-CN': zhCN,
'en-US': enUS
}
}
}
}
</script>
全局监听切换语言
使用事件总线,全局监听切换语言时更改语言配置,用stroe存储当前语言选项
// 在main.js 中定义事件总线
new Vue({
router,
store,
i18n,
render: h => h(App),
data: { Bus: new Vue() } // 定义事件总线
}).$mount('#app')
在app.vue中可以使用this.$root.Bus.$on监听事件,在切换语言的界面使用this.$root.Bus.$emit触发事件
// 在切换语言的界面.vue
methods: {
// 切换语言
switchLanguage (type) {
this.$root.Bus.$emit('switchLanguage', type)
}
}
// app.vue
<template>
<div id="app">
<a-config-provider :locale="locale">
<router-view/>
</a-config-provider>
</div>
</template>
<script>
// 引入antdesignvue的语言包
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN'
import enUS from 'ant-design-vue/lib/locale-provider/en_US'
export default {
data () {
return {
locale: zhCN, // 默认中文
lang: {
'zh-CN': zhCN,
'en-US': enUS
}
}
},
created () {
this.$root.Bus.$on('switchLanguage', type => {
this.$i18n.locale = type
this.locale = this.lang[type]
this.$store.commit('updateState', { key: 'locale', value: type }) // 存到store
})
}
}
</script>
根据语言切换css
同一句话在切换语言的时候会因为文字的长度不同,导致页面上的样式结构错位。因此可能需要准备两套的样式,根据不同语言,动态的去切换每个页面根元素的class
// example.vue
<template>
<div class="internationalView" :class="langClass">
<div class="lang-wrap">
<a-button type="primary" @click="switchLanguage('zh-CN')"> 中文 </a-button>
<a-button style="margin-left: 20px" @click="switchLanguage('en-US')"> English</a-button>
</div>
<p class="detail">{
{ $t('link.detailLink') }}</p>
</div>
</template>
<script>
export default {
name: 'internationalView',
computed: {
langClass () {
return this.$store.state.locale
}
},
methods: {
// 切换语言
switchLanguage (type) {
this.$root.Bus.$emit('switchLanguage', type)
}
}
}
</script>
<style lang="less" scoped>
.zh-CN {
.detail {
color: red;
}
}
.en-US {
.detail {
color: green;
}
}
</style>