Files
2026Technology-Competition/docs/superpowers/specs/2026-07-26-i18n-design.md
T

15 KiB
Raw Blame History

i18n 国际化 — Extension Design Spec

1. 概述

为 vscode-code-reviewer 实现运行时动态语言切换。用户在设置面板选择语言后,所有 webview 面板、通知、QuickPick、报告等 UI 文字立即生效,无需重载 VS Code 窗口。

语言源:复用现有 ai.outputLanguage 配置项(zh-CN / en / ja)。

范围

区域 是否纳入 说明
Webview 面板(设置/审查报告/导入预览) 动态重渲染
通知(showInformationMessage 等) 下次调用用新语言
QuickPick 下次调用用新语言
进度条(withProgress 下次调用用新语言
报告导出(Markdown 导出时取当前语言
适配器错误消息 每次调用取当前语言
package.json contributes 跟随 VS Code 机制,不影响
AI 提示词(engine.ts / fixer.ts 保持中文,保证 AI 输出质量稳定

2. 核心模块:src/i18n/messages.ts

2.1 类型定义

export type Language = 'zh-CN' | 'en' | 'ja';

const defaultLang: Language = 'zh-CN';

2.2 消息注册

单文件注册所有文案,每条包含三种语言的值。命名采用 模块.场景.含义,点分隔,全小写。

const messages = {
  'review.noEditor': {
    'zh-CN': '请先打开一个文件',
    en: 'Please open a file first',
    ja: '最初にファイルを開いてください',
  },
  // ...
};

类型约束:`Record<string, Record<Language, string>>`,确保所有消息三种语言都有值。

### 2.3 运行时语言

```typescript
let currentLang: Language = defaultLang;

2.4 t() 函数

export function t(key: string): string {
  const msg = messages[key]?.[currentLang] ?? messages[key]?.[defaultLang];
  return msg ?? key;
}

插件内所有文案都通过 t() 获取,不再硬编码。无模板插值参数,简单直接。

2.5 语言切换

const languageChangeEmitter = new vscode.EventEmitter<Language>();

export function setLanguage(lang: Language): void {
  if (currentLang === lang) return;
  currentLang = lang;
  languageChangeEmitter.fire(lang);
}

export function onLanguageChange(listener: (lang: Language) => void): vscode.Disposable {
  return languageChangeEmitter.event(listener);
}

export function getLanguage(): Language {
  return currentLang;
}

3. 语言切换流程

采用"写配置 → 事件驱动"的单一入口模式:

用户在设置面板改语言下拉
  ↓
webview postMessage 'setLanguage'
  ↓
extension 端 handleMessage:
  vscode.workspace.getConfiguration('vscode-code-reviewer')
    .update('ai.outputLanguage', lang, true)
  ↓
onDidChangeConfiguration 监听到变化(ext.activate 中注册)
  ↓
if (changed.key === 'vscode-code-reviewer.ai.outputLanguage')
  setLanguage(newLang)
  ↓
onLanguageChange 触发
  ↓
所有 webview 回调: postMessage 推送新翻译 → 全量重渲染
所有通知/QuickPick: 下次调用时 t() 取新语言

3.1 为什么不用同步 setLanguage + update

  • 用户可能通过 VS Code 原生设置界面改语言,onDidChangeConfiguration 能自动捕获
  • 单一入口、无分支、逻辑内聚

3.2 初始化

extension.tsactivate() 中:

// 从当前配置初始化语言
const lang = getAIOutputLanguage() as Language;
setLanguage(lang);

// 监听配置变更
context.subscriptions.push(
  vscode.workspace.onDidChangeConfiguration(e => {
    if (e.affectsConfiguration('vscode-code-reviewer.ai.outputLanguage')) {
      const newLang = getAIOutputLanguage() as Language;
      setLanguage(newLang);
    }
  })
);

4. Webview 刷新策略

4.1 消息推送

扩展端构建翻译后的消息 map 通过 postMessage 发给 webview

// 只推送当前 webview 需要的 key
function pushLanguage(webview: vscode.Webview) {
  const translated: Record<string, string> = {};
  for (const key of webviewI18nKeys) {
    translated[key] = t(key);
  }
  webview.postMessage({ type: 'lang', lang: currentLang, messages: translated });
}

4.2 Webview 端处理

window.addEventListener('message', e => {
  if (e.data.type === 'lang') {
    render(e.data.messages, e.data.lang);
  }
});

4.3 重渲染

全量重渲染。每个 webview 在收到 lang 消息后重建 HTML。

设置面板特殊处理:

  • 保存表单当前值到 JS 变量中
  • 语言下拉变化时:先持久化当前表单值(API Key 等),再改语言,最后重建
  • 重建后用保存的变量回填表单

4.4 Webview HTML 生成方式

当前 webview 在扩展端生成 HTML 字符串。改造后:

  • 被翻译的文案在生成 HTML 时用 t() 注入(扩展端调用)
  • 生成完整 HTML 时文案已经翻译好,webview 端 JS 无需再翻译
  • webview 端 JS 只是接收到 lang 消息时重新请求全集 HTML(或接受新 HTML 字符串替换)

三种面板处理方式:

面板 策略
审查报告 重新生成 HTML → postMessage → 替换 document.body.innerHTML
设置面板 保留表单 JS 变量,重新生成 HTML 后回填
导入预览 重新生成 HTML → postMessage → 替换

5. 消息清单设计

预估约 60 条文案,按命名空间分组。

5.1 review.* (审查类)

Key zh-CN en (参考)
review.noEditor 请先打开一个文件 Please open a file first
review.running 正在审查... Reviewing...
review.staticAnalysis 运行静态分析... Running static analysis...
review.aiReview 运行 AI 审查... Running AI review...
review.completeSelection 选中代码审查完成: {0} 个问题 Selection review: {0} issues
review.needRunFirst 请先运行完整审查生成报告 Run a full review first
review.noSelection 请先选中要审查的代码 Select code to review first
review.needApiKey 请先在设置面板中配置 API Key Configure API Key in Setup first
review.fixNotAvailable 单条修复功能开发中 Single fix under development
review.fixAllNotAvailable 批量修复功能开发中 Batch fix under development

5.2 export.* (导出类)

Key Description
export.selectMethod 选择导出方式
export.copyToClipboard 复制到剪贴板
export.downloadMarkdown 下载 Markdown 文件
export.copied 报告已复制到剪贴板
export.saveDialogTitle 保存审查报告
export.saved 报告已保存到 {0}

5.3 setup.* (设置面板)

Key Description
setup.header 净码特工 · 代码审查 · 设置
setup.quickStart 快速开始
setup.gettingStarted 三步启用代码审核
setup.step1 安装插件后,配置 AI 模型及 API Key...
setup.step2 启用自定义规则,补充团队特有的编码规范
setup.step3 保存并测试连接,验证配置无误后即可触发审核
setup.step3Hint 按 Ctrl + Shift + R 快捷键触发审核...
setup.engineSection 审核引擎
setup.commonRules 共通规则
setup.linterStatic Linter 静态分析
setup.customRules 自定义规则
setup.teamCoding 团队编码规范
setup.aiReview AI 审核
setup.deepReview 深度代码审查
setup.aiConfig AI 模型配置
setup.provider 模型提供商
setup.notConfigured 未配置
setup.model 模型名称
setup.modelHint 建议使用支持结构化输出的模型
setup.apiKey API Key
setup.baseUrl Base URL
setup.keyStorageHint Key 仅存储在本地 VS Code 安全存储中
setup.outputLang 输出语言
setup.outputLangHint AI 审查结果输出语言
setup.customRulesSection 自定义规则
setup.ruleList 规则列表
setup.ruleCount {0} 条
setup.ruleNamePlaceholder 输入规则名称...
setup.add + 添加
setup.ruleNameHint 建议使用英文名称...
setup.reset 重置
setup.saveAndTest 保存并测试连接
setup.testSuccess ✓ 连接成功
setup.testFail ✗ 连接失败: {0}
setup.setApiKeyFirst 请先设置 API Key
setup.setBaseUrlFirst 请先设置 Base URL
setup.selectRuleFile 选择规则文件
setup.fileExists 文件 {0} 已存在
setup.importSuccess 规则文件已导入: {0}
setup.importCancelled 导入已取消
setup.importDedupResult 规则已导入: ... ({0} 条,{1} 条重复已注释,{2} 条重叠已标注)
setup.importFail 规则导入失败: {0}
setup.openSetupFail 无法打开设置面板
setup.openSettingsJson 打开设置 (JSON)
setup.noWorkspace 请先打开工作区
setup.manageRulesHint 请在设置面板中管理自定义规则
setup.languageLabels 中文(简体)/ English / 日本語

5.4 report.* (审查报告)

Key Description
report.title 代码审查报告
report.panelTitle 净码特工 · 代码审查报告
report.totalIssues 总计问题
report.errors 错误
report.warnings 警告
report.info 建议
report.fixAll 全部修复
report.rerun 重新审查
report.export 导出报告
report.sourceLinter Linter
report.sourceCustom 自定义
report.sourceAI AI
report.noIssues 未发现任何问题
report.noRuleViolations 未发现规则违规
report.noAIFindings 无 AI 审查建议
report.skipCustomRules 当前文件语言无匹配的自定义规则
report.executionErrors 执行错误
report.degraded AI 审查未完成,报告仅包含部分结果
report.degradedBanner 部分 AI 功能不可用,报告已降级
report.file 文件
report.language 语言
report.duration 耗时
report.tools 分析工具
report.totalSummary 总计: {0} | 错误: {1} | 警告: {2} | 建议: {3}
report.staticSection 静态分析 · {0} 个问题
report.customSection 自定义规则 · {0} 个问题
report.aiSection AI 审查 · {0} 条建议
report.suggestion 建议
report.noProblems 未发现问题

5.5 import.* (规则导入)

Key Description
import.previewTitle 规则导入预览
import.source 来源:{0} · 检测到 {1} 条规则
import.fullDuplicate 完全重复 {0} 条
import.partialOverlap 部分重叠 {0} 条
import.noDuplicate 无重复 {0} 条
import.willKeep 将保留 {0} 条规则,注释 {1} 条规则
import.keep 保留
import.comment 注释
import.cancel 取消
import.confirm 确认导入
import.emptyFile 所选文件为空
import.needApiKey 请先在设置面板中配置 API Key
import.timeout AI 生成规则超时,请检查网络或增大 ai.timeout 配置
import.aiFail AI 生成规则失败: {0}
import.emptyResponse AI 返回内容为空
import.excelReadFail 读取 Excel 文件失败: {0}
import.excelEmpty Excel 文件没有工作表
import.excelNoData Excel 工作表中没有数据
import.docxReadFail 读取 Word 文件失败: {0}
import.docxEmpty Word 文件中没有可提取的文本内容
import.pptxReadFail 读取 PowerPoint 文件失败: {0}
import.pptxEmpty PowerPoint 文件中没有可提取的文本内容

5.6 adapter.* (适配器错误)

Key Description
adapter.javaNotInstalled Java 11+ 未安装或不在 PATH 中
adapter.sqlfluffNotInstalled sqlfluff 未安装,请执行 pip install sqlfluff
adapter.invalidApiKey API Key 无效,请重新设置
adapter.noApiKey 未配置 API Key
adapter.createProviderFail 创建 Provider 失败: {0}
adapter.customRuleParseFail 自定义规则响应解析失败: {0}
adapter.customRuleRequestFail 自定义规则请求失败: {0}
adapter.aiReviewParseFail AI 审查响应解析失败: {0}
adapter.aiReviewRequestFail AI 审查请求失败: {0}

5.7 extension.* (插件级)

Key Description
extension.activated 净码特工 · Code Purifier 已激活

5.8 命令标题(仅作参考,不修改 package.json

命令标题在 package.json 保持中文不变,不纳入本次范围。


6. 文件变更清单

变更类型 文件 说明
新增 src/i18n/messages.ts 核心 i18n 模块
新增 src/i18n/messages.test.ts 消息完整性测试
修改 src/extension.ts activate 中初始化语言 + 监听配置变更
修改 src/activation/commands.ts 通知/进度条/QuickPick 文案替换为 t()
修改 src/views/setupView.ts 设置面板 HTML 生成用 t(),语言下拉即时生效
修改 src/panel/webview.ts 审查报告 HTML 生成用 t(),监听语言变化重渲染
修改 src/views/import-preview.ts 导入预览 HTML 用 t()
修改 src/utils/report.ts 报告生成用 t()
修改 src/adapters/pmd.ts 错误消息替换
修改 src/adapters/sql-lint.ts 错误消息替换
修改 src/ai/engine.ts 错误消息替换(提示词不修改)
修改 src/ai/providers/openai-compatible.ts 错误消息替换
修改 src/rules/import-service.ts 错误消息替换
修改 src/rules/converters/excel-converter.ts 错误消息替换
修改 src/rules/converters/docx-converter.ts 错误消息替换
修改 src/rules/converters/pptx-converter.ts 错误消息替换

7. 实现顺序

  1. 创建 src/i18n/messages.ts(核心模块 + 全部消息注册)
  2. 编写 messages.test.ts(验证三种语言完整性)
  3. 改造 src/extension.tsinit + onDidChangeConfiguration
  4. 改造 src/activation/commands.ts
  5. 改造 src/panel/webview.ts
  6. 改造 src/views/setupView.ts
  7. 改造 src/views/import-preview.ts
  8. 改造 src/utils/report.ts
  9. 改造 src/adapters/pmd.tssql-lint.ts
  10. 改造 src/ai/engine.tsopenai-compatible.ts
  11. 改造各 converter 错误消息
  12. 运行 npm test 验证

8. 边界处理

场景 处理
某个 key 不存在于 messages fallback zh-CN,再 fallback 返回 key 本身
某条消息缺某种语言翻译 fallback zh-CN
传入非法语言值 TypeScript 类型系统 Language 防止编译时错误
setLanguage 同语言重复调 短路 return,不触发事件
切换语言时 webview 未打开 下次打开 webview 时取当前语言渲染,无影响
切换语言时正在显示通知 已显示的通知不更新,下次通知用新语言

9. 验证标准

  • 在设置面板切语言后:设置面板文字立即变,审查报告文字立即变
  • 重新触发审查:通知/进度条用新语言
  • 导出报告:报告标题和标签用新语言
  • 重启 VS Code:语言保持上次设置的值
  • AI 审查:提示词不变,审查质量不退化