公司后台管理系统需要使用多语言版本,本次记录使用i18n实现多语言切换的流程步骤:
1、安装工具包

npm install vue-i18n

2、在项目src目录下新建lang文件夹,目录结构如下:

-lang
	|----index.js // 脚本文件
	|----en.js // 我们自己的英文包
	|----zh.js // 我们自己的中文包

element-ui本身有自己的语言包,我们需要先引入。我这里引入了js-cookie工具包来读写cookie,从cookie中看有没有设置中英文标识,没有,就获取浏览器的语言信息来确定中英文标识。

上面indexjs文件内容:

// lang/index.js
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import Cookies from 'js-cookie'
import elementEnLocale from 'element-ui/lib/locale/lang/en' // element-ui lang
import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN'// element-ui lang
import enLocale from './en'
import zhLocale from './zh'

Vue.use(VueI18n)

const messages = {
  en: {
    ...enLocale,
    ...elementEnLocale
  },
  zh: {
    ...zhLocale,
    ...elementZhLocale
  }
}
export function getLanguage() {
  const chooseLanguage = Cookies.get('language')
  if (chooseLanguage) return chooseLanguage

  // if has not choose language
  const language = (navigator.language || navigator.browserLanguage).toLowerCase()
  const locales = Object.keys(messages)
  for (const locale of locales) {
    if (language.indexOf(locale) > -1) {
      return locale
    }
  }
  return 'zh'
}
const i18n = new VueI18n({
  // set locale
  // options: en | zh | es
  locale: getLanguage(),
  // set locale messages
  messages
})

export default i18n

zh.js中文包,我是按页面分的,页面下的标识符对应中英文翻译。到时候在页面中使用标识符就可以了。

// lang/zh.js
export default {
  navbar: {
    dashboard: '首页',
    logOut: '退出登录',
    profile: '个人中心',
    theme: '换肤',
    size: '布局大小'
  },
  login: {
    title: '系统登录',
    logIn: '登录',
    usernameTips: '请输入用户名',
    passwordTips: '请输入密码',
    remeberPsd: '记住密码',
    forgotPsd: '忘记密码?',
    freeRegister: '免费注册',
    usernameCheckedTips: '请输入用户名',
    passwordCheckedTips: '请输入密码',
    codeCheckedTips: '请输入验证码'
  }
}

对应的en.js英文包

// lang/en.js
export default {
  navbar: {
    dashboard: 'Home',
    logOut: 'Logout',
    profile: 'Personal Center',
    theme: 'Change Theme',
    size: 'Layout Size'
  },
  login: {
    title: 'xxx',
    logIn: 'xxx',
    usernameTips: 'xxx',
    passwordTips: 'xxx',
    remeberPsd: 'xxx',
    forgotPsd: 'xxx?',
    freeRegister: 'xxx',
    usernameCheckedTips: 'xxx',
    passwordCheckedTips: 'xxx',
    codeCheckedTips: 'xxx'
  }
}

3、在项目的main.js文件中引入多语言国际化

// main.js
import Vue from 'vue'
import App from './App'
import store from './store'
import router from './router'
// 引入element-ui框架
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI, {
  i18n: (key, value) => i18n.t(key, value)
})
import i18n from './lang' // 语言国际化方案
new Vue({
  el: '#app',
  router,
  store,
  i18n, // 挂载i18n
  render: h => h(App)
})

element-ui需要按照官方说的配置多语言方案。再引入我们自己的i8n配置, 最好挂载到根vue实例上。

4、(可选)在vuex和cookie中保存选择语言的标识
我的vuex目录文件夹为store

store
	|---modules
			|---app.js
	|---getters.js
	|---index.js

app.js文件内容为

// store/modules/app.js
import Cookies from 'js-cookie'
import { getLanguage } from '@/lang/index'
const state = {
  language: getLanguage()
}

const mutations = {
  SET_LANGUAGE: (state, language) => {
    state.language = language
    Cookies.set('language', language)
  }
}
const actions = {
  setLanguage({ commit }, language) {
    commit('SET_LANGUAGE', language)
  }
}
export default {
  namespaced: true,
  state,
  mutations,
  actions
}

getters.js内容为

const getters = {
  language: state => state.app.language
}
export default getters

index.js内容

// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import app from './modules/app'

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    app
  },
  getters
})

export default store

一样的,最后在main.js引入store并且挂载到vue根实例。

5、在页面中使用
例如, 我在login.vue文件中使用多语言
原来的是这样的

<div class="login-title">
    <span>登录</span>
</div>

替换为

<div class="login-title">
    <span>{{ $t('login.title') }}</span>
</div>

$t(' ')来获取i8n,属性上使用需要属性绑定,script中使用需要this.$t(''),加this来获取。
在中英文切换按钮上绑定一个切换中英文的方法

 <div >
        <span @click="handleSetLanguage('zh')">简体中文</span>
        <span>|</span>
        <span @click="handleSetLanguage('en')">English</span>
</div>
// 中间省略
 handleSetLanguage(lang) {
      this.$i18n.locale = lang
      this.$store.dispatch('app/setLanguage', lang)
      this.reload() // fix语言切换后,element-ui弹窗提示文字不能切换,必须强制刷新页面才能解决的bug
    },

备注:this.reload()是我为了修复element-ui,输入框错误提示文字,不会随着切换语言而自动切换的bug,添加了一个强制刷新当前页面的全局方法,使用了vue的provide/reject方式,有需要的可以自己百度。

6、附加需求,我的请求接口也需要传递中英文切换后的语言代码给后台,返回对应的语言版本的后台数据。
所有我的请求头需要配置多语言支持。
可以在axios请求拦截器中统一设置,其他代码略。

service.interceptors.request.use(
  config => {
    // 请求发送前的设置
    config.headers['lan'] = store.getters.language
    return config
  },
  error => {
    console.log(error) // for debug
    return Promise.reject(error)
  }
)

7、路由菜单导航面包屑的i18n国际化
我的菜单名称是根据路由中的meta中的title字段来显示的,譬如我的路由定义:

  // 首页
  {
    path: '/',
    component: Layout,
    redirect: '/home',
    children: [{
      path: 'home',
      name: 'Home',
      component: () => import('@/views/home/index'),
      meta: { title: 'Home', icon: 'home', affix: true }
    }]
  },

并且我的导航菜单,有一部分是定义在本地的,有一部分是异步从服务器获取的。
so,需要一个定义一个转换函数:

// 路由与面包屑导航栏国际化工具函数
export function generateTitle(title) {
  const hasKey = this.$te('route.' + title)
  if (hasKey) {
    const translatedTitle = this.$t('route.' + title)
    return translatedTitle
  }
  return title
}

$te$t一样,是i18n定义的函数,测试参数是否在语言包中定义,返回布尔值。文章末尾参考连接中讲i8n源码的文章有提到这些函数,可以参考。
然后在导航菜单的组件内引入使用:

// menu.vue
<template>
 <span>{{ generateTitle(item.meta.title) }}</span> // 使用函数
</template>
<script>
import { generateTitle } from '@/utils/i18n' //引入函数
methods: {
generateTitle, // 这里需要声明一下。
其他函数...
}
</script>
 

最后附上两个参考文字地址:
1、https://blog.csdn.net/DOCALLEN/article/details/78408137

2、https://blog.csdn.net/wxl1555/article/details/85112530

3、vue中如何使用i18n实现国际化:https://segmentfault.com/a/1190000016445415

4、前端国际化之Vue-i18n源码分析,提到了$te等其他i18n全局方法。

Logo

前往低代码交流专区

更多推荐