--- url: https://bosens-china.github.io/ai-i18n/guide/getting-started/vanilla.md --- # Vanilla 快速上手 ## 开始前 ai-i18n 要求 Vite 8 或更高版本,并且当前只支持浏览器端应用。需要 SSR、按请求选择语言或避免首屏 源码回退的项目,暂不适合接入当前版本。 ## 创建项目 下面以 pnpm 和 TypeScript 模板为例: ```sh pnpm create vite ai-i18n-vanilla --template vanilla-ts cd ai-i18n-vanilla pnpm install pnpm add @ai-i18n/vite@alpha ``` 项目尚未发布正式版。正式版发布前请保留 `@alpha`,避免安装到较旧的 `latest`。 已有 Vite 项目可以跳过创建步骤,直接安装 `@ai-i18n/vite@alpha`。 ## 配置 Vite 在 `vite.config.ts` 中注册 `aiI18n()`。没有检测到 Vue 或 React Vite 插件时,插件自动使用 Vanilla 模式: ```ts import { aiI18n } from '@ai-i18n/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ aiI18n({ sourceLang: 'zh-CN', locales: [ { value: 'zh-CN', label: '中文' }, { value: 'en-US', label: 'English' }, ], }), ], }); ``` ## 翻译并更新 DOM 从虚拟模块导入 Runtime API。Vanilla 模式需要在语言变化后主动更新 DOM: ```ts import { getLangs, setLang, subscribe, t } from 'virtual:ai-i18n'; function render() { document.querySelector('#app')!.textContent = t('保存'); } render(); const unsubscribe = subscribe(render); console.log(getLangs()); await setLang('en-US'); window.addEventListener('pagehide', () => unsubscribe(), { once: true }); ``` ## 运行与验证 ```sh pnpm dev pnpm build ``` Dev 只提取浏览器实际请求过的模块。首次接入后应执行一次完整 Build,确认入口可达源码均已 提取。生成文件及 Git 提交规则见[生成文件与 Git](/ai-i18n/guide/basic/directory.md)。 ## 下一步 - [保存语言偏好](/ai-i18n/api/vite/interfaces/ai-i18n-persist-options.md):按需使用 localStorage 记住用户选择。 - [测试(Vitest)](/ai-i18n/guide/quality/testing.md):使用专用内存 Runtime 测试业务模块。 - [通用文案写法](/ai-i18n/guide/basic/static-analysis/common.md):处理动态值、文案集合和业务枚举。 --- url: https://bosens-china.github.io/ai-i18n/guide/getting-started/vue.md --- # Vue 快速上手 ## 开始前 ai-i18n 要求 Vite 8 或更高版本,并且当前只支持浏览器端应用。需要 SSR、按请求选择语言或避免首屏 源码回退的项目,暂不适合接入当前版本。 ## 创建项目 下面以 pnpm 和 Vite 的 `vue-ts` 模板为例: ```sh pnpm create vite ai-i18n-vue --template vue-ts cd ai-i18n-vue pnpm install pnpm add @ai-i18n/vite@alpha ``` 项目尚未发布正式版。正式版发布前请保留 `@alpha`,避免安装到较旧的 `latest`。 已有 Vite + Vue 项目可以跳过创建步骤,直接安装 `@ai-i18n/vite@alpha`。请保留现有的 `@vitejs/plugin-vue`,无需安装额外的 ai-i18n Vue 适配包。 ## 配置 Vite 在 `vite.config.ts` 中注册 `aiI18n()`: ```ts import { aiI18n } from '@ai-i18n/vite'; import vue from '@vitejs/plugin-vue'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ aiI18n({ sourceLang: 'zh-CN', locales: [ { value: 'zh-CN', label: '中文' }, { value: 'en-US', label: 'English' }, ], }), vue(), ], }); ``` ai-i18n 会从最终的 Vite 插件列表识别 Vue 模式。只有自定义插件环境无法识别时,才需要显式 设置 `framework: 'vue'`。 ## 编写第一个翻译组件 选择项目正在使用的 Vue API 风格,将 `src/App.vue` 替换为对应示例。新组件推荐使用 ` ``` **Options API** 纯 Options API 组件把 `i18nComputed()` 展开到 `computed`,获得已经解包的语言状态。 ```vue title="src/App.vue" ``` 当前示例使用显式导入,因此普通 ` ``` Ant Design Vue 使用相同方式,把 locale 传给 `ConfigProvider`。日期组件还需同步 Day.js 等 日期库的 locale。 ## 下一步 - [Vue 常见问题](/ai-i18n/guide/faq/vue.md):排查模板 binding、Options 响应式状态和翻译 getter。 - [保存语言偏好](/ai-i18n/api/vite/interfaces/ai-i18n-persist-options.md):按需使用 localStorage 记住用户选择。 - [测试(Vitest)](/ai-i18n/guide/quality/testing.md):使用 Vue 插件与专用内存 Runtime 测试组件。 - [自动导入](/ai-i18n/guide/basic/auto-import.md):显式开启后可直接省略 `t` 等 import。 - [TypeScript 与生成声明](/ai-i18n/guide/quality/typescript.md):了解 Vue 的两个声明文件并排查类型问题。 - [Vue 在线演示](/ai-i18n/demo/vue.md):查看可交互的完整示例。 --- url: https://bosens-china.github.io/ai-i18n/guide/getting-started/react.md --- # React 快速上手 ## 开始前 ai-i18n 要求 Vite 8 或更高版本,并且当前只支持浏览器端应用。需要 SSR、按请求选择语言或避免首屏 源码回退的项目,暂不适合接入当前版本。 ## 创建项目 下面以 pnpm 和 Vite 的 `react-ts` 模板为例: ```sh pnpm create vite ai-i18n-react --template react-ts cd ai-i18n-react pnpm install pnpm add @ai-i18n/vite@alpha ``` 项目尚未发布正式版。正式版发布前请保留 `@alpha`,避免安装到较旧的 `latest`。 已有 Vite + React 项目可以跳过创建步骤,直接安装 `@ai-i18n/vite@alpha`。请保留现有的 React Vite 插件,无需安装额外的 ai-i18n React 适配包。 ## 配置 Vite 在 `vite.config.ts` 中注册 `aiI18n()`: ```ts import { aiI18n } from '@ai-i18n/vite'; import react from '@vitejs/plugin-react'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ aiI18n({ sourceLang: 'zh-CN', locales: [ { value: 'zh-CN', label: '中文' }, { value: 'en-US', label: 'English' }, ], }), react(), ], }); ``` ai-i18n 会从最终的 Vite 插件列表识别 React 模式。只有自定义插件环境无法识别时,才需要 显式设置 `framework: 'react'`。 ## 编写第一个翻译组件 将 `src/App.tsx` 替换为: ```tsx import { useI18n } from 'virtual:ai-i18n'; export default function App() { const { currentLang, langs, setLang, t } = useI18n(); async function changeLanguage(value: string) { try { await setLang(value); } catch { // 切换失败时保留当前语言;完整项目可显示 langLoadState 中的错误。 } } return (

