ShadcnVueAdmin 的国际化是怎么实现的

用 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>

总结

这套方案的核心思路:

  1. vue-i18n 负责翻译
  2. useStorage 负责持久化
  3. JSON 文件 负责翻译内容管理
  4. 一个组件 负责语言切换

4 个文件,干净利落。

如果你也在做 Vue3 项目的国际化,这套方案可以直接拿去用。只需要改一下 en.jsonzh.json 的内容就行。

相关推荐
㳺三才人子2 小时前
容器內的 H2 控制台
开发语言·前端·javascript
光影少年2 小时前
vite+rust生态链工具链
开发语言·前端·后端·rust·前端框架
skywalk81632 小时前
当前有什么流行的lisp的web框架吗?
开发语言·前端·lisp
IT_陈寒2 小时前
为什么我的JavaScript变量老是不听使唤?
前端·人工智能·后端
HookJames2 小时前
设计Section 06 · Component Sourcing & BOM Risk Control
前端
zhenxin01222 小时前
HTML头部元信息避坑指南
前端·html
布局呆星2 小时前
Vite代理解决前端跨域问题 | fetch请求 | 环境变量
前端
sghuter3 小时前
HTML头部元信息避坑指南
c语言·前端·html·cocoa
无心使然云中漫步3 小时前
Openlayers调用ArcGis地图服务之三 —— 要素查询(/query)
前端·arcgis·vue·数据可视化