From d0aa1cf9a7e564f786e1833707f9599207cec6ba Mon Sep 17 00:00:00 2001 From: npeter83 Date: Sun, 26 Jul 2026 22:17:04 +0200 Subject: [PATCH] refactor(api): code-review fixes (R7 S1) - localizeDetail: don't leak FastAPI's snake_case `loc` field names into a translated 422 toast; return a clean, fully localized validation message (drops the loc filter/pop parsing entirely) - me(): drop the dead `r &&` guard now that req types r non-nullable --- frontend/src/i18n/locales/en/errors.json | 2 +- frontend/src/i18n/locales/hu/errors.json | 2 +- frontend/src/lib/api.ts | 15 +++++---------- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/frontend/src/i18n/locales/en/errors.json b/frontend/src/i18n/locales/en/errors.json index 8a8ec37..3a61b69 100644 --- a/frontend/src/i18n/locales/en/errors.json +++ b/frontend/src/i18n/locales/en/errors.json @@ -1,7 +1,7 @@ { "title": "Couldn't complete that", "generic": "The server couldn't carry out that action. Please try again.", - "validation": "Invalid value for “{{field}}”. Please check it and try again.", + "validation": "Some of the values you entered weren't valid. Please check them and try again.", "server": "Server error", "ok": "OK", "offline": { diff --git a/frontend/src/i18n/locales/hu/errors.json b/frontend/src/i18n/locales/hu/errors.json index 4bd1342..a8847c5 100644 --- a/frontend/src/i18n/locales/hu/errors.json +++ b/frontend/src/i18n/locales/hu/errors.json @@ -1,7 +1,7 @@ { "title": "Nem sikerült", "generic": "A szerver nem tudta végrehajtani a műveletet. Próbáld újra.", - "validation": "Érvénytelen érték: „{{field}}”. Ellenőrizd, majd próbáld újra.", + "validation": "Néhány megadott érték érvénytelen volt. Ellenőrizd, majd próbáld újra.", "server": "Szerverhiba", "ok": "OK", "offline": { diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 509285f..497bbd6 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -228,15 +228,10 @@ class HttpError extends Error { function localizeDetail(d: unknown): string { const t = i18n.t.bind(i18n); // FastAPI request-validation errors: `detail` is an ARRAY of { loc, msg, type }. The UI sends - // well-formed requests, so this only fires on genuinely malformed input — surface the offending - // field name (localized) rather than FastAPI's raw English `msg`, which reads wrong in a HU UI. - if (Array.isArray(d)) { - const loc = (d[0] as { loc?: unknown } | undefined)?.loc; - const field = Array.isArray(loc) - ? loc.filter((s): s is string => typeof s === "string" && s !== "body").pop() - : undefined; - return field ? t("errors.validation", { field }) : t("errors.generic"); - } + // well-formed requests, so this only fires on genuinely malformed input. The per-field `msg` and + // `loc` field names are English, snake_case internal tokens — surface a clean, fully localized + // "check your input" message rather than leaking them into a translated sentence. + if (Array.isArray(d)) return t("errors.validation"); const o = d as { code?: string; reason?: string; limit?: number } | null | undefined; if (o?.code === "quota") { if (o.reason === "max_bytes") { @@ -1117,7 +1112,7 @@ export const api = { me: async (): Promise => { // Always 200: `{ authenticated: false }` when logged out, else the full Me + `authenticated`. const r = await req<{ authenticated: boolean } & Partial>("/api/me"); - return r && r.authenticated ? (r as Me) : null; + return r.authenticated ? (r as Me) : null; }, accounts: (): Promise => req("/api/me/accounts"), deleteAccount: (): Promise<{ deleted: boolean }> => req("/api/me/account", { method: "DELETE" }),