fix(i18n): preserve public auth commands and feedback across language changes

This commit is contained in:
cesnimda
2026-11-04 01:44:39 +01:00
parent 368e90d572
commit fa6bd5d98e
20 changed files with 343 additions and 58 deletions
@@ -7,18 +7,20 @@ import { useNavigate } from "react-router-dom";
import { api, getApiErrorMessage } from "../api";
import { useToast } from "../toast";
import { useI18n } from "../i18n/I18nProvider";
import type { TranslationKey } from "../i18n/translations";
import AuthPageFrame from "../layout/AuthPageFrame";
export default function ForgotPasswordPage() {
const { toast } = useToast();
const { t } = useI18n();
const currentTranslation = useRef(t); currentTranslation.current = t;
const navigate = useNavigate();
const [email, setEmail] = useState("");
const [loading, setLoading] = useState(false);
const [submitted, setSubmitted] = useState(false);
const [emailError, setEmailError] = useState<string | undefined>(undefined);
const [submitError, setSubmitError] = useState<string | null>(null);
const [emailError, setEmailError] = useState<TranslationKey | undefined>(undefined);
const [submitError, setSubmitError] = useState<{ cause: unknown } | null>(null);
const emailRef = useRef<HTMLInputElement>(null);
const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
@@ -35,12 +37,12 @@ export default function ForgotPasswordPage() {
e.preventDefault();
const trimmed = email.trim();
if (!trimmed) {
setEmailError(t("emailRequired"));
setEmailError("emailRequired");
emailRef.current?.focus();
return;
}
if (!EMAIL_PATTERN.test(trimmed)) {
setEmailError(t("invalidEmail"));
setEmailError("invalidEmail");
emailRef.current?.focus();
return;
}
@@ -52,17 +54,17 @@ export default function ForgotPasswordPage() {
.post("/auth/request-password-reset", { email: email.trim() })
.then(() => {
setSubmitted(true);
toast(t("passwordResetRequestSent"), "success");
toast(currentTranslation.current("passwordResetRequestSent"), "success");
})
.catch((error: any) => {
setSubmitError(getApiErrorMessage(error, t("passwordResetRequestFailed")));
setSubmitError({ cause: error });
})
.finally(() => setLoading(false));
}}
sx={{ display: "flex", flexDirection: "column", gap: 1.5 }}
>
{submitted ? <Alert severity="success" role="status">{t("passwordResetRequestSent")}</Alert> : null}
{submitError ? <Alert severity="error">{submitError}</Alert> : null}
{submitError ? <Alert severity="error">{getApiErrorMessage(submitError.cause, t("passwordResetRequestFailed"))}</Alert> : null}
<TextField
label={t("profileEmail")}
type="email"
@@ -72,7 +74,7 @@ export default function ForgotPasswordPage() {
autoFocus
inputRef={emailRef}
error={Boolean(emailError)}
helperText={emailError}
helperText={emailError ? t(emailError) : undefined}
fullWidth
/>