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等大厂的经验
、精品学习资料
、职业路线
、副业思维
,微信搜索逆锋起笔
关注!
评论