测试(Vitest)
在 vitest.config.ts 中使用 aiI18nVitest(),即可测试导入 virtual:ai-i18n 的业务模块,无需
手写 alias 或 mock。测试环境不执行自动翻译,也不会修改项目中的翻译文件。
如果 Vitest 输出“仅支持浏览器 Runtime,已跳过 SSR 转换/注入”,说明测试配置加载了生产用的
aiI18n()。不要忽略或静默过滤该提示;从 @ai-i18n/vite/vitest 改用
aiI18nVitest(),并确保同一测试配置只注册其中一个插件。
它支持 t()、useI18n()、Vue tRef()、纯 Options 的 i18nComputed() /
tComputed()、消息集合宏和自动导入。测试配置的 autoImport 应与正式 Vite 配置保持一致。
Jest 或直接 Node.js 执行不会处理消息集合宏,请改用 Vitest 配置或避免执行包含宏的源码。
快速开始
// vitest.config.ts
import { aiI18nVitest } from '@ai-i18n/vite/vitest';
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vitest/config';
export default defineConfig({
plugins: [
aiI18nVitest({
sourceLang: 'zh-CN', // 测试 Runtime 固定回退的源码语言
// value 是语言标识,label 是组件中展示的名称。
locales: [
{ value: 'zh-CN', label: '中文' },
{ value: 'en-US', label: 'English' },
],
autoImport: true, // 仅当正式 Vite 配置也开启自动导入时保持一致
}),
react(), // 提供 React 转换,并让测试插件自动识别 React 模式
],
});
Vue 项目保留自己的 Vite Vue 插件:
// vitest.config.ts
import { aiI18nVitest } from '@ai-i18n/vite/vitest';
import vue from '@vitejs/plugin-vue';
import { defineConfig } from 'vitest/config';
export default defineConfig({
plugins: [
aiI18nVitest({
sourceLang: 'zh-CN',
locales: [
{ value: 'zh-CN', label: '中文' },
{ value: 'en-US', label: 'English' },
],
autoImport: true,
}),
vue(),
],
});
Vanilla 项目不需要框架插件:
// vitest.config.ts
import { aiI18nVitest } from '@ai-i18n/vite/vitest';
import { defineConfig } from 'vitest/config';
export default defineConfig({
plugins: [
aiI18nVitest({
sourceLang: 'zh-CN',
locales: [
{ value: 'zh-CN', label: '中文' },
{ value: 'en-US', label: 'English' },
],
autoImport: true,
}),
],
});
保留项目原有的 Vue 或 React Vite 插件。大多数项目不需要设置 framework;只有自定义构建环境
无法识别框架时,才显式传入该选项。
与正式配置共享 options
AiI18nVitestOptions 是 AiI18nOptions 的子集,只保留 sourceLang、defaultLang、
locales、framework、persist、autoImport。把这部分抽成共享文件,vite.config.ts
与 vitest.config.ts 各自引用,语言列表和运行时策略只需要改一处:
// ai-i18n.options.ts
export const aiI18nOptions = {
sourceLang: 'zh-CN', // 源码文案使用的语言
defaultLang: 'zh-CN', // 没有有效持久化值时的初始语言
// value 是语言标识,label 是组件中展示的名称。
locales: [
{ value: 'zh-CN', label: '中文' },
{ value: 'en-US', label: 'English' },
],
persist: { key: 'app-lang' }, // 使用指定 localStorage key 保存语言偏好
autoImport: true, // 两种环境使用同一模式化自动导入契约
} as const;
// vite.config.ts
import { aiI18n } from '@ai-i18n/vite';
import { aiI18nOptions } from './ai-i18n.options';
export default defineConfig({
plugins: [
aiI18n(aiI18nOptions),
react(), // 保留宿主 React 转换
],
});
// vitest.config.ts
import { aiI18nVitest } from '@ai-i18n/vite/vitest';
import { aiI18nOptions } from './ai-i18n.options';
export default defineConfig({
plugins: [
aiI18nVitest(aiI18nOptions),
react(), // 保留宿主 React 转换
],
});
html、loading、cache、provider、directory、dts 等构建期字段不属于
AiI18nVitestOptions;直接把完整的 aiI18n() 配置对象传给 aiI18nVitest() 会被 TypeScript
拒绝多余字段,按需只挑测试需要的子集传入即可。
测试环境的能力范围
由于没有加载任何目标语言译文,t('保存') 始终返回 "保存",即使调用过
await setLang('en-US') 之后也是如此。可以把这类测试理解为契约测试——只断言组件确实调用了
t() 并渲染出结果,不断言具体译文内容。
loading 不属于 AiI18nVitestOptions,测试 Runtime 不创建语言 chunk loader。
getLangLoadState() 以及 useI18n() 的 loading/error 字段仍存在,但固定为 idle;真实
loading/error 变化应由应用自己的抽象单测或生产 Vite 集成测试覆盖。
单元测试不应断言某个语言一定翻译为特定字词。译文质量通过人工审校或
AI 翻译流程确认;CI 可以额外运行一次真实的 vite build。
常见问题
测试环境需要先跑过 vite build 或存在 Translation Memory 吗?
不需要。测试插件不依赖项目中的翻译文件,也能正常解析 virtual:ai-i18n。
能不能在同一个 vitest.config.ts 里同时注册 aiI18n() 和 aiI18nVitest()?
不要这样做。两者都会尝试解析 virtual:ai-i18n,只注册 aiI18nVitest() 即可。
端到端测试(Playwright 等)呢?
aiI18nVitest() 只覆盖 Vitest 场景。端到端测试应运行真实的 vite dev 或 vite build,
以覆盖实际的语言切换和翻译结果。