国际化
AI Chat UI 内置中英双语(zh-CN / en-US),默认 zh-CN,安装即用、零配置。内部基于 vue-i18n(legacy: false)的模块级单例 aiChatI18n——不要求宿主 app.use,与宿主自有的 vue-i18n 实例天然隔离;宿主也可以通过它注入任意语言或覆盖内置文案。
使用语言切换组件
最简单的方式是直接放置语言切换组件。非可控模式下,用户在组件里选择语言即切换全局语言并持久化:
<script setup lang="ts">
import { LanguageToggle } from '@toimc/vue'
</script>
<template>
<LanguageToggle />
</template>默认提供「简体中文 / English」两项。自定义语言列表、v-model 可控用法见 LanguageToggle 文档。
编程式切换
不需要 UI 时,用 setAiChatLocale 直接切换:
import { setAiChatLocale } from '@toimc/vue'
setAiChatLocale('en-US')setAiChatLocale 一次完成三件事:
- 写入
aiChatI18n实例的 locale; - 同步
<html lang>属性(无障碍 / 字体选择友好); - 持久化到
localStorage(key 为ai-chat-locale),刷新后保留。
不希望跨会话保留时传 { persist: false }:
// 只切换当前会话,不写 localStorage
setAiChatLocale('en-US', { persist: false })字典组织
字典源码位于 packages/vue/src/locales/:
packages/vue/src/locales/
├── zh-CN.ts # 中文字典(source of truth,类型由它推导)
├── en-US.ts # 英文字典(satisfies MessageSchema)
└── index.ts # aiChatI18n 单例 + setAiChatLocale / getInitialLocale字典按组件域拆分命名空间,key 一律 camelCase:
| 命名空间 | 覆盖文案 |
|---|---|
shared | 通用操作(关闭、复制、已复制) |
promptInput | 输入区占位符、免责声明、附件上传 |
conversation | 空态标题/描述、未读滚动提示 |
message | 消息身份标签(你 / AI Chat UI) |
toolCall | 工具调用面板(六态状态、参数、结果、错误) |
citation | 引用来源(角标卡、来源计数、上一个/下一个) |
attachments | 附件区空态 |
comparison | 对比消息标签与按钮 |
markdown | 图表渲染中 / 渲染失败 |
thinking | 思考过程(标题、已思考耗时、步骤状态) |
welcome | 欢迎页标题与描述 |
prompts | 提示词面板标题 |
feedback | 点赞点踩与评论 |
confirmation | 工具审批卡(允许 / 拒绝) |
branchPicker | 分支翻页(上一个/下一个版本、版本计数) |
jsonDiff | JSON 差异视图(修改前后标签、内容相同) |
modelIcon | 未知模型兜底文案 |
messageActions | 消息操作(复制、重新生成、编辑) |
suggestion | 输入建议无匹配项 |
provider | Provider 设置对话框(服务类型、预设、表单校验) |
imageLightbox | 图片预览(上一张/下一张) |
codeBlock | 代码块展开 / 收起 |
类型安全由 MessageSchema 保证:zh-CN.ts 是 source of truth(export type MessageSchema = typeof zhCN),en-US.ts 用 satisfies MessageSchema 约束——新增中文 key 时英文缺 key 或写错 key 会在编译期报错,不会静默回退。
组件文案模式
带文案的组件 props 遵循「props 优先、t() 兜底」:宿主显式传了 props 就用 props,没传则回退到当前语言的字典。这样单实例场景零配置拿到正确语言,多语言之外的定制(如特定文案 A/B)也不用动字典:
<!-- 不传 placeholder:跟随当前语言,中文显示「给 AI Chat UI 发送消息...」,英文显示 "Send a message to AI Chat UI..." -->
<PromptInput>
<PromptInputTextarea />
</PromptInput>
<!-- 传了 placeholder:props 优先,不进字典 -->
<PromptInput placeholder="问我任何关于订单的问题">
<PromptInputTextarea />
</PromptInput>组件内部统一通过库内单例取翻译函数:
import { aiChatI18n } from '@toimc/vue'
const { t } = aiChatI18n.global
// props.placeholder ?? t('promptInput.placeholder')宿主自定义语言 / 覆盖文案
内置语言之外,宿主可注入任意语言。注意 setLocaleMessage 是整体替换——合并自定义内容时要带上 getLocaleMessage 返回的已有内容:
import { aiChatI18n, setAiChatLocale } from '@toimc/vue'
aiChatI18n.global.setLocaleMessage('ja-JP', {
...aiChatI18n.global.getLocaleMessage('ja-JP'), // 已有内容(首次为空)
myApp: { hello: 'こんにちは' },
})
setAiChatLocale('ja-JP')新语言只需注入差异 key:命中不到的 key 会按
fallbackLocale: 'zh-CN'回退,不必一次翻译整本字典。
覆盖内置文案同理(对已存在的 locale 做合并):
aiChatI18n.global.setLocaleMessage('zh-CN', {
...aiChatI18n.global.getLocaleMessage('zh-CN'),
promptInput: { placeholder: '有话直说…' },
})配合 LanguageToggle 的 locales prop 自定义下拉列表,即可提供完整的第三方语言入口:
<LanguageToggle
:locales="[
{ value: 'zh-CN', label: '简体中文' },
{ value: 'ja-JP', label: '日本語' },
]"
/>初始化顺序
首次加载时,getInitialLocale() 按以下顺序决定初始语言:
localStorage['ai-chat-locale'](用户上次的选择);navigator.language(浏览器语言,en*前缀 →en-US);- 兜底
zh-CN。
初始化只读不写(不会把浏览器语言回写进 localStorage),用户首次显式切换后才产生持久化记录。SSR 环境下固定返回 zh-CN,到客户端再按上述顺序校正。