translated component

This commit is contained in:
Max Peintner
2025-06-19 14:39:52 +02:00
parent 3cb8729f20
commit ef8931a17c
20 changed files with 85 additions and 89 deletions

View File

@@ -2,7 +2,7 @@
import { Boundary } from "@/components/boundary";
import { Button } from "@/components/button";
import { useTranslations } from "next-intl";
import { Translated } from "@/components/translated";
import { useEffect } from "react";
export default function Error({ error, reset }: any) {
@@ -10,8 +10,6 @@ export default function Error({ error, reset }: any) {
console.log("logging error:", error);
}, [error]);
const t = useTranslations("error");
return (
<Boundary labels={["Login Error"]} color="red">
<div className="space-y-4">
@@ -20,7 +18,7 @@ export default function Error({ error, reset }: any) {
</div>
<div>
<Button data-i18n-key="error.tryagain" onClick={() => reset()}>
{t("tryagain")}
<Translated i18nKey="tryagain" namespace="error" />
</Button>
</div>
</div>

View File

@@ -3,7 +3,7 @@
import { Boundary } from "@/components/boundary";
import { Button } from "@/components/button";
import { ThemeWrapper } from "@/components/theme-wrapper";
import { useTranslations } from "next-intl";
import { Translated } from "@/components/translated";
export default function GlobalError({
error,
@@ -12,8 +12,6 @@ export default function GlobalError({
error: Error & { digest?: string };
reset: () => void;
}) {
const t = useTranslations("error");
return (
// global-error must include html and body tags
<html>
@@ -26,7 +24,7 @@ export default function GlobalError({
</div>
<div>
<Button data-i18n-key="error.tryagain" onClick={() => reset()}>
{t("tryagain")}
<Translated i18nKey="tryagain" namespace="error" />
</Button>
</div>
</div>

View File

@@ -13,7 +13,6 @@ import {
import { create } from "@zitadel/client";
import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb";
import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { FieldValues, useForm } from "react-hook-form";
@@ -23,6 +22,7 @@ import { Button, ButtonVariants } from "./button";
import { TextInput } from "./input";
import { PasswordComplexity } from "./password-complexity";
import { Spinner } from "./spinner";
import { Translated } from "./translated";
type Inputs =
| {
@@ -46,7 +46,6 @@ export function ChangePasswordForm({
requestId,
organization,
}: Props) {
const t = useTranslations("password");
const router = useRouter();
const { register, handleSubmit, watch, formState } = useForm<Inputs>({
@@ -203,8 +202,8 @@ export function ChangePasswordForm({
onClick={handleSubmit(submitChange)}
data-testid="submit-button"
>
{loading && <Spinner className="h-5 w-5 mr-2" />}
{t("change.submit")}
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
<Translated i18nKey="change.submit" namespace="password" />
</Button>
</div>
</form>

View File

@@ -3,9 +3,9 @@ import {
PasskeysType,
} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
import { useTranslations } from "next-intl";
import { Alert, AlertType } from "./alert";
import { PASSKEYS, PASSWORD } from "./auth-methods";
import { Translated } from "./translated";
type Props = {
authMethods: AuthenticationMethodType[];
@@ -18,16 +18,23 @@ export function ChooseAuthenticatorToSetup({
params,
loginSettings,
}: Props) {
const t = useTranslations("authenticator");
if (authMethods.length !== 0) {
return <Alert type={AlertType.ALERT}>{t("allSetup")}</Alert>;
return (
<Alert type={AlertType.ALERT}>
<Translated i18nKey="allSetup" namespace="authenticator" />
</Alert>
);
} else {
return (
<>
{loginSettings.passkeysType == PasskeysType.NOT_ALLOWED &&
!loginSettings.allowUsernamePassword && (
<Alert type={AlertType.ALERT}>{t("noMethodsAvailable")}</Alert>
<Alert type={AlertType.ALERT}>
<Translated
i18nKey="noMethodsAvailable"
namespace="authenticator"
/>
</Alert>
)}
<div className="grid grid-cols-1 gap-5 w-full pt-4">

View File

@@ -6,9 +6,9 @@ import {
SecondFactorType,
} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation";
import { EMAIL, SMS, TOTP, U2F } from "./auth-methods";
import { Translated } from "./translated";
type Props = {
userId: string;
@@ -37,7 +37,6 @@ export function ChooseSecondFactorToSetup({
emailVerified,
force,
}: Props) {
const t = useTranslations("mfa");
const router = useRouter();
const params = new URLSearchParams({});
@@ -112,7 +111,7 @@ export function ChooseSecondFactorToSetup({
type="button"
data-testid="reset-button"
>
{t("set.skip")}
<Translated i18nKey="set.skip" namespace="mfa" />
</button>
)}
</>

View File

@@ -8,6 +8,7 @@ import { useState } from "react";
import { Alert } from "./alert";
import { Button, ButtonVariants } from "./button";
import { Spinner } from "./spinner";
import { Translated } from "./translated";
export function ConsentScreen({
scope,
@@ -50,7 +51,7 @@ export function ConsentScreen({
<ul className="list-disc space-y-2 w-full">
{scopes?.length === 0 && (
<span className="w-full text-sm flex flex-row items-center bg-background-light-400 dark:bg-background-dark-400 border border-divider-light py-2 px-4 rounded-md transition-all">
{t("device.scope.openid")}
<Translated i18nKey="device.scope.openid" namespace="device" />
</span>
)}
{scopes?.map((s) => {
@@ -91,7 +92,7 @@ export function ConsentScreen({
data-testid="deny-button"
>
{loading && <Spinner className="h-5 w-5 mr-2" />}
{t("device.request.deny")}
<Translated i18nKey="device.request.deny" namespace="device" />
</Button>
<span className="flex-grow"></span>
@@ -102,7 +103,7 @@ export function ConsentScreen({
className="self-end"
variant={ButtonVariants.Primary}
>
{t("device.request.submit")}
<Translated i18nKey="device.request.submit" namespace="device" />
</Button>
</Link>
</div>

View File

@@ -2,7 +2,6 @@
import { Alert } from "@/components/alert";
import { getDeviceAuthorizationRequest } from "@/lib/server/oidc";
import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { useForm } from "react-hook-form";
@@ -10,14 +9,13 @@ import { BackButton } from "./back-button";
import { Button, ButtonVariants } from "./button";
import { TextInput } from "./input";
import { Spinner } from "./spinner";
import { Translated } from "./translated";
type Inputs = {
userCode: string;
};
export function DeviceCodeForm({ userCode }: { userCode?: string }) {
const t = useTranslations("verify");
const router = useRouter();
const { register, handleSubmit, formState } = useForm<Inputs>({
@@ -87,8 +85,8 @@ export function DeviceCodeForm({ userCode }: { userCode?: string }) {
onClick={handleSubmit(submitCodeAndContinue)}
data-testid="submit-button"
>
{loading && <Spinner className="h-5 w-5 mr-2" />}
{t("verify.submit")}
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
<Translated i18nKey="verify.submit" namespace="verify" />
</Button>
</div>
</form>

View File

@@ -6,7 +6,6 @@ import { create } from "@zitadel/client";
import { RequestChallengesSchema } from "@zitadel/proto/zitadel/session/v2/challenge_pb";
import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation";
import { useEffect, useRef, useState } from "react";
import { useForm } from "react-hook-form";
@@ -15,6 +14,7 @@ import { BackButton } from "./back-button";
import { Button, ButtonVariants } from "./button";
import { TextInput } from "./input";
import { Spinner } from "./spinner";
import { Translated } from "./translated";
// either loginName or sessionId must be provided
type Props = {
@@ -42,8 +42,6 @@ export function LoginOTP({
code,
loginSettings,
}: Props) {
const t = useTranslations("otp");
const [error, setError] = useState<string>("");
const [loading, setLoading] = useState<boolean>(false);
@@ -223,7 +221,7 @@ export function LoginOTP({
<Alert type={AlertType.INFO}>
<div className="flex flex-row">
<span className="flex-1 mr-auto text-left">
{t("verify.noCodeReceived")}
<Translated i18nKey="verify.noCodeReceived" namespace="otp" />
</span>
<button
aria-label="Resend OTP Code"
@@ -243,7 +241,7 @@ export function LoginOTP({
}}
data-testid="resend-button"
>
{t("verify.resendCode")}
<Translated i18nKey="verify.resendCode" namespace="otp" />
</button>
</div>
</Alert>
@@ -277,8 +275,8 @@ export function LoginOTP({
})}
data-testid="submit-button"
>
{loading && <Spinner className="h-5 w-5 mr-2" />}
{t("verify.submit")}
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
<Translated i18nKey="verify.submit" namespace="otp" />
</Button>
</div>
</form>

View File

@@ -9,13 +9,13 @@ import {
UserVerificationRequirement,
} from "@zitadel/proto/zitadel/session/v2/challenge_pb";
import { Checks } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation";
import { useEffect, useRef, useState } from "react";
import { Alert } from "./alert";
import { BackButton } from "./back-button";
import { Button, ButtonVariants } from "./button";
import { Spinner } from "./spinner";
import { Translated } from "./translated";
// either loginName or sessionId must be provided
type Props = {
@@ -35,8 +35,6 @@ export function LoginPasskey({
organization,
login = true,
}: Props) {
const t = useTranslations("passkey");
const [error, setError] = useState<string>("");
const [loading, setLoading] = useState<boolean>(false);
@@ -234,7 +232,7 @@ export function LoginPasskey({
}}
data-testid="password-button"
>
{t("verify.usePassword")}
<Translated i18nKey="verify.usePassword" namespace="passkey" />
</Button>
) : (
<BackButton />
@@ -273,8 +271,8 @@ export function LoginPasskey({
}}
data-testid="submit-button"
>
{loading && <Spinner className="h-5 w-5 mr-2" />}
{t("verify.submit")}
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
<Translated i18nKey="verify.submit" namespace="passkey" />
</Button>
</div>
</div>

View File

@@ -4,7 +4,6 @@ import { resetPassword, sendPassword } from "@/lib/server/password";
import { create } from "@zitadel/client";
import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { useForm } from "react-hook-form";
@@ -13,6 +12,7 @@ import { BackButton } from "./back-button";
import { Button, ButtonVariants } from "./button";
import { TextInput } from "./input";
import { Spinner } from "./spinner";
import { Translated } from "./translated";
type Inputs = {
password: string;
@@ -35,8 +35,6 @@ export function PasswordForm({
promptPasswordless,
isAlternative,
}: Props) {
const t = useTranslations("password");
const { register, handleSubmit, formState } = useForm<Inputs>({
mode: "onBlur",
});
@@ -136,7 +134,7 @@ export function PasswordForm({
disabled={loading}
data-testid="reset-button"
>
{t("verify.resetPassword")}
<Translated i18nKey="verify.resetPassword" namespace="password" />
</button>
)}
@@ -173,8 +171,8 @@ export function PasswordForm({
onClick={handleSubmit(submitPassword)}
data-testid="submit-button"
>
{loading && <Spinner className="h-5 w-5 mr-2" />}
{t("verify.submit")}
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
<Translated i18nKey="verify.submit" namespace="password" />
</Button>
</div>
</form>

View File

@@ -1,9 +1,9 @@
"use client";
import { LegalAndSupportSettings } from "@zitadel/proto/zitadel/settings/v2/legal_settings_pb";
import { useTranslations } from "next-intl";
import Link from "next/link";
import { useState } from "react";
import { Checkbox } from "./checkbox";
import { Translated } from "./translated";
type Props = {
legal: LegalAndSupportSettings;
@@ -16,7 +16,6 @@ type AcceptanceState = {
};
export function PrivacyPolicyCheckboxes({ legal, onChange }: Props) {
const t = useTranslations("register");
const [acceptanceState, setAcceptanceState] = useState<AcceptanceState>({
tosAccepted: false,
privacyPolicyAccepted: false,
@@ -25,7 +24,7 @@ export function PrivacyPolicyCheckboxes({ legal, onChange }: Props) {
return (
<>
<p className="flex flex-row items-center text-text-light-secondary-500 dark:text-text-dark-secondary-500 mt-4 text-sm">
{t("agreeTo")}
<Translated i18nKey="agreeTo" namespace="register" />
{legal?.helpLink && (
<span>
<Link href={legal.helpLink} target="_blank">
@@ -66,7 +65,7 @@ export function PrivacyPolicyCheckboxes({ legal, onChange }: Props) {
<div className="mr-4 w-[28rem]">
<p className="text-sm text-text-light-500 dark:text-text-dark-500">
<Link href={legal.tosLink} className="underline" target="_blank">
{t("termsOfService")}
<Translated i18nKey="termsOfService" namespace="register" />
</Link>
</p>
</div>
@@ -95,7 +94,7 @@ export function PrivacyPolicyCheckboxes({ legal, onChange }: Props) {
className="underline"
target="_blank"
>
{t("privacyPolicy")}
<Translated i18nKey="privacyPolicy" namespace="register" />
</Link>
</p>
</div>

View File

@@ -1,7 +1,6 @@
"use client";
import { registerUserAndLinkToIDP } from "@/lib/server/register";
import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { FieldValues, useForm } from "react-hook-form";
@@ -10,6 +9,7 @@ import { BackButton } from "./back-button";
import { Button, ButtonVariants } from "./button";
import { TextInput } from "./input";
import { Spinner } from "./spinner";
import { Translated } from "./translated";
type Inputs =
| {
@@ -45,8 +45,6 @@ export function RegisterFormIDPIncomplete({
idpId,
idpUserName,
}: Props) {
const t = useTranslations("register");
const { register, handleSubmit, formState } = useForm<Inputs>({
mode: "onBlur",
defaultValues: {
@@ -149,8 +147,8 @@ export function RegisterFormIDPIncomplete({
onClick={handleSubmit(submitAndRegister)}
data-testid="submit-button"
>
{loading && <Spinner className="h-5 w-5 mr-2" />}
{t("submit")}
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
<Translated i18nKey="submit" namespace="register" />
</Button>
</div>
</form>

View File

@@ -6,7 +6,6 @@ import {
LoginSettings,
PasskeysType,
} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { FieldValues, useForm } from "react-hook-form";
@@ -21,6 +20,7 @@ import { Button, ButtonVariants } from "./button";
import { TextInput } from "./input";
import { PrivacyPolicyCheckboxes } from "./privacy-policy-checkboxes";
import { Spinner } from "./spinner";
import { Translated } from "./translated";
type Inputs =
| {
@@ -51,8 +51,6 @@ export function RegisterForm({
loginSettings,
idpCount = 0,
}: Props) {
const t = useTranslations("register");
const { register, handleSubmit, formState } = useForm<Inputs>({
mode: "onBlur",
defaultValues: {
@@ -173,7 +171,7 @@ export function RegisterForm({
loginSettings.passkeysType == PasskeysType.ALLOWED && (
<>
<p className="mt-4 ztdl-p mb-6 block text-left">
{t("selectMethod")}
<Translated i18nKey="selectMethod" namespace="register" />
</p>
<div className="pb-4">
@@ -184,12 +182,16 @@ export function RegisterForm({
</div>
</>
)}
{!loginSettings?.allowUsernamePassword &&
loginSettings?.passkeysType != PasskeysType.ALLOWED &&
loginSettings?.passkeysType !== PasskeysType.ALLOWED &&
(!loginSettings?.allowExternalIdp || !idpCount) && (
<div className="py-4">
<Alert type={AlertType.INFO}>{t("noMethodAvailableWarning")}</Alert>
<Alert type={AlertType.INFO}>
<Translated
i18nKey="noMethodAvailableWarning"
namespace="register"
/>
</Alert>
</div>
)}
@@ -217,7 +219,7 @@ export function RegisterForm({
data-testid="submit-button"
>
{loading && <Spinner className="h-5 w-5 mr-2" />}
{t("submit")}
<Translated i18nKey="submit" namespace="register" />
</Button>
</div>
</form>

View File

@@ -5,7 +5,6 @@ import {
registerPasskeyLink,
verifyPasskeyRegistration,
} from "@/lib/server/passkeys";
import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { useForm } from "react-hook-form";
@@ -13,6 +12,7 @@ import { Alert } from "./alert";
import { BackButton } from "./back-button";
import { Button, ButtonVariants } from "./button";
import { Spinner } from "./spinner";
import { Translated } from "./translated";
type Inputs = {};
@@ -29,8 +29,6 @@ export function RegisterPasskey({
organization,
requestId,
}: Props) {
const t = useTranslations("passkey");
const { handleSubmit, formState } = useForm<Inputs>({
mode: "onBlur",
});
@@ -198,7 +196,7 @@ export function RegisterPasskey({
continueAndLogin();
}}
>
{t("set.skip")}
<Translated i18nKey="set.skip" namespace="passkey" />
</Button>
) : (
<BackButton />
@@ -213,8 +211,8 @@ export function RegisterPasskey({
onClick={handleSubmit(submitRegisterAndContinue)}
data-testid="submit-button"
>
{loading && <Spinner className="h-5 w-5 mr-2" />}
{t("set.submit")}
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
<Translated i18nKey="set.submit" namespace="passkey" />
</Button>
</div>
</form>

View File

@@ -5,13 +5,13 @@ import { getNextUrl } from "@/lib/client";
import { addU2F, verifyU2F } from "@/lib/server/u2f";
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
import { RegisterU2FResponse } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { Alert } from "./alert";
import { BackButton } from "./back-button";
import { Button, ButtonVariants } from "./button";
import { Spinner } from "./spinner";
import { Translated } from "./translated";
type Props = {
loginName?: string;
@@ -30,8 +30,6 @@ export function RegisterU2f({
checkAfter,
loginSettings,
}: Props) {
const t = useTranslations("u2f");
const [error, setError] = useState<string>("");
const [loading, setLoading] = useState<boolean>(false);
@@ -218,8 +216,8 @@ export function RegisterU2f({
onClick={submitRegisterAndContinue}
data-testid="submit-button"
>
{loading && <Spinner className="h-5 w-5 mr-2" />}
{t("set.submit")}
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
<Translated i18nKey="set.submit" namespace="u2f" />
</Button>
</div>
</form>

View File

@@ -9,6 +9,7 @@ import { useRouter } from "next/navigation";
import { useState } from "react";
import { Avatar } from "./avatar";
import { isSessionValid } from "./session-item";
import { Translated } from "./translated";
export function SessionClearItem({
session,
@@ -89,7 +90,7 @@ export function SessionClearItem({
<span className="flex-grow"></span>
<div className="relative flex flex-row items-center">
<div className="mr-6 px-2 py-[2px] text-xs hidden group-hover:block transition-all text-warn-light-500 dark:text-warn-dark-500 bg-[#ff0000]/10 dark:bg-[#ff0000]/10 rounded-full flex items-center justify-center">
{t("clear")}
<Translated i18nKey="clear" namespace="logout" />
</div>
{valid ? (

View File

@@ -3,11 +3,11 @@
import { clearSession } from "@/lib/server/session";
import { timestampDate } from "@zitadel/client";
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
import { useTranslations } from "next-intl";
import { redirect, useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import { Alert, AlertType } from "./alert";
import { SessionClearItem } from "./session-clear-item";
import { Translated } from "./translated";
type Props = {
sessions: Session[];
@@ -22,7 +22,6 @@ export function SessionsClearList({
postLogoutRedirectUri,
organization,
}: Props) {
const t = useTranslations("logout");
const [list, setList] = useState<Session[]>(sessions);
const router = useRouter();
@@ -97,10 +96,14 @@ export function SessionsClearList({
);
})}
{list.length === 0 && (
<Alert type={AlertType.INFO}>{t("noResults")}</Alert>
<Alert type={AlertType.INFO}>
<Translated i18nKey="noResults" namespace="logout" />
</Alert>
)}
</div>
) : (
<Alert>{t("noResults")}</Alert>
<Alert>
<Translated i18nKey="noResults" namespace="logout" />
</Alert>
);
}

View File

@@ -2,10 +2,10 @@
import { timestampDate } from "@zitadel/client";
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
import { useTranslations } from "next-intl";
import { useState } from "react";
import { Alert } from "./alert";
import { SessionItem } from "./session-item";
import { Translated } from "./translated";
type Props = {
sessions: Session[];
@@ -13,7 +13,6 @@ type Props = {
};
export function SessionsList({ sessions, requestId }: Props) {
const t = useTranslations("accounts");
const [list, setList] = useState<Session[]>(sessions);
return sessions ? (
<div className="flex flex-col space-y-2">
@@ -44,6 +43,8 @@ export function SessionsList({ sessions, requestId }: Props) {
})}
</div>
) : (
<Alert>{t("noResults")}</Alert>
<Alert>
<Translated i18nKey="noResults" namespace="accounts" />
</Alert>
);
}

View File

@@ -24,6 +24,7 @@ import { Button, ButtonVariants } from "./button";
import { TextInput } from "./input";
import { PasswordComplexity } from "./password-complexity";
import { Spinner } from "./spinner";
import { Translated } from "./translated";
type Inputs =
| {
@@ -207,7 +208,7 @@ export function SetPasswordForm({
}}
data-testid="resend-button"
>
{t("set.resend")}
<Translated i18nKey="set.resend" namespace="password" />
</button>
</div>
</Alert>
@@ -279,8 +280,8 @@ export function SetPasswordForm({
onClick={handleSubmit(submitPassword)}
data-testid="submit-button"
>
{loading && <Spinner className="h-5 w-5 mr-2" />}
{t("set.submit")}
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
<Translated i18nKey="set.submit" namespace="password" />
</Button>
</div>
</form>

View File

@@ -18,6 +18,7 @@ import { Button, ButtonVariants } from "./button";
import { TextInput } from "./input";
import { PasswordComplexity } from "./password-complexity";
import { Spinner } from "./spinner";
import { Translated } from "./translated";
type Inputs =
| {
@@ -163,8 +164,8 @@ export function SetRegisterPasswordForm({
onClick={handleSubmit(submitRegister)}
data-testid="submit-button"
>
{loading && <Spinner className="h-5 w-5 mr-2" />}
{t("password.submit")}
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
<Translated i18nKey="password.submit" namespace="register" />
</Button>
</div>
</form>