{t('保存')}

); } ``` 组件需要展示随语言变化的文案时,应使用 `useI18n()` 返回的 `t`。不要在渲染路径中只调用 Runtime 顶层 `t`,否则组件不会建立订阅。 ## 运行与验证 ```sh pnpm dev pnpm build ``` 打开开发页面后切换语言。缺少目标译文时,`t()` 会先回退源码文案。首次接入后执行完整 Build,确认入口可达源码均已提取,并检查以下文件: ```text src/ai-i18n.d.ts i18n/translations/ i18n/overrides.json i18n/extracted/ i18n/locales/ i18n/storage.json # 仅 SQLite ``` 应提交声明和项目内译文;SQLite 还需提交存储标记。忽略可重新生成的 `extracted/` 与 `locales/`。 完整规则见 [生成文件与 Git](/ai-i18n/guide/basic/directory.md)。 ## 接入 UI 组件库 ai-i18n 负责业务文案,组件库内置文案仍由组件库自己的 locale 控制。常见组件库都可以从 `currentLang` 派生 locale,再传给根部 Provider: | 组件库 | Provider | Locale 模块 | | ---------- | ---------------- | ---------------------- | | Ant Design | `ConfigProvider` | `antd/locale/*` | | MUI | `ThemeProvider` | `@mui/material/locale` | 以 Ant Design 为例: ```tsx import { ConfigProvider } from 'antd'; import enUS from 'antd/locale/en_US'; import zhCN from 'antd/locale/zh_CN'; import type { PropsWithChildren } from 'react'; import { useI18n } from 'virtual:ai-i18n'; export function AppLocale({ children }: PropsWithChildren) { const { currentLang } = useI18n(); const locale = currentLang === 'en-US' ? enUS : zhCN; return {children}; } ``` MUI 使用 `createTheme({}, locale)` 创建本地化主题,再交给 `ThemeProvider`。MUI X Date Pickers 还需同步日期适配器的 locale。 ## 下一步 - [React 常见问题](/ai-i18n/guide/faq/react.md):排查 JSX 提取、组件订阅与 React Compiler。 - [保存语言偏好](/ai-i18n/api/vite/interfaces/ai-i18n-persist-options.md):按需使用 localStorage 记住用户选择。 - [测试(Vitest)](/ai-i18n/guide/quality/testing.md):使用 React 插件与专用内存 Runtime 测试组件。 - [自动导入](/ai-i18n/guide/basic/auto-import.md):显式开启后省略 `useI18n` import。 - [React 在线演示](/ai-i18n/demo/react.md):查看可交互的完整示例。 --- url: https://bosens-china.github.io/ai-i18n/guide/basic/static-analysis/common.md --- # 通用文案写法 ai-i18n 只处理明确传给翻译 API 的文案,不会猜测哪些普通文本需要翻译。因此,请把需要翻译的 内容写入 `t()`。 本页介绍三个框架共用的写法。框架差异见 [Vue 文案写法](/ai-i18n/guide/basic/static-analysis/vue.md) 和 [React 文案写法](/ai-i18n/guide/basic/static-analysis/react.md)。 ## 支持的源码 | 模式 | 参与提取的源码 | | ------- | ---------------------------------------------- | | Vanilla | `.js`、`.mjs`、`.ts`、`.mts` | | Vue | `.js`、`.mjs`、`.ts`、`.mts`、`.jsx`、`.tsx`、`.vue` | | React | `.js`、`.mjs`、`.ts`、`.mts`、`.jsx`、`.tsx` | 表中的 JavaScript 与 TypeScript 源码必须作为浏览器端 ESM 模块使用。ai-i18n 不处理 `.cjs`、`.cts`,也不识别通过 `require()` 获得的翻译 API。Vite 对配置文件或依赖中 CommonJS 的兼容,不代表这些文件会参与 ai-i18n 提取。 `index.html` 默认不参与提取。设置 `html: true` 后,插件会分析完整的 `t()` 文本节点, 以及 `alt`、`aria-label`、`placeholder`、`title` 属性: ```ts aiI18n({ // 省略 sourceLang 与 locales 等基础配置。 html: true, }); ``` 普通 HTML 文本、混合文本(例如 `前缀 t('保存')`)、非白名单属性和内联脚本不会由 HTML 提取器处理。 ## 识别 `t()` 可以从 `virtual:ai-i18n` 导入 `t`,也可以在导入时改名: ```ts import { t as translate } from 'virtual:ai-i18n'; translate('保存'); ``` Vue 或 React 构建中的普通 ESM 工具模块也可以显式导入顶层 `t`: ```ts import { t } from 'virtual:ai-i18n'; export const getRetryMessage = () => t('请重试'); ``` 开启 [自动导入](/ai-i18n/guide/basic/auto-import.md) 后,可以省略导入。局部变量、函数参数和显式导入的同名 标识符仍按你的代码处理,不会被覆盖。 ## 支持的参数 日常文案优先使用字符串、静态 `const` 或条件表达式: ```ts t('保存'); const label = '取消'; t(label); t(canSubmit ? '提交' : '返回'); ``` 动态值使用 tagged template。表达式会变成可重排的编号占位符,不会发送给翻译模型: ```ts t`你好 ${user.name},你有 ${unreadCount} 条消息`; ``` 需要返回 HTML 字符串时,不要把结构性标签写进待翻译文案。把由代码维护的 HTML 片段作为 插值传入,让译文只负责自然语言、标点、单位和占位符顺序: ```ts const valueHtml = `${voltage}`; t`电压:${valueHtml} V`; ``` 这条文案会提取为 `电压:{{0}} V`。翻译者可以调整语序和单位,但不需要维护 `` 标签。 传入的动态内容仍应来自可信数据或完成必要的转义;模板插值不会自动净化 HTML。 启用 [`ai-i18n/no-embedded-markup`](/ai-i18n/guide/quality/eslint-rules.md#no-embedded-markup) 后, ESLint 会对最终可提取 source 中的静态 HTML 或 SVG 发出 warning。 需要一次得到整组译文时,可以直接传入静态纯文案树: ```ts const messages = { actions: { save: '保存', cancel: '取消' }, states: ['等待中', '处理中', '已完成'], }; const labels = t(messages); ``` 所有字符串叶子都会翻译。本地或导入的静态 `const` 都可使用,不需要 `as const`。 需要按属性或索引挑选单条文案时,使用无需 import 的编译宏: ```ts const messages = defineI18nMessages({ actions: { save: '保存', cancel: '取消' }, states: ['等待中', '处理中', '已完成'], }); t(messages.actions.save); t(messages.states[index]); ``` `defineI18nMessages()` 同样适用于普通 `.js` / `.ts` 文件。它不需要 import;TypeScript 类型来自 Vite 生成的主声明。编辑器找不到该名字时,按 [TypeScript 与生成声明](/ai-i18n/guide/quality/typescript.md)排查。 ### 动态业务数据只翻译展示标签 数据库、接口参数和业务判断应保存稳定 code,不要保存当前语言的译文。为有限枚举建立静态 文案映射,在展示时按 code 选择并翻译: ```ts type SportType = 'running' | 'cycling' | 'swimming'; const sportLabels = defineI18nMessages>({ running: '跑步', cycling: '骑行', swimming: '游泳', }); export function getSportLabel(sportType: SportType) { return t(sportLabels[sportType]); } ``` 例如记录中始终保存 `running`,界面才根据当前语言显示“跑步”或“Running”。这样切换语言不会 改变持久数据,排序、筛选和接口契约也不依赖展示文案。运行时可能出现未知 code 时,先由业务代码 决定回退或报错,不要把不受约束的动态字符串直接传给 `t()`。 翻译注释同样需要静态求值: ```ts t('保存', { comment: '工具栏按钮' }); const options = { comment: '结算按钮' }; t('提交', options); ``` `comment` 只用于说明翻译语境。相同原文在不同语境下可以得到不同译文。 ## 推荐写法与限制 | 写法 | Vite 提取 | ESLint | | ------------------------------------ | --------- | -------- | | `t('保存')` | 提取 | 允许 | | `const label = '保存'; t(label)` | 提取 | 允许 | | `t(ok ? '保存' : '取消')` | 提取两个候选 | 允许 | | `` t`你好 ${name}` `` | 提取编号模板 | 允许 | | `t({ save: '保存', states: ['等待中'] })` | 提取所有字符串叶子 | 允许 | | `t(messages.states[index])`,集合已用宏标记 | 提取有限候选 | 允许 | | `t('保' + '存')` | 不推荐 | 报错 | | `t(ok && '保存')` | 不推荐 | 报错 | | `let label = '保存'; t(label)` | 不推荐 | 报错 | | 普通对象或数组成员传给 `t()` | 使用宏 | 报错并建议使用宏 | 建议启用 [ESLint](/ai-i18n/guide/quality/eslint.md),在本地尽早发现不推荐的写法。 ## 提取成功不等于会刷新 文案被识别不代表界面会自动刷新。语言切换后的更新还取决于 `t()` 的执行时机: | 写法 | 提取 | 语言切换行为 | | --------------------------------------- | -- | --------------- | | `export const label = t('保存')` | 是 | 初始化时保存快照,不会自动更新 | | `export const getLabel = () => t('保存')` | 是 | 每次调用读取当前语言 | 组件还需要建立框架订阅。具体规则见 [Vue 文案写法](/ai-i18n/guide/basic/static-analysis/vue.md) 和 [React 文案写法](/ai-i18n/guide/basic/static-analysis/react.md)。 ## 不支持的写法 - 不提取普通字符串、普通 JSX 文本、普通 Vue 模板文本或普通 HTML 文本。 - 函数调用、`await`、`JSON.parse()` 和其他运行时结果不能作为 `t()` 参数。 - 普通对象或数组成员需要先用 `defineI18nMessages()` 标记,才能按属性或索引选择文案。 - 文案树只适合普通对象、数组和基础值;不要混入路由、业务 key、函数或运行时数据。 - 普通 JSX、Vue 模板和 HTML 文本不会自动翻译,必须显式调用翻译 API。 - 开发服务器只处理已访问模块;提交或补译前请运行完整 Build。 - 当前运行时只支持浏览器端,不支持 SSR。 完整签名与边界见 [`t()`](/ai-i18n/api/runtime/functions/t.md)。 --- url: https://bosens-china.github.io/ai-i18n/guide/basic/static-analysis/vue.md --- # Vue 文案写法 本页只介绍 Vue 特有写法。参数、文案树和宏的通用规则见[通用文案写法](/ai-i18n/guide/basic/static-analysis/common.md)。 ## 支持的源码 Vue 模式分析 `.js`、`.mjs`、`.ts`、`.mts`、`.jsx`、`.tsx` 与 `.vue` 源码。JavaScript 与 TypeScript 模块必须使用 ESM,不支持 `.cjs`、`.cts` 或 CommonJS 调用方式。JSX/TSX 项目需要使用 `@vitejs/plugin-vue-jsx`。 Vue SFC 会分析 ` ``` 普通 Options API 也调用同一个顶层 `t`: ```vue ``` 普通 Options 的 import 不会自动成为组件实例属性,因此 template 要直接写 `t()` 时,需要 像上例一样把它暴露为 `methods: { t }`。这是一个真实的 Vue method,不使用 `globalProperties`。脚本内仍直接调用词法作用域中的 `t()`,不要改写成 `this.t()`。 `useI18n().t` 与顶层导出的 `t` 是同一个函数。它们都读取 Vue adapter 维护的共享 revision;template、render 或 computed 执行 `t()` 时,Vue 会收集这项依赖。响应式刷新 不是由每个组件调用 `useI18n()` 后单独订阅得到的。 新代码需要语言状态或 action 时,让 `useI18n()` 只提供这些值即可: ```ts import { t, useI18n } from 'virtual:ai-i18n'; const { currentLang, isLangLoading, setLang } = useI18n(); ``` `useI18n()` 仍返回 `t`,既有解构写法与顶层 import 完全等价,不属于废弃能力。 开启 `autoImport: true` 后,可以删除 `t` 的 import。` ``` 整棵静态文案树不要求 `as const` 或 `defineI18nMessages()`。 不要在 template 中直接调用 `tRef()`,否则每次渲染都会创建新的 `computed`。 Vue 的 ` ``` 这里的顶层 `t` 与 `useI18n().t` 是同一个函数。新代码需要响应式语言状态时, `useI18n()` 通常只解构 Ref 和 action。 纯 Options API 不需要用 `methods: { t }` 建立模板桥接。脚本中的 computed / method 与 template 都可以直接调用词法作用域或模板作用域中的 `t()`: ```vue ``` 插件只为未绑定的值引用注入 API。模板局部变量以及组件自身的 prop、data、computed、 method、inject 或 setup 返回值会遮挡自动导入;本地同名 binding 始终优先。`this.t()`、 `this.$t()`、mixin 与 `globalProperties` 不属于 ai-i18n 调用。 ### 关闭自动导入时 `autoImport: false` 时仍需从 `virtual:ai-i18n` 显式导入。` ``` 普通 Options ` ``` 这项显式导入 bridge 的静态边界见 [Vue 文案写法](/ai-i18n/guide/basic/static-analysis/vue.md#显式导入下的-options-bridge)。 顶层 `t` 应在实际需要文案时调用,不要在模块初始化期间保存译后字符串: ```ts export const label = t('保存'); // 不会刷新;ESLint preset 会 warning export const getLabel = () => t('保存'); // 每次调用读取当前语言 ``` ## TypeScript 支持 自动导入依靠插件生成的 TypeScript 声明。Vue 模式还会生成相邻的 `.vue.d.ts` template 类型桥。两个文件的职责、自定义 `dts` 路径和常见类型问题统一见 [TypeScript 与生成声明](/ai-i18n/guide/quality/typescript.md)。 ## ESLint 配置 TypeScript 声明不会自动配置 ESLint。开启自动导入后,请按最终框架模式使用 `@ai-i18n/eslint-plugin` 的 `configs['vanilla-auto-import']`、 `configs['vue-auto-import']` 或 `configs['react-auto-import']`。这些预设会声明对应的 只读全局,并检查静态提取语法。完整配置见 [ESLint](/ai-i18n/guide/quality/eslint.md)。它们还会提示初始化期译文快照;React preset 会提示 组件渲染路径中没有订阅的顶层 `t`。Vue / React preset 都会检查模块顶层或组件渲染中的 `getLang()` / `getLangLoadState()` 快照。如果项目希望禁止自动导入模式中残留的 `virtual:ai-i18n` 显式导入,可以按完整框架 API 列表额外启用可自动修复的 `ai-i18n/no-redundant-auto-import`;该规则默认不包含在 preset 中。 --- url: https://bosens-china.github.io/ai-i18n/guide/basic/locale-loading.md --- # 语言分包与按需加载 默认情况下,ai-i18n 会把所有目标语言注册到同一个 Runtime。配置 `loading` 后,每个目标 locale 会生成独立的 Vite chunk;未提前加载的语言会在首次 `setLang()` 时按需加载。 ## 配置分包策略 ```ts // vite.config.ts import { aiI18n } from '@ai-i18n/vite'; aiI18n({ sourceLang: 'zh-CN', // source locale 同步可用,不生成独立语言 chunk // value 是语言标识,label 是界面中的展示名称。 locales: [ { value: 'zh-CN', label: '中文' }, { value: 'en-US', label: 'English' }, { value: 'ja-JP', label: '日本語' }, { value: 'fr-FR', label: 'Français' }, ], loading: { // 启用按 locale 分包并声明资源加载提示 preload: ['en-US'], // 通过 modulepreload 尽早准备 prefetch: ['ja-JP'], // 通过 prefetch 低优先级缓存 }, }); ``` | 语言 | 加载方式 | | ------- | ------------------------------------------------------------- | | `zh-CN` | source locale,不生成语言 chunk | | `en-US` | 通过 `modulepreload` 尽早准备;非 source 的 `defaultLang` 也会自动 preload | | `ja-JP` | 通过 `prefetch` 提示浏览器低优先级缓存 | | `fr-FR` | 首次调用 `setLang('fr-FR')` 时加载 | `modulepreload` 与 `prefetch` 都是浏览器调度提示,不保证资源在某个时刻已经完成下载。 如果 `defaultLang` 保持 source,并希望所有目标语言都在切换时再加载,只需传入空对象: ```ts aiI18n({ sourceLang: 'zh-CN', // 默认语言保持 source locales, // 复用上方完整语言列表 loading: {}, // 启用分包,其他目标语言首次 setLang() 时再加载 }); ``` 省略 `loading` 并不等于 `loading: {}`。前者保留默认的全语言注册模式,后者会启用分包, 并让未指定的目标语言完全按需加载。 ## 显示切换中的加载状态 `setLang()` 返回 Promise。目标语言 chunk 尚未加载时,它会等待资源完成;成功后才切换语言 并通知订阅者更新。Runtime 同时维护共享状态。Vue adapter 统一维护响应式 revision; Composition 组件通过 `useI18n()` 读取共享 Ref,纯 Options 组件通过 `i18nComputed()` 读取已解包状态。React 组件通过 `useI18n()` 订阅,Vanilla JS 通过 `subscribe()` 订阅。 **Vue** ```vue ``` **Vue Options** ```vue ``` **React** ```tsx import { useI18n } from 'virtual:ai-i18n'; export function LanguageButton() { const { isLangLoading, langLoadState, setLang, t } = useI18n(); async function switchToFrench() { try { await setLang('fr-FR'); } catch { // 仅在这里添加业务级恢复动作;通用错误展示直接读取 langLoadState.status。 } } return ( <> {langLoadState.status === 'error' ? (

