Localize user-facing UI, agent output, and backend messages to Simplified Chinese
ci / go (push) Waiting to run
ci / go-db (agent) (push) Waiting to run
ci / go-db (config) (push) Waiting to run
ci / go-db (db) (push) Waiting to run
ci / go-db (evidence) (push) Waiting to run
ci / go-db (llmrec) (push) Waiting to run
ci / go-db (server) (push) Waiting to run
detections / detections (push) Waiting to run
docs / links (push) Waiting to run
web / web (push) Waiting to run

This commit is contained in:
dela
2026-10-09 14:08:31 +08:00
parent 8af63417c8
commit 97668dab7e
148 changed files with 1671 additions and 1672 deletions
+2 -2
View File
@@ -19,8 +19,8 @@ const FindingRetestAgentKey = "retester"
// retestServiceRestartReason 은 재시작 복구(RecoverFindingRetests)가 미완 재검증을 봉인할 때 쓴다.
// 작은따옴표 없는 상수라 SQL 리터럴 자리에 그대로 이어 붙여도 안전하다.
const (
retestNoConclusionReason = "에이전트가 재검증 결론을 저장하지 않았습니다. 대화를 확인한 뒤 다시 재검증해 주세요"
retestServiceRestartReason = "서비스가 재시작되어 재검증이 중단되었습니다. 다시 시작해 주세요"
retestNoConclusionReason = "代理未保存复测结论。请检查对话后重新复测"
retestServiceRestartReason = "服务已重启,复测被中断。请重新开始"
)
var ErrRetestNotRunning = errors.New("本次复测已结束或尚未开始,请从漏洞详情发起新的复测")
+11 -11
View File
@@ -8,22 +8,22 @@ import (
// assertRetestReasonKorean 은 재검증 사유 상수가 한글을 포함하고 중국어 한자가 없음을
// 단언한다(F9). FinishFindingRetest·RecoverFindingRetests 의 SQL 리터럴 자리에 상수로
// 이어 붙이므로, 상수를 핀 고정하면 패널에 노출되는 사용자 문구도 함께 보호된다.
func assertRetestReasonKorean(t *testing.T, name, s string) {
func assertRetestReasonChinese(t *testing.T, name, s string) {
t.Helper()
if s == "" {
t.Fatalf("%s: 빈 문자열", name)
t.Fatalf("%s: 空字符串", name)
}
hasHangul := false
hasHan := false
for _, r := range s {
if unicode.Is(unicode.Han, r) {
t.Fatalf("%s: 중국어 한자가 남아 있습니다: %q", name, s)
}
if unicode.Is(unicode.Hangul, r) {
hasHangul = true
t.Fatalf("%s: 仍残留韩文: %q", name, s)
}
if unicode.Is(unicode.Han, r) {
hasHan = true
}
}
if !hasHangul {
t.Fatalf("%s: 한글이 없습니다: %q", name, s)
if !hasHan {
t.Fatalf("%s: 缺少汉字: %q", name, s)
}
}
@@ -32,6 +32,6 @@ func assertRetestReasonKorean(t *testing.T, name, s string) {
// server/conversations.go 의 형제 사유(convRetest*)와 같은 컬럼·패널이라, 둘 중 하나만
// 한국어면 같은 패널에서 언어가 섞인다.
func TestFindingRetestReasonsLocalized(t *testing.T) {
assertRetestReasonKorean(t, "retestNoConclusionReason", retestNoConclusionReason)
assertRetestReasonKorean(t, "retestServiceRestartReason", retestServiceRestartReason)
assertRetestReasonChinese(t, "retestNoConclusionReason", retestNoConclusionReason)
assertRetestReasonChinese(t, "retestServiceRestartReason", retestServiceRestartReason)
}
+2 -2
View File
@@ -13,7 +13,7 @@ const (
MaxTaskAssetMutationCount = 100
MaxTaskAssetSummaryRunes = 500
defaultTaskAssetSource = "system"
manualTaskScopeSummary = "사용자가 테스트 자산 페이지에서 직접 추가"
manualTaskScopeSummary = "用户在测试资产页面手动添加"
)
var (
@@ -394,7 +394,7 @@ SELECT intent.id, asset.id, asset.type,
ELSE '#' || asset.id::text
END,
COALESCE(link.source,'anchor'),
COALESCE(NULLIF(link.source_summary,''), '의도가 앵커로 연결한 자산'),
COALESCE(NULLIF(link.source_summary,''), '由意图锚点关联的资产'),
link.source_node_id, context.task_id, context.inherited
FROM context
JOIN exploration_nodes intent ON intent.exploration_id=context.exploration_id AND intent.kind='intent'
+8 -8
View File
@@ -13,18 +13,18 @@ import (
// via the symbol, so pinning the constant here protects the user-facing text too.
func TestManualTaskScopeSummaryLocalized(t *testing.T) {
if manualTaskScopeSummary == "" {
t.Fatal("manualTaskScopeSummary: 빈 문자열")
t.Fatal("manualTaskScopeSummary: 空字符串")
}
hasHangul := false
hasHan := false
for _, r := range manualTaskScopeSummary {
if unicode.Is(unicode.Han, r) {
t.Fatalf("manualTaskScopeSummary: 중국어 한자가 남아 있습니다: %q", manualTaskScopeSummary)
}
if unicode.Is(unicode.Hangul, r) {
hasHangul = true
t.Fatalf("manualTaskScopeSummary: 仍残留韩文: %q", manualTaskScopeSummary)
}
if unicode.Is(unicode.Han, r) {
hasHan = true
}
}
if !hasHangul {
t.Fatalf("manualTaskScopeSummary: 한글이 없습니다: %q", manualTaskScopeSummary)
if !hasHan {
t.Fatalf("manualTaskScopeSummary: 缺少汉字: %q", manualTaskScopeSummary)
}
}
+2 -2
View File
@@ -267,7 +267,7 @@ WITH requested(company_id, position) AS (
FROM unnest($2::bigint[]) WITH ORDINALITY AS requested(company_id, position)
), inserted AS (
INSERT INTO task_scope(task_id, kind, company_id, source, reason)
SELECT $1, 'company', companies.id, 'manual', '작업 생성 시 연결된 회사'
SELECT $1, 'company', companies.id, 'manual', '任务创建时关联的公司'
FROM requested
JOIN companies ON companies.id=requested.company_id
ORDER BY requested.position
@@ -295,7 +295,7 @@ WHERE company_id=ANY($2::bigint[])`, taskID, companyIDs); err != nil {
}
if _, err := tx.Exec(`
INSERT INTO task_asset_links(task_id, asset_id, source, source_summary)
SELECT $1, asset.id, $3, '작업 생성 시 연결된 회사: ' || company.name
SELECT $1, asset.id, $3, '任务创建时关联的公司: ' || company.name
FROM assets asset
JOIN companies company ON company.id=asset.company_id
WHERE asset.company_id=ANY($2::bigint[])
+1 -1
View File
@@ -607,7 +607,7 @@ RETURNING id`, domainB, companyB).Scan(&companyAssetB); err != nil {
t.Errorf("company asset %d missing from task", assetID)
continue
}
if asset.TaskSource != taskCompanyAssetSource || asset.TaskSourceSummary != "작업 생성 시 연결된 회사: "+companyName {
if asset.TaskSource != taskCompanyAssetSource || asset.TaskSourceSummary != "任务创建时关联的公司: "+companyName {
t.Errorf("asset %d provenance=%q/%q", assetID, asset.TaskSource, asset.TaskSourceSummary)
}
}