Vue 项目前端多语言方案
作者:Paian
http://mobilesite.github.io
一、通常有哪些内容需要处理
<template>标签中的文字内容title二、基本思路
1、首先,需要确定以什么样的方式来获取到当前应该展示何种语言
?lang=en或者?lang=zh-CN这样的传递参数的形式。这样做的好处在于可以通过链接指定用哪种语言。但是,只依赖于地址栏参数也是不方便的。比如,在页面跳转的时候,这个地址栏参数可能就丢失了。这会导致你在页面跳转之后就不知道该用哪种语言展示了。而理想的的方式应该是,进入某个页面的时候带有这个参数(这个时候就获取到该使用何种语言了),等再跳转到其它页面的时候就不必再带这个lang参数了,因为此时你已经知道该用哪种语言了。所以,应该在一进入第一个页面的时候就把这个参数存下来,比如,存在localstorage中,存在vuex的state中。lang参数,localstorage中可能也有相关的存储字段(因为上次访问过本应用),你可能还想设置默认的降级语言,等等。其优先级应该如何处理呢?navigator.language获取浏览器默认语言,看是否是你的应用所支持的语言,若是,则采用之;2、其次,采用什么工具来解决语言转换和打包的问题?
<span>$t('真实姓名', 'Real Name')</span> 
this.$t('真实姓名', 'Real Name') 
import i18n from 'simplest-i18n'; 
import getLang from '../../getLang';
const t = i18n({
locale: getLang.lang, // 当前语言
locales: getLang.langs // 支持的语言列表
});
export default t;
import t from './t'; 
Vue.$t = Vue.prototype.$t = t;
$t这个方法挂载到了Vue.js的全局。Vue实例中也可以通过this.$t访问到,使用上还是非常简单的。confirm: 
zh-CN: 确认
en: confirm
confirm: 确认 
confirm: confirm 
<i18n>标签。比如,在自定义组件中我可以这么写:<i18n> 
confirm:
zh-CN: 确认
en: confirm
<i18n>
<i18n>标签中的多语言配置信息导出至我们所配置的一个Yaml文件中,而把<i18n>标签从我们的自定义组件中移除。const componentsLocales = require('json-loader!yaml-loader!../../locales/components.yml'); // 这就得到了一个语言包的json格式 
3、如何通知后端接口返回何种语言的数据?
Accept-Language, 并把这个值的内容设置成前端所获得应使用的语言(如,zh-CN 或 en 等)。这样,就集中在一处把这个问题处理掉了。三、具体实践中的一些细节
1、获取当前应该采用何种语言的getLang模块的实现
import { getQueryObj } from '../utils/url'; 
import { setItem, getItem } from '../utils/storage';
const langs = ['zh-CN', 'en']; // 支持哪些语言
const defaultLang = 'en'; // 默认语言,暂时并没有对外抛出
function getLang() {
let queries = getQueryObj();
let storeLang = getItem('lang');
let rawLang;
let flag = false;
if (queries && queries['lang']) {
rawLang = queries['lang'];
setItem('lang', rawLang);
} else {
rawLang = storeLang || navigator.language;
}
langs.map(item => {
if (item === rawLang) {
flag = true;
}
});
return flag ? rawLang : defaultLang;
}
const lang = getLang(langs, defaultLang);
export default {
lang, // 获取到当前语言
langs // 所支持的语言列表
}
2、Vux组件的多语言包的配置
src/locales/all.yml拷贝过来(同一目录下的src/locales/zh-CN.yml、src/locales/en.yml分别是其中文部分和英文部分),根据你自己的需要略作修改即可。const vuxLocales = require('json-loader!yaml-loader!../../locales/all.yml'); 
3、vux-loader的配置
webpack.dev.conf.js中:resolve(vuxLoader.merge(devWebpackConfig, { 
plugins_dir: [
'vux-ui',
{
name: 'i18n',
vuxStaticReplace: false,
staticReplace: false,
extractToFiles: 'src/locales/components.yml',
localeList: ['en','zh-CN']
}
]
}))
resolve(vuxLoader.merge(buildWebpackConfig, { 
plugins_dir: [
'vux-ui',
{
name: 'i18n',
vuxStaticReplace: false,
staticReplace: false,
extractToFiles: 'src/locales/components.yml',
localeList: ['en','zh-CN']
}
]
}))
localeList: ['en','zh-CN']就是指定你的应用支持哪几种语言。extractToFiles: 'src/locales/components.yml'就是指定你的自定义组件中所用到的那些<i18n>标签中的语言包信息,应该导出到哪个Yaml文件中。也就是说,你在各个自定义组件中使用的<i18n>标签中的语言包信息都会被vux-loader集中抽取到这个文件中。const componentsLocales = require('json-loader!yaml-loader!../../locales/components.yml'); 
4、自定义组件内外文案的多语言化
<i18n>标签中即可。同时,为了避免不同的自定义组件中多语言字段的命名冲突,在每个字段的名字前面加上以组件名-式的前缀。<i18n>标签中,所以我们单独新建一个global.yml来存放这些全局性的多语言信息。这些内容直接写在global.yml中即可,并且,为了表面与其它的语言包字段相冲突,我们在每个字段的前面加上global-前缀。const componentsLocales = require('json-loader!yaml-loader!../../locales/global.yml'); 
5、vuex-i18n的实现
import VuexI18n from 'vuex-i18n'; 
export default new Vuex.Store中增加:i18n: VuexI18n.store 
import VuexI18n from 'vuex-i18n'; 
import getLang from '../../getLang';
Vue.use(VuexI18n.plugin, store);
const vuxLocales = require('json-loader!yaml-loader!../../locales/all.yml');
const componentsLocales = require('json-loader!yaml-loader!../../locales/components.yml');
const finalLocales = {
'en': Object.assign(vuxLocales['en'], componentsLocales['en']),
'zh-CN': Object.assign(vuxLocales['zh-CN'], componentsLocales['zh-CN'])
}
for (let i in finalLocales) {
Vue.i18n.add(i, finalLocales[i])
}
Vue.i18n.set(globalVars.lang);
6、图片的多语言化
7、在当前页面通过按钮切换当前语言后,如何更新当前页面的内容?
lang参数就可以了,并不涉及到此问题。<button @click="changeLang('zh-CN')">中文</button> 
<button @click="changeLang('en')">英文</button>
changeLang(lang){ 
location.href = this.$utils.url.replaceParam(this.$router.history.current.path, 'lang', lang);
},
lang字段的变化,通过v-if局部刷新某些相关组件:data(){ 
return {
lang: this.$i18n.locale()
}
}
changeLang(lang){
this.$i18n.set(lang);
this.lang = this.$i18n.locale();
},
watch: {
lang(newVal, oldVal) {
if(newVal === oldVal) {
return;
}
// 在这里通过改变某个标志位 结合 v-if 来触发某个局部组件的重新渲染
}
}
8、Yaml中特殊字符的转义
[、]等,需要进行转义。转的方式是给键值加上单引号引起来。str: 'labor''s day' 
逆锋起笔是一个专注于程序员圈子的技术平台,你可以收获最新技术动态、最新内测资格、BAT等大厂的经验、精品学习资料、职业路线、副业思维,微信搜索逆锋起笔关注!
评论
