背景
一个现有的中文的大型且复杂的VUE项目,页面巨多,有n多个组件和页面!!!需要国际化语言,翻译成英文。
需要干的事
1.引入vue-i18n(vue的国际化插件),配置语言包,注意用了组件的,还得将组件的语言包导进来。
2.将项目里的文本提取出来,并翻译,作为翻译的语言包。
3.替换js和vue的文本。
说明
在这个项目中,需要把现有的巨多的页面文本都提取出来做一个翻译语言包,而且页面巨多,文本巨多。如果采用中文一个语言包(例如:{"note":"保存的名称重复"}),英文一个语言包({"note":"The saved name is duplicated."}),不仅要另外取属性名字,而且页面文本替换也不方便,得把中文文本替换成改的属性名,再包裹翻译方法。
于是,我们最终决定采用这样的一个语言包格式,中英文都在这一个包里面,例如:{"保存的名称重复":"The saved name is duplicated."} ,即左边中文,右边英文。这样不仅不用另外取属性名,方便语言包的提取和翻译,而且在页面中可以直接在中文文本上包裹翻译方法。就无需再替换中文文本为取的属性名,再包裹翻译方法了。
具体实现
1.引入vue-i18n(vue的国际化插件),配置语言包,注意用了组件的,还得将组件的语言包导进来。
安装
要安装指定版本的自行加@版本号
npm install vue-i18n
创建文件夹
在src文件夹下创建i18n文件夹(如图目录结构)
lan文件夹下存放各个页面用到的语言包
注:本来是准备将lan里面的文本语言包直接放在一个js文件里面的,但是页面实在是太多了,就对应把view目录下的所有文本,放到view.js(虽然一个view.js里面还是有好几百条数据,但是结构会清晰一点);components目录下的所有文本,放到component.js中这样了。最后再在lan文件夹下的index.js里把lan文件夹下的所有语言包(view.js,component.js,router.js等这些)合为一个语言包,暴露出去。(这么干就是为了结构清晰一点,和一个文件的语言包没啥区别)
再来以view.js为例,看看语言包格式长啥样吧,如下图。
在i18n下创建index.js,用来引入VueI18n并且导入语言包。
这里需要注意,要把组件的语言包也导进去,不然引用的组件还是中文的,本项目中用的组件是iview组件,国际化导包可以去对应的组件官网查看
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import iView from 'iview';
import en from './lan';
//iview组件国际化语言包
import zhLocale from 'iview/src/locale/lang/zh-CN';
import enLocale from 'iview/src/locale/lang/en-US';
Vue.use(VueI18n);
// 自动根据浏览器系统语言设置语言
const navLang = navigator.language
const localLang = (navLang === 'zh-CN' || navLang === 'en-US') ? navLang : false
let lang = localLang || 'zh-CN'
Vue.config.lang = lang;
//lan里面的中文语言包
const customZhCn = function () {
return Object.keys(en).reduce((acc, key) => {
acc[key] = key; // 中文环境下,键和值相同
return acc;
}, {})
}
export const i18n = new VueI18n({
locale: lang,
// locale: 'en-US',
messages: {
/**
这里是在将项目里的文本和iview组件里的包合并为一个包。
如果只需要一个项目里的语言包,不用iview组件的话,就直接'en-US':en这样**/
'zh-CN': Object.assign(customZhCn(), zhLocale),
'en-US': Object.assign(en, enLocale)
}
})
Vue.use(iView, {
i18n: (key, value) => i18n.t(key, value)
})
export default i18n;
在main.js里面全局引用i18n
2.将项目里的文本提取出来,并翻译,作为翻译的语言包。
3.替换js和vue的文本。
这两步真的累死个人,页面巨多,妥妥搬砖打杂,就单纯找项目里的所有文本提取到语言包里去,格式就是上面提到的view.js这样。
替换vue的文本,例如:
标签里的文本:<div>您好</div> 替换为 <div>{{$t('您好')}}</div>,
标签有属性的:<input placeholder="输入文本" ></input > 替换为 <input :placeholder="$t('输入文本')" ></input >
替换js的文本,例如:
1.在每个页面需要用到的先导入 import lang from '@/i18n'
再把js里面的文本用lang.t方法包裹,进行翻译,如下图:
2.如果不在每个js用翻译的地方import lang from '@/i18n'的话,就直接使用全局挂载的t方法。
例如:this.$t('请注意')
3.要注意的是!!
要是js里面有return的template的html语法,里面有文本的话,记得包裹{lang.t('文本')}翻译,如图:
4.还有要注意的是,一段文本里面,既有文本又有属性的时候,要包裹正确,如图:
当然这里i18n里面有占位的翻译,就不用去拆分一句话了。(可以去官网查看)
不过!我的同事在项目里写脚本全局提取中文文本,生成对应的目录结构存到里面!(虽然可能脚本写的可能不是很全,有些文本没有提取进去,也就是这样,我又干了很多打杂的活,去找文本提取,很栓q啊!)
和全局替换vue页面的(像<div>您好</div>,直接全局替换成了<div>{{$t('您好')}}</div>),不过属性的替换规则暂时还没想到好的提取,只能全局替换成(像<input placeholder="输入文本" ></input >,全局替换成<input placeholder="$t('输入文本')" ></input >,这时候就需要手动加 :了,变成<input :placeholder="$t('输入文本')" >您好</input >这样才对)
和全局替换js文本,用lang.t(")包裹,并在使用了这个方法的script中,自动引入import lang from '@/i18n'。
当然,我不会这脚本,待我去研究研究,偷师学艺一下,哈哈哈。