使用vue-i18n实现国际化


在 vue 的项目中,我们不需要手写这么复杂的一些基础代码,可以直接使用 vue-i18n 进行实现(注意:vue3 下需要使用 V 9.x 的 i18n)

vue-i18n 的使用可以分为四个部分:

  1. 创建 messages 数据源
  2. 创建 locale 语言变量
  3. 初始化 i18n 实例
  4. 注册 i18n 实例

  1. 安装 vue-i18n:
npm install vue-i18n@next
  1. 创建 i18n/index.js 文件
import {
  createI18n
} from 'vue-i18n'
const messages = {
  en: {
    msg: {
      test: 'hello world'
    }
  },
  zh: {
    msg: {
      test: '你好世界'
    }
  }
}

// 创建locale语言变量
const locale = 'en'

// 初始化 i18n 实例
export const i18n = createI18n({
  // 使用 Composition API 模式,则需要将其设置为false
  legacy: false,
  // 全局注入 $t 函数
  globalInjection: true,
  locale,
  messages
})

export default app => {
  app.use(i18n)
}

  1. 在 main.js 中导入
// i18n (PS:导入放到 APP.vue 导入之前,因为后面我们会在 app.vue 中使用国际化内容)
import i18n from '@/i18n'

app.use(i18n)
  1. 在 layout/components/Sidebar/index.vue 中使用 i18n

{{ $t('msg.test') }}

  1. 修改 locale 的值,即可改变展示的内容
<script setup>
// 引入i18n的hook
import { useI18n } from 'vue-i18n'
import { defineProps, computed } from 'vue'
import { useStore } from 'vuex'
import { ElMessage } from 'element-plus'

defineProps({
  effect: {
    type: String,
    default: 'dark',
    validator: function(value) {
      // 这个值必须匹配下列字符串中的一个
      return ['dark', 'light'].indexOf(value) !== -1
    }
  }
})

const store = useStore()
const language = computed(() => store.getters.language)

// 获取全局的i18n
const i18n = useI18n()
// 切换语言
const handleSetLanguage = lang => {
  i18n.locale.value = lang
  store.commit('app/setLanguage', lang)
  ElMessage.success('更新成功')
}
</script>
  1. 使用Element-Plus完成进行国际化处理
    对@/plugins/element.js进行语言包选择设置:
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'
// 引入中文
import zhCn from 'element-plus/lib/locale/lang/zh-cn'
// 引入英文
import en from 'element-plus/lib/locale/lang/en'
import store from '@/store'

export default (app) => {
// 根据当前store设置好的语言,切换Element-Plus组件的中英文
  app.use(ElementPlus, {
    locale: store.getters.language === 'en' ? en : zhCn
  })
}

在i18n/index.js下完成Element-Plus组件的国际化处理

import enLocale from 'element-plus/lib/locale/lang/en'
import zhLocale from 'element-plus/lib/locale/lang/zh-cn'

const messages = {
  en: {
    el: enLocale.el
  },
  zh: {
    el: zhLocale.el
  }
}

const locale = 'en'

export const i18n = createI18n({
  // 使用 Composition API 模式,则需要将其设置为false
  legacy: false,
  // 全局注入 $t 函数
  globalInjection: true,
  locale,
  messages
})

export default app => {
  app.use(i18n)
}

做到这里,按理说,Element-Plus已经可以根据我们的选择切换中英文了,但是现阶段Element-Plus还未完成vue-i18n进行联动的相关处理,所以需要我们自定义处理。

  1. 自定义语言包国际化处理
    将自定义语言包导入@/i18n目录下:
    其中,一个为中文语言包zh.js,一个为英文语言包en.js,
    zh.js:
