掌握 Vue3 国际化:从基础到实战

978 阅读3分钟

动画.gif

这样的切换语言功能,在一些组件库文档、框架使用文档、API 文档等都有这样的功能

那这个到底是怎么实现的?

国际化基本原理

创建下项目

 npm init vite-app vue3-local

进入文件夹中

 cd vue3-local

安装下依赖

 npm install

创建 src/i18nTest/test.vue

 <!--
 @description: 国际化
 -->
 ​
 <template>
   <div>{{ t('msg') }}</div>
 </template>
 ​
 <script setup lang='ts'>
 // 1. 定义 msg 值的数据源
 const messages = {
   en: {
     msg: 'hello word'
   },
   zn: {
     msg: '你好世界'
   }
 }
 ​
 // 2. 定义切换变量
 const local = 'zn'
 ​
 // 3. 定义赋值函数
 function t(key) {
   return messages[local][key]
 }
 ​
 </script>

App.vue 中导入 src/i18nTest/Local.vue

 <template>
   <Local />
 </template>
 ​
 <script setup lang="ts">
 import Local from './i18nTest/Local.vue'
 </script>
  1. 通过一个变量来控制语言环境
  2. 所有语言环境下的数据源要预先定义好
  3. 通过一个方法来获取当前语言指定属性的值
  4. 该值即为国际化下展示值 (中/音切换)

启动下项目,打开 http://localhost:3000

 npm run dev

image-20240529232142187.png 我们修改下语言,为英文 image-20240529232213053.png image-20240529232232287.png

基本效果是实现了,那我们在工作中,总不能这样去写吧!

我们可以使用这样一个插件 vue-i18n

[注]

vue3 下 vue-i18n 需要 v 9.0.x 的 i18n

vue-i18n 的使用分为 四个部分

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

vue-i18n 实现国际化

安装 vue-i18n

 npm install vue-i18n@next

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

 import { createI18n } from 'vue-i18n'
 // 这里可以把,msg 换成你要导入的语言包
 const messages = {
   en: {
     msg: {
       test: 'hello word'
     }
   },
   zh: {
     msg: {
       test: '你好世界'
     }
   }
 }
 ​
 const locale = 'en'
 ​
 const i18n = createI18n({
   // 使用 composition API
   legacy: false,
   // 全局使用 t 函数
   globalInjection: true,
   locale,
   messages
 })
 ​
 export default i18n

main.js 中 注册

 import { createApp } from "vue";
 import i18n from "./i18n";
 import App from "./App.vue";
 import "./index.css";
 ​
 const app = createApp(App);
 ​
 app.use(i18n)
 app.mount("#app");

src/i18nTest/index.vue 文件中使用 i18n,修改 i18n/index.js 中为 locale = 'zh',可切换展示内容

 <!--
 @description: i18n 国际化演示
 -->
 ​
 <template>
   <div>
     <button @click="handleSetLanguage">切换</button>
   </div>
   <div>
     setup 语法糖写法: {{ t('msg.test') }}
   </div>
   <div>
     template 旧版写: {{ $t('msg.test') }}
   </div>
 </template>
 ​
 <script setup lang='js'>
 /* ------------------------ 导入 与 引用 ----------------------------------- */
 import { ref, reactive } from 'vue'
 import { useI18n } from 'vue-i18n' // 【注意】 不管新旧版的写法,都要引入 useI18n 才有办法使用
 /* ------------------------ 变量 与 数据 ----------------------------------- */
 const { t, locale } = useI18n()
 /* ------------------------ 函数 与 方法 ----------------------------------- */
 // 切换语言的方法
 const  handleSetLanguage = () => {
   // 切换 i18n 的 locale
   locale.value === 'en' ? locale.value = 'zh' : locale.value = 'en'
 }
 </script>

APP.vue 文件导入 src/i18nTest/index.vue

 <template>
   <div>
     <I18nTest />
   </div>
 </template>
 ​
 <script setup lang="ts">
 import I18nTest from './i18nTest/index.vue';
 ​
 </script>

image-20230709191605245.png

[注]

该方案主要用于 自定义 语言包管理

后续可添加 持久化 等等

element-plus 国际化实现

[注]

element-plus 的国际化,只针对 element-plus 组件做 国际化,并不会对一些后端返回数据,或者自定义内容做国际化

也就是说,element-plus 引入的语言包只支持,element-plus 组件

安装 element-plus

npm install element-plus

main.js 中导入element-plus

import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import i18n from "./i18n";
import App from './App.vue'const app = createApp(App)
​
app.use(ElementPlus)
app.use(i18n)
​
app.mount('#app')

src/i18nTest/index.vue 在原有基础上引入了 element-plus 的分页组件 image-20240530093016941.png

引入 element-plus 组件已经翻译好的语言包 image-20240530093043436.png

根据 local 来判断当前语言,并替换为对应语言包 image-20240530093213467.png

 <!--
 @description: i18n 国际化演示
 -->
 ​
 <template>
   <div class="middle">
     <div>
       <button @click="handleSetLanguage">切换</button>
     </div>
     <div>
       setup 语法糖写法: {{ t('msg.test') }}
     </div>
     <div>
       template 旧版写: {{ $t('msg.test') }}
     </div>
     <div style="width: 400px;">
       <el-config-provider :locale="elementLocale">
         <el-table mb-1 :data="[]" />
         <el-pagination :total="100" />
       </el-config-provider>
     </div>
   </div>
 </template>
 ​
 <script setup lang='js'>
 /* ------------------------ 导入 与 引用 ----------------------------------- */import { ref, computed } from 'vue'
 import { useI18n } from 'vue-i18n'import zh from 'element-plus/dist/locale/zh-cn.mjs'
 import en from 'element-plus/dist/locale/en.mjs'/* ------------------------ 变量 与 数据 ----------------------------------- */const { t, locale } = useI18n()
 const elementLocale = computed(() => (locale.value === 'zh' ? zh : en))
 ​
 /* ------------------------ 函数 与 方法 ----------------------------------- */
 // 切换语言的方法
 const  handleSetLanguage = () => {
   // 切换 i18n 的 locale
   locale.value = locale.value === 'zh' ? 'en' : 'zh'
 }
 ​
 </script>
 ​
 <style scoped lang="scss">
 .middle {
   width: 100vw;
   display: flex;
   align-items: center;
   justify-content: center;
   flex-direction: column;
 }
 </style>

image-20230709202327877.png

小结

国际化的主要原理是通过一个功能函数,对语言进行切换

我们可以使用 vue-i18n 插件这个比较完善的插件替换不同语言包

如果要对组件库组件也进行国际化,那么直接去下载 element plus 对应语言包,不必自己再去一个一个翻译了