系统国际化双语 i18n 方案

1. 依赖安装

使用如下命令安装

npm install vue-i18n --save

2. 配置

在 项目的src目录下新建lang目录,其结构如下图:

image.png

各文件内容如下:

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-en(英文)
import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN'// element-ui lang-zh(中文)
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

  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 'en'
}
const i18n = new VueI18n({
  // set locale
  // options: en | zh
  locale: getLanguage(),
  // set locale messages
  messages
})

export default i18n
// 按模块配置
const cn = {
  route: {
    home: '首页',
    link: '链接'
  },
   home: {
    home: '首页',
    ...
  },
  login: {
    login: '登录',
  }
  ... // 中文词库
}

export default cn;
const en = {
  route: {
    home: 'Home',
    link: 'Link'
  },
  home: {
    home: 'Home',
    ...
  },
  login: {
    login: 'Login',
    ...
  }
  ... // 英文词库
}

export default en;

main.js 中引入,并将其注入到vue实例中

import i18n from './lang'
// 设置ElementUI语言
Vue.use(ElementUI, {
  i18n: (key, value) => i18n.t(key, value)
})
new Vue({
  el: '#app',
  router,
  store,
  i18n, 
  render: h => h(App)
})

结合cookies和vuex使用

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
}

3. 模版中使用

a. html 中使用

*: 括号内属性必须加 '' 文本中使用格式 {{t('message.lang')}}或者使用 v-textshuv-text=t('login.login') vue 标签的属性中可使用绑定值: 标签

b. js 中使用

  1. 在 vue 的methods 中可以使用全局属性访问到

getLang() { return this.$t('obj.prop')}

  1. data 属性处理

但是在 data 属性中的数据需要刷新后才会切换语言,官方文档的建议解决方案为:data中要使用 i18n 的数据放在 computed属性中处理,如下实例中对表单校验规则的处理:

computed: {
  rules() {
    return {
      username: [{ required: true, message: this.$t('login.tip1'), trigger: "blur" }],
      password: [{ required: true, message: this.$t('login.tip2'), trigger: "blur" }]
    }
  }
  },

其他方法:

  • 不使用message传入错误提示 ,手动传入验证规则
let validateCode = (rule, value, callback) => {
  if (!value) {
    return callback(new Error(this.$t('common.validateCode')))
  } else {
    return callback()
  }
};
rules: {
  code: [
    {validator: validateCode, trigger: 'blur'}
  ]
}
  • 监听i18n,切换语言进行处理
computed: {
  lang() {
    return this.$store.getters.language
  }
}
watch: {
  lang(val) {
    this.accuracyContent()
  }
}
  1. 在单独的 js 文件中使用

需要引入 i18n.js 模块进行访问

//中英文切换 
import i18n from '@/lang/index.js'; 
var a = i18n.t('obj.prop')`;
  1. 面包屑及导航栏中中英文切换封装方法
export function generateTitle(title) {
  const hasKey = this.$te('route.' + title)

  if (hasKey) {
    const translatedTitle = this.$t('route.' + title)

    return translatedTitle
  }
  return title
}
  1. js 中使用 $t注意事项

如果你使用如 select组件,它的值是通过 v-for而来,如:

<el-select v-model="value">
  <el-option
    v-for="item in options"
    :key="item.value"
    :label="item.label"
    :value="item.value"/>
</el-select>
this.options = [
  {
    value: '1',
    label: this.$t('i18nView.one')
  },
  {
    value: '2',
    label: this.$t('i18nView.two')
  },
  {
    value: '3',
    label: this.$t('i18nView.three')
  }
]

这种情况下,国际化只会执行一次,因为在 js 中的this.options只会在初始化的时候执行一次,它的数据并不会随着你本地 lang的变化而变化,所以需要你在lang变化的时候手动重设this.options。

export default {
  watch: {
    lang() {
      this.setOptions()
    }
  },
  methods: {
    setOptions() {
      this.options = [
        {
          value: '1',
          label: this.$t('i18nView.one')
        },
        {
          value: '2',
          label: this.$t('i18nView.two')
        },
        {
          value: '3',
          label: this.$t('i18nView.three')
        }
      ]
    }
  }

5. 全局控件

image.png
<template>
  <el-dropdown trigger="click" class="international" @command="handleSetLanguage">
    <div>
      <svg-icon class-name="international-icon" icon-class="language" style="fill: #36a3f7" />
    </div>
    <el-dropdown-menu slot="dropdown">
      <el-dropdown-item :disabled="language==='zh'" command="zh">
        中文
      </el-dropdown-item>
      <el-dropdown-item :disabled="language==='en'" command="en">
        English
      </el-dropdown-item>
    </el-dropdown-menu>
  </el-dropdown>
</template>

<script>
export default {
  computed: {
    language() {
      return this.$store.getters.language
    }
  },
  methods: {
    handleSetLanguage(lang) {
      // console.log(this.$store.state.user.system, 'kkk')
      this.$i18n.locale = lang
      this.$store.dispatch('app/setLanguage', lang)
      this.$message({
        message: `${lang === 'zh' ? '中文切换成功' : 'English Switch Succeeded'}`,
        type: 'success'
      })
    }
  }
}
</script>
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容