国际化实现原理
假设我们有一个变量 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.js
import { createI18n } from 'vue-i18n'
const messages = {
en: {
msg: {
test: 'hello'
}
},
zh: {
msg: {
test: '你好'
}
}
}
const locale = 'en'
const i18n = createI18n({
legacy: false, // 使用了Vue3 composition API的话这项一定要为false
globalInjection: true, // 全局使用 t 函数
locale,
messages
})
export default i18n
注册 i18n 实例
// main.js
import i18n from '@/i18n'
app.use(i18n).mount('#app')
测试
<template>
<div class="">
{{ $t('msg.test') }} <!-- 页面上会显示 hello -->
</div>
</template>
<script setup>
import {} from 'vue'
</script>
<style lang="scss" scoped></style>
项目中完成国际化
封装 langSelect 组件用于修改 locale
- 定义 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: {}
}
- 创建 LangSelect 组件
<template>
<el-dropdown
trigger="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 的 locale
store.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' ? 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的话这项一定要为false
globalInjection: 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()
}
}