当网站要给国外用户展示的时候,要怎么办?

311 阅读4分钟

需求背景

最近在工作中,使用的产品要对海外用户进行演示,国际化的功能是必不可少的,那么 如何在Vue3中使用国际化,以及在 Element UI 中使用 vue-i18n 遇见的一些问题 就是这篇文章主要介绍的

主要内容

这篇文章主要介绍有以下几点:

  1. vue3 如何使用 vue-i18n 插件
  2. 如何做到不同语言自由切换
  3. 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

enzh-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中使用国际化的方法,那么呈现出来的就是这样

Kapture 2024-10-10 at 14.42.17.gif
那我们如何切换语言呢?
我们在页面中引用插件提供的 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 组件并且按照上面说的我们写出了代码,那效果是怎样的呢? Kapture 2024-10-10 at 15.37.57.gif

可以看到,当我们切换语言的时候,校验提示也发生了改变,这就是我们想要的效果,那我们就可以开心的使用国际化了。

持久化

如果想做到语言持久化,那可以在 localStorage 中存储个全局变量,在配置 i18n 实例的时候 locale 的值从 localStorage 中获取就可以了, 具体的实现就不写了,有兴趣的可以自己去尝试一下。

总结

这篇文章主要介绍了一下 Vue3 中使用国际化的方法,以及在使用 Element UI 组件的时候遇到的一些问题,以及解决方法,希望能给大家带来帮助。