feat: AI 引擎提示词三语化 + 语言下拉框母语名称
- engine.ts: CUSTOM_RULE_SYSTEM_PROMPT / DEEP_REVIEW_SYSTEM_PROMPT 从硬编码中文改为三语模板(zh-CN/en/ja);parseJsonResponse 错误消息改用 t() 本地化;用户消息标签按语言本地化 - setupView.ts: 删除未使用的 getLanguageLabel / languageLabel;语言下拉选项文本固定为母语名称(中文(简体)/English/日本語),不再随界面语言翻译
This commit is contained in:
+86
-12
@@ -9,7 +9,7 @@ import type {
|
||||
TranslatedDiagnostic,
|
||||
AIFinding,
|
||||
} from './schema';
|
||||
import { t } from '../i18n/messages';
|
||||
import { t, getLanguage } from '../i18n/messages';
|
||||
|
||||
function buildCustomRulePrompt(rules: CustomRule[]): string {
|
||||
return rules.map(r =>
|
||||
@@ -61,7 +61,7 @@ function parseJsonResponse(raw: string): object {
|
||||
const start = trimmed.indexOf('{');
|
||||
const end = trimmed.lastIndexOf('}');
|
||||
if (start === -1 || end === -1) {
|
||||
throw new Error(`响应中未找到 JSON。原始响应(前200字符):${trimmed.slice(0, 200)}`);
|
||||
throw new Error(t('engine.jsonNotFound', { 0: trimmed.slice(0, 200) }));
|
||||
}
|
||||
let jsonStr = trimmed.substring(start, end + 1);
|
||||
try {
|
||||
@@ -71,29 +71,103 @@ function parseJsonResponse(raw: string): object {
|
||||
try {
|
||||
return JSON.parse(jsonStr);
|
||||
} catch {
|
||||
throw new Error(`JSON 解析失败。原始响应(前200字符):${jsonStr.slice(0, 200)}`);
|
||||
throw new Error(t('engine.jsonParseFail', { 0: jsonStr.slice(0, 200) }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const CUSTOM_RULE_SYSTEM_PROMPT = `你是代码规则审查员,只评估以下自定义规则是否被违反。
|
||||
function buildCustomRuleSystemPrompt(): string {
|
||||
const lang = getLanguage();
|
||||
if (lang === 'ja') {
|
||||
return `あなたはコードルールレビュアーです。以下のカスタムルールに違反しているかどうかのみを評価してください。
|
||||
意味を理解し、テキストの一致ではなく判断してください。
|
||||
JSONのみを出力、形式:
|
||||
{ "customRuleResults": [{ "ruleId": "ルールID", "line": 行番号, "severity": "error|warning|info", "message": "違反の説明" }] }
|
||||
ルールに違反していない場合は空の配列を返してください。
|
||||
|
||||
出力言語:ja`;
|
||||
}
|
||||
if (lang === 'en') {
|
||||
return `You are a code rule reviewer. Only evaluate whether the following custom rules are violated.
|
||||
Understand semantics, not text matching.
|
||||
Output JSON only, format:
|
||||
{ "customRuleResults": [{ "ruleId": "rule id", "line": line number, "severity": "error|warning|info", "message": "violation description" }] }
|
||||
If no rules are violated, return an empty array.
|
||||
|
||||
Output language: en`;
|
||||
}
|
||||
return `你是代码规则审查员,只评估以下自定义规则是否被违反。
|
||||
理解语义而非文本匹配。
|
||||
仅输出 JSON,格式:
|
||||
{ "customRuleResults": [{ "ruleId": "规则ID", "line": 行号, "severity": "error|warning|info", "message": "触发描述" }] }
|
||||
如果没有违反任何规则,返回空数组。`;
|
||||
如果没有违反任何规则,返回空数组。
|
||||
|
||||
const DEEP_REVIEW_SYSTEM_PROMPT = `你是资深代码审查专家,完成两个任务:
|
||||
输出语言:zh-CN`;
|
||||
}
|
||||
|
||||
function buildDeepReviewSystemPrompt(): string {
|
||||
const lang = getLanguage();
|
||||
if (lang === 'ja') {
|
||||
return `あなたはシニアコードレビュー専門家です。2つのタスクを実行してください:
|
||||
1. 英語の静的解析結果を出力言語に翻訳し、修正提案を追加する
|
||||
2. コードを詳細にレビューし、静的解析でカバーされていない問題を発見する
|
||||
重点分野:セキュリティ脆弱性、論理エラー、パフォーマンス問題、設計欠陥
|
||||
静的解析ですでに報告された問題を重複しないでください。
|
||||
|
||||
JSONのみを出力。文字列内の二重引用符は \\" でエスケープしてください。
|
||||
形式:
|
||||
{
|
||||
"translatedDiagnostics": [{ "originalRuleId": "元のID", "translatedMessage": "翻訳メッセージ", "translatedSuggestion": "提案", "codeDiff": "任意" }],
|
||||
"findings": [{ "ruleId": "kebab-case", "severity": "error|warning|info", "category": "bug|performance|security|style|design", "title": "タイトル", "description": "説明", "suggestion": "提案", "codeDiff": "任意", "line": 行番号 }]
|
||||
}
|
||||
|
||||
出力言語:ja`;
|
||||
}
|
||||
if (lang === 'en') {
|
||||
return `You are a senior code review expert. Complete two tasks:
|
||||
1. Translate English static analysis results into the output language and add fix suggestions
|
||||
2. Deeply review the code to find issues not covered by static analysis
|
||||
Focus on: security vulnerabilities, logic errors, performance issues, design flaws
|
||||
Do not duplicate issues already reported by static analysis.
|
||||
|
||||
Output JSON only. Double quotes in strings must be escaped with \\".
|
||||
Format:
|
||||
{
|
||||
"translatedDiagnostics": [{ "originalRuleId": "original id", "translatedMessage": "translated message", "translatedSuggestion": "suggestion", "codeDiff": "optional" }],
|
||||
"findings": [{ "ruleId": "kebab-case", "severity": "error|warning|info", "category": "bug|performance|security|style|design", "title": "title", "description": "description", "suggestion": "suggestion", "codeDiff": "optional", "line": line number }]
|
||||
}
|
||||
|
||||
Output language: en`;
|
||||
}
|
||||
return `你是资深代码审查专家,完成两个任务:
|
||||
1. 将英文静态分析结果翻译为输出语言,并补充修复建议
|
||||
2. 深度审查代码,发现静态分析未覆盖的问题
|
||||
重点:安全漏洞、逻辑错误、性能问题、设计缺陷
|
||||
不要重复静态分析已报告的问题。
|
||||
|
||||
仅输出 JSON,字符串中的双引号必须用 \" 转义。
|
||||
仅输出 JSON,字符串中的双引号必须用 \\" 转义。
|
||||
格式:
|
||||
{
|
||||
"translatedDiagnostics": [{ "originalRuleId": "原始ID", "translatedMessage": "翻译", "translatedSuggestion": "建议", "codeDiff": "可选" }],
|
||||
"findings": [{ "ruleId": "kebab-case", "severity": "error|warning|info", "category": "bug|performance|security|style|design", "title": "标题", "description": "描述", "suggestion": "建议", "codeDiff": "可选", "line": 行号 }]
|
||||
}`;
|
||||
}
|
||||
|
||||
输出语言:zh-CN`;
|
||||
}
|
||||
|
||||
function buildUserPromptCustomRules(customRules: CustomRule[], numberedCode: string): string {
|
||||
const lang = getLanguage();
|
||||
const label = lang === 'ja' ? 'カスタムルール' : lang === 'en' ? 'Custom Rules' : '自定义规则';
|
||||
const codeLabel = lang === 'ja' ? 'コード(行番号付き)' : lang === 'en' ? 'Code (with line numbers)' : '代码(带行号)';
|
||||
return `## ${label}\n${buildCustomRulePrompt(customRules)}\n\n## ${codeLabel}\n${numberedCode}`;
|
||||
}
|
||||
|
||||
function buildUserPromptDeepReview(numberedCode: string, staticDiagnostics: LinterDiagnostic[]): string {
|
||||
const lang = getLanguage();
|
||||
const codeLabel = lang === 'ja' ? 'コード(行番号付き)' : lang === 'en' ? 'Code (with line numbers)' : '代码(带行号)';
|
||||
const resultLabel = lang === 'ja' ? '静的解析結果' : lang === 'en' ? 'Static Analysis Results' : '静态分析结果(英文)';
|
||||
return `## ${codeLabel}\n${numberedCode}\n\n## ${resultLabel}\n${buildLinterDiagnosticsPrompt(staticDiagnostics)}`;
|
||||
}
|
||||
|
||||
export async function runAIReview(
|
||||
context: vscode.ExtensionContext,
|
||||
@@ -141,15 +215,15 @@ export async function runAIReview(
|
||||
const requestA =
|
||||
customRules.length > 0
|
||||
? provider.chat(
|
||||
CUSTOM_RULE_SYSTEM_PROMPT,
|
||||
`## 自定义规则\n${buildCustomRulePrompt(customRules)}\n\n## 代码(带行号)\n${numberedCode}`,
|
||||
buildCustomRuleSystemPrompt(),
|
||||
buildUserPromptCustomRules(customRules, numberedCode),
|
||||
options
|
||||
)
|
||||
: Promise.resolve('{}');
|
||||
|
||||
const requestB = provider.chat(
|
||||
`${DEEP_REVIEW_SYSTEM_PROMPT}\n输出语言:${getAIOutputLanguage()}`,
|
||||
`## 代码(带行号)\n${numberedCode}\n\n## 静态分析结果(英文)\n${buildLinterDiagnosticsPrompt(staticDiagnostics)}`,
|
||||
buildDeepReviewSystemPrompt(),
|
||||
buildUserPromptDeepReview(numberedCode, staticDiagnostics),
|
||||
options
|
||||
);
|
||||
|
||||
|
||||
+4
-14
@@ -13,16 +13,7 @@ import { TxtConverter } from '../rules/converters/txt-converter';
|
||||
import { ExcelConverter } from '../rules/converters/excel-converter';
|
||||
import { DocxConverter } from '../rules/converters/docx-converter';
|
||||
import { PptxConverter } from '../rules/converters/pptx-converter';
|
||||
import { t, onLanguageChange, Language } from '../i18n/messages';
|
||||
|
||||
function getLanguageLabel(lang: string): string {
|
||||
switch (lang) {
|
||||
case 'zh-CN': return t('lang.zhCN');
|
||||
case 'en': return t('lang.en');
|
||||
case 'ja': return t('lang.ja');
|
||||
default: return lang;
|
||||
}
|
||||
}
|
||||
import { t, onLanguageChange } from '../i18n/messages';
|
||||
|
||||
export class SetupViewProvider implements vscode.WebviewViewProvider {
|
||||
private _view?: vscode.WebviewView;
|
||||
@@ -146,7 +137,6 @@ export class SetupViewProvider implements vscode.WebviewViewProvider {
|
||||
baseUrl: baseUrlConfigured ? config.baseUrl : '',
|
||||
baseUrlConfigured,
|
||||
language: config.outputLanguage,
|
||||
languageLabel: getLanguageLabel(config.outputLanguage),
|
||||
apiKeyConfigured,
|
||||
},
|
||||
providers: getAllProviderMeta(),
|
||||
@@ -599,9 +589,9 @@ input::placeholder { color: var(--vscode-input-placeholderForeground, var(--vsco
|
||||
<div class="field">
|
||||
<label class="field-label">${t('setup.outputLangHint')}</label>
|
||||
<select id="languageSelect" onchange="postMsg('setLanguage', this.value)">
|
||||
<option value="zh-CN"${config.outputLanguage === 'zh-CN' ? ' selected' : ''}>${t('lang.zhCN')}</option>
|
||||
<option value="en"${config.outputLanguage === 'en' ? ' selected' : ''}>${t('lang.en')}</option>
|
||||
<option value="ja"${config.outputLanguage === 'ja' ? ' selected' : ''}>${t('lang.ja')}</option>
|
||||
<option value="zh-CN"${config.outputLanguage === 'zh-CN' ? ' selected' : ''}>中文(简体)</option>
|
||||
<option value="en"${config.outputLanguage === 'en' ? ' selected' : ''}>English</option>
|
||||
<option value="ja"${config.outputLanguage === 'ja' ? ' selected' : ''}>日本語</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user