🌐 Localized Language Names
The source and target language dropdowns no longer rely on a static English name table:
- Option labels are resolved with
Intl.DisplayNamesin the visitor’s UI language — the same option reads “Japanese” on the English site and 「日语」 on the Chinese site. - Google-specific codes (
zh-CN,zh-TW,tl) are mapped to their BCP-47 equivalents (zh-Hans,zh-Hant,fil) before lookup. Intl.DisplayNamesinstances are cached per locale, and codes missing from CLDR fall back to the built-in English names.
⏱️ Request Timeouts & Clearer Failure Guidance
A hung request no longer stalls a relay:
- Every request now has a hard 10-second timeout (
AbortSignal.timeout); timeouts are treated as retryable errors with their own localized message. - The Google dictionary endpoint’s retry budget was trimmed from 3 to 2 attempts, bounding the worst-case wait per round.
- When a provider fails, the status bar now appends a hint: switch the engine and press Continue to resume from the failed round.
🛡️ MyMemory Error Handling
MyMemory reports business-level failures (exhausted quota, invalid language pairs) inside an HTTP 200 body via its responseStatus field:
- Responses are now only accepted when
responseStatusis200. - Business failures surface as a localized “Translation service returned an error (HTTP {status})” message;
responseDetailsis logged for debugging.
🧭 Route Expansion Fixes
- The final round’s card expands exactly when the relay finishes — no longer while it is still running.
- Rounds you manually collapsed stay collapsed.
📱 Mobile Layout Polish
- Long status messages wrap with
break-wordsinstead of overflowing. - Share actions reflow into a grid on small screens with consistent alignment.
- Tighter padding and type scale across the form, history entries, and route stop cards.
🗣️ Localization
- Provider selection, resume, timeout and MyMemory error strings are translated across all seven locales: English, 简体中文, 繁體中文, العربية, Bahasa Indonesia, Bahasa Melayu, and Português (BR).