国际化实现原理
假设我们有一个变量 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
- 定义 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-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()}}