Vue-i18n是对vue项目国际化得一种实现(react-i18n同理),当然也可以使用i18next,本文只对Vue-i18n进行讲解。
一,首先自己学习官方文档
安装vue-i18n的依赖包,安装完成后,新建i18n.js文件。
npm install vue-i18n
二,配置i18n到项目中的步骤
(1)在i18n.js中引入所需的包如下
import Vue from 'vue';
import VueI18n from 'vue-i18n'
import zhTranslation from './public/locales/zh-CN'; // 中文语言环境
import enTranslation from './public/locales/en-US'; // 英文语言环境
import zh from 'element-ui/lib/locale/lang/zh-CN.js'; //element-ui的中文语言环境
import locale from 'element-ui/lib/locale' // element-ui的语言环境
import axios from 'axios'
接下来就是使用这些引入的包了,先呢new一个vue-i18n对象,看过文档的应该都会。
const messages = {};
// 将项目的中文语言环境和element-ui中文环境合并,然后添加到messages里
messages['zh'] = Object.assign({}, zhTranslation, zh);
Vue.use(VueI18n);
export const i18n = new VueI18n({
locale: 'zh', // 设置地区
messages, // 设置地区信息,
fallbackLocale: 'zh' // 回退语言环境
});
locale.i18n((key, value) => i18n.t(key, value)) // 重点:为了实现element插件的多语言切换
const loadedLanguages = ['zh']; // 默认安装的语言
(2)接下来的要做的事情就是:在切换语言的时候,1.异步加载element-ui的目标语言环境,2.请求项目自身的语言环境,一步步来,代码贴上:
/**
* @name: changeElementLang
* @msg: 异步请求element-ui的语言环境
* @param {string} lang 目标语言
* @return: Promise 目标语言环境element-ui的locale
*/
function changeElementLang(lang) {
return new Promise((resolve, reject) => {
const elementLang = () => import(`element-ui/lib/locale/lang/${lang}`); // import属于异步操作
elementLang().then((langRes) => {
const eleLang = langRes['default'];
resolve(eleLang);
}).catch(() => {
reject(lang);
})
})
}
/**
* @name: loadLanguageAsync
* @param {string} lang 目标切换语言
* @return:
*/
export function loadLanguageAsync(lang) {
if(i18n.locale !== lang) {
if(!loadedLanguages.includes(lang)) {
// 异步请求目标语言环境的loacle
const languagePromise = new Promise((resolve ,reject) => {
axios.get(`/api/newsweb/`).then(res => {
resolve(enTranslation);
}).catch(() =>{
reject(lang);
})
})
const elementLanguage = changeElementLang(lang); // 异步请求目标语言环境element-ui的locale
const arrayLanguage = [languagePromise, elementLanguage];
return Promise.all(arrayLanguage).then((arrayLanguage) => {
loadedLanguages.push(lang); // 请求成功后进行标记,避免重复请求
// 将element的locale信息和请求回来的locale合并
messages[lang] = Object.assign({}, arrayLanguage[0], arrayLanguage[1]);
i18n.setLocaleMessage(locale, messages); // 设置语言环境的 locale 信息
i18n.locale = lang; // 修改语言环境
setI18nLanguage(lang);
}).catch(() => {
console.log('切换失败,语言回滚');
})
} else {
i18n.locale = lang;
return Promise.resolve(setI18nLanguage(lang));
}
} else {
return Promise.resolve(lang);
}
}
这个函数有点长,两个if条件判断可以根据变量去判断的逻辑关系,这里只解释异步请求和Promise.all()这两个地方,languagePromise
是一个promise对象,异步请求项目的语言环境,这里的url不用在意,因为我用本地的英语语言环境resolve(enTranslation)
去代替请求回来的数据,为了方便测试而已。
Promise.all()
不熟悉的同学可以先去了解下(只能传入一个数组或者字符串),这里传入一个数组,数组的元素就是前面两个用promise对象包起来的异步操作,等到这两个异步操作都执行了resolve()
,才会执行Promise.all().then()
,参数中有一个异步操作执行了reject()
,Promise.all()
就会执行catch()
。
等到两个参数都resolve()
后,将resolve过来的数据进行合并,然后调用setLocaleMessage()
修改语言环境,最后的i18n.locale = lang;
才是改变语言的操作。
最后贴上setI18nLanguage(lang)
函数的代码:
function setI18nLanguage(lang) {
// 请求头带上语言的字段,告诉后端自己需要的数据语言
axios.defaults.headers.common['Accept-Language'] = lang;
document.querySelector('html').setAttribute('lang', lang);
return lang;
}
三,测试
贴上测试代码:
<template>
<div>
{{ $t('language.title') }}
:
<button @click="changeLanguage('zh')" :class="{active: isLang('zh')}">
{{ $t('language.zh') }}
</button>
<button @click="changeLanguage('en')" :class="{active: isLang('en')}">
{{ $t('language.en') }}
</button>
</div>
</template>
<script>
import { loadLanguageAsync } from '../../i18n'
export default {
data() {
return {};
},
mounted() {
this.changeLanguage('zh');
},
methods: {
isLang(lng) {
return this.$i18n.locale === lng;
},
changeLanguage(lng) {
loadLanguageAsync(lng);
// 切换语言后强制重新渲染,重新请求对应语言的数据
Promise.resolve().then(_ => {
this.$forceUpdate();
})
},
},
};
</script>
项目展示:



别忘了i18n对象要传递给Vue app
网友评论