欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 幼教 > Vue实现国际化与国际化原理深究(前端国际化通用解决方案)

Vue实现国际化与国际化原理深究(前端国际化通用解决方案)

2024/10/24 19:15:42 来源:https://blog.csdn.net/u013946061/article/details/141233912  浏览:    关键词:Vue实现国际化与国际化原理深究(前端国际化通用解决方案)

文章目录

  • 国际化实现原理
  • 基于 vue-i18n V9 的国际化实现方案分析
    • 项目中完成国际化分成以下几步进行
  • 封装 langSelect 组件
  • element-plus 国际化处理(旧版本)
  • 自定义语言包国际化处理
  • 处理项目国际化内容
  • 国际化缓存处理(刷新页面后国际化丢失)
  • 国际化方案总结
  • 关于 element-plus 国际化问题更新

国际化实现原理

我们有一个变量 msg ,但是这个 msg 有且只能有两个值:

  1. hello world
  2. 你好世界

要求:根据需要切换 msg 的值

js 实现:
1. 定义 msg 值的数据源
定义一个对象【messages】,属性是 locale 为语言比如 zh、en 等,value 是一个对象(key、value 的形式),比如定义一个 msg 属性,里面就是对应的值。
2. 定义切换变量【定义locale】
3. 定义赋值函数 t 【参数为 key,返回messages[locale][key]】
4. 为 msg 赋值 【调用 t 函数,传递 key,比如 zh】

<script>// 1. 定义 msg 值的数据源const messages = {en: {msg: 'hello world'},zh: {msg: '你好世界'}}// 2. 定义切换变量let locale = 'en'// 3. 定义赋值函数function t(key) {return messages[locale][key]}// 4. 为 msg 赋值 let msg = t('msg')console.log(msg);// 修改 locale, 重新执行 t 方法,获取不同语言环境下的值</script>

总结:

  1. 通过一个变量来 控制 语言环境【locale】
  2. 所有语言环境下的数据源要 预先 定义好
  3. 通过一个方法来获取 当前语言指定属性 的值 (如上t函数)
  4. 该值即为国际化下展示值

基于 vue-i18n V9 的国际化实现方案分析

使用 vue-i18n 进行实现(V9 版本)
vue-i18n 的使用可以分为四个部分:

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

1、 安装

npm install vue-i18n@next

2、 创建 i18n/index.js 文件
创建 messages 数据源 (对象)

const messages = {en: {msg: {test: 'hello world'}},zh: {msg: {test: '你好世界'}}
}

3、创建 locale 语言变量 (默认英文)
const locale = 'en'
4、初始化 i18n 实例
lang/index.js

import { createI18n } from 'vue-i18n'const i18n = createI18n({// 使用 Composition API 模式,则需要将其设置为falselegacy: false,// 全局注入 $t 函数globalInjection: true,locale,messages
})export default i18n; // 方便其他js文件使用,可以import导入

5、把 i18n 注册到 vue 实例

export default i18n

6、在 main.js 中导入

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

项目中完成国际化分成以下几步进行

  1. 封装 langSelect 组件用于修改 locale
  2. 导入 el-locale 语言包
    1. 语言包分为两种
      1. elementUI 语言包
      2. 自定义的语言(比如一些特殊名称等等)
  3. 创建自定义语言包

封装 langSelect 组件

国际化最终会在全局做国际化的内容修改,因此应当把国际化保存到vuex中,还有对应的本地缓存中。
首先在 vuex 中创建国际化相关的变量

