i18n国际化的内容比较多,写文章的时间也用得比较长,从上周五开始到本周一,断断续续完成了。
虽然实际工作中很多项目都不需要国际化,但是了解国际化的用法还是很有必要的。
i18n
Vue I18n 是 Vue.js 的国际化插件。它可以轻松地将一些本地化功能集成到你的 Vue.js 应用程序中。
Vue I8n 官方文档: https://vue-i18n.intlify.dev/
首先,安装匹配Vue3的vue-i18n
npm install vue-i18n@9
在Vue3中引入i8n
src下新建文件夹locales,其下新建入口文件index.ts和两个语言包:en.json、zh.json
locales/en.json
{
"common": {
"home": "home",
"about": "About",
"tobeCoded": "To be coded",
"signIn": "sign in",
"signUp": "sign out"
},
...
}
locales/zh.json
"common": {
"home": "首页",
"about": "关于",
"tobeCoded": "待开发",
"signIn": "登录",
"signUp": "注册"
},
...
}
locales/index.ts
默认使用当前浏览器界面语言。如果本地缓存有locale
值,则使用缓存中记录的语言设置。
import { createI18n } from 'vue-i18n'
import zh from './zh.json'
import en from './en.json'
// 获取浏览器界面语言,默认语言
// https://developer.mozilla.org/zh-CN/docs/Web/API/Navigator/language
let currentLanguage = navigator.language.replace(/-(\S*)/, '')
// 如果本地缓存记录了语言环境,则使用本地缓存
let lsLocale = localStorage.getItem('locale') || ''
if (lsLocale) {
currentLanguage = JSON.parse(lsLocale)?.curLocale
}
export default createI18n({
locale: currentLanguage,
legacy: false, // 修复组件引入i18n时vite脚手架报错的问题
globalInjection: true, // 全局注册 $t
messages: {
zh,
en
}
})
export const langs = [
{ key: 'zh', title: '中文' },
{ key: 'en', title: 'English' }
]
main.ts中引入
...
// i18n
import i18n from './locales'
app.use(i18n)
...
本地持久化
当我们把中文改成English后,再刷新页面,语言环境又会回到中文,所以我们需要做一点工作来保持国际化状态。
本项目使用pinia配合localStorage来完成这个任务,可参考专栏之前的文章《从零开始Vue3+Element Plus后台管理系统(六)——状态管理Pinia和持久化》
- store中的locale值默认为i18n初始化时的值,
- 在需要切换语言的地方,调用store的setLocale方法。
- 通过添加persis:true 实现持久化
store/locales.ts
import { defineStore } from 'pinia'
import { ref } from 'vue'
import i18n from '~/locales'
export const useLocaleStore = defineStore(
'locale',
() => {
let locale = ref(i18n.global.locale.value)
// 设置locale
function setLocale(lang) {
locale.value = lang
i18n.global.locale.value = lang
}
return { locale, setLocale }
},
{
persist: true
}
)
在页面中切换语言
<template>
<el-dropdown @command="handleCommand">
<span class="el-dropdown-link">
{{ currentLan }}
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-for="lang in langs" :command="lang">{{ lang.title }}</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { langs } from '~/locales'
import { useLocaleStore } from '~/store/locale'
const useLocale = useLocaleStore()
let curLocale = useLocale.locale
let currentLan = ref(langs.find((cur) => cur.key === curLocale)?.title || '')
function handleCommand(command: any) {
currentLan.value = command.title
useLocale.setLocale(command.key)
}
</script>
路由菜单国际化
- 把路由的meta.title都改成语言包对应的key,
- 修改侧边栏组件
SidebarItem.vue
中,把显示title的位置改成$t方法
主要代码如下:
// locales/en.ts
route: {
...
about: 'About'
}
}
//router/modules/about.ts
{
path: '/about',
name: 'about',
meta: {
title: 'about', // about 对应语言文件的route.about
icon: 'ep-mic',
order: 100
},
component: () => import('~/views/system/About.vue')
}
// SidebarItem.vue
{{ $t(`route.${item.meta.title}`) }}
script中使用
如果需要直接在脚本中使用国际化定义的某个值,我们可以单独引入useI18n再使用
<el-button @click="trigger">test</el-button>
import { ElMessage } from 'element-plus'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
function trigger() {
ElMessage(t('common.about'))
}
element Plus 切换语言
Element Plus 提供了一个 Vue 组件 ConfigProvider 用于全局配置国际化的设置。
只需根据当前语言环境,动态更改el-config-provider的locale即可。
<template>
<el-config-provider :locale="locales[useLocale.locale]">
<router-view />
</el-config-provider>
</template>
<script setup lang="ts">
import { ElConfigProvider } from 'element-plus'
import zh from 'element-plus/es/locale/lang/zh-cn'
import en from 'element-plus/es/locale/lang/en'
import { useLocaleStore } from './store/locale'
const locales = {
zh: zh,
en: en
}
const useLocale = useLocaleStore()
</script>
问题记录
i18n-ally插件不生效
en: 文案路径 “common.tobeCoded” 不存在(i18n-ally-key-missing),i18n-ally插件不生效。
原因是语言包默认应该使用json,但我开始使用了ts,所以可以额外配置一下
.vscode/settings.json
{
"i18n-ally.localesPaths": "src/locales",
"i18n-ally.enabledParsers": ["ts"] // 这里使用ts
}
不过后来我还是改成了使用json文件语言包
控制台报错 Not available in legacy mode
message-compiler.cjs.js:58 Uncaught (in promise) SyntaxError: Not available in legacy mode
修改i18n配置项
/ locales/index.ts
export default createI18n({
...
legacy: false, // you must set `false`, to use Composition API
...
})
项目地址
本项目GIT地址:github.com/lucidity99/…
如果有帮助,给个star ✨ 点个赞👍