export default {
  login: {
    title: '用户登录',
    loginBtn: '登录',
    usernameRule: '用户名为必填项',
    passwordRule: '密码不能少于6位',
    desc: `
    测试权限账号:
提供三种权限账号:
1. 超级管理员账号: super-admin
2. 管理员账号:admin
3. 测试可配置账号:test
密码统一为:123456

导入用户账号:
可使用导入的用户名登录
密码统一为:123456
注意:导入用户区分中英文库!!!! ` }, route: { profile: '个人中心', user: '用户', excelImport: 'Excel导入', userManage: '员工管理', userInfo: '员工信息', roleList: '角色列表', permissionList: '权限列表', article: '文章', articleRanking: '文章排名', articleCreate: '创建文章', articleDetail: '文章详情', articleEditor: '文章编辑' }, toast: { switchLangSuccess: '切换语言成功' }, tagsView: { refresh: '刷新', closeRight: '关闭右侧', closeOther: '关闭其他' }, theme: { themeColorChange: '主题色更换', themeChange: '主题更换' }, universal: { confirm: '确定', cancel: '取消' }, navBar: { themeChange: '主题修改', headerSearch: '页面搜索', screenfull: '全屏替换', lang: '国际化', guide: '功能引导', home: '首页', course: '课程主页', logout: '退出登录' }, guide: { close: '关闭', next: '下一个', prev: '上一个', guideTitle: '引导', guideDesc: '打开引导功能', hamburgerTitle: '汉堡按钮', hamburgerDesc: '打开和关闭左侧菜单', breadcrumbTitle: '面包屑', breadcrumbDesc: '指示当前页面位置', searchTitle: '搜索', searchDesc: '页面链接搜索', fullTitle: '全屏', fullDesc: '页面显示切换', themeTitle: '主题', themeDesc: '更换项目主题', langTitle: '国际化', langDesc: '语言切换', tagTitle: '标签', tagDesc: '已打开页面标签', sidebarTitle: '菜单', sidebarDesc: '项目功能菜单' }, profile: { muted: '《vue3 改写 vue-element-admin,实现后台前端综合解决方案》项目演示', introduce: '介绍', projectIntroduction: '项目介绍', projectFunction: '项目功能', feature: '功能', chapter: '章节', author: '作者', name: 'Sunday', job: '一个前端开发程序猿', Introduction: '高级技术专家,曾就职于国内一线互联网公司,统筹过的多个大型项目用户数已过千万级。致力于研究大前端技术,多次受邀参加国内前端技术分享会,如:2018 年 Google 中国技术分享会。' }, userInfo: { print: '打印', title: '员工信息', name: '姓名', sex: '性别', nation: '民族', mobile: '手机号', province: '居住地', date: '入职时间', remark: '备注', address: '联系地址', experience: '经历', major: '专业', glory: '荣耀', foot: '签字:___________日期:___________' }, uploadExcel: { upload: '点击上传', drop: '将文件拖到此处' }, excel: { importExcel: 'excel 导入', exportExcel: 'excel 导出', exportZip: 'zip 导出', name: '姓名', mobile: '联系方式', avatar: '头像', role: '角色', openTime: '开通时间', action: '操作', show: '查看', showRole: '角色', defaultRole: '员工', remove: '删除', removeSuccess: '删除成功', title: '导出为 excel', placeholder: 'excel 文件名称', defaultName: '员工管理表', close: '取 消', confirm: '导 出', importSuccess: ' 条员工数据导入成功', dialogTitle1: '确定要删除用户 ', dialogTitle2: ' 吗?', roleDialogTitle: '配置角色' }, role: { buttonTxt: '新增角色', index: '序号', name: '名称', desc: '描述', action: '操作', assignPermissions: '分配权限', removeRole: '删除角色', dialogTitle: '新增角色', dialogRole: '角色名称', dialogDesc: '角色描述', updateRoleSuccess: '用户角色更新成功' }, permission: { name: '权限名称', mark: '权限标识', desc: '权限描述' }, article: { ranking: '排名', title: '标题', author: '作者', publicDate: '发布时间', desc: '内容简介', action: '操作', dynamicTitle: '动态展示', show: '查看', remove: '删除', edit: '编辑', dialogTitle1: '确定要删除文章 ', dialogTitle2: ' 吗?', removeSuccess: '文章删除成功', titlePlaceholder: '请输入文章标题', markdown: 'markdown', richText: '富文本', commit: '提交', createSuccess: '文章创建成功', editorSuccess: '文章修改成功', sortSuccess: '文章排名修改成功' } }

en.js

...

在@/i18n/index.js中完成自定义语言包国际化处理:

import {
  createI18n
} from 'vue-i18n'
import enLocale from 'element-plus/lib/locale/lang/en'
import zhLocale from 'element-plus/lib/locale/lang/zh-cn'
// 引入自定义语言包
import mZhLocale from './lang/zh'
import mEnLocale from './lang/en'
const messages = {
  en: {
    el: enLocale.el,
    msg: {
      ...mEnLocale
    }
  },
  zh: {
    el: zhLocale.el,
    msg: {
      ...mZhLocale
    }
  }
}

const locale = 'en'

export const i18n = createI18n({
  // 使用 Composition API 模式,则需要将其设置为false
  legacy: false,
  // 全局注入 $t 函数
  globalInjection: true,
  locale,
  messages
})

export default app => {
  app.use(i18n)
}

同理,如果需要别的语言包,也可以按这种方式自定义

  1. 处理项目国际化内容

在组件标签中使用$t()进行处理:

// 在组件中需要中英文切换,不能写死的地方通过i18n提供的$t()获取i18n提供的中英文完成内容的替换,如下:
{{ $t('msg.test') }}

在.vue的script中进行处理:

// 引入i18n的钩子函数
import { useI18n } from 'vue-i18n'
// 获取i18n全局实例
const i18n = useI18n()
// 使用全局实例调用t()处理
ElMessage.success(i18n.t('msg.toast.swithLangSuccess'))

在.js中进行处理:

import i18n from '@/i18n'
export const validatePassword = () => {
  return (rule, value, callback) => {
    if (value.length < 6) {
      callback(new Error(i18n.global.t('msg.login.passwordRule')))
    } else {
      callback()
    }
  }
}