{t('语言包加载失败,请重试')}

) : null} {langLoadState.status === 'loading' ? ( {t('目标语言:')} {langLoadState.targetLang} ) : null} ); } ``` **Vanilla JS** ```js import { getLangLoadState, setLang, subscribe, t } from 'virtual:ai-i18n'; const button = document.querySelector('#switch-language'); const status = document.querySelector('#language-status'); function render() { const state = getLangLoadState(); button.disabled = state.status === 'loading'; button.textContent = state.status === 'loading' ? t('正在加载语言包…') : t('切换到法语'); status.textContent = state.status === 'error' ? t('语言包加载失败,请重试') : ''; } button.addEventListener('click', () => { // 共享状态不会消费 rejected Promise,调用方仍需显式 catch。 void setLang('fr-FR').catch(() => {}); }); render(); const unsubscribe = subscribe(render); // 页面或视图销毁时调用 unsubscribe()。 ``` 加载失败时,Runtime 会保留当前语言并让 Promise reject。应用可以像上例一样捕获错误, 执行日志、重试计数等业务动作;只需要通用 UI 时可以直接使用内置状态。 普通 JavaScript / TypeScript 模块如果只需要当前值,可以读取一次快照: ```ts import { getLangLoadState } from 'virtual:ai-i18n'; const state = getLangLoadState(); ``` 需要持续响应变化时,应像 Vanilla 示例一样配合 `subscribe()` 重新读取。状态的完整类型与 并发语义见 [`getLangLoadState()`](/ai-i18n/api/runtime/functions/get-lang-load-state.md)。 ## 配置规则 - `preload` 与 `prefetch` 只能填写 `locales` 中的目标 locale,不能填写 `sourceLang`。 - 同一 locale 不能同时出现在两个列表中;同一列表内的重复值会自动去重。 - 非 source 的 `defaultLang` 会自动按 preload 处理。不要再把它填入 `prefetch`,否则配置会在启动时 报错。资源就绪前先渲染 source fallback,加载完成后再通知订阅者更新。 - 相同 locale 的并发调用会复用同一次底层语言包加载请求,不保证各次 `setLang()` 返回的 Promise 引用相等。不同 locale 的并发切换以最后一次调用为准。 - 缺失或值为 `null` 的译文始终回退到 source 文案。 完整字段类型与边界见 [`AiI18nLocaleLoadingOptions`](/ai-i18n/api/vite/interfaces/ai-i18n-locale-loading-options.md)。 --- url: https://bosens-china.github.io/ai-i18n/guide/basic/directory.md --- # 生成文件与 Git ai-i18n 默认在 Vite root 下创建 `i18n/` 目录,用来保存译文和本地构建产物: ```text i18n/ ├── translations/ # 默认 JSON 存储 │ ├── manifest.json │ └── 00.json ... ff.json ├── overrides.json ├── extracted/ ├── locales/ └── storage.json # 仅 SQLite 存储 ``` 你通常只需要关注两类文件: - `translations/`:默认的分片 JSON Translation Memory,保存自动翻译或 Agent 补齐的译文。 - `storage.json`:仅在选择 SQLite 时生成。缺少该文件表示使用默认 JSON;文件不包含本机数据库路径。 - `overrides.json`:人工确认过的最终译文。它优先于自动翻译结果。 `extracted/` 和 `locales/` 都是构建产物。插件会根据源码和上述译文重新生成它们,不要直接编辑。 ## Git 提交规则 将以下文件与源码一起提交: - `src/ai-i18n.d.ts`,或通过 `dts` 配置的声明文件; - Vue 自动导入模式生成的相邻 `.vue.d.ts` 声明文件; - `i18n/translations/**/*.json`(使用默认 JSON 存储时); - `i18n/storage.json`(使用 SQLite 存储时); - `i18n/overrides.json`。 将以下目录加入 `.gitignore`: ```text i18n/extracted/ i18n/locales/ logs/ *.log ``` `logs/` 与 `*.log` 是 OpenAI Provider 的本地审查日志,可能包含完整提示词、业务文案和模型输出, 不得提交。使用自定义日志目录时也要忽略该目录。详情见 [LLM 日志与排障](/ai-i18n/guide/advanced/llm-logs.md)。 默认的分片 JSON 适合团队协作。它可以随源码提交,也便于在 PR 中审查译文变化。团队成员与 CI 拉取 同一份仓库后,可以直接复用已经提交的自动译文和人工译文。 :::important 译文文件与引用它们的源码应在同一个 PR 中提交。这样其他开发者和 CI 才能得到一致的翻译结果。 ::: 选择 `translationMemory.storage: 'sqlite'` 时,全局数据库位于用户目录,不提交 Git;项目仍提交 `storage.json` 与 `overrides.json`。SQLite 是本机缓存,新机器和 CI 需要 Provider 重新生成自动 译文。因此,需要跨机器共享自动译文的团队应使用默认的分片 JSON。两种存储的选择见 [Translation Memory](/ai-i18n/guide/advanced/translation-memory.md)。 声明文件的作用和自定义路径见 [TypeScript 与生成声明](/ai-i18n/guide/quality/typescript.md)。 ## 什么时候运行完整 Build 开发服务器只处理浏览器实际访问过的模块。以下情况请运行一次完整 `vite build`: 1. 首次接入 ai-i18n; 2. 准备补译、审校或提交译文; 3. 切换分支后,或修改了源码、Vite 配置和提取相关配置; 4. `i18n/extracted/` 缺失、为空,或不确定它是否仍与当前源码一致。 完整 Build 会处理从应用入口可达的模块。未被应用引用的文件不会进入翻译结果。 ## Monorepo 中的目录归属 一个 Vite build 必须独占一个 i18n 目录。例如: ```text apps/ ├── web/ │ └── i18n/ └── admin/ └── i18n/ packages/ └── ui/ └── src/ ``` `web` 引用 `packages/ui` 的本地 ESM 源码时,完整 Build 会把 UI 文案纳入 `apps/web/i18n`。共享源码包不需要重复注册 ai-i18n,也不需要单独创建 i18n 目录,除非它 自己拥有独立的 Vite build。 不要让 Web、Admin 或包构建共用一个目录。完整 Build 会按当前应用的模块图重建 `extracted/` 和 `locales/`,不同构建会相互覆盖。补译或审校时也应分别选择每个应用。 ## 缺译时会发生什么 目标语言缺少译文时,页面会显示源码文案。你可以配置 [AI 翻译](/ai-i18n/guide/advanced/ai-translation.md),也可以按 [补译与审校](/ai-i18n/guide/basic/translations.md) 手动处理。 同一句原文在不同语境下需要不同译法时,为 `t()` 提供 `comment`: ```ts t('提交', { comment: '创建 Git 提交' }); t('提交', { comment: '表单按钮' }); ``` ## 处理合并冲突 合并冲突时保留 `translations/` 与 `overrides.json` 的有效内容,不要手工调整消息所属分片。同一人工 译文出现不同版本时,由负责人确认最终措辞。解决冲突后运行一次 Build,再检查页面效果。 如果同时使用 Agent 或 Provider 写入译文,避免在编辑器中并行手改同一份译文文件。先完成一方操作,再进行 另一方操作。 --- url: https://bosens-china.github.io/ai-i18n/guide/basic/translations.md --- # 补译与审校 ai-i18n 不会用空字符串代替缺失译文。缺译时页面会回退显示源码文案,因此可以先完成开发,再逐步处理翻译。 ## 推荐流程 1. 运行一次完整 `vite build`,让当前应用的可达文案进入翻译结果。 2. 选择一种补译方式:配置 [AI 翻译](/ai-i18n/guide/advanced/ai-translation.md),或使用 [Agent + MCP](/ai-i18n/guide/advanced/ai-tools.md)。 3. 检查关键页面和产品术语。 4. 对不满意或需要固定的译文进行人工审校。 5. 再运行一次 Build,并按当前存储模式提交源码、Translation Memory 标记与 `overrides.json`。 ## 自动翻译与人工译文 自动翻译默认写入 `i18n/translations/` 分片。人工确认的译文写入 `i18n/overrides.json`,并且始终优先 显示。也可以将自动译文放进用户级全局 SQLite,详见 [Translation Memory](/ai-i18n/guide/advanced/translation-memory.md)。 适合人工审校的情况包括: - 品牌名、产品术语和法律文案; - 同一原文在不同页面代表不同含义; - 需要符合团队既有的语言风格。 同一句原文有不同含义时,请为调用添加静态 `comment`,再按该语境分别审校: ```ts t('保存', { comment: '保存文件按钮' }); t('保存', { comment: '保存状态' }); ``` ## 直接编辑译文文件 Provider 或 Agent + MCP 会自动维护文件结构,适合批量补译和按语境审校。需要手工调整少量译文时, 也可以编辑现有 JSON 文件,但不要用下面的示例覆盖已经生成的内容。 默认存储下,`translations/*.json` 保存自动译文。先在分片中搜索目标 `source`,保留 `version`、消息 标识和源码信息,只修改目标消息 `translations` 下的语言值。不要修改 `manifest.json`,也不要手工把 消息移动到另一个分片。以下分片示例对应不带 `comment` 的 `t('保存')`: ```json { "version": 1, "messages": { "保存": { "source": "保存", "sourceLang": "zh-CN", "translations": { "en-US": "Save" } } } } ``` SQLite 模式不适合直接编辑数据库,请使用 Provider 或 Agent + MCP。少量已确认措辞仍建议写入 `overrides.json`,这样可以提交并在不同电脑间保持一致。 `overrides.json` 使用便于审查的扁平 `rules` 保存人工决定。只写 `source` 时,译文对当前 Vite 应用内的所有同源文案生效: ```json { "version": 2, "rules": [ { "source": "保存", "translations": { "en-US": "Save" } } ] } ``` 同一句话只需要在部分文件采用不同译法时,为规则增加 `files`。路径必须是相对 Vite `root` 的 标准化 POSIX 路径,并与列表工具返回的 `source_file` 完全一致;不接受绝对路径、路径片段或 glob。 一个规则可以列出多个文件,以复用完全相同的审校决定: ```json { "version": 2, "rules": [ { "source": "保存", "files": ["src/editor/actions.ts", "src/editor/toolbar.ts"], "translations": { "en-US": "Save file" } }, { "source": "保存", "comment": "保存状态", "files": ["src/status/panel.ts"], "translations": { "en-US": "Keep" } } ] } ``` `comment` 与 `files` 可以单独使用,也可以组合。最终优先级从高到低是:文件 + `comment`、全局 + `comment`、文件默认、全局默认、自动译文、源码回退。建议使用 [Agent + MCP](/ai-i18n/guide/advanced/ai-tools.md) 列出现有文案和精确路径,确认措辞后再写入;不要自行构造 语境标识。生成目录 `i18n/extracted/` 和 `i18n/locales/` 不接受人工编辑。 ## 提交前检查 - 切换每一种支持语言,确认关键页面没有意外回退到源码文案; - 确认占位符、代码和品牌名没有被误译; - 运行 `vite build`; - 遵循[生成文件与 Git](/ai-i18n/guide/basic/directory.md)的提交规则。 --- url: https://bosens-china.github.io/ai-i18n/guide/quality/typescript.md --- # TypeScript 与生成声明 本页只说明 ai-i18n 为 TypeScript 项目增加的内容。通过 Vite 模板创建的项目可以继续使用模板 自带的 TypeScript 配置,不需要为了接入 ai-i18n 重写 `tsconfig`。 ## 接入类型声明 首次启动 Vite Dev Server 或执行 Build 后,插件会在 Vite root 下生成声明文件。默认路径是: ```text src/ai-i18n.d.ts ``` 它位于 Vite 模板默认包含的 `src/` 中,因此通常不需要额外配置。业务源码也不应 import 这个 `.d.ts` 文件;正常导入 `virtual:ai-i18n`,或按需开启自动导入即可。 ```ts import { t, useI18n } from 'virtual:ai-i18n'; ``` 如果编辑器在文件生成后仍保留旧错误,先重启 TypeScript language service 或编辑器,再运行 项目已有的类型检查命令。 ## 生成文件各自负责什么 ### `ai-i18n.d.ts` 主声明适用于 Vanilla、Vue 和 React,除非显式设置 `dts: false`。它负责: - 声明 `virtual:ai-i18n` 及当前框架可用的 Runtime API; - 声明无需 import 的 `defineI18nMessages()` 编译宏; - 开启 `autoImport: true` 后,为脚本中的自动导入 API 提供全局类型。 这个文件解决的是 TypeScript 脚本作用域中的类型问题。 ### `ai-i18n.vue.d.ts` Vue 模式同时开启 `autoImport: true` 时,还会在主声明旁生成: ```text src/ai-i18n.d.ts src/ai-i18n.vue.d.ts ``` 第二个文件扩展 Vue 的组件类型,让 Vue language-tools(Volar)与 `vue-tsc` 识别 template 中的裸 `t()`。主声明会引用它,因此两个文件应保持相邻。 这个文件只是 template 的类型桥,不会向组件实例安装 method。即使编辑器能识别 `{{ t('保存') }}`,脚本中也不要改写成 `this.t()` 或 `this.$t()`。 生成声明由插件维护,不要手工修改。是否提交到 Git 以及其他生成文件的归属见 [生成文件与 Git](/ai-i18n/guide/basic/directory.md)。 ## 显式导入与自动导入 | 使用方式 | 脚本类型来源 | Vue template 类型来源 | | ---------------------- | --------- | -------------------------------------- | | 从 `virtual:ai-i18n` 导入 | 主声明中的模块声明 | ` ``` 开启 `autoImport: true` 后,可以只保留 template: ```vue ``` 插件生成的声明会让 Vue language-tools(Volar)与 `vue-tsc` 识别这个裸 `t`, 无需为了 IDE 添加 import。` ``` Options 的普通 ` ``` 需要完整签名和文案树示例时,查看 [`tRef()` API](/ai-i18n/api/runtime/vue/t-ref.md)。 ## 纯 Options API 如何预声明响应式文案? 使用 [`tComputed()`](/ai-i18n/api/runtime/vue/t-computed.md),并把返回的 getter 放入 Options `computed`: ```ts export default defineComponent({ computed: { saveLabel: tComputed('保存'), labels: tComputed({ save: '保存', cancel: '取消' }), }, }); ``` 不要把 `tComputed()` 放入 `data()`,也不要在 template 或 render 中调用。依赖 `this` 的动态插值应写成普通 computed,并在 getter 中调用 `t()`。 --- url: https://bosens-china.github.io/ai-i18n/guide/faq/react.md --- # React 常见问题 ## 为什么普通 JSX 文本没有被提取? ai-i18n 不猜测普通 UI 文本。把需要翻译的文本放入 `useI18n()` 返回的 `t()`: ```tsx import { useI18n } from 'virtual:ai-i18n'; function SaveButton() { const { t } = useI18n(); return ; } ``` 支持的静态表达式、文案树与限制见 [React 文案写法](/ai-i18n/guide/basic/static-analysis/react.md)。 ## 为什么切换语言后组件没有刷新? 组件渲染必须调用 `useI18n()` 返回的 `t`。从 `virtual:ai-i18n` 单独导入的顶层 `t` 只读取 当前语言,不会让组件订阅后续更新。 也不要把 `t('保存')` 的结果放入模块常量或长期 state。保留 source 文案,在每次渲染时调用 Hook 返回的 `t()`。 ## 非组件 TS 文件如何读取或切换语言? 普通模块、store action、路由和事件处理器不能调用 React Hook,应使用顶层 Runtime API。 开启 `autoImport: true` 后,可以直接调用 `setLang()`、`getLang()`、`getLangs()`、 `getLangLoadState()` 与 `subscribe()`。 其中 `getLang()` 与 `getLangLoadState()` 返回调用时快照。组件需要展示这些状态时仍应使用 `useI18n()`,否则语言变化不会触发重新渲染。 ## React Compiler 能否替代 `useI18n()`? 不能。React Compiler 可以缓存渲染计算,但不会为 Runtime 顶层 `t` 自动建立外部状态订阅。 `useI18n()` 内部使用 `useSyncExternalStore`,Runtime 更新时还会刷新 `t` 的函数引用,因此 无论是否启用 React Compiler,组件渲染都应使用 Hook 返回的 `t`。 ## 普通工具模块不能调用 Hook,应该怎么翻译? 普通 `.js` 或 `.ts` 工具模块可以导入 Runtime 顶层 `t`,但应在实际调用时翻译: ```ts import { t } from 'virtual:ai-i18n'; export const getRetryMessage = () => t('请重试'); ``` 不要导出 `const retryMessage = t('请重试')`,它只保存模块初始化时的译文快照。组件渲染仍 使用 `useI18n()`。 ## 本地 link 后为什么出现 Invalid Hook Call? 先确认应用只解析到一份 `react` 和 `react-dom`。本地工作区或 link 场景可在 Vite 中添加: ```ts export default defineConfig({ resolve: { dedupe: ['react', 'react-dom'], }, }); ``` 正常安装通常由 peer dependency 复用应用自己的 React,不需要额外配置。 --- url: https://bosens-china.github.io/ai-i18n/api/index.md --- # API 总览 需要完成安装、配置和业务接入时,从[快速上手](/ai-i18n/guide/getting-started/vue.md)与 [接入与使用](/ai-i18n/guide/basic/static-analysis/common.md)开始。本节只负责记录公开 API 的准确签名、 配置字段、默认值与行为边界,不重复教程流程。 API 参考按导入入口组织。选择入口后,再按函数、接口、类型别名或编译宏查找具体符号。 | 入口 | 用途 | | ---------------------- | -------------------------------- | | `@ai-i18n/vite` | 注册 Vite 插件,配置提取、翻译和自定义 Provider。 | | `@ai-i18n/vite/vitest` | 在 Vitest 中提供内存 Runtime 与编译宏转换。 | | `virtual:ai-i18n` | 在浏览器业务代码中翻译文案和切换语言。 | | `@ai-i18n/openai` | 创建 OpenAI-compatible Translator。 | ## 查找入口 - 配置插件:[`aiI18n()`](/ai-i18n/api/vite/functions/ai-i18n.md) - 查询全部插件选项:[`AiI18nOptions`](/ai-i18n/api/vite/interfaces/ai-i18n-options.md) - 翻译文案:[`t()`](/ai-i18n/api/runtime/functions/t.md) - 在 Vue setup 中创建响应式翻译值:[`tRef()`](/ai-i18n/api/runtime/vue/t-ref.md) - 读取语言资源加载状态:[`getLangLoadState()`](/ai-i18n/api/runtime/functions/get-lang-load-state.md) - 在 Vue 中读取响应式语言状态:[`useI18n()`](/ai-i18n/api/runtime/vue/use-i18n.md) - 在 React 中订阅语言变化:[`useI18n()`](/ai-i18n/api/runtime/react/use-i18n.md) - 配置 Vitest:[`aiI18nVitest()`](/ai-i18n/api/vitest/functions/ai-i18n-vitest.md) - 连接模型:[`openAI()`](/ai-i18n/api/openai/functions/open-ai.md) - 实现自定义翻译器:[`Translator`](/ai-i18n/api/vite/type-aliases/translator.md) ## 本节职责 本节记录应用接入所依赖的公开契约。Analyzer、文件 Schema、Translation Memory 事务和框架 适配器等低层基础设施不作为普通应用的稳定接入入口。除非文档明确列出,否则不要依赖包中 的其他导出。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/functions/ai-i18n.md --- # aiI18n() 从 `@ai-i18n/vite` 导入: ```ts import { aiI18n } from '@ai-i18n/vite'; ``` ## 签名 ```ts function aiI18n(options: AiI18nOptions): Plugin; ``` `aiI18n()` 返回一个 Vite 插件。每个 Vite build 只应注册一次。 ## 示例 ```ts import { aiI18n } from '@ai-i18n/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ aiI18n({ sourceLang: 'zh-CN', locales: [ { value: 'zh-CN', label: '中文' }, { value: 'en-US', label: 'English' }, ], }), ], }); ``` 配置完成后,业务代码从 `virtual:ai-i18n` 导入 Runtime API: ```ts import { setLang, t } from 'virtual:ai-i18n'; ``` ## 参数 | 参数 | 类型 | 说明 | | --------- | ------------------------------------------------------------------ | ------------ | | `options` | [`AiI18nOptions`](/ai-i18n/api/vite/interfaces/ai-i18n-options.md) | Vite 插件完整配置。 | ## 返回值 返回 Vite 的 `Plugin` 对象。插件负责静态提取、协议文件同步、可选 Provider 调度、虚拟 Runtime 和声明文件生成。 ## 相关内容 - [Vue 快速上手](/ai-i18n/guide/getting-started/vue.md) - [React 快速上手](/ai-i18n/guide/getting-started/react.md) - [Vanilla 快速上手](/ai-i18n/guide/getting-started/vanilla.md) - [通用文案写法](/ai-i18n/guide/basic/static-analysis/common.md) - [生成文件与 Git](/ai-i18n/guide/basic/directory.md) --- url: https://bosens-china.github.io/ai-i18n/api/vite/interfaces/ai-i18n-options.md --- # AiI18nOptions 从 `@ai-i18n/vite` 导入: ```ts import type { AiI18nOptions } from '@ai-i18n/vite'; ``` ## 定义 ```ts interface AiI18nOptions { framework?: AiI18nFramework; autoImport?: boolean; dts?: string | false; sourceLang: string; defaultLang?: string; locales: readonly LangOption[]; persist?: boolean | AiI18nPersistOptions; loading?: AiI18nLocaleLoadingOptions; translationMemory?: AiI18nTranslationMemoryOptions; provider?: AiI18nProviderOptions; directory?: string; cleanup?: AiI18nCleanupOptions; html?: boolean | HtmlExtractorOptions; } ``` ## 字段 | 字段 | 类型 | 必填 | 默认值 | 作用 | | ------------------- | ------------------------------------------------------------------------------------------------------ | -- | -------------------- | -------------------------- | | `sourceLang` | `string` | 是 | 无 | 源码文案所属语言。 | | `locales` | [`readonly LangOption[]`](/ai-i18n/api/vite/interfaces/lang-option.md) | 是 | 无 | 项目支持的语言列表。 | | `defaultLang` | `string` | 否 | `sourceLang` | 没有有效持久化值时使用的初始语言。 | | `persist` | `boolean` 或 [`AiI18nPersistOptions`](/ai-i18n/api/vite/interfaces/ai-i18n-persist-options.md) | 否 | `false` | 使用 localStorage 保存语言偏好。 | | `loading` | [`AiI18nLocaleLoadingOptions`](/ai-i18n/api/vite/interfaces/ai-i18n-locale-loading-options.md) | 否 | 全语言注册 | 按 locale 拆分语言资产。 | | `framework` | [`AiI18nFramework`](/ai-i18n/api/vite/type-aliases/ai-i18n-framework.md) | 否 | 自动检测 | 指定 Vanilla、Vue 或 React 模式。 | | `autoImport` | `boolean` | 否 | `false` | 自动注入当前框架模式的 Runtime API。 | | `dts` | `string \| false` | 否 | `'src/ai-i18n.d.ts'` | 设置声明文件路径,或关闭生成。 | | `directory` | `string` | 否 | `'i18n'` | 设置协议目录;相对路径基于 Vite `root`。 | | `provider` | [`AiI18nProviderOptions`](/ai-i18n/api/vite/type-aliases/ai-i18n-provider-options.md) | 否 | 不调用模型 | 配置自动翻译函数、缓存与调度策略。 | | `html` | [`boolean \| HtmlExtractorOptions`](/ai-i18n/api/vite/interfaces/html-extractor-options.md) | 否 | `false` | 开启 `index.html` 文本和属性提取。 | | `translationMemory` | [`AiI18nTranslationMemoryOptions`](/ai-i18n/api/vite/interfaces/ai-i18n-translation-memory-options.md) | 否 | 分片 JSON | 选择存储方式,并按需限制历史译文容量。 | | `cleanup` | [`AiI18nCleanupOptions`](/ai-i18n/api/vite/interfaces/ai-i18n-cleanup-options.md) | 否 | 保留默认清理策略 | 控制失效提取文件和孤立消息的清理。 | ## 语言约束 `locales` 至少包含一项,且每一项的 `value` 必须唯一。`sourceLang` 与 `defaultLang` 必须匹配 某个 `value`。 目标语言缺译或值为 `null` 时,Runtime 返回 source 文案。插件不会为 `sourceLang` 生成重复的 目标语言文件。 初始语言按以下顺序选择: 1. localStorage 中有效的持久化值; 2. `defaultLang`; 3. 省略 `defaultLang` 时使用 `sourceLang`。 ## 框架与自动导入 省略 `framework` 时,插件读取 Vite 最终插件列表: | 检测结果 | 模式 | | ------------------------------ | --------- | | 存在 `vite:vue` 或 `vite:vue-jsx` | `vue` | | 存在 `vite:react*` | `react` | | 都不存在 | `vanilla` | 同一个 build 同时出现 Vue 与 React 插件时会报错。显式设置 `framework` 不会绕过这项检查。 显式值只能是 `'vanilla'`、`'vue'` 或 `'react'`;JavaScript 配置中的其他值也会在启动时被拒绝。 `autoImport: true` 注入的 API 取决于最终模式。三种模式都有 `t`、`setLang`、`getLang`、 `getLangs`、`getLangLoadState` 与 `subscribe`;Vue 额外注入 `useI18n`、`tRef`、 `i18nComputed`、`tComputed`,React 额外注入 `useI18n`。 完整接入方法见[自动导入](/ai-i18n/guide/basic/auto-import.md)。 ## 路径 `directory` 与 `dts` 的相对路径都基于 Vite `root` 解析;传入绝对路径时直接使用该路径。 ## 相关内容 - [`aiI18n()`](/ai-i18n/api/vite/functions/ai-i18n.md) - [语言分包与按需加载](/ai-i18n/guide/basic/locale-loading.md) - [生成文件与 Git](/ai-i18n/guide/basic/directory.md) - [TypeScript 与生成声明](/ai-i18n/guide/quality/typescript.md) - [Translation Memory](/ai-i18n/guide/advanced/translation-memory.md) - [ESLint](/ai-i18n/guide/quality/eslint.md) --- url: https://bosens-china.github.io/ai-i18n/api/vite/interfaces/ai-i18n-persist-options.md --- # AiI18nPersistOptions 从 `@ai-i18n/vite` 导入: ```ts import type { AiI18nPersistOptions } from '@ai-i18n/vite'; ``` ## 定义 ```ts interface AiI18nPersistOptions { key: string; } ``` ## 字段 | 字段 | 类型 | 必填 | 作用 | | ----- | -------- | -- | ------------------------- | | `key` | `string` | 是 | 保存当前语言的 localStorage key。 | `key` 去除首尾空白后不能为空。 ## 用法 [`AiI18nOptions.persist`](/ai-i18n/api/vite/interfaces/ai-i18n-options.md) 支持三种写法: | 写法 | 行为 | | ------------------------- | ------------------ | | `false` 或省略 | 不读写 localStorage。 | | `true` | 使用 `ai-i18n:lang`。 | | `{ key: 'app-language' }` | 使用指定 key。 | 存储不可用或保存值不在 `locales` 中时,Runtime 会忽略该值。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/interfaces/ai-i18n-locale-loading-options.md --- # AiI18nLocaleLoadingOptions 从 `@ai-i18n/vite` 导入: ```ts import type { AiI18nLocaleLoadingOptions } from '@ai-i18n/vite'; ``` ## 定义 ```ts interface AiI18nLocaleLoadingOptions { preload?: readonly string[]; prefetch?: readonly string[]; } ``` ## 字段 | 字段 | 类型 | 默认值 | 作用 | | ---------- | ------------------- | ---- | ---------------------------- | | `preload` | `readonly string[]` | `[]` | 通过 `modulepreload` 尽早准备语言模块。 | | `prefetch` | `readonly string[]` | `[]` | 通过 `prefetch` 提示浏览器低优先级缓存。 | ## 行为 设置 `loading` 后,每个目标 locale 会生成独立 Vite chunk。省略 `loading` 时,插件继续使用 全语言注册模式;`loading: {}` 则会启用分包,并在首次 `setLang()` 时加载目标语言。 列表必须满足以下约束: - 只能引用 `locales` 中的目标 locale; - 不能包含 `sourceLang`; - 同一 locale 不能同时出现在两个列表中; - 单个列表中的重复值会自动去重。 非 source 的 `defaultLang` 会自动加入 `preload`,因此不能再把它列入 `prefetch`;该组合会在启动时 报错。相同 locale 的并发调用复用底层加载请求;不同 locale 的并发切换以最后一次 `setLang()` 调用为准。 ## 示例 ```ts aiI18n({ sourceLang: 'zh-CN', defaultLang: 'en-US', locales, loading: { preload: ['en-US'], prefetch: ['ja-JP'], }, }); ``` 完整使用流程见[语言分包与按需加载](/ai-i18n/guide/basic/locale-loading.md)。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/interfaces/ai-i18n-translation-memory-capacity-options.md --- # AiI18nTranslationMemoryCapacityOptions 从 `@ai-i18n/vite` 导入: ```ts import type { AiI18nTranslationMemoryCapacityOptions } from '@ai-i18n/vite'; ``` ## 定义 ```ts interface AiI18nTranslationMemoryCapacityOptions { maxMessages?: number; maxBytes?: number; } ``` ## 字段 | 字段 | 类型 | 默认值 | 作用 | | ------------- | -------- | --- | ----------------------------- | | `maxMessages` | `number` | 不限制 | 最多保留的 Translation Memory 消息数。 | | `maxBytes` | `number` | 不限制 | Memory 快照稳定序列化后的 UTF-8 字节软上限。 | 两个字段都必须是正整数。两项同时存在时,Memory 需要同时满足两个限制。容量统计包含当前项目的 Translation Memory 元数据与消息,不包含 `overrides`、`extracted` 或 `locales`。JSON 与 SQLite 使用相同的逻辑快照计算方式。 插件只淘汰当前源码不再引用的消息。活动消息始终保留;活动消息自身超限时,插件输出 warning,因此 这两个字段是保护数据安全的软上限。`cleanup.orphanMessages: true` 会先删除全部非活跃消息。 ## 用法 ```ts aiI18n({ sourceLang: 'zh-CN', locales, translationMemory: { storage: 'json', capacity: { maxMessages: 20_000, maxBytes: 10 * 1024 * 1024, }, }, }); ``` --- url: https://bosens-china.github.io/ai-i18n/api/vite/interfaces/ai-i18n-cleanup-options.md --- # AiI18nCleanupOptions 从 `@ai-i18n/vite` 导入: ```ts import type { AiI18nCleanupOptions } from '@ai-i18n/vite'; ``` ## 定义 ```ts interface AiI18nCleanupOptions { missingSourceFiles?: boolean; orphanMessages?: boolean; } ``` ## 字段 | 字段 | 默认值 | 作用 | | -------------------- | ------- | --------------------------------- | | `missingSourceFiles` | `true` | 删除源文件不存在时对应的 `extracted` 文件。 | | `orphanMessages` | `false` | 删除当前源码不再引用的历史 Translation Memory。 | `orphanMessages: true` 会先删除当前项目的全部非活跃消息,再执行容量淘汰。它不会删除 `overrides.json`。SQLite 模式只影响当前项目的数据,不会删除其他项目的共享候选。 首次启用或修改清理策略后,运行一次完整 Build,确认当前入口可达模块已完成提取。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/interfaces/ai-i18n-translation-memory-options.md --- # AiI18nTranslationMemoryOptions 从 `@ai-i18n/vite` 导入: ```ts import type { AiI18nTranslationMemoryOptions } from '@ai-i18n/vite'; ``` ## 定义 ```ts interface AiI18nTranslationMemoryOptions { storage?: 'json' | 'sqlite'; capacity?: AiI18nTranslationMemoryCapacityOptions; } ``` ## 字段 | 字段 | 类型 | 默认值 | 作用 | | ---------- | ----------------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------- | | `storage` | `'json' \| 'sqlite'` | `'json'` | 使用项目内可提交的分片 JSON,或用户级全局 SQLite。 | | `capacity` | [`AiI18nTranslationMemoryCapacityOptions`](/ai-i18n/api/vite/interfaces/ai-i18n-translation-memory-capacity-options.md) | 不限制 | 限制当前项目保留的历史译文容量。 | `storage: 'sqlite'` 使用用户目录中的同一个本地数据库,在不同项目间复用唯一译文候选。数据库不在 项目目录内,也不应提交 Git;`overrides.json` 仍保留在项目内并拥有最高优先级。 Provider 的进程级刷新通过 `provider.cache` 配置,不属于存储选项,也不影响 MCP。完整行为和选型建议见 [Translation Memory](/ai-i18n/guide/advanced/translation-memory.md)。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/interfaces/html-extractor-options.md --- # HtmlExtractorOptions 从 `@ai-i18n/vite` 导入: ```ts import type { HtmlExtractorOptions } from '@ai-i18n/vite'; ``` ## 定义 ```ts interface HtmlExtractorOptions { attributes?: readonly string[]; } ``` ## 字段 | 字段 | 类型 | 默认值 | 作用 | | ------------ | ------------------- | ---------------------------------------- | ------------ | | `attributes` | `readonly string[]` | `alt`、`aria-label`、`placeholder`、`title` | 替换默认属性提取白名单。 | 属性名必须由小写字母开头,后续只能包含小写字母、数字和连词线。重复属性会自动去重。 ## 用法 | `AiI18nOptions.html` 写法 | 行为 | | ----------------------- | ------------------------ | | `false` 或省略 | 不处理 HTML。 | | `true` | 提取完整的静态 `t()` 文本节点与默认属性。 | | `{ attributes }` | 提取完整的静态 `t()`,并替换属性白名单。 | 普通 HTML 文本、混合文本、内联脚本和非白名单属性不会自动翻译。HTML 提取与 `framework` 模式 相互独立。完整写法见[通用文案写法](/ai-i18n/guide/basic/static-analysis/common.md#html)。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/interfaces/lang-option.md --- # LangOption 从 `@ai-i18n/vite` 导入: ```ts import type { LangOption } from '@ai-i18n/vite'; ``` ## 定义 ```ts interface LangOption { value: string; label: string; } ``` ## 字段 | 字段 | 类型 | 必填 | 作用 | | ------- | -------- | -- | ----------------------------- | | `value` | `string` | 是 | 语言标识,用于 `setLang()` 和目标语言文件名。 | | `label` | `string` | 是 | 面向用户的语言名称,由 `getLangs()` 返回。 | `AiI18nOptions.locales` 至少包含一项,且所有 `value` 必须唯一。 ```ts const locales: readonly LangOption[] = [ { value: 'zh-CN', label: '中文' }, { value: 'en-US', label: 'English' }, ]; ``` --- url: https://bosens-china.github.io/ai-i18n/api/vite/interfaces/translation-options.md --- # TranslationOptions 该类型从 `@ai-i18n/vite` 导出,并用于 `virtual:ai-i18n` 的 `t()` 签名: ```ts import type { TranslationOptions } from '@ai-i18n/vite'; ``` ## 定义 ```ts interface TranslationOptions { comment?: string; } ``` ## 字段 | 字段 | 类型 | 必填 | 作用 | | --------- | -------- | -- | -------------- | | `comment` | `string` | 否 | 向翻译器说明文案的业务语境。 | `comment` 必须能在构建期确定。插件会去除首尾空白;非空 `comment` 会参与消息身份与 Translation Memory。相同原文使用不同的 `comment` 时属于不同翻译单元,不会共享译文。 ```ts t('保存', { comment: '按钮' }); t('保存', { comment: '文件状态' }); ``` 模型只翻译 source,comment 只用于理解语境,不会进入最终译文。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/interfaces/translation-message.md --- # TranslationMessage 从 `@ai-i18n/vite` 导入: ```ts import type { TranslationMessage } from '@ai-i18n/vite'; ``` ## 定义 ```ts interface TranslationMessage { source: string; comment?: string; } ``` ## 字段 | 字段 | 类型 | 必填 | 作用 | | --------- | -------- | -- | --------------- | | `source` | `string` | 是 | 需要翻译的源文案。 | | `comment` | `string` | 否 | 用于理解业务语境,不进入译文。 | Vite 不会把 message ID、文件路径或源码位置交给 Translator。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/interfaces/translation-batch.md --- # TranslationBatch 从 `@ai-i18n/vite` 导入: ```ts import type { TranslationBatch } from '@ai-i18n/vite'; ``` ## 定义 ```ts interface TranslationBatch { batchId?: string; logging?: TranslationLogging; locales: readonly string[]; messages: readonly TranslationMessage[]; } ``` ## 字段 | 字段 | 类型 | 必填 | 作用 | | ---------- | -------------------------------------------------------------------------------------- | -- | --------------------- | | `batchId` | `string` | 否 | 本批诊断 ID;由 Vite 调度器生成。 | | `logging` | [`TranslationLogging`](/ai-i18n/api/vite/type-aliases/translation-logging.md) | 否 | 关闭日志,或给出已解析日志目录。 | | `locales` | `readonly string[]` | 是 | 本批所有消息共同缺失的语言。 | | `messages` | [`readonly TranslationMessage[]`](/ai-i18n/api/vite/interfaces/translation-message.md) | 是 | 按固定下标排列的消息。 | Vite 按缺失 locale 集合分组,再根据 `AiI18nProviderOptions.batchLength` 切分批次。 `batchId` 只用于把调度、模型日志、状态应用和持久化事件关联起来,不发送给模型,也不参与 message ID、缓存键或 Translation Memory 文件格式。直接调用 Translator 时,Translator 可以为缺失的 `batchId` 生成本地诊断 ID。 Vite 根据 `provider.logging` 传入 `logging`。启用时,字符串是基于 Vite root 解析后的绝对目录; 关闭时为 `false`。自定义 Translator 可以忽略该可选字段;官方 OpenAI Provider 在值为 `false` 时 仍执行翻译,但不创建或追加日志。实现 `reportBatchEvent` 的 Translator 仍会收到生命周期事件。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/interfaces/translation-batch-event.md --- # TranslationBatchEvent 从 `@ai-i18n/vite` 导入: ```ts import type { TranslationBatchEvent } from '@ai-i18n/vite'; ``` ## 定义 ```ts type TranslationBatchEvent = | { batchId: string; logging: false | string; stage: 'scheduled'; locales: readonly string[]; messageCount: number; } | { batchId: string; logging: false | string; stage: 'state-applied'; resultCount: number; affectedModules: number; } | { batchId: string; logging: false | string; stage: 'persisted' } | { batchId: string; logging: false | string; stage: 'failed'; locales: readonly string[]; messageCount: number; reason: string; }; ``` `logging` 与对应 [`TranslationBatch`](/ai-i18n/api/vite/interfaces/translation-batch.md) 一致。启用时是基于 Vite root 解析后的绝对日志目录;关闭时为 `false`。实现了 `reportBatchEvent` 的 Translator 始终接收 事件;日志关闭只表示不应写入日志文件。该字段不进入持久化协议。 ## 阶段 | `stage` | 必有字段 | 含义 | | --------------- | --------------------------------- | ------------------------------------ | | `scheduled` | `locales`、`messageCount` | Vite 已形成实际 Translator 批次。 | | `state-applied` | `resultCount`、`affectedModules` | Provider 结果已通过校验并应用到当前项目状态。 | | `persisted` | 无 | 包含该批结果的文件和 Translation Memory 已写入成功。 | | `failed` | `locales`、`messageCount`、`reason` | Translator、结果校验或后续批次处理失败。 | 事件接收器只用于观察,不能依赖它改变翻译流程。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/type-aliases/ai-i18n-provider-options.md --- # AiI18nProviderOptions 从 `@ai-i18n/vite` 导入: ```ts import type { AiI18nProviderOptions } from '@ai-i18n/vite'; ``` ## 定义 ```ts type AiI18nProviderOptions = { translator: Translator; cache?: 'reuse' | 'fresh'; debounceMs?: number; batchLength?: number; maxConcurrency?: number; strict?: boolean; logging?: boolean | string; }; ``` ## 字段 | 字段 | 类型 | 必填 | 默认值 | 作用 | | ---------------- | ------------------------------------------------------------ | -- | --------- | ------------------------------ | | `translator` | [`Translator`](/ai-i18n/api/vite/type-aliases/translator.md) | 是 | 无 | 执行自动翻译。 | | `cache` | `'reuse' \| 'fresh'` | 否 | `'reuse'` | 复用历史结果,或在本次进程中刷新一次。 | | `debounceMs` | `number` | 否 | `100` | Dev 中合并连续请求的等待时间,单位为毫秒。 | | `batchLength` | `number` | 否 | `12_000` | 单批序列化请求的字符长度上限,不是 token 数。 | | `maxConcurrency` | `number` | 否 | `5` | 同时执行的翻译批次数。 | | `strict` | `boolean` | 否 | `false` | 在 flush 时抛出翻译失败或仍有 `null` 的错误。 | | `logging` | `boolean \| string` | 否 | `false` | 关闭日志,或启用并选择日志目录。 | `debounceMs` 必须大于或等于 `0`。`batchLength` 和 `maxConcurrency` 必须是正整数。 Vite 按消息的“缺失 locale 集合”分组,再按 `batchLength` 切分。一个批次失败时,其他成功 批次仍会写入。Dev 中的模型调用不阻塞首次模块响应;Build 会在结束前等待必要批次。 日志默认关闭。`logging: true` 使用 Vite root 下的 `logs/`;字符串指定目录,相对路径基于 Vite root,绝对路径保持不变。空字符串无效。开启后,Vite 会把解析后的目录传给 Translator 和批次 生命周期事件。官方 OpenAI Provider 会据此记录 REQUEST、RESPONSE、VALIDATION 等日志;省略或设为 `false` 时不创建或追加日志,但翻译、状态应用和持久化继续执行。自定义 Translator 可以选择支持该 诊断字段。完整说明见 [LLM 日志与排障](/ai-i18n/guide/advanced/llm-logs.md)。 `cache: 'fresh'` 只影响当前 Vite 进程发起的 Provider 调用。已有译文仍可供 Runtime 使用;本进程 生成的新结果会立即缓存,普通 HMR 不会重复请求。该选项不传给 Translator,也不影响 MCP 或 AI Agent 读写 Translation Memory。它与 `translationMemory.capacity` 无关:前者控制一次 Provider 刷新,后者 控制历史 Translation Memory 的容量。 ## 示例 ```ts aiI18n({ sourceLang: 'zh-CN', locales, provider: { translator, batchLength: 12_000, maxConcurrency: 5, strict: true, logging: 'diagnostics/llm', }, }); ``` Provider 的完整接入流程见 [AI 翻译](/ai-i18n/guide/advanced/ai-translation.md)。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/type-aliases/ai-i18n-framework.md --- # AiI18nFramework 从 `@ai-i18n/vite` 导入: ```ts import type { AiI18nFramework } from '@ai-i18n/vite'; ``` ## 定义 ```ts type AiI18nFramework = 'vanilla' | 'vue' | 'react'; ``` ## 值 三种模式都提供 `t()`、`setLang()`、`getLang()`、`getLangs()`、`getLangLoadState()` 与 `subscribe()`。框架模式决定 `virtual:ai-i18n` 额外提供的适配 API: | 值 | 额外导出 | | ----------- | --------------------------------------------------- | | `'vanilla'` | 无 | | `'vue'` | `useI18n()`、`tRef()`、`i18nComputed()`、`tComputed()` | | `'react'` | React `useI18n()` | 省略 [`AiI18nOptions.framework`](/ai-i18n/api/vite/interfaces/ai-i18n-options.md) 时,插件根据最终 Vite 插件列表自动检测。一个 build 同时包含 Vue 与 React 插件时会报错。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/type-aliases/lang-load-state.md --- # LangLoadState 从 `@ai-i18n/vite` 导入类型: ```ts import type { LangLoadState } from '@ai-i18n/vite'; ``` ## 定义 ```ts type LangLoadState = | Readonly<{ status: 'idle'; targetLang: null; error: null }> | Readonly<{ status: 'loading'; targetLang: string; error: null }> | Readonly<{ status: 'error'; targetLang: string; error: unknown }>; ``` ## 语义 | `status` | `targetLang` | `error` | 含义 | | --------- | ------------ | --------- | -------------- | | `idle` | `null` | `null` | 当前没有语言资源等待或错误。 | | `loading` | `string` | `null` | 正在加载指定目标语言。 | | `error` | `string` | `unknown` | 指定目标语言加载失败。 | 快照及其字段只读。`error` 保留 loader reject 的原始值,可能是 falsy;判断失败必须使用 `status === 'error'`。应用应在展示前把详情映射为自己的用户文案。 读取方式见 [`getLangLoadState()`](/ai-i18n/api/runtime/functions/get-lang-load-state.md),Vue / React 的 响应式派生值分别见 [Vue `useI18n()`](/ai-i18n/api/runtime/vue/use-i18n.md) 和 [React `useI18n()`](/ai-i18n/api/runtime/react/use-i18n.md)。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/type-aliases/message-tree.md --- # MessageTree 从 `@ai-i18n/vite` 导入类型: ```ts import type { MessageTree, MessageTreeValue } from '@ai-i18n/vite'; ``` ## 定义 ```ts type MessageTreeValue = | string | number | boolean | bigint | null | undefined | readonly MessageTreeValue[] | { readonly [key: string]: MessageTreeValue }; type MessageTree = readonly MessageTreeValue[] | { readonly [key: string]: MessageTreeValue }; ``` 每个字符串叶子都是待翻译文案;其他基础类型原样保留。运行时只接受普通对象和数组,不支持 `Map`、`Set`、函数、getter 或循环引用。调用 `t(messages)` 或 Vue `tRef(messages)` 时, 静态本地或导入对象不要求显式标注该类型,也不要求 `as const`。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/type-aliases/translated-message-tree.md --- # TranslatedMessageTree 从 `@ai-i18n/vite` 导入类型: ```ts import type { TranslatedMessageTree } from '@ai-i18n/vite'; ``` ## 定义 ```ts type TranslatedMessageTree = T extends string ? string : T extends readonly unknown[] ? { [K in keyof T]: TranslatedMessageTree } : T extends object ? { [K in keyof T]: TranslatedMessageTree } : T; ``` 该类型递归保留对象、数组和非字符串叶子的结构,只把字符串叶子映射为译文字符串。 [`t()`](/ai-i18n/api/runtime/functions/t.md) 返回该结构的当前快照;Vue [`tRef()`](/ai-i18n/api/runtime/vue/t-ref.md) 返回包含该结构的只读计算属性。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/type-aliases/translator.md --- # Translator 从 `@ai-i18n/vite` 导入: ```ts import type { Translator } from '@ai-i18n/vite'; ``` ## 定义 ```ts type Translator = (( batch: TranslationBatch, ) => Promise) & { reportBatchEvent?: (event: TranslationBatchEvent) => void | Promise; }; ``` ## 契约 Translator 返回的数组必须与 `batch.messages` 等长。每一行必须且只能包含 `batch.locales` 中的语言键,值为译文或 `null`。输入和输出通过数组下标对应,不需要返回 message ID。 `reportBatchEvent` 是可选的旁路诊断接收器。Vite 会报告 `scheduled`、`state-applied`、 `persisted` 或 `failed`;接收器缺失、同步抛错或异步拒绝都不会改变翻译与 Build 结果。实现日志 Provider 时可用同一 `batchId` 把这些事件和模型请求关联起来。普通函数 Translator 不需要实现它。 ## 示例 ```ts import type { Translator } from '@ai-i18n/vite'; export const translator: Translator = async ({ locales, messages }) => messages.map((message) => Object.fromEntries( locales.map((locale) => [locale, translate(locale, message.source)]), ), ); ``` 实现 Translator 时必须自行处理鉴权、超时和供应商返回值,再按上述契约返回结果。 相关类型: - [`TranslationBatch`](/ai-i18n/api/vite/interfaces/translation-batch.md) - [`TranslationBatchEvent`](/ai-i18n/api/vite/interfaces/translation-batch-event.md) - [`TranslationMessage`](/ai-i18n/api/vite/interfaces/translation-message.md) - [`TranslationResult`](/ai-i18n/api/vite/type-aliases/translation-result.md) --- url: https://bosens-china.github.io/ai-i18n/api/vite/type-aliases/translation-result.md --- # TranslationResult 从 `@ai-i18n/vite` 导入: ```ts import type { TranslationResult } from '@ai-i18n/vite'; ``` ## 定义 ```ts type TranslationResult = Readonly>; ``` 键必须与当前 [`TranslationBatch.locales`](/ai-i18n/api/vite/interfaces/translation-batch.md) 完全一致。 任意字符串(包括空字符串)都是有效译文;`null` 表示该目标语言仍缺译。Runtime 只对 `null` 或 缺失字段回退 source 文案。 ```ts const result: TranslationResult = { 'en-US': 'Save', 'ja-JP': null, }; ``` Translator 返回值中缺少语言键、包含额外键,或使用非字符串且非 `null` 的值时,Vite 会拒绝 该批结果。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/type-aliases/translation-batch-stage.md --- # TranslationBatchStage 从 `@ai-i18n/vite` 导入: ```ts import type { TranslationBatchStage } from '@ai-i18n/vite'; ``` ## 定义 ```ts type TranslationBatchStage = 'scheduled' | 'state-applied' | 'persisted' | 'failed'; ``` 各阶段含义见 [`TranslationBatchEvent`](/ai-i18n/api/vite/interfaces/translation-batch-event.md)。 --- url: https://bosens-china.github.io/ai-i18n/api/vite/type-aliases/translation-logging.md --- # TranslationLogging 从 `@ai-i18n/vite` 导入: ```ts import type { TranslationLogging } from '@ai-i18n/vite'; ``` ## 定义 ```ts type TranslationLogging = false | string; ``` Vite 会把用户配置的 `provider.logging` 规范化后传给 Translator:关闭时为 `false`,开启时为基于 Vite root 解析后的绝对目录。自定义 Translator 可以忽略该诊断字段;它不参与消息身份、缓存键或 Translation Memory。实现了 `reportBatchEvent` 时,无论此值是否为 `false`,都会收到生命周期事件。 --- url: https://bosens-china.github.io/ai-i18n/api/vitest/functions/ai-i18n-vitest.md --- # aiI18nVitest() 从 `@ai-i18n/vite/vitest` 导入: ```ts import { aiI18nVitest } from '@ai-i18n/vite/vitest'; ``` ## 签名 ```ts function aiI18nVitest(options: AiI18nVitestOptions): Plugin; ``` `aiI18nVitest()` 返回一个 Vite 插件。它解析 `virtual:ai-i18n`,并提供只驻留在内存中的测试 Runtime。 ## 行为 - 保留生产环境的 `t()`、`setLang()`、`getLangLoadState()`、框架 `useI18n()` 与 Vue-only `tRef()` 契约; - `autoImport: true` 时注入与生产框架模式相同的 Runtime API; - 消除 `defineI18nMessages()` 编译宏; - 不提取翻译; - 不调用 Provider; - 不读取或写入 `i18n/` 协议文件。 测试 Runtime 没有目标语言译文,因此 `t()` 始终返回 source 文案。 它也不创建语言 chunk loader,因此 `getLangLoadState()` 与 `useI18n()` 的加载状态字段固定 为 `idle`;这里只保留 API 形状,不模拟生产加载失败。 ## 示例 ```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' }, ], }), ], }); ``` 完整配置方式见[测试(Vitest)](/ai-i18n/guide/quality/testing.md)。 --- url: https://bosens-china.github.io/ai-i18n/api/vitest/type-aliases/ai-i18n-vitest-options.md --- # AiI18nVitestOptions 从 `@ai-i18n/vite/vitest` 导入: ```ts import type { AiI18nVitestOptions } from '@ai-i18n/vite/vitest'; ``` ## 定义 ```ts type AiI18nVitestOptions = Pick< AiI18nOptions, | 'sourceLang' | 'defaultLang' | 'locales' | 'framework' | 'persist' | 'autoImport' >; ``` ## 字段 | 字段 | 必填 | 说明 | | ------------- | -- | --------------------------------- | | `sourceLang` | 是 | 测试源码使用的语言。 | | `locales` | 是 | Runtime 支持的语言列表。 | | `defaultLang` | 否 | 没有有效持久化值时使用的初始语言。 | | `framework` | 否 | 覆盖 Vanilla、Vue 或 React 的自动检测结果。 | | `persist` | 否 | 测试 Runtime 的 localStorage 语言偏好配置。 | | `autoImport` | 否 | 注入与生产框架模式相同的未绑定 Runtime API。 | `html`、`loading`、`cache`、`provider`、`directory`、`dts` 等构建期字段不属于该类型。 完整字段契约见 [`AiI18nOptions`](/ai-i18n/api/vite/interfaces/ai-i18n-options.md)。 --- url: https://bosens-china.github.io/ai-i18n/api/runtime/overview.md --- # Runtime 概览 Runtime API 从 `virtual:ai-i18n` 导入。显式导入始终可用,不受 `autoImport` 影响。 ```ts import { getLang, getLangLoadState, getLangs, setLang, subscribe, t, } from 'virtual:ai-i18n'; ``` `t()` 除了字符串和 tagged template,也可以一次翻译整棵静态文案对象或数组。Vue setup 可以使用 `tRef()` 创建响应式翻译 Ref;纯 Options API 使用 `i18nComputed()` 和 `tComputed()`。 ## 可用范围 | API | Vanilla | Vue | React | 自动导入 | | ----------------------------------------------------------------------------- | ------- | --- | ----- | ------- | | [`t()`](/ai-i18n/api/runtime/functions/t.md) | 是 | 是 | 是 | 全部模式 | | [`setLang()`](/ai-i18n/api/runtime/functions/set-lang.md) | 是 | 是 | 是 | 全部模式 | | [`getLang()`](/ai-i18n/api/runtime/functions/get-lang.md) | 是 | 是 | 是 | 全部模式 | | [`getLangs()`](/ai-i18n/api/runtime/functions/get-langs.md) | 是 | 是 | 是 | 全部模式 | | [`getLangLoadState()`](/ai-i18n/api/runtime/functions/get-lang-load-state.md) | 是 | 是 | 是 | 全部模式 | | [`subscribe()`](/ai-i18n/api/runtime/functions/subscribe.md) | 是 | 是 | 是 | 全部模式 | | [Vue `useI18n()`](/ai-i18n/api/runtime/vue/use-i18n.md) | 否 | 是 | 否 | 仅 Vue | | [React `useI18n()`](/ai-i18n/api/runtime/react/use-i18n.md) | 否 | 否 | 是 | 仅 React | | [`tRef()`](/ai-i18n/api/runtime/vue/t-ref.md) | 否 | 是 | 否 | 仅 Vue | | [`i18nComputed()`](/ai-i18n/api/runtime/vue/i18n-computed.md) | 否 | 是 | 否 | 仅 Vue | | [`tComputed()`](/ai-i18n/api/runtime/vue/t-computed.md) | 否 | 是 | 否 | 仅 Vue | Vue 业务组件可以在 template、render、computed 与 Options method 中直接调用顶层 `t()`; Vue 适配器会追踪语言 revision。React 业务组件使用 `useI18n()` 建立订阅。`getLang()` 和 `getLangLoadState()` 仍是调用时快照;普通模块应在函数或 getter 中按需调用,避免在模块 初始化时保存不会刷新的值。 Vue 开启 `autoImport: true` 后,script 与 template 都可以直接使用裸 `t()`,生成声明会提供 IDE 类型。关闭自动导入时,` ``` `useI18n()` 仍返回 `t`。既有解构写法,以及自动导入模式下希望保持零 ai-i18n import 的 写法,都可以继续使用: ```vue ``` 这里的 `t` 与顶层导出是同一个函数,不是 Ref,因此不需要 `.value`,也不是即将废弃的 兼容分支。Vue adapter 统一维护共享 revision;template、render 或 computed 调用 `t()` 时,Vue 会收集这项依赖。翻译刷新不依赖每个组件调用 `useI18n()` 后再建立一份组件级订阅。 不要在 setup 阶段提前保存译后字符串: ```ts const label = t('保存'); // 只计算一次,不会随语言切换更新 ``` 需要在脚本中预先声明响应式展示值时,使用 [`tRef()`](/ai-i18n/api/runtime/vue/t-ref.md): ```ts import { tRef } from 'virtual:ai-i18n'; const label = tRef('保存'); ``` `tRef` 是独立的 Vue API,不在 `useI18n()` 返回值中。对象或数组展示值也可以直接写 `const labels = tRef(messages)`,得到随语言变化更新的同形只读计算属性。 ## 示例 ```vue ``` 建议在 ` ``` 在脚本中读取 `.value`;模板会自动解包 Ref。 ## 响应式对象与数组 需要在 setup 中复用一组会随语言切换更新的文案时,可以直接把静态文案树交给 `tRef()`: ```vue ``` 静态本地对象和导入对象都支持,不要求 `as const` 或 `defineI18nMessages()`。每个字符串叶子 都会翻译,其他基础类型原样保留。输入必须是纯文案的普通对象或数组;不支持 `Map`、`Set`、 函数、循环引用、getter、运行时生成的集合,也不能为单个叶子设置 `comment` 或插值。 ## 与 `t()` 的分工 - 模板或渲染函数当场展示:直接使用 [`t()`](/ai-i18n/api/runtime/functions/t.md)。 - Vue setup / composable 需要预先声明响应式字符串、对象或数组:使用 `tRef()`。 - 纯 Options API 的 computed:使用 [`tComputed()`](/ai-i18n/api/runtime/vue/t-computed.md)。 - 事件、日志或普通工具函数需要即时字符串:使用 `t()`。 不要在 template 或渲染函数中直接调用 `tRef()`: ```vue ``` 应在 setup 中创建一次,再把返回的 Ref 用于模板。对应生命周期问题由 [`ai-i18n/no-unsubscribed-t`](/ai-i18n/guide/quality/eslint-rules.md) 提示。静态提取规则见 [Vue 文案写法](/ai-i18n/guide/basic/static-analysis/vue.md)。 --- url: https://bosens-china.github.io/ai-i18n/api/runtime/vue/i18n-computed.md --- # i18nComputed() `i18nComputed()` 是 Vue 模式专用的 Options API 配置工厂: ```ts import { i18nComputed } from 'virtual:ai-i18n'; ``` 它不创建组件,也不要求 `setup()`。把返回值展开到组件的 `computed`,Vue 会为每个组件 实例创建和清理对应的 computed watcher。 ## 签名 ```ts function i18nComputed(): { currentLang(): string; langs(): readonly LangOption[]; langLoadState(): LangLoadState; isLangLoading(): boolean; langLoadError(): unknown | null; }; ``` 返回值与 [`useI18n()`](/ai-i18n/api/runtime/vue/use-i18n.md) 表示同一份 Runtime 状态,但 Options computed 中读取的是 已经解包的值,不需要 `.value`。 ## 基本用法 ```vue ``` Options `watch` 由 Vue 管理生命周期,组件卸载时会自动清理。组件外的长期监听仍使用 [`subscribe()`](/ai-i18n/api/runtime/functions/subscribe.md)。 ## TypeScript 与 IDE 提示 TypeScript 组件使用 `defineComponent()`。Vue 自身的 Options `watch` 类型不会根据被监听 的 key 推断回调参数,因此应像上例一样显式标注 `next` 和 `previous`。自动导入的声明文件、 组件实例类型和常见错误统一见 [TypeScript 与生成声明](/ai-i18n/guide/quality/typescript.md)。 ## 同名 computed 展开后声明的同名字段会覆盖默认 getter: ```ts computed: { ...i18nComputed(), currentLang() { return 'custom'; }, }, ``` 除非组件确实需要替换产品语义,否则不要覆盖这些字段。 `langLoadError` 保留 loader reject 的原始值。判断加载是否失败时,以 `langLoadState.status === 'error'` 为准;展示前应转换为应用自己的用户文案。 --- url: https://bosens-china.github.io/ai-i18n/api/runtime/vue/t-computed.md --- # tComputed() `tComputed()` 是 Vue 模式专用的 Options API 翻译 getter 工厂: ```ts import { tComputed } from 'virtual:ai-i18n'; ``` 它与 [`tRef()`](/ai-i18n/api/runtime/vue/t-ref.md) 支持相同的静态文案输入,但返回 Options `computed` 接受的 getter, 而不是 `ComputedRef`。 ## 签名 ```ts function tComputed(source: string, options?: TranslationOptions): () => string; function tComputed( strings: TemplateStringsArray, ...values: unknown[] ): () => string; function tComputed( messages: T, ): () => TranslatedMessageTree; ``` ## 基本用法 ```vue ``` 语言或翻译模块变化后,Vue 会使这些 computed 失效并在下次读取时重新计算。每个组件实例拥有 自己的 computed 缓存。 ## 动态组件状态 如果插值依赖 `data`、props 或其他 `this` 属性,直接编写普通 computed,并在 getter 中调用 [`t()`](/ai-i18n/api/runtime/functions/t.md): ```ts computed: { greeting() { return t`你好 ${this.name}`; }, }, ``` ## 使用位置 `tComputed()` 应直接作为 Options computed 的值: ```ts computed: { label: tComputed('保存'), }, ``` 不要在 `data()`、template 或 render 函数中调用: ```ts data() { return { label: tComputed('保存'), // 得到的是 getter,不是译文 }; }, ``` ```vue ``` setup 和 composable 使用 [`tRef()`](/ai-i18n/api/runtime/vue/t-ref.md);template、render 或手写 computed getter 当场展示时直接使用 [`t()`](/ai-i18n/api/runtime/functions/t.md)。 --- url: https://bosens-china.github.io/ai-i18n/api/runtime/react/use-i18n.md --- # React useI18n() React 模式从 `virtual:ai-i18n` 导出 `useI18n()`: ```ts import { useI18n } from 'virtual:ai-i18n'; ``` ## 签名 ```ts interface ReactI18n { t: I18nRuntime['t']; setLang: I18nRuntime['setLang']; currentLang: string; langs: readonly LangOption[]; langLoadState: LangLoadState; isLangLoading: boolean; langLoadError: unknown | null; } type UseI18n = () => ReactI18n; ``` `useI18n()` 没有参数。 ## 返回值 | 字段 | 类型 | 作用 | | --------------- | ------------------------ | ------------- | | `t` | `I18nRuntime['t']` | 翻译文案 | | `setLang` | `I18nRuntime['setLang']` | 切换语言 | | `currentLang` | `string` | 当前语言 | | `langs` | `readonly LangOption[]` | 支持的语言列表 | | `langLoadState` | `LangLoadState` | 完整加载状态快照 | | `isLangLoading` | `boolean` | 是否正在加载目标语言 | | `langLoadError` | `unknown \| null` | 最近一次有效切换的加载错误 | `langLoadError` 保留 loader reject 的原始值,因此类型是 `unknown`,也可能是 `undefined`、`null`、空字符串等 falsy 值。判断是否失败必须使用 `langLoadState.status === 'error'`。`langLoadError` 只用于读取详情,展示前应转换为应用 自己的用户文案。下一次有效切换开始或加载成功后会清除它。完整三态见 [`getLangLoadState()`](/ai-i18n/api/runtime/functions/get-lang-load-state.md)。 ## 解构或改名 `t` React 可以直接解构或改名 `t`。分析器会识别这个绑定,并按顶层 `t()` 相同的规则提取 普通文本、静态变量、条件表达式、tagged template 和静态文案树: ```tsx const { t: translate } = useI18n(); const title = translate('订单详情'); const labels = translate({ save: '保存', cancel: '取消' }); ``` 这里的 `translate` 仍然来自 Hook。解构或改名只改变本地变量名,不会把它降级为无订阅的 Runtime 顶层 `t`。 ## 示例 ```tsx import { useI18n } from 'virtual:ai-i18n'; export function LanguagePicker() { const { isLangLoading, langLoadState, setLang, t } = useI18n(); const labels = t({ loading: '正在加载语言包…', switchLanguage: '切换语言', }); async function switchLanguage() { try { await setLang('en-US'); } catch { // 通用错误 UI 读取共享状态;这里终结 rejected Promise。 } } return ( <> {langLoadState.status === 'error' ? (

{t('语言包加载失败,请重试')}

) : null} ); } ``` React 中必须遵守 Hook 调用规则。 React 适配器使用 `useSyncExternalStore` 订阅 Runtime revision。revision 改变时,Hook 返回的 `t` 也会获得新的函数引用,因此 React Compiler 可以使依赖该引用的缓存失效。直接 导入 Runtime 顶层 `t` 没有这个订阅边界;`"use memo"` 或 `"use no memo"` 都不能替代 `useI18n()`。 文案写法见 [React 文案写法](/ai-i18n/guide/basic/static-analysis/react.md)。 --- url: https://bosens-china.github.io/ai-i18n/api/runtime/macros/define-i18n-messages.md --- # defineI18nMessages() `defineI18nMessages()` 是全局编译宏,不是 `virtual:ai-i18n` 的 Runtime 导出,因此无需 import。 ## 签名 ```ts function defineI18nMessages(value: T): T; ``` ## 用法 ```ts const messages = defineI18nMessages({ save: '保存', states: ['等待中', '处理中', '已完成'], }); t(messages.save); t(messages.states[index]); ``` 宏用于“先定义集合,再把其中某个成员交给 `t()`”的写法。如果需要一次翻译整棵纯文案对象 或数组,可以直接写 `t(messages)`;Vue setup 中可以写 `tRef(messages)`。这两种整树调用 不需要宏,也不要求 `as const`: ```ts export const messages = { save: '保存', states: ['等待中', '处理中'], }; const labels = t(messages); ``` 宏接受任意类型,并在 Vite 或 `aiI18nVitest()` 转换时消除为原参数。它不会冻结、拷贝或校验 对象;作用只是告诉静态分析器,这个对象或数组是可枚举的消息集合。 动态索引会提取集合中可以证明有限的候选值。函数调用、getter、`await` 等用户代码不会在分析 阶段执行。 ## 限制 宏必须直接写成 `defineI18nMessages(value)`。不能将它赋值给别名、作为值传递,或在未经 `aiI18n()` / `aiI18nVitest()` 转换的 Node、Jest 环境中执行。 局部声明同名 `defineI18nMessages` 时,局部 binding 优先,不会被识别为编译宏。 插件生成的 `ai-i18n.d.ts` 会提供全局 TypeScript 声明。ESLint 的候选数量检查见 [ESLint](/ai-i18n/guide/quality/eslint.md#static-candidate-limit-选项)。 --- url: https://bosens-china.github.io/ai-i18n/api/openai/functions/open-ai.md --- # openAI() 从 `@ai-i18n/openai` 导入: ```ts import { openAI } from '@ai-i18n/openai'; ``` ## 签名 ```ts function openAI(options: OpenAIOptions): Translator; ``` ## 参数 | 参数 | 类型 | 说明 | | --------- | -------------------------------------------------------------------- | ------------- | | `options` | [`OpenAIOptions`](/ai-i18n/api/openai/interfaces/open-ai-options.md) | 模型、服务地址和请求配置。 | ## 返回值 返回 [`Translator`](/ai-i18n/api/vite/type-aliases/translator.md),可直接传给 [`AiI18nProviderOptions.translator`](/ai-i18n/api/vite/type-aliases/ai-i18n-provider-options.md)。 ## 示例 ```ts import { openAI } from '@ai-i18n/openai'; const translator = openAI({ baseURL: 'https://example.com/v1', model: 'model-name', apiKey: process.env.AI_API_KEY, }); ``` `openAI()` 对收到的每个批次调用模型一次。目标 locale 分组、批次切分、并发限制和结果写回由 `@ai-i18n/vite` 负责。 每次调用 `openAI()` 都会创建独立的惰性日志 session,但日志默认关闭。Vite 的 `provider.logging` 显式启用后的第一个模型批次才生成文件。Dev/HMR 或 Build Watch 复用同一个 translator 时,后续响应会追加到同一文件。 日志以批次生命周期、REQUEST、RESPONSE、VALIDATION 和 ERROR 块组织。Vite 调度时,同一批次从 BATCH SCHEDULED、REQUEST、RESPONSE、VALIDATION、STATE APPLIED 到 PERSISTED 使用相同 `batchId`;失败则记录 BATCH FAILED。REQUEST 展示实际 messages,RESPONSE 完整保留每个 choice 的 assistant message,包括兼容服务提供的 reasoning、tool calls、refusal 和未知扩展字段,但过滤 SDK runtime 与常规传输噪声。并发调用使用独立异步上下文,日志块不会串到其他批次。 经过 Vite 使用时,设置 `provider.logging: true` 使用 Vite root 下的 `logs/`,也可以用字符串指定 相对或绝对目录。完整阅读方法见 [LLM 日志与排障](/ai-i18n/guide/advanced/llm-logs.md)。 Provider 使用 OpenAI-compatible JSON mode。目标语言和批次长度会生成本批唯一的结构化 Schema; 同一 Schema 同时约束模型输出并校验实际响应,因此返回对象的顶层字段、数组长度、语言键和译文 类型都必须精确匹配,额外字段也会被拒绝。占位符一致性在结构校验后单独检查。模型服务需要支持 Chat Completions 和 `response_format: { type: "json_object" }`。 完整接入流程见 [AI 翻译](/ai-i18n/guide/advanced/ai-translation.md)。 --- url: https://bosens-china.github.io/ai-i18n/api/openai/interfaces/open-ai-options.md --- # OpenAIOptions 从 `@ai-i18n/openai` 导入: ```ts import type { OpenAIOptions } from '@ai-i18n/openai'; ``` ## 定义 ```ts interface OpenAIOptions { baseURL: string; model: string; apiKey?: string; temperature?: number; maxTokens?: number; timeoutMs?: number; maxRetries?: number; headers?: HeadersInit; systemPrompt?: string; langSmith?: LangSmithOptions; } ``` ## 字段 | 字段 | 类型 | 必填 | 默认值 | 约束 | 作用 | | -------------- | ------------------------------------------------------------------------ | -- | --------- | ------ | ----------------------------- | | `baseURL` | `string` | 是 | 无 | 非空 | OpenAI-compatible API 根地址。 | | `model` | `string` | 是 | 无 | 非空 | 显式选择模型。 | | `apiKey` | `string` | 否 | 本地服务使用占位值 | 无 | 请求认证密钥。 | | `temperature` | `number` | 否 | `1` | ≥ 0 | 传给模型的 temperature。 | | `maxTokens` | `number` | 否 | 由模型决定 | 整数;> 0 | 单次响应 token 上限。 | | `timeoutMs` | `number` | 否 | `120000` | 整数;> 0 | 单次请求超时,单位为毫秒。 | | `maxRetries` | `number` | 否 | `3` | 整数;≥ 0 | LangChain 层的最大重试次数。 | | `headers` | `HeadersInit` | 否 | 无 | 无 | 追加到 Provider 请求的 HTTP Header。 | | `systemPrompt` | `string` | 否 | 内置翻译提示词 | 非空 | 覆盖产品领域、术语和风格要求。 | | `langSmith` | [LangSmithOptions](/ai-i18n/api/openai/interfaces/lang-smith-options.md) | 否 | 不启用 | 无 | 启用 LangSmith tracing。 | `baseURL`、`model` 和显式传入的 `systemPrompt` 去除首尾空白后不能为空。`temperature` 必须 大于或等于 `0`;`maxTokens` 与 `timeoutMs` 必须是正整数;`maxRetries` 必须是非负整数。 `headers` 会按标准 `HeadersInit` 解析并规范化。所有配置在创建 Provider 时一次性校验;任一字段 无效都会在模型请求发出前报告具体字段,不会等到 Dev 或 Build 的首个翻译批次才失败。 Provider 不主动读取宿主的 `OPENAI_API_KEY`。密钥必须显式传入;省略时使用本地服务占位值, 避免意外把宿主环境变量发送到其他地址。 ## 日志 OpenAI Provider 不提供第二套日志开关。经过 Vite 调用时,只由 `provider.logging` 决定是否记录及 写入目录;默认关闭,`true` 使用 Vite root 下的 `logs/`,字符串可指定相对或绝对目录。 启用后,一个 `openAI()` translator 实例在对应目录使用一个日志文件。同一实例处理多个批次时持续 追加;新建实例会生成带本地日期时间、PID 和序号的新文件。Vite 触发的 BATCH SCHEDULED、REQUEST、RESPONSE、 VALIDATION、STATE APPLIED、PERSISTED 或 BATCH FAILED 块带有同一 `batchId`;并发批次使用各自的 ID。日志完整记录最终发送的 messages,以及每个响应 choice 的 reasoning、assistant content 和 message 扩展字段;同时保留模型、请求 ID、状态、耗时、usage、Provider 校验结果与错误。未设置 请求参数、SDK runtime 字段和常规传输 Header 会被过滤。日志写入失败只警告一次,不改变翻译或 Build 的结果。 日志包含发送给模型的文案和模型输出,应将 `logs/`、`*.log` 或自定义目录加入 `.gitignore`。 显式 API key 由 Provider 脱敏,常见认证 Header 由 OpenAI SDK 脱敏。日志不等同于逐字节 HTTP 抓包,也无法记录服务或 SDK 没有暴露的内部响应正文。 完整阅读与排障方法见 [LLM 日志与排障](/ai-i18n/guide/advanced/llm-logs.md)。 ## systemPrompt `systemPrompt` 只需要描述翻译要求。Provider 会追加目标语言、`source` / `comment` 输入约定、 占位符规则和固定 JSON 输出约束。 推荐说明: - 产品领域和目标读者; - UI 文案的语气、长度与大小写习惯; - 必须保留的品牌名、代码、URL 和占位符; - 固定术语及其目标语言写法; - 如何利用 `comment` 消除歧义。 不要在自定义提示词中重复定义返回 JSON 的字段。完整示例见 [AI 翻译](/ai-i18n/guide/advanced/ai-translation.md#如何编写-systemprompt)。 --- url: https://bosens-china.github.io/ai-i18n/api/openai/interfaces/lang-smith-options.md --- # LangSmithOptions 从 `@ai-i18n/openai` 导入: ```ts import type { LangSmithOptions } from '@ai-i18n/openai'; ``` ## 定义 ```ts interface LangSmithOptions { apiKey: string; project?: string; endpoint?: string; workspaceId?: string; } ``` ## 字段 | 字段 | 类型 | 必填 | 默认值 | 约束 | 作用 | | ------------- | -------- | -- | -------------- | -- | ------------------ | | `apiKey` | `string` | 是 | 无 | 非空 | LangSmith API key。 | | `project` | `string` | 否 | LangSmith 默认项目 | 无 | 写入的项目名。 | | `endpoint` | `string` | 否 | LangSmith 默认地址 | 无 | 自托管或代理地址。 | | `workspaceId` | `string` | 否 | 无 | 无 | 目标 workspace。 | 只有传入 `OpenAIOptions.langSmith` 时,Provider 才会创建 tracing callback。 ```ts openAI({ baseURL, model, langSmith: { apiKey: process.env.LANGSMITH_API_KEY!, project: 'ai-i18n', }, }); ``` --- url: https://bosens-china.github.io/ai-i18n/demo/vue.md --- # Vue 3 示例 ## Vue 3 集成演示 示例提供两个 Tab: - **Setup + `lang="ts"`**:新组件的推荐写法。自动导入的 `t()` 同时用于 script 与 template,`useI18n()` 只读取 `currentLang`、加载状态与切换 action;预声明响应式文案 使用 `tRef()`。 - **纯 Options API**:不使用 `setup()`。通过 `i18nComputed()` 暴露响应式状态, `tComputed()` 创建响应式文案,script 与 template 直接使用自动导入的 `t()`。 两个 Tab 共用同一个 Runtime。任一 Tab 切换语言后,另一个 Tab 的文案、当前语言与加载状态 会同步更新;加载失败也会保留当前语言并展示共享错误状态。 ## Vue 3 集成演示 [单独打开 ↗](/ai-i18n/examples/vue/) 配置步骤和组件库 locale 同步见 [Vue 快速上手](/ai-i18n/guide/getting-started/vue.md)。 --- url: https://bosens-china.github.io/ai-i18n/demo/react.md --- # React 示例 ## React 集成演示 基于 `useI18n` Hook 订阅 Runtime 变更,切换语言后组件树即时重渲染。 ## React 集成演示 [单独打开 ↗](/ai-i18n/examples/react/) 配置步骤和组件库 locale 同步见 [React 快速上手](/ai-i18n/guide/getting-started/react.md)。 --- url: https://bosens-china.github.io/ai-i18n/demo/vanilla.md --- # Vanilla JS 示例 ## Vanilla JS 集成演示 显式调用 `t()`,通过 `subscribe()` 监听语言切换事件并更新原生 DOM。 ## Vanilla JS 集成演示 [单独打开 ↗](/ai-i18n/examples/vanilla/) --- url: https://bosens-china.github.io/ai-i18n/index.md --- # ai-i18n Vite AI 国际化 > 直接编写源文案,自动提取、翻译并生成语言包。 [快速上手](/guide/getting-started/vanilla) | [在线演示](/demo/vue) ## Features - [**快速上手**](/guide/getting-started/vue): 按 Vanilla、Vue 或 React 完成安装、Vite 配置和第一次 Build。 - [**接入与使用**](/guide/basic/static-analysis/common): 查找文案写法、自动导入、语言加载、生成文件和 Git 规则。 - [**工程质量**](/guide/quality/typescript): 接入 TypeScript 生成声明、ESLint 静态检查和 Vitest 测试。 - [**翻译自动化**](/guide/advanced/ai-translation): 选择应用内 Provider 或外部 Agent 补齐译文,并保留人工审校入口。 - [**排查问题**](/guide/faq/common): 按通用、Vue 和 React 场景定位接入与运行问题。 - [**API 参考**](/api): 按包入口查询公开函数、配置字段、类型与默认行为。