mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 21:32:18 +00:00
refactor(i18n): ask the catalogue for a sentence in one helper
`t()` answers a missing key with the key, so "does this code have a sentence" was a comparison written inline at every site that wanted a code's sentence or a fallback, twenty-odd times in several spellings. translateOrNull, translateCodeOrNull and translateCode in src/lib/i18n/translate-code.ts now hold that probe, every site uses them, and a guard refuses the inline comparison anywhere else.
This commit is contained in:
1 parent
2f7f04ecab
commit
6e54f33901
32 files changed
+291
-119
No files matched your search
@@ -58,6 +58,7 @@ import {
|
||||
import { AvatarSection } from "./avatar-section";
|
||||
import { SetupCard } from "./setup-card";
|
||||
import { dateOnlyKey } from "@/lib/tz/date-only";
|
||||
import { translateCodeOrNull } from "@/lib/i18n/translate-code";
|
||||
|
||||
export { resolveInitialTimezone } from "./account-section-utils";
|
||||
|
||||
@@ -368,10 +369,7 @@ export function AccountSection() {
|
||||
setFieldErrors(describeRejectedProfileFields(json?.details?.issues, t));
|
||||
if (errorCode === "profile.update.nothingSaved" && field) {
|
||||
setSaveMsg({ key: "settings.profileNothingSaved", params: { field } });
|
||||
} else if (
|
||||
errorCode &&
|
||||
t(`apiErrors.${errorCode}`) !== `apiErrors.${errorCode}`
|
||||
) {
|
||||
} else if (translateCodeOrNull(t, "apiErrors", errorCode) !== null) {
|
||||
// Only a code with a sentence of its own: every refusal carries a
|
||||
// code now, and the generic `http.*` family has no translation.
|
||||
setSaveMsg({ key: `apiErrors.${errorCode}` });
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
useSyncOutcomeMessage,
|
||||
type SyncOutcomeState,
|
||||
} from "./sync-outcome";
|
||||
import { translateCode } from "@/lib/i18n/translate-code";
|
||||
|
||||
export interface ProviderSync {
|
||||
syncing: boolean;
|
||||
@@ -151,11 +152,12 @@ export function ActionResultLines({
|
||||
const { t } = useTranslations();
|
||||
|
||||
function describeError(errorCode: string): string {
|
||||
const key = `settings.testConnection.errors.${errorCode}`;
|
||||
const translated = t(key);
|
||||
return translated === key
|
||||
? t("settings.testConnection.errors.generic")
|
||||
: translated;
|
||||
return translateCode(
|
||||
t,
|
||||
"settings.testConnection.errors",
|
||||
errorCode,
|
||||
"settings.testConnection.errors.generic",
|
||||
);
|
||||
}
|
||||
|
||||
const busy = sync?.syncing || test?.testing;
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
import { useTranslations } from "@/lib/i18n/context";
|
||||
import { queryKeys } from "@/lib/query-keys";
|
||||
import { apiFetchRaw, apiGet } from "@/lib/api/api-fetch";
|
||||
import { translateCodeOrNull } from "@/lib/i18n/translate-code";
|
||||
|
||||
interface NtfySettings {
|
||||
enabled: boolean;
|
||||
@@ -80,13 +81,13 @@ export function NtfyCard({ isAuthenticated }: { isAuthenticated: boolean }) {
|
||||
};
|
||||
// A coded refusal (the private-origin policy) translates like the
|
||||
// test button's; anything else shows the server sentence.
|
||||
const code = json.meta?.errorCode;
|
||||
const key = code ? `settings.testConnection.errors.${code}` : null;
|
||||
const translated = key ? t(key) : null;
|
||||
throw new Error(
|
||||
translated && translated !== key
|
||||
? translated
|
||||
: json.error || t("common.error"),
|
||||
translateCodeOrNull(
|
||||
t,
|
||||
"settings.testConnection.errors",
|
||||
json.meta?.errorCode,
|
||||
) ??
|
||||
(json.error || t("common.error")),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@ import { CheckCircle2, Loader2, Plug, XCircle } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useTranslations } from "@/lib/i18n/context";
|
||||
import { apiFetchRaw } from "@/lib/api/api-fetch";
|
||||
import { translateCode } from "@/lib/i18n/translate-code";
|
||||
|
||||
/**
|
||||
* Shared "Test connection" UX for the settings integrations + notifications
|
||||
@@ -151,13 +152,12 @@ export function TestConnectionButton({
|
||||
}
|
||||
|
||||
function describeError(errorCode: string): string {
|
||||
const key = `settings.testConnection.errors.${errorCode}`;
|
||||
const translated = t(key);
|
||||
// `t()` returns the raw key when missing — fall back to generic.
|
||||
if (translated === key) {
|
||||
return t("settings.testConnection.errors.generic");
|
||||
}
|
||||
return translated;
|
||||
return translateCode(
|
||||
t,
|
||||
"settings.testConnection.errors",
|
||||
errorCode,
|
||||
"settings.testConnection.errors.generic",
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -24,6 +24,7 @@ import { useTranslations } from "@/lib/i18n/context";
|
||||
import { queryKeys } from "@/lib/query-keys";
|
||||
import { apiFetchRaw, apiGet } from "@/lib/api/api-fetch";
|
||||
import type { WebhookPayloadFormat } from "@/lib/notifications/types";
|
||||
import { translateCodeOrNull } from "@/lib/i18n/translate-code";
|
||||
|
||||
interface WebhookSettings {
|
||||
enabled: boolean;
|
||||
@@ -89,13 +90,13 @@ export function WebhookCard({ isAuthenticated }: { isAuthenticated: boolean }) {
|
||||
};
|
||||
// A coded refusal (the private-origin policy) translates like the
|
||||
// test button's; anything else shows the server sentence.
|
||||
const code = json.meta?.errorCode;
|
||||
const key = code ? `settings.testConnection.errors.${code}` : null;
|
||||
const translated = key ? t(key) : null;
|
||||
throw new Error(
|
||||
translated && translated !== key
|
||||
? translated
|
||||
: json.error || t("common.error"),
|
||||
translateCodeOrNull(
|
||||
t,
|
||||
"settings.testConnection.errors",
|
||||
json.meta?.errorCode,
|
||||
) ??
|
||||
(json.error || t("common.error")),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user