前端Vue实现国际化

国际化实现原理

假设我们有一个变量 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.js
import { createI18n } from 'vue-i18n'

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

const locale = 'en'
const i18n = createI18n({
  legacy: false, // 使用了Vue3 composition API的话这项一定要为false
  globalInjection: true, // 全局使用 t 函数
  locale,
  messages
})

export default i18n

注册 i18n 实例

// main.js
import i18n from '@/i18n'
app.use(i18n).mount('#app')

测试

<template>
  <div class="">
    {{ $t('msg.test') }} <!-- 页面上会显示 hello -->
  </div>
</template>

<script setup>
import {} from 'vue'
</script>

<style lang="scss" scoped></style>

项目中完成国际化

封装 langSelect 组件用于修改 locale
  1. 定义 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: {}
}
  1. 创建 LangSelect 组件
<template>
  <el-dropdown
    trigger="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 的 locale
  store.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' ? 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的话这项一定要为false
  globalInjection: 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()
  }
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大杯美式不加糖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值