vite中实现i18n按需编译注入的核心是:不打包全部语言包,而是根据环境变量或配置动态加载指定locale的翻译资源,通过自定义插件、define静态注入或virtual module+hmr实现零运行时开销或热切换,并推荐使用unplugin-vue-i18n插件配合include和transform过滤非目标语言资源。

在 Vite 项目中实现国际化(i18n)资源的按需编译注入,核心思路是:**不打包全部语言包,而是根据当前环境或运行时配置,只加载所需语言的翻译资源,并通过插件机制在构建阶段动态注入或替换占位符**。这既能减小初始包体积,又能保持开发体验流畅。
利用 Vite 插件预扫描并注入语言资源
你可以编写一个自定义 Vite 插件,在 buildStart 或 transform 阶段读取指定目录下的语言文件(如 locales/zh.json、locales/en.json),解析后按需注入到模块中。常见做法是拦截对 i18n 工具函数(如 useI18n() 或 import { messages } from '@/locales')的引用,动态替换为实际语言内容。
- 插件监听
.json或.ts语言文件导入,用resolveId和load拦截请求 - 根据
process.env.VUE_APP_I18N_LOCALE或vite.config.ts中的配置决定加载哪个 locale - 将对应 JSON 内容转为 JS 对象字面量,返回给模块,避免运行时异步加载
配合 define 配置做编译期静态注入
Vite 的 define 选项支持在构建时将变量内联进代码。你可以把当前语言的翻译对象直接序列化后注入全局常量,例如:
// vite.config.ts
import { defineConfig } from 'vite'
import fs from 'fs'
import path from 'path'
const locale = process.env.I18N_LOCALE || 'zh'
const messages = JSON.parse(
fs.readFileSync(path.resolve(__dirname, `src/locales/${locale}.json`), 'utf-8')
)
export default defineConfig({
define: {
__I18N_MESSAGES__: JSON.stringify(messages)
}
})
然后在业务代码中直接使用:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
// utils/i18n.ts
export const messages = __I18N_MESSAGES__
export function t(key: string) {
return key.split('.').reduce((o, k) => o?.[k], messages) || key
}
这种方式零运行时开销,但每次切换语言需重新构建。
用插件 + virtual module 实现“伪按需”热切换
若希望开发时支持语言热切换(不刷新页面),可结合虚拟模块(virtual module)和 HMR。插件注册一个虚拟模块如 virtual:i18n-messages,并在 handleHotUpdate 中监听 locale 文件变化,触发模块更新:
- 插件返回
{ id: 'virtual:i18n-messages', code: `export default ${JSON.stringify(messages)}` } - 组件中
import messages from 'virtual:i18n-messages',Vite 会自动 HMR - 搭配
watch或chokidar监听 locale 目录,实时更新虚拟模块内容
推荐组合:unplugin-vue-i18n + 构建参数控制
生产级项目建议直接使用成熟插件 unplugin-vue-i18n,它原生支持按需导入、格式化、编译为函数等能力,并可通过配置实现“只包含指定 locale”:
// vite.config.ts
import vueI18n from '@intlify/unplugin-vue-i18n/vite'
export default defineConfig({
plugins: [
vueI18n({
include: path.resolve(__dirname, './src/locales/**'),
// 只编译当前环境指定的语言(构建前设置 I18N_LOCALE=ja)
compositionOnly: true,
forceStringify: true,
runtimeOnly: false,
fullInstall: true,
// 关键:过滤不需要的语言
transform: (content, id) => {
const locale = process.env.I18N_LOCALE || 'zh'
if (!id.includes(`/${locale}.`)) return null // 跳过非目标语言
return content
}
})
]
})
再配合 import { useI18n } from 'vue-i18n',所有未匹配语言的资源不会进入最终 bundle。