import { LANG } from '@/constant' // 常量
import { getItem, setItem } from '@/utils/storage'
export default {namespaced: true,state: () => ({...language: getItem(LANG) || 'zh' // 优先从本地缓存获取}),mutations: {.../*** 设置国际化*/setLanguage(state, lang) {setItem(LANG, lang) // 保存本地缓存state.language = lang  // 设置新值}},actions: {}
}

使用el-dropdown组件
如果当前语言是中文,选型中已经选择的“中文”是灰色的不能点击的。

<template><el-dropdowntrigger="click" // 点击事件class="international"@command="handleSetLanguage" // 点击事件回调方法,当用户选择下拉菜单中的选项时,触发 handleSetLanguage 方法,该方法根据用户选择的语言进行处理。>el-dropdown上会有提示<div> // 实现鼠标移入到el-dropdown上会有提示<el-tooltip content="国际化" :effect="effect"> // effect实现对应样式,tooltip的样式<svg-icon icon="language" /></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 { useI18n } from 'vue-i18n'import { defineProps, computed } from 'vue'import { useStore } from 'vuex'import { ElMessage } from 'element-plus'defineProps({ // 接收父组件的props// tooltip的样式effect: {type: String,default: 'dark',validator: function(value) { // 只有两个值// 这个值必须匹配下列字符串中的一个return ['dark', 'light'].indexOf(value) !== -1}}})const store = useStore()const language = computed(() => store.getters.language) // 获取到当前中英文的状态// 切换语言的方法const i18n = useI18n()const handleSetLanguage = lang => { // 根据el-dropdown-item的command属性// 切换i18n的localei18n.locale.value = lang// 修改vuex保存的languagestore.commit('app/setLanguage', lang)// 对应的提示ElMessage.success('更新成功')}
</script>

具名插槽在组件内部是这样定义的, 在组件内部,el-dropdown 可能像这样定义了 dropdown 插槽:

<slot name="dropdown"></slot>

navbar 中导入 LangSelect 使用

<template><div class="navbar">...<div class="right-menu"><lang-select class="right-menu-item hover-effect" /><!-- 头像 -->...</div></div>
</template><script setup>
import LangSelect from '@/components/LangSelect'
...
</script><style lang="scss" scoped>
.navbar {....right-menu {...::v-deep .right-menu-item {display: inline-block;padding: 0 18px 0 0;font-size: 24px;color: #5a5e66;vertical-align: text-bottom;&.hover-effect {cursor: pointer;}}...
}
</style>

element-plus 国际化处理(旧版本)

那么对于语言包来说,我们整个项目中会分成两部分:

  1. element-plus 语言包:用来处理 element 组件的国际化功能
  2. 自定义语言包:用来处理 element 组件的国际化功能

目前最新版本的element-plus 支持 vue-i18n 功能,以前是不支持的,需要自己单独处理。【暂时不管】
plugins/index 中导入 element 的中文、英文语言包:

import zhCn from 'element-plus/es/locale/lang/zh-cn'
import en from 'element-plus/lib/locale/lang/en'

注册 element 时,根据当前语言选择使用哪种语言包

import store from '@/store'export default app => {app.use(ElementPlus, {locale: store.getters.language === 'en' ? en : zhCn})
}

自定义语言包国际化处理

自定义语言包我们使用了 commonJS 导出了一个对象,这个对象就是所有的 自定义语言对象
中文语言包

export default {login: {title: '用户登录',loginBtn: '登录',usernameRule: '用户名为必填项',passwordRule: '密码不能少于6位',desc: `测试权限账号:<br />提供三种权限账号:<br />1. 超级管理员账号: super-admin <br />2. 管理员账号:admin <br />3. 测试可配置账号:test <br />密码统一为:123456 <br /><br />导入用户账号:<br />可使用导入的用户名登录 <br />密码统一为:123456  <br /><b>注意:导入用户区分中英文库!!!!</b>`},route: {profile: '个人中心',chart: '数据可视化', // ...

英文语言包

export default {login: {title: 'User Login',loginBtn: 'Login',usernameRule: 'Username is required',passwordRule: 'Password cannot be less than 6 digits',desc: `Test authority account:<br />Provide three kinds of authority accounts:<br />1. Super administrator account: super-admin <br />2. Administrator account: admin <br />3. Test configurable account: test <br />The uniform password is: 123456 <br /><br />Import user account:<br />You can log in with the imported username <br />The password is unified as: 123456 <br /><b>Note: Import user-discriminatory Chinese and English libraries! ! ! ! </b>`},route: {profile: 'Profile',chart: 'chart',

lang/index 中,导入语言包

import mZhLocale from './lang/zh'
import mEnLocale from './lang/en'const messages = {en: {msg: {...mEnLocale}},zh: {msg: {...mZhLocale}}
}

处理项目国际化内容

在 Vue 的模版中使用国际化:

<div class="title-container"><h3 class="title">{{ $t('msg.login.title') }}</h3><lang-select class="lang-select" effect="light"></lang-select>
</div>

在 Vue 的 js 代码中使用的话【组件中使用 i18n】:

// 验证规则
const i18n = useI18n()
const loginRules = ref({username: [{required: true,trigger: 'blur',message: computed(() => {return i18n.t('msg.login.usernameRule')})}],

在 js 代码中直接导入即可
code\src\views\login\rules.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()}}
}

国际化缓存处理(刷新页面后国际化丢失)

问题:切换英文后,没有保留,所以刷新页面后又变成默认中文的界面了。
我们希望在 刷新页面后,当前的国际化选择可以被保留,所以想要实现这个功能,那么就需要进行 国际化的缓存处理
此处的缓存,我们依然通过两个方面进行:

  1. **vuex**** 缓存**
  2. **LocalStorage**** 缓存**

**i18n/index** 中,创建 **getLanguage** 方法:(之前已经缓存过了,这里只需要读取即可)

import store from '@/store'
/*** 返回当前 lang*/
function getLanguage() {return store && store.getters && store.getters.language
}

修改 createI18nlocalegetLanguage()

const i18n = createI18n({...locale: getLanguage()
})

国际化方案总结

国际化是前端项目中的一个非常常见的功能,那么在前端项目中实现国际化主要依靠的就是 vue-i18n 这个第三方的包。
i18n 的使用,整体来说就分为这么四步:

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

核心的内容其实就是 数据源的部分,但是大家需要注意,如果你的项目中使用了 第三方组件库 ,那么不要忘记 第三方组件库的数据源 需要 单独 进行处理!

关于 element-plus 国际化问题更新

现在 element-plus 已经提供了 国际化的处理方案,我们可以直接通过 el-config-provider 组件中的 locale 属性来指定当前国际化环境。

<template><el-config-provider :locale="zhCn"><app /></el-config-provider>
</template><script setup lang="ts">import { ElConfigProvider } from 'element-plus'import zhCn from 'element-plus/es/locale/lang/zh-cn'
</script>

code\src\App.vue

<template><el-config-provider :locale="store.getters.language === 'en' ? en : zhCn"><router-view /></el-config-provider>
</template><script setup>// ......import zhCn from 'element-plus/lib/locale/lang/zh-cn'import en from 'element-plus/lib/locale/lang/en'// ......
</script>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com