现象
所有后端失败文案都以英文原文抵达用户,出现在一个中文界面里。连成功文案也是——探测通过时显示的是 OpenAI Chat Completions connection test passed.(internal/provider/client.go:103)。
根因是一行
frontend/src/backend/errors.ts:31-32:
if (error instanceof OneAgentApiError) {
return { message: error.message, code: error.code, retryable: error.retryable };
}
中文 fallback 只在抛出的值不是 Error 时才用。而 normalizeWailsError(frontend/src/backend/wails.ts:87-99)会把每一个后端失败都包成 OneAgentApiError,所以 t("无法保存模型服务") 这类 fallback 几乎永不触发——它们看起来做了本地化,实际上是死代码。
internal/errors/errors.go:11-20 那 10 个错误码目前只用于控制样式(只有 API_KEY_REJECTED 被特殊处理,ConnectionStatus.tsx:33)和重试判断,从未用于查中文文案。前端没有任何「错误码 → 本地化文案」的映射表。
最难读的几条
Cannot reach endpoint: %s — internal/provider/client.go:333、:343。%s 是 Go 的原始错误,用户看到的是 Cannot reach endpoint: Post "https://api.ppio.com/openai/v1/chat/completions": dial tcp: lookup api.ppio.com: no such host。泄露完整 URL、HTTP 方法和 dial tcp 内部细节。
Unexpected token } in JSON at position 412 — 导入损坏文件时 JSON.parse 的浏览器原生报错,frontend/src/pages/TransferPage.tsx:130 直接抛出。
Endpoint returned HTTP %d. — internal/provider/client.go:292、:322。429 限流和 402 额度耗尽都落在这里,是新用户最常遇到的两种真实失败,却只显示一个数字。而且 Retryable 只在 >= 500 时为 true(:294),所以 429 被标为不可重试。
- 空 message 的
OperationError — 导入密码错误时 AES-GCM 校验失败(frontend/src/state/settingsTransfer.ts:29-32),用户无法区分「密码错」和「文件坏」。
超时与不可达无法区分
transportCode(internal/provider/client.go:350-362)在错误码层面区分了 Timeout 和 ProviderUnreachable,但两者产生的 message 完全相同。10 秒卡住和主机名写错,用户看到的是同一句话。
另有三条未走 i18n 的中文字面量
英文 locale 下反而显示中文:
文件格式无效 — frontend/src/state/settingsTransfer.ts:55、:56
模型服务文件格式无效 — frontend/src/state/settingsTransfer.ts:71
(是否加密apikey 单独记在 #110。)
其中 文件格式无效 还被两个不同条件共用:版本号不为 1、以及 providers/profiles 不是数组。makeTransfer 硬编码 version: 1(:45),所以将来版本号一变,旧文件就是这条报错,而它从不说明期望版本和实际版本。
期望
- 建立错误码到本地化文案的映射,让
internal/errors 的 10 个码真正被用于展示。
Cannot reach endpoint 不应把原始 Go 错误拼进用户可见文案;至少区分超时与 DNS/连接失败。
- 429/402 给出可读解释而不是裸状态码。
- 三条中文字面量补进 i18n;
文件格式无效 拆分为可区分的两条,并带上版本信息。
参考
frontend/src/backend/errors.ts:31-32
frontend/src/backend/wails.ts:87-99
internal/provider/client.go:103、:292、:322、:333、:343、:350-362
internal/errors/errors.go:11-20
frontend/src/state/settingsTransfer.ts:29-32、:55-56、:71
现象
所有后端失败文案都以英文原文抵达用户,出现在一个中文界面里。连成功文案也是——探测通过时显示的是
OpenAI Chat Completions connection test passed.(internal/provider/client.go:103)。根因是一行
frontend/src/backend/errors.ts:31-32:中文 fallback 只在抛出的值不是
Error时才用。而normalizeWailsError(frontend/src/backend/wails.ts:87-99)会把每一个后端失败都包成OneAgentApiError,所以t("无法保存模型服务")这类 fallback 几乎永不触发——它们看起来做了本地化,实际上是死代码。internal/errors/errors.go:11-20那 10 个错误码目前只用于控制样式(只有API_KEY_REJECTED被特殊处理,ConnectionStatus.tsx:33)和重试判断,从未用于查中文文案。前端没有任何「错误码 → 本地化文案」的映射表。最难读的几条
Cannot reach endpoint: %s—internal/provider/client.go:333、:343。%s是 Go 的原始错误,用户看到的是Cannot reach endpoint: Post "https://api.ppio.com/openai/v1/chat/completions": dial tcp: lookup api.ppio.com: no such host。泄露完整 URL、HTTP 方法和dial tcp内部细节。Unexpected token } in JSON at position 412— 导入损坏文件时JSON.parse的浏览器原生报错,frontend/src/pages/TransferPage.tsx:130直接抛出。Endpoint returned HTTP %d.—internal/provider/client.go:292、:322。429 限流和 402 额度耗尽都落在这里,是新用户最常遇到的两种真实失败,却只显示一个数字。而且Retryable只在>= 500时为 true(:294),所以 429 被标为不可重试。OperationError— 导入密码错误时 AES-GCM 校验失败(frontend/src/state/settingsTransfer.ts:29-32),用户无法区分「密码错」和「文件坏」。超时与不可达无法区分
transportCode(internal/provider/client.go:350-362)在错误码层面区分了Timeout和ProviderUnreachable,但两者产生的 message 完全相同。10 秒卡住和主机名写错,用户看到的是同一句话。另有三条未走 i18n 的中文字面量
英文 locale 下反而显示中文:
文件格式无效—frontend/src/state/settingsTransfer.ts:55、:56模型服务文件格式无效—frontend/src/state/settingsTransfer.ts:71(
是否加密apikey单独记在 #110。)其中
文件格式无效还被两个不同条件共用:版本号不为 1、以及providers/profiles不是数组。makeTransfer硬编码version: 1(:45),所以将来版本号一变,旧文件就是这条报错,而它从不说明期望版本和实际版本。期望
internal/errors的 10 个码真正被用于展示。Cannot reach endpoint不应把原始 Go 错误拼进用户可见文案;至少区分超时与 DNS/连接失败。文件格式无效拆分为可区分的两条,并带上版本信息。参考
frontend/src/backend/errors.ts:31-32frontend/src/backend/wails.ts:87-99internal/provider/client.go:103、:292、:322、:333、:343、:350-362internal/errors/errors.go:11-20frontend/src/state/settingsTransfer.ts:29-32、:55-56、:71