国际化
前言
为了支持多语言全球化运营,模板项目内置集成了 Vue I18n (v9+),默认支持简体中文、英文和俄语的切换。此外,系统设计了运行时持久化和 Cookie 联动机制,以确保前后端的多语言状态能够无缝保持一致。
国际化系统简介
项目中的国际化方案实现了以下两个维度的语言适配:
- 业务级语言包:存放于模板本地,管理所有页面表单、路由菜单、按钮及提示等业务相关的翻译字典。
- 组件库语言包:来自底层
Uniboot UI依赖包(如表格分页文字、日期选择器提示等)。两者在初始化时进行混入合并,从而实现整站翻译的完整性。
语言编码统一使用 BCP 47 形式(带连字符),如 zh-CN、en-US、ru-RU,与 src/locales/*.json 文件名一致。
语言文件目录结构
业务国际化翻译资源存放在 @/locales 目录下:
src/
└── locales/
├── zh-CN.json # 简体中文翻译字典
├── en-US.json # 英文翻译字典
└── ru-RU.json # 俄语翻译字典字典顶层通常会包含语言名称本身(供语言切换菜单展示),例如:
{
"en-US": "English",
"zh-CN": "简体中文",
"ru-RU": "Русский"
}语言包分类说明
在 src/i18n.ts 中,本地翻译包与底层组件库自带的语言包进行解构混入:
import enLocale from 'uniboot-ui/es/packages/locale/lang/en'
import ruLocale from 'uniboot-ui/es/packages/locale/lang/ru'
import zhCnLocale from 'uniboot-ui/es/packages/locale/lang/zh-cn'
import en from '@/locales/en-US.json'
import ru from '@/locales/ru-RU.json'
import zh from '@/locales/zh-CN.json'在初始化时,底层依赖语言包(如 zhCnLocale)和本地语言包(如 zh)合并成同一套 messages,提供给应用程序消费。
国际化挂载与初始化
根组件插件注入
i18n 对象的创建和实例化逻辑位于 src/i18n.ts:
/** 项目实际支持的语言(与 src/locales/*.json 对应) */
export const SUPPORTED_LOCALES = ['zh-CN', 'en-US', 'ru-RU'] as const
export type SupportedLocale = (typeof SUPPORTED_LOCALES)[number]
const i18n = createI18n({
locale: getLocale() || 'zh-CN', // 默认从本地缓存加载已选语言,缺省为简体中文
fallbackLocale: 'en-US', // 当前语言缺少词条时回退到英文
legacy: false, // 必须为 false,才能在 Composition API 中使用
messageResolver: undefined,
messages: {
'en-US': { ...enLocale, ...en },
'zh-CN': { ...zhCnLocale, ...zh },
'ru-RU': { ...ruLocale, ...ru },
},
})
export const t = i18n.global.tSUPPORTED_LOCALES 是项目语言白名单,语言切换组件与 setI18nLanguage 都会以它为准,避免误切到未提供业务字典的语言。
模板项目采用插件式自动挂载,无需在 main.ts 中手写注入。在 src/install/plugins/i18n.ts 中注册:
import type { App } from 'vue'
import i18n from '@/i18n'
export default (app: App<Element>) => {
app.use(i18n)
}该文件会被 @/install/index.ts 自动扫描引入,并在程序引导时全局注入。
运行时语言切换机制
项目封装了统一的多语言切换辅助函数 setI18nLanguage(locale)。语言下拉组件(language-drop-down.vue)遍历 SUPPORTED_LOCALES,切换时调用该函数并刷新页面。
数据持久化与 Cookie 协同
export function setI18nLanguage(locale: string) {
// 0. 白名单校验:不在 SUPPORTED_LOCALES 中的语言直接忽略
if (!(SUPPORTED_LOCALES as readonly string[]).includes(locale)) {
return
}
// 1. 更新全局 i18n 实例的 locale,触发表单 / 组件响应式翻译
i18n.global.locale.value = locale as SupportedLocale
// 2. 调用 setLocale 写入本地缓存,保证刷新后状态不丢失
setLocale(locale)
// 3. 修改 html 根标签的 lang 属性(如 <html lang="en-US">),兼顾 SEO 与无障碍
document.querySelector('html')?.setAttribute('lang', locale)
// 4. 与后端协同:SESSION_COOKIE 授权模式下写入名为 locale 的 Cookie,
// 便于服务端读取并返回匹配语种的文案
if (config.authMethod === AuthMethodEnum.SESSION_COOKIE) {
Cookies.set('locale', locale)
}
}如何使用与新增翻译
在 Vue 模板中渲染
在 SFC 模板中可直接使用全局辅助函数 $t:
<template>
<div class="card">
<h2>{{ $t('login.welcome') }}</h2>
<p>{{ $t('login.desc') }}</p>
</div>
</template>在脚本代码中调用
在 <script setup> 或通用 .ts 文件(路由守卫、网络拦截器、接口提示等)中,导入并使用全局导出的 t:
<script lang="ts" setup>
import { t } from '@/i18n'
import { feedback } from '@/utils/feedback'
function onSubmitSuccess() {
feedback.msgSuccess(t('common.saveSuccess'))
}
</script>添加新的国家语言包
若需引入新语种(例如繁体中文 zh-TW),按以下流程扩展:
新建字典文件:在
src/locales/下创建zh-TW.json,填入文案(建议同时补充各现有语言包中对该语言名的翻译键):json{ "zh-TW": "繁體中文", "login": { "welcome": "歡迎使用" } }导入并挂载新包:打开
src/i18n.ts:tsimport zhTwLocale from 'uniboot-ui/es/packages/locale/lang/zh-tw' import tw from '@/locales/zh-TW.json' export const SUPPORTED_LOCALES = [ 'zh-CN', 'en-US', 'ru-RU', 'zh-TW', ] as const const i18n = createI18n({ // ... messages: { 'en-US': { ...enLocale, ...en }, 'zh-CN': { ...zhCnLocale, ...zh }, 'ru-RU': { ...ruLocale, ...ru }, 'zh-TW': { ...zhTwLocale, ...tw }, }, })调用切换:语言菜单基于
SUPPORTED_LOCALES自动展示新项;用户选择后调用setI18nLanguage('zh-TW')即可完成整站切换。