需求背景
最近在工作中,使用的产品要对海外用户进行演示,国际化的功能是必不可少的,那么 如何在Vue3
中使用国际化,以及在 Element UI
中使用 vue-i18n
遇见的一些问题 就是这篇文章主要介绍的
主要内容
这篇文章主要介绍有以下几点:
vue3
如何使用vue-i18n
插件- 如何做到不同语言自由切换
- 在
Element UI
中使用vue-i18n
遇见的一些问题,以及解决方法
Vue3 国际化
要想在 Vue3
中使用国际化,首先需要安装 vue-i18n 插件,然后在main.js
中进行配置具体的配置
安装 vue-i18n
初始化项目后安装 vue-i18n
插件
npm install vue-i18n@next --save
配置国际化
目录结构
在 src
中新建 lang
文件夹,在 lang
中分别创建以下文件
├── src
│ ├── lang
│ │ ├── index.ts # 导出创建的i18n实例
│ │ ├── zh-CN.ts # 中文配置
│ │ └── en.ts # 英文配置
使用插件方法
在 index.ts
中我们需要引入插件做一些配置,并导出给app
实例使用
import { createI18n } from 'vue-i18n'
import enUS from './en'
import zhCN from './zh-CN'
const i18n = createI18n({
locale: 'zh-CN',
messages: {
'en-US': enUS,
'zh-CN': zhCN
}
})
export default i18n
在 en
和 zh-CN
中分别导出要用到中文和英文的翻译(当然如果是其他语言也可以在这个基础上添加,道理都是一样的)
// en.ts
export default {
message: {
hello: 'Hello!'
}
}
// zh-CN.ts
export default {
message: {
hello: '你好!',
}
}
接下来在 main.ts
中引入导出的 i18n
并且使用就好了
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import i18n from './locale'
const app = createApp(App)
app.use(i18n)
app.use(createPinia())
app.mount('#app')
在 App.vue
中使用
<template>
<h1>{{ $t('message.hello') }}</h1>
</template>
上面就是在Vue3中使用国际化的方法,那么呈现出来的就是这样
那我们如何切换语言呢?
我们在页面中引用插件提供的 useI18n
函数解构出 locale
变量,通过修改这个值就可以了,当然这个钩子只能在 setup
中使用,否则会报错,所以把我想对他封装的想法给扼杀了
<template>
<div>{{ $t('message.hello') }}</div>
<button @click="handleClick('en-US')">英文</button>
<button @click="handleClick('zh-CN')">中文</button>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
const { locale } = useI18n()
const handleClick = (lang: string) => {
locale.value = lang
}
</script>
那到这里的话,国际化的基本使用方法就介绍的差不多了,但是当我觉得一切都变得很顺利时候,发现了一个问题,那就是国际化结合 Element UI
组件的时候,遇见了一些问题,那具体是什么问题呢,我们来看一下
在 Element UI 使用 vue-i18n 遇到的问题
form表单的校验提示
原始想法
因为网站需要登录等功能,那么避免不了使用 Element UI
的表单组件,也避免不了让表单展示进行输入的校验提示,那么这个提示我们该如何进行切换?
一开始我的思路是: 因为可以在 useI18n
中能够解构出 t
函数,那么我直接将提示的 message
的属性值赋值成 t('xxx')
是不是就可以了?如果你的思路和我一样的话,那就不用去尝试了,因为我试过是不行的😭,当我进行语言切换的时候,校验提示不会动态的变化。
新的思路
那这种思路行不通就换个思维喽~,于是经过查阅,我选择的方式是:通过监听 locale
的值当发生改变的时候获取当前表单元素实例并调用提供的 clearValidate
方法,这样当输入框失焦未通过校验时此时的校验提示就发生了改变,那这样是否可行,让我们拭目以待
功能实现
<template>
<el-form ref="ruleFormRef" style="max-width: 300px" :model="ruleForm" :rules="rules">
<el-form-item :label="t('message.name')" prop="name">
<el-input v-model="ruleForm.name" />
</el-form-item>
<el-form-item> </el-form-item>
</el-form>
<el-button type="" @click="handleClick('zh-CN')"> 中文 </el-button>
<el-button type="" @click="handleClick('en-US')"> 英文 </el-button>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue'
import type { ComponentSize, FormInstance, FormRules } from 'element-plus'
import { useI18n } from 'vue-i18n'
const { locale, t } = useI18n()
interface RuleForm {
name: string
}
const handleClick = (lang: string) => {
locale.value = lang
}
const ruleFormRef = ref<FormInstance>()
const formatterFn = (rule: any, value: any, callback: any) => {
if (value === '') {
callback(new Error(t('message.nameValidate')))
} else {
callback()
}
}
const ruleForm = reactive<RuleForm>({
name: ''
})
const rules = reactive<FormRules<RuleForm>>({
name: [
{
validator: formatterFn,
trigger: 'blur'
}
]
})
watch(locale, () => {
ruleFormRef.value?.clearValidate()
})
</script>
那引入了 Element 组件并且按照上面说的我们写出了代码,那效果是怎样的呢?
可以看到,当我们切换语言的时候,校验提示也发生了改变,这就是我们想要的效果,那我们就可以开心的使用国际化了。
持久化
如果想做到语言持久化,那可以在 localStorage
中存储个全局变量,在配置 i18n
实例的时候 locale
的值从 localStorage
中获取就可以了, 具体的实现就不写了,有兴趣的可以自己去尝试一下。
总结
这篇文章主要介绍了一下 Vue3
中使用国际化的方法,以及在使用 Element UI
组件的时候遇到的一些问题,以及解决方法,希望能给大家带来帮助。