老板说我们的项目要和国际接轨,于是乎,加上了多语言(vue-i18n)。项目用到的UI框架是element ui ,后续echarts、joint等全都得加上多语言。
一、言归正传,i18n在vue项目里如何使用呢?
第一步,Hold On!不对啊,肯定是先install啊,不install怎么use?急得我都和国际接轨了!!!
npm install vue-i18n -save
看到这段话得时候相信you and me 已经把它install好了,现在,してください....额,有点太接轨了吧!日语都出来了,咳咳,现在,我们是不是得在main.js里边引入vue-i18n呢,然后在目录下建立language文件夹了呢!!!
import VueI18n from "vue-i18n";
客官且慢,先别急着动你的small 手手哦!在什么目录下建立语言包的文件夹呢?难道要在main.js下?
想了想觉得不对。还是在utils文件夹下,建立一个locales文件夹,最后在main.js里边引入。
第二步,随便你在哪里建立一个locales文件夹,在locales下建立index.js、en.json(English)、和zh.json(中文)三个文件。
不要问我en.json以及zh.json是用来干嘛的,问就是用来存放语言的!
我们以 ‘你好帅’ 作为多语言的案例,注意,两个文件里边key一定要是一样的。
en.json 文件:
{ "handsome":“ZZC,You're handsome” }
zh.json 文件:
{ "handsome":“ZZC,你好帅” }
第三步,我们在index.js来写多语言的实现。好,两分钟已经过去了,代码已经写好了!哈哈哈,看下边代码吧,有注释哦~
import Vue from 'vue' // 引入vue实例 import VueI18n from 'vue-i18n' // 引入vue-i18n多语言包 Vue.use(VueI18n) // vue使用vue-i18n const DEFAULT_LANG = 'en' // 默认语言为英文 const LOCALE_KEY = 'DemoLanguage' // localStorage来存放的key,名字随便定,接下来会用到。 const locales = { // 引入zh.json以及en.json zh: require('./zh.json'), en: require('./en.json') } const i18n = new VueI18n({ // 创建带有选项的 VueI18n 实例 locale: DEFAULT_LANG, // 语言标识,在这里默认为en,即为英文 messages : locales // 语言包,上边创建的json文件 }) export const setup = lang => { //切换语言的函数,lang为语言标识,en或者zh // 在此判断lang的值,如果未定义,则让lang默认为DEFAULT_LANG,目的是为了让用户在未选择语言的时候默认为英文。 if(lang == undefined){ lang = window.localStorage.getItem(LOCALE_KEY) if ( locales[lang] == undefined ) { lang = DEFAULT_LANG } }
// 若lang有值,那么存入localStorage中,key为LOCALE_KEY,value为lang。 window.localStorage.setItem(LOCALE_KEY, lang) Object.keys(locales).forEach(item => { document.body.classList.remove('lang-${item}') }) document.body.classList.add('lang-${lang}') document.body.setAttribute('lang', lang) Vue.config.lang = lang i18n.locale = lang } setup() export default i18n
第四步,代码写好以后,在main.js注入多语言vue-i18n依赖。
import i18n from '../utils/locale' // ··· new Vue({ store, router, i18n, render: h => h(App) })
最后,接着就可以在vue页面中使用了,在这里我们只讲$t的使用。
<template> <section> <h3>{{$t("handsome")}}</h3> <el-button @click="changeLanguage('en')">English</el-button> <el-button @click="changeLanguage('zh')">中文</el-button>
</section>
</template> ... import { setup } from "../utils/locales"; // methods changeLanguage(lang) { this.$i18n.locale = lang
setup(lang);
location.reload() // 为了重新实例化vue-router对象,避免一些bug
}
扩展,具体请转到https://hachijiang.github.io/vue-i18n%E5%8E%9F%E7%90%86%E8%A7%A3%E6%9E%90/
基本方法:
-
$t
:普通词 -
$tc
:单复数 -
$te
:check 翻译key是否存在 -
$d
:时间日期 -
$n
:货币数字
自定义指令:v-t
高阶:
- linked locale messages
-
<i18n></i18n>
:组件块的拼接与复用
二、到这里还没结束呢, 要怎么结合element ui 呢?
我们都知道,element ui有它自带的一套国际化配置。像日期控件、分页控件等,不会随着vue-i18n的配置改变而改变,换句话说,以上的代码,是不能够切换element ui内部控件的语言类型。
嗯,那么问题来了,怎么在切换语言的时候同时切换element ui 内部的控件呢???
别急,我们还是来到刚才的那段代码中,添加一些神秘的代码,就可以切换了。
好了,20秒已经过去了,代码已经写好了。客官请看粗大...啊呸!加粗加大部分!
import Vue from 'vue' import VueI18n from 'vue-i18n'
// 引入element ui自带语言包 import ElementUILocale from 'element-ui/lib/locale' import enLocale from 'element-ui/lib/locale/lang/en' import zhLocale from 'element-ui/lib/locale/lang/zh-CN' Vue.use(VueI18n) const DEFAULT_LANG = 'en' const LOCALE_KEY = 'DemoLanguage' const locales = { zh: require('./zh.json'), en: require('./en.json') } const i18n = new VueI18n({ locale: DEFAULT_LANG, messages : locales, }) const UIlocales = { zh: zhLocale, en: enLocale }
// 通过判断lang语言标志符来return先对应的语言 const setUIlocales = lang =>{ switch (lang) { case 'zh': return UIlocales.zh case 'en': return UIlocales.en } } export const setup = lang => { if(lang == undefined){ lang = window.localStorage.getItem(LOCALE_KEY) if ( locales[lang] == undefined ) { lang = DEFAULT_LANG } } window.localStorage.setItem(LOCALE_KEY, lang) Object.keys(locales).forEach(item => { document.body.classList.remove('lang-${item}') }) document.body.classList.add('lang-${lang}') document.body.setAttribute('lang', lang) Vue.config.lang = lang i18n.locale = lang ElementUILocale.use(setUIlocales(lang)) // element ui 切换语言 } setup() export default i18n
哈哈哈,是不是很简单啊!现在快去试试看切换语言后分页或者时间等其他控件是否有change呢!!!
三、怎么结合vue-router呢?
看到这个问题之后,你肯定会有疑问!之前不是已经配置好了吗,一个路由,不写个$t('xxx')就OK了?这还能难道聪明的我???跟下图一样:
router.js文件
// ×××错误写法
export const constantRouterMap = [ {
path: '/home',
name: this.$t('home')
component: () => import('@/views/home/index),
hidden: true
} ]
如果觉得自己胸有成竹,请你把代码按照这个写法写,不出错要什么我都不给你!!!哈哈哈!
对的,肯定报错的,vue-i18n和vue-router属于同级,你怎么去用呢???
哈哈哈,仔细思考一下,既然$t('key')这种写法不对,那么,我们还能想到什么呢???给你三分钟思考的时间!!!
滴~滴~滴~老司机说三小时都过去了,你想出来了吗???
对!!!这个key才是你要翻译的name,为何纠结于一定用$t('key')这种行不通的法子捏?
既然方法不重要,key重要,那么我们就把$t拿掉,留下key。
export const constantRouterMap = [ { path: '/home', name: 'home' component: () => import('@/views/home/index), hidden: true } ]
zh.json
{ "home":"我的主页" }
en.json
{ "home":"My Home" }
这样的话,我们只要在渲染的时候把相应的name用$t('name')来切换就可以了。关注加粗的部分就行了!
<div>
<template v-for="item in routes" v-if="!item.hidden&&item.children">
<el-submenu v-if="hasChildren(item)" :index="item.name||item.path" :key="item.name">
<template slot="title">
<span class="router_border"></span>
<svg-icon v-if="item.meta&&item.meta.icon" :icon-class="item.meta.icon"></svg-icon>
<span v-if="item.name" slot="title">{{$t(item.name)}}</span>
</template>
</el-submenu>
</template>
</div
到这就结束了!!!新的一天,也请继续加油吧!!!