Skip to content

i18n(loop/errors): localize DeepSeek error messages#441

Closed
esengine wants to merge 2 commits into
mainfrom
feat/loop-errors-i18n
Closed

i18n(loop/errors): localize DeepSeek error messages#441
esengine wants to merge 2 commits into
mainfrom
feat/loop-errors-i18n

Conversation

@esengine

@esengine esengine commented May 8, 2026

Copy link
Copy Markdown
Owner

Why

formatLoopError, reasonPrefixFor, and errorLabelFor were all hardcoded English. A Chinese user hitting a 503 / 401 / context-overflow saw raw English in the chat — same class of UX gap as #440, just on the i18n axis.

This includes the new 5xx outage notice from #440 (since this PR is stacked on top of it).

What

New errors.* i18n namespace covering:

  • context overflow (with V4 / legacy limit mention)
  • 401 auth / 402 balance / 422 param / 400 bad request
  • 5xx head + reachable / unreachable / two action variants
  • reason prefix and label for budget / aborted / context-guard / stuck
  • (no message) fallback for empty error bodies

zh-CN translations included for all 20 keys. The user-visible {inner} server message (e.g. "Authentication Fails") is preserved verbatim — translating DS's own response would be wrong.

Test plan

  • 26 existing EN cases still pass (vitest setupFiles pins runtime to EN)
  • 2 new cases flip to zh-CN and confirm runtime translation works ("服务不可用", "认证失败")
  • full suite 2299/2299
  • tsc + biome clean

Stacking

Built on top of #440 — merge that first to avoid a clean errors.ts collision.

esengine added 2 commits May 8, 2026 03:51
Raw `DeepSeek 503: <body>` was bubbling straight to the UI. Users on
flaky DS days couldn't tell if it was DS-side (their service was
overloaded) or Reasonix-side (we crashed). The header comment in
loop/errors.ts even claimed retry.ts swallowed all 5xx — but retry.ts
returns the last response instead of swallowing, so 5xx did reach the
formatter and just fell through to a passthrough branch.

Now formatLoopError takes an optional probe result. The catch in
step() detects 5xx, fires a 1.5s `/user/balance` probe, and passes
the result back. Three message variants:
  - no probe         → DS-side outage notice + retry hints
  - probe reachable  → "main API answered, /chat/completions failing"
  - probe down       → "DS unreachable from your network — check net"

All three include "this is a DeepSeek-side problem, not Reasonix" and
a status-page link so users know where to look.
formatLoopError, reasonPrefixFor, and errorLabelFor were all
hardcoded English. A Chinese user hitting a 503 / 401 / context
overflow saw raw English (and on top of that, the new 5xx outage
notice from #440 was also English).

Move the strings to a new errors.* i18n namespace covering:
  - context overflow (with V4/legacy limit mention)
  - 401 auth / 402 balance / 422 param / 400 bad request
  - 5xx head + reachable / unreachable / two action variants
  - reason prefix and label for budget/aborted/context-guard/stuck
  - "(no message)" fallback for empty error bodies

zh-CN translations included. Existing tests still cover EN (vitest
setupFile pins runtime to EN); two new tests flip to zh-CN to confirm
runtime switch actually translates.

Stacked on #440 — merge that first.
Base automatically changed from fix/loop-deepseek-5xx-friendly to main May 8, 2026 11:23
@esengine

esengine commented May 8, 2026

Copy link
Copy Markdown
Owner Author

Reopened as #444 with base on main after #440 merged. Same commit.

@esengine esengine closed this May 8, 2026
@esengine esengine deleted the feat/loop-errors-i18n branch May 13, 2026 01:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant