Vue3 国际化方案:从 vue-i18n 到动态加载优化
背景与问题界定 随着前端应用向全球化发展,国际化(i18n)已成为大多数商业项目的标配能力。Vue3 生态中最成熟的 i18n 方案是 vue-i18n,它在 v9 版本中全面拥抱 Vue3 Composition API 和 TypeScript。但在实际项目中,简单的 $t('key') 使用方式远远不够。几个典型的工程挑战:一是语言包膨胀——当应用包含 20 个国际化模块时,全量加载所有语言的 JSON 文件可能导致首屏体积增加数百 KB;二是运行时切换的响应式性能——语言切换时大量 DOM 节点的文本更新可能造成界面卡顿;三是动态内容的翻译——后端返回的模板字符串(如"您有 {count} 条未读消息")如何在前端正确解析不同语言下的占位符序差异;四是类型安全——翻译 key 的拼写错误只在运行时暴露,缺乏编译期检查。 目标拆解与工程约束 语言包按需加载:只有当前语言的翻译资源加载到内存中,切换语言时异步下载新语言包,下载期间降级显示 key 本身或 fallback 语言。 模板中的翻译类型安全:翻译 key 必须通过 TypeScript 类型约束,IDE 输入翻译 key 时有自动补全,拼写错误在编译期报错。 运行时切换不卡顿:语言切换后,页面中所有使用 $t 的文本应在 16ms 内完成更新,不出现明显的布局偏移或闪烁。 复数规则与格式化:支持不同语言的字数规则(如中文"1 条消息"/“2 条消息"不分单复数,而英文要求单复数区分的语法)。 方案设计 vue-i18n 集成与类型安全 使用 vue-i18n v9 的 Composition API 模式,配合 TypeScript Schema 生成翻译 key 的类型签名: // locales/schema.ts — 定义翻译资源类型 export type MessageSchema = { common: { confirm: string cancel: string empty: string } user: { login: string logout: string welcome: (name: string) => string unread: (count: number) => string } } // i18n.ts — 类型化的 createI18n import { createI18n } from 'vue-i18n' import type { MessageSchema } from './locales/schema' const i18n = createI18n<[MessageSchema], 'zh-CN' | 'en-US' | 'ja-JP'>({ locale: 'zh-CN', fallbackLocale: 'en-US', messages: { 'zh-CN': { common: { confirm: '确认', cancel: '取消', empty: '暂无数据' }, user: { login: '登录', logout: '退出', welcome: (n) => `您好,${n}!`, unread: (c) => `您有 ${c} 条未读消息` } } } }) 这种模式下,组件中的 t('user.login') 会得到完整的类型检查和自动补全。 ...