用 vue-i18n 做中英文切换,整个方案只有 4 个文件。
前言
大家好,我是张大鹏。最近在开发 ShadcnVueAdmin 这个后台管理系统时,我做了一个功能:中英文切换。
国际化这个东西,说简单也简单,说复杂也能搞得很复杂。我最终的方案只用了 4 个文件,就实现了整个项目的中英文切换,包括语言持久化、语言切换组件、翻译文件管理。
今天把这套方案分享出来,如果你也在做 Vue3 项目的国际化,可以直接参考。

技术选型
Vue3 项目的国际化,主流方案就一个:vue-i18n。
ShadcnVueAdmin 用的是 vue-i18n v11+,搭配 VueUse 的 useStorage 做语言持久化。
为什么不用 vue-i18n 自带的持久化?因为 useStorage 更灵活,而且项目其他配置(主题、侧边栏状态)也都是用它来持久化的,保持统一。
整体结构
整个国际化方案就 4 个文件:
src/plugins/i18n/
├── index.ts # 类型定义、语言常量、持久化
├── setup.ts # i18n 初始化
├── en.json # 英文翻译
└── zh.json # 中文翻译
src/components/
└── language-change.vue # 语言切换组件
核心实现
1. 语言常量和持久化(index.ts)
这个文件定义了支持的语言、默认语言,以及语言偏好的持久化:
typescript
import { useStorage } from '@vueuse/core'
export type Language = 'en' | 'zh'
export const SUPPORTED_LOCALES = new Set<Language>(['en', 'zh'])
export const DEFAULT_LOCALE: Language = 'en'
// 语言偏好持久化到 localStorage
export const appLocale = useStorage<Language>('app-locale', DEFAULT_LOCALE)
// 监听变化,防止设置不支持的语言
watch(appLocale, (newLocale) => {
if (!SUPPORTED_LOCALES.has(newLocale)) {
appLocale.value = DEFAULT_LOCALE
}
}, { immediate: true })
useStorage 会自动把语言偏好存到 localStorage,key 是 app-locale。用户下次打开页面,会自动恢复上次选择的语言。
2. i18n 初始化(setup.ts)
typescript
import { createI18n } from 'vue-i18n'
import { appLocale, DEFAULT_LOCALE } from '.'
import en from './en.json'
import zh from './zh.json'
export function setupI18n(app: App) {
const i18n = createI18n({
legacy: false, // 使用 Composition API 模式
locale: appLocale.value, // 从持久化中读取语言
fallbackLocale: DEFAULT_LOCALE,
messages: { zh, en },
})
app.use(i18n)
}
注意 legacy: false,这很重要。它让我们可以在 <script setup> 中使用 useI18n() 的 Composition API,而不是 Options API 的 this.$t()。
3. 翻译文件(en.json / zh.json)
翻译文件用嵌套的 JSON 结构,按功能模块组织:
json
{
"login": "登录",
"email": "邮箱",
"password": "密码",
"marketing": {
"hero": {
"title": "每个0.01%的进化都在熔铸命运的质变...",
"subtitle": "时光沙漏正迸发着惊雷..."
},
"features": {
"title": "功能",
"feature1": {
"title": "使用现代技术",
"description": "更加现代化的组件库,自由定制每一个组件"
}
}
}
}
英文版结构完全对应,只是值不同:
json
{
"login": "Login",
"email": "Email",
"password": "Password",
"marketing": {
"hero": {
"title": "Do you dare to use 365 days...",
"subtitle": "The hourglass of time is bursting..."
}
}
}
4. 语言切换组件(language-change.vue)
vue
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import { appLocale, DEFAULT_LOCALE, SUPPORTED_LOCALES } from '@/plugins/i18n'
const { locale } = useI18n()
function handleLocaleChange(val: AcceptableValue) {
if (typeof val !== 'string' || !SUPPORTED_LOCALES.has(val as Language)) {
locale.value = DEFAULT_LOCALE
appLocale.value = DEFAULT_LOCALE
return
}
locale.value = val as Language
appLocale.value = val as Language
}
</script>
关键点:切换语言时要同时更新两个地方 ------locale(vue-i18n 的当前语言)和 appLocale(持久化的语言偏好)。
在组件中使用
模板中用 $t():
vue
<template>
<h1>{{ $t('marketing.hero.title') }}</h1>
<p>{{ $t('marketing.hero.subtitle') }}</p>
</template>
脚本中用 useI18n() 的 t():
vue
<script setup>
const { t } = useI18n()
const features = [
{ title: t('marketing.features.feature1.title') },
{ title: t('marketing.features.feature2.title') },
]
</script>
总结
这套方案的核心思路:
- vue-i18n 负责翻译
- useStorage 负责持久化
- JSON 文件 负责翻译内容管理
- 一个组件 负责语言切换
4 个文件,干净利落。
如果你也在做 Vue3 项目的国际化,这套方案可以直接拿去用。只需要改一下 en.json 和 zh.json 的内容就行。