Vue3 + Element-Plus 实现国际化 I18n

前言:本文将vue部署在了electron上,需注意根目录并非为@而是@renderer,仅需替换,不影响其它vue的使用方法

1. 安装依赖

1
pnpm add vue-i18n element-plus --save

2. 配置目录

  • src
    • locales
      • en.json
      • zh-cn.json
      • zh-tw.json
      • 其它语言文件…
    • i18n
      • index.ts

三个语言文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// zh-cn
{
"message": {
"hello": "你好,世界",
"welcome": "欢迎来到 Vue 3"
}
}

// zh-tw
{
"message": {
"hello": "你好,世界",
"welcome": "歡迎來到 Vue 3"
}
}

// en
{
"message": {
"hello": "Hello World",
"welcome": "Welcome to Vue 3"
}
}

3. 初始化 vue-i18n

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import { createI18n } from 'vue-i18n'

// 从本地存储获取语言设置,默认为简体中文
const getDefaultLocale = (): string => {
return localStorage.getItem('locale') || 'zh-cn'
}

// 初始化 i18n
const i18n = createI18n({
legacy: false,
locale: getDefaultLocale(),
messages: {
'zh-cn': {}, // 简体中文
'zh-tw': {}, // 繁体中文
en: {} // 英文
}
})

// 动态加载语言包
const loadLocaleMessages = async (locale: string): Promise<void> => {
try {
// 检查语言包是否存在(去除ts报错)
switch (locale) {
case 'zh-cn':
case 'zh-tw':
case 'en':
break
default:
throw new Error(`未知国际化配置值: ${locale}`)
}
const messages = await import(`@renderer/locales/${locale}.json`)
i18n.global.setLocaleMessage(locale, messages.default)
i18n.global.locale.value = locale
localStorage.setItem('locale', locale) // 记录到本地存储
} catch (error) {
console.error(`Failed to load locale messages for ${locale}:`, error)
}
}

export { getDefaultLocale, i18n, loadLocaleMessages }

4. 配置main.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

// 引入 Element Plus 国际化语言包
import { getDefaultLocale, i18n, loadLocaleMessages } from './i18n'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import zhTw from 'element-plus/es/locale/lang/zh-tw'
import en from 'element-plus/es/locale/lang/en'

const switchLocale = (locale: string): any => {
switch (locale) {
case 'zh-cn':
return zhCn
case 'zh-tw':
return zhTw
case 'en':
return en
default:
return zhCn
}
}

const app = createApp(App)

const locale = getDefaultLocale()
loadLocaleMessages(locale)
app.use(i18n)
app.use(ElementPlus, { locale: switchLocale(locale) })

app.mount('#app')

5. 示例使用与切换方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<script setup lang="ts">
import { ref } from 'vue'
import { useI18n } from 'vue-i18n';
import { loadLocaleMessages } from '@renderer/i18n';

const { locale } = useI18n();
const currentLang = ref(locale.value);

const switchLanguage = async (lang: string): Promise<void> => {
await loadLocaleMessages(lang);
currentLang.value = lang;
};
</script>

<template>
<div>
<el-select v-model="currentLang" @change="switchLanguage" placeholder="选择语言">
<el-option label="简体中文" value="zh-cn"></el-option>
<el-option label="繁體中文" value="zh-tw"></el-option>
<el-option label="English" value="en"></el-option>
</el-select>

<p>{{ $t('message.hello') }}</p>
<p>{{ $t('message.welcome') }}</p>
</div>
</template>