fix(i18n): localize API error messages by code (no more raw English)

Error toasts surfaced the raw English backend message. Added an errors namespace (fa/ar/en) keyed by error code + a useApiError() resolver that maps ApiClientError.code to the localized message (fallback to a localized generic). Wired into menu, tables, demo banner, and subscription checkout; hardened getErrorMessage so it never returns the raw backend message.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-02 00:04:48 +03:30
parent 7519f474f3
commit 75d5bbc84a
9 changed files with 123 additions and 19 deletions
@@ -4,6 +4,7 @@ import { useEffect, useMemo, useState } from "react";
import { useSearchParams } from "next/navigation";
import { useQuery, useMutation } from "@tanstack/react-query";
import { useTranslations } from "next-intl";
import { useApiError } from "@/lib/use-api-error";
import { useRouter } from "@/i18n/routing";
import { ArrowRight, ArrowLeft, ShieldCheck } from "lucide-react";
import { apiGet, apiPost } from "@/lib/api/client";
@@ -34,6 +35,7 @@ export function CheckoutScreen() {
const t = useTranslations("subscription");
const tc = useTranslations("subscription.checkout");
const tPlans = useTranslations("settings.plans");
const apiError = useApiError();
const searchParams = useSearchParams();
const router = useRouter();
const user = useAuthStore((s) => s.user);
@@ -81,8 +83,7 @@ export function CheckoutScreen() {
window.location.href = data.paymentUrl;
},
onError: (err: unknown) => {
const msg = err instanceof Error ? err.message : String(err);
setPayError(msg || tc("paymentFailed"));
setPayError(apiError(err, tc("paymentFailed")));
},
});