mirror of
https://gh-proxy.org/https://github.com/klinsmaya/multica.git
synced 2026-11-08 17:36:45 +08:00
Add a standalone Simplified Chinese UI to the mobile app, with a Settings → Language picker (Follow system / English / 简体中文) whose manual choice persists across restarts. Mobile keeps its own i18next resources rather than reusing web/desktop copy, following the conventions.mdx glossary: issue statuses and categories stay lowercase English identifiers, Squad is 小队. - Failure reasons: REASONS now mirrors web's REASON_LABEL, and a drift test pins it to the en/zh-Hans failure_reason keys. - Production env: .env.production stays committed with the public multica.ai defaults; the *:prod scripts layer a gitignored .env.production.local on top for self-hosting or a custom bundle ID. - Duplicate-mark activity rows from #8741 are localized too.
26 lines
1.1 KiB
TypeScript
26 lines
1.1 KiB
TypeScript
/**
|
|
* Map backend auth errors to user-facing strings. The backend returns raw
|
|
* English messages that are fine for logs but should not surface as-is —
|
|
* we map the known shapes to friendlier copy and fall back to the caller's
|
|
* default for anything unrecognised.
|
|
*/
|
|
type Translate = (key: string) => string;
|
|
|
|
export function mapAuthError(err: unknown, fallback: string, t?: Translate): string {
|
|
if (!(err instanceof Error)) return fallback;
|
|
const msg = err.message.toLowerCase();
|
|
if (/invalid|incorrect|wrong/.test(msg)) {
|
|
return t ? t("verify.mismatch") : "That code didn't match. Double-check and try again.";
|
|
}
|
|
if (/expired/.test(msg)) {
|
|
return t ? t("verify.expired") : "That code has expired. Tap resend to get a new one.";
|
|
}
|
|
if (/rate.?limit|too many|throttle/.test(msg)) {
|
|
return t ? t("verify.rate_limited") : "Too many attempts. Wait a moment and try again.";
|
|
}
|
|
if (/network|fetch|timeout|unreachable/.test(msg)) {
|
|
return t ? t("verify.network") : "Can't reach Multica. Check your connection and retry.";
|
|
}
|
|
return fallback;
|
|
}
|