国际化实现原理

假设我们有一个变量 msg,但是这个 msg 有两个值,一个是 hello,一个是 你好,现在需要我们根据需要切换 msg 的值,如何做呢?

// 定义 msg 值的数据源const msgList = {en: {msg: 'hello'},zh: {msg: '你好'}}// 定义切换变量let locale = 'en'// 定义赋值函数function t(key) {return msgList[locale][key]}// 为 msg 赋值let msg = t('msg')console.log(msg) // hello

总结

  • 通过一个变量来控制语言环境
  • 所有语言环境下的数据源要预先定义好
  • 通过一个方法来获取当前语言下指定属性的值
  • 该值为国际化下展示值

基于 vue-i18n V9(Vue3 适用) 的国际化实现方案

安装 vue-i8n

npm install vue-i18n@next

src目录下创建 i18n/index.js 文件

创建数据源、创建 locale 语言变量、初始化 i18n 实例

// index.jsimport { createI18n } from 'vue-i18n'const messages = {en: {msg: {test: 'hello'}},zh: {msg: {test: '你好'}}}const locale = 'en'const i18n = createI18n({legacy: false, // 使用了Vue3 composition API的话这项一定要为falseglobalInjection: true, // 全局使用 t 函数locale,messages})export default i18n

注册 i18n 实例

// main.jsimport i18n from '@/i18n'app.use(i18n).mount('#app')

测试

<template><div class="">{{ $t('msg.test') }} </div></template><script setup>import {} from 'vue'</script><style lang="scss" scoped></style>

项目中完成国际化

封装 langSelect 组件用于修改 locale
  1. 定义 store/app.js
export default {namespaced: true,state: {language: window.localStorage.getItem('language') || 'zh'},mutations: {/** * 设置国际化 */setLanguage(state, lang) {window.localStorage.setItem('language', lang)state.language = lang}},actions: {}}
  1. 创建 LangSelect 组件
<template><el-dropdowntrigger="click"class="international"@command="handleSetLanguage"><div><el-tooltip content="国际化"><svg-icon icon="language"></svg-icon></el-tooltip></div><template #dropdown><el-dropdown-menu><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></template></el-dropdown></template><script setup>import { computed } from 'vue'import { useStore } from 'vuex'import { useI18n } from 'vue-i18n'const store = useStore()const language = computed(() => store.getters.language)// 切换语言const i18n = useI18n()const handleSetLanguage = lang => {i18n.locale.value = lang // 切换 i18n 的 localestore.commit('app/setLanguage', lang) // 修改 vuex 中的 language}</script><style scoped></style>

导入 el-locale 语言包

在ElementUi中可以配合vue-i18n进行国际化,详细可看文档
但是在ElementPlus中不行(切换完语言需要刷新页面才能生效),只能临时进行处理:

import ElementPlus from 'element-plus'import 'element-plus/dist/index.css'import zhCn from 'element-plus/es/locale/lang/zh-cn'import en from 'element-plus/lib/locale/lang/en'import store from '@/store'export default (app) => {app.use(ElementPlus, {locale: store.getters.language === 'en' " />: zhCn})}

注意:使用的elementPlus版本为1.1.0-beta.15,版本不同不同文件位置可能不一样,引入的时候需要注意

创建自定义语言包

在 i18n 下新建 lang 文件夹,下面有 en.js 和 zh.js 两个语言包,在 i18n 下的 index.js 中引入

import { createI18n } from 'vue-i18n'import zhLocale from './lang/zh'import enLocale from './lang/en'const messages = {en: {msg: {...enLocale}},zh: {msg: {...zhLocale}}}const locale = 'zh'const i18n = createI18n({legacy: false, // 使用了Vue3 composition API的话这项一定要为falseglobalInjection: true, // 全局使用 t 函数locale,messages})export default i18n

en.js 和 zh.js 需要自己编写,分别是英文与中文环境下字段的数据:


处理项目国际化内容

将页面中写死的数据改为用 $t 函数,比如登录页的标题:

<h1 class="title">用户登录</div>
<h1 class="title">{{ $t('msg.login.title') }}</div>

vue 组件中:

const loginRules = ref({username: [{required: true,trigger: 'blur',message: '用户名为必填项'}]})
import { useI18n } from 'vue-i18n'const i18n = useI18n()const loginRules = ref({username: [{required: true,trigger: 'blur',message: i18n.t('msg.login.usernameRule')}]})

js 中:

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