diff --git a/apps/login/src/app/(login)/authenticator/set/page.tsx b/apps/login/src/app/(login)/authenticator/set/page.tsx index 95b89af92d..25917715a8 100644 --- a/apps/login/src/app/(login)/authenticator/set/page.tsx +++ b/apps/login/src/app/(login)/authenticator/set/page.tsx @@ -3,6 +3,7 @@ import { BackButton } from "@/components/back-button"; import { ChooseAuthenticatorToSetup } from "@/components/choose-authenticator-to-setup"; import { DynamicTheme } from "@/components/dynamic-theme"; import { SignInWithIdp } from "@/components/sign-in-with-idp"; +import { Translated } from "@/components/translated"; import { UserAvatar } from "@/components/user-avatar"; import { getSessionCookieById } from "@/lib/cookies"; import { getServiceUrlFromHeaders } from "@/lib/service-url"; @@ -27,7 +28,6 @@ export default async function Page(props: { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "authenticator" }); - const tError = await getTranslations({ locale, namespace: "error" }); const { loginName, requestId, organization, sessionId } = searchParams; @@ -99,7 +99,11 @@ export default async function Page(props: { !sessionWithData.factors || !sessionWithData.factors.user ) { - return {tError("unknownContext")}; + return ( + + + + ); } const branding = await getBrandingSettings({ diff --git a/apps/login/src/app/(login)/error.tsx b/apps/login/src/app/(login)/error.tsx index bee6516a59..37e7c5003d 100644 --- a/apps/login/src/app/(login)/error.tsx +++ b/apps/login/src/app/(login)/error.tsx @@ -19,7 +19,9 @@ export default function Error({ error, reset }: any) { Error: {error?.message}
- +
diff --git a/apps/login/src/app/(login)/loginname/page.tsx b/apps/login/src/app/(login)/loginname/page.tsx index adb6ec0eef..859fbae085 100644 --- a/apps/login/src/app/(login)/loginname/page.tsx +++ b/apps/login/src/app/(login)/loginname/page.tsx @@ -1,5 +1,6 @@ import { DynamicTheme } from "@/components/dynamic-theme"; import { SignInWithIdp } from "@/components/sign-in-with-idp"; +import { Translated } from "@/components/translated"; import { UsernameForm } from "@/components/username-form"; import { getServiceUrlFromHeaders } from "@/lib/service-url"; import { @@ -9,15 +10,12 @@ import { getLoginSettings, } from "@/lib/zitadel"; import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb"; -import { getLocale, getTranslations } from "next-intl/server"; import { headers } from "next/headers"; export default async function Page(props: { searchParams: Promise>; }) { const searchParams = await props.searchParams; - const locale = getLocale(); - const t = await getTranslations({ locale, namespace: "loginname" }); const loginName = searchParams?.loginName; const requestId = searchParams?.requestId; @@ -63,8 +61,12 @@ export default async function Page(props: { return (
-

{t("title")}

-

{t("description")}

+

+ +

+

+ +

)} - {!(loginName || sessionId) && {tError("unknownContext")}} + {!(loginName || sessionId) && ( + + + + )} {sessionFactors ? ( )} - {!(loginName || sessionId) && {tError("unknownContext")}} + {!(loginName || sessionId) && ( + + + + )} - {!valid && {tError("sessionExpired")}} + {!valid && ( + + + + )} {isSessionValid(sessionWithData).valid && loginSettings && diff --git a/apps/login/src/app/(login)/otp/[method]/page.tsx b/apps/login/src/app/(login)/otp/[method]/page.tsx index ee58420c42..08007c1819 100644 --- a/apps/login/src/app/(login)/otp/[method]/page.tsx +++ b/apps/login/src/app/(login)/otp/[method]/page.tsx @@ -1,6 +1,7 @@ import { Alert } from "@/components/alert"; import { DynamicTheme } from "@/components/dynamic-theme"; import { LoginOTP } from "@/components/login-otp"; +import { Translated } from "@/components/translated"; import { UserAvatar } from "@/components/user-avatar"; import { getSessionCookieById } from "@/lib/cookies"; import { getServiceUrlFromHeaders } from "@/lib/service-url"; @@ -21,7 +22,6 @@ export default async function Page(props: { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "otp" }); - const tError = await getTranslations({ locale, namespace: "error" }); const _headers = await headers(); const { serviceUrl } = getServiceUrlFromHeaders(_headers); @@ -94,7 +94,9 @@ export default async function Page(props: { {!session && (
- {tError("unknownContext")} + + +
)} diff --git a/apps/login/src/app/(login)/otp/[method]/set/page.tsx b/apps/login/src/app/(login)/otp/[method]/set/page.tsx index d3fc4c89f7..79aa8c4786 100644 --- a/apps/login/src/app/(login)/otp/[method]/set/page.tsx +++ b/apps/login/src/app/(login)/otp/[method]/set/page.tsx @@ -3,6 +3,7 @@ import { BackButton } from "@/components/back-button"; import { Button, ButtonVariants } from "@/components/button"; import { DynamicTheme } from "@/components/dynamic-theme"; import { TotpRegister } from "@/components/totp-register"; +import { Translated } from "@/components/translated"; import { UserAvatar } from "@/components/user-avatar"; import { getServiceUrlFromHeaders } from "@/lib/service-url"; import { loadMostRecentSession } from "@/lib/session"; @@ -27,7 +28,6 @@ export default async function Page(props: { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "otp" }); - const tError = await getTranslations({ locale, namespace: "error" }); const { loginName, organization, sessionId, requestId, checkAfter } = searchParams; @@ -131,7 +131,9 @@ export default async function Page(props: {

{t("set.title")}

{!session && (
- {tError("unknownContext")} + + +
)} diff --git a/apps/login/src/app/(login)/passkey/page.tsx b/apps/login/src/app/(login)/passkey/page.tsx index e24585e7e0..b6b199bec8 100644 --- a/apps/login/src/app/(login)/passkey/page.tsx +++ b/apps/login/src/app/(login)/passkey/page.tsx @@ -1,6 +1,7 @@ import { Alert } from "@/components/alert"; import { DynamicTheme } from "@/components/dynamic-theme"; import { LoginPasskey } from "@/components/login-passkey"; +import { Translated } from "@/components/translated"; import { UserAvatar } from "@/components/user-avatar"; import { getSessionCookieById } from "@/lib/cookies"; import { getServiceUrlFromHeaders } from "@/lib/service-url"; @@ -15,7 +16,6 @@ export default async function Page(props: { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "passkey" }); - const tError = await getTranslations({ locale, namespace: "error" }); const { loginName, altPassword, requestId, organization, sessionId } = searchParams; @@ -67,7 +67,11 @@ export default async function Page(props: { )}

{t("verify.description")}

- {!(loginName || sessionId) && {tError("unknownContext")}} + {!(loginName || sessionId) && ( + + + + )} {(loginName || sessionId) && ( - {tError("unknownContext")} + + +
)} diff --git a/apps/login/src/app/(login)/password/change/page.tsx b/apps/login/src/app/(login)/password/change/page.tsx index 05f8cd6a10..723591e4f6 100644 --- a/apps/login/src/app/(login)/password/change/page.tsx +++ b/apps/login/src/app/(login)/password/change/page.tsx @@ -1,6 +1,7 @@ import { Alert } from "@/components/alert"; import { ChangePasswordForm } from "@/components/change-password-form"; import { DynamicTheme } from "@/components/dynamic-theme"; +import { Translated } from "@/components/translated"; import { UserAvatar } from "@/components/user-avatar"; import { getServiceUrlFromHeaders } from "@/lib/service-url"; import { loadMostRecentSession } from "@/lib/session"; @@ -21,7 +22,6 @@ export default async function Page(props: { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "password" }); - const tError = await getTranslations({ locale, namespace: "error" }); const { loginName, organization, requestId } = searchParams; @@ -61,7 +61,9 @@ export default async function Page(props: { {(!sessionFactors || !loginName) && !loginSettings?.ignoreUnknownUsernames && (
- {tError("unknownContext")} + + +
)} @@ -86,7 +88,9 @@ export default async function Page(props: { /> ) : (
- {tError("failedLoading")} + + +
)} diff --git a/apps/login/src/app/(login)/password/page.tsx b/apps/login/src/app/(login)/password/page.tsx index 506454a275..56b0ee4473 100644 --- a/apps/login/src/app/(login)/password/page.tsx +++ b/apps/login/src/app/(login)/password/page.tsx @@ -1,6 +1,7 @@ import { Alert } from "@/components/alert"; import { DynamicTheme } from "@/components/dynamic-theme"; import { PasswordForm } from "@/components/password-form"; +import { Translated } from "@/components/translated"; import { UserAvatar } from "@/components/user-avatar"; import { getServiceUrlFromHeaders } from "@/lib/service-url"; import { loadMostRecentSession } from "@/lib/session"; @@ -11,17 +12,12 @@ import { } from "@/lib/zitadel"; import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb"; import { PasskeysType } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb"; -import { getLocale, getTranslations } from "next-intl/server"; import { headers } from "next/headers"; export default async function Page(props: { searchParams: Promise>; }) { const searchParams = await props.searchParams; - const locale = getLocale(); - const t = await getTranslations({ locale, namespace: "password" }); - const tError = await getTranslations({ locale, namespace: "error" }); - let { loginName, organization, requestId, alt } = searchParams; const _headers = await headers(); @@ -66,15 +62,21 @@ export default async function Page(props: {

- {sessionFactors?.factors?.user?.displayName ?? t("verify.title")} + {sessionFactors?.factors?.user?.displayName ?? ( + + )}

-

{t("verify.description")}

+

+ +

{/* show error only if usernames should be shown to be unknown */} {(!sessionFactors || !loginName) && !loginSettings?.ignoreUnknownUsernames && (
- {tError("unknownContext")} + + +
)} diff --git a/apps/login/src/app/(login)/password/set/page.tsx b/apps/login/src/app/(login)/password/set/page.tsx index 26e065438c..ed461b748c 100644 --- a/apps/login/src/app/(login)/password/set/page.tsx +++ b/apps/login/src/app/(login)/password/set/page.tsx @@ -1,6 +1,7 @@ import { Alert, AlertType } from "@/components/alert"; import { DynamicTheme } from "@/components/dynamic-theme"; import { SetPasswordForm } from "@/components/set-password-form"; +import { Translated } from "@/components/translated"; import { UserAvatar } from "@/components/user-avatar"; import { getServiceUrlFromHeaders } from "@/lib/service-url"; import { loadMostRecentSession } from "@/lib/session"; @@ -21,7 +22,6 @@ export default async function Page(props: { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "password" }); - const tError = await getTranslations({ locale, namespace: "error" }); const { userId, loginName, organization, requestId, code, initial } = searchParams; @@ -79,7 +79,9 @@ export default async function Page(props: { {/* show error only if usernames should be shown to be unknown */} {loginName && !session && !loginSettings?.ignoreUnknownUsernames && (
- {tError("unknownContext")} + + +
)} @@ -115,7 +117,9 @@ export default async function Page(props: { /> ) : (
- {tError("failedLoading")} + + +
)}
diff --git a/apps/login/src/app/(login)/register/page.tsx b/apps/login/src/app/(login)/register/page.tsx index be872b4dc7..543814072f 100644 --- a/apps/login/src/app/(login)/register/page.tsx +++ b/apps/login/src/app/(login)/register/page.tsx @@ -2,6 +2,7 @@ import { Alert } from "@/components/alert"; import { DynamicTheme } from "@/components/dynamic-theme"; import { RegisterForm } from "@/components/register-form"; import { SignInWithIdp } from "@/components/sign-in-with-idp"; +import { Translated } from "@/components/translated"; import { getServiceUrlFromHeaders } from "@/lib/service-url"; import { getActiveIdentityProviders, @@ -22,7 +23,6 @@ export default async function Page(props: { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "register" }); - const tError = await getTranslations({ locale, namespace: "error" }); let { firstname, lastname, email, organization, requestId } = searchParams; @@ -83,7 +83,11 @@ export default async function Page(props: {

{t("title")}

{t("description")}

- {!organization && {tError("unknownContext")}} + {!organization && ( + + + + )} {legal && passwordComplexitySettings && diff --git a/apps/login/src/app/(login)/u2f/page.tsx b/apps/login/src/app/(login)/u2f/page.tsx index b16dc88f4b..bac94b2ecc 100644 --- a/apps/login/src/app/(login)/u2f/page.tsx +++ b/apps/login/src/app/(login)/u2f/page.tsx @@ -1,6 +1,7 @@ import { Alert } from "@/components/alert"; import { DynamicTheme } from "@/components/dynamic-theme"; import { LoginPasskey } from "@/components/login-passkey"; +import { Translated } from "@/components/translated"; import { UserAvatar } from "@/components/user-avatar"; import { getSessionCookieById } from "@/lib/cookies"; import { getServiceUrlFromHeaders } from "@/lib/service-url"; @@ -15,7 +16,6 @@ export default async function Page(props: { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "u2f" }); - const tError = await getTranslations({ locale, namespace: "error" }); const { loginName, requestId, sessionId, organization } = searchParams; @@ -71,7 +71,11 @@ export default async function Page(props: { )}

{t("verify.description")}

- {!(loginName || sessionId) && {tError("unknownContext")}} + {!(loginName || sessionId) && ( + + + + )} {(loginName || sessionId) && ( - {tError("unknownContext")} + + + )} diff --git a/apps/login/src/app/(login)/verify/page.tsx b/apps/login/src/app/(login)/verify/page.tsx index 7634ff063a..17f9712401 100644 --- a/apps/login/src/app/(login)/verify/page.tsx +++ b/apps/login/src/app/(login)/verify/page.tsx @@ -1,5 +1,6 @@ import { Alert, AlertType } from "@/components/alert"; import { DynamicTheme } from "@/components/dynamic-theme"; +import { Translated } from "@/components/translated"; import { UserAvatar } from "@/components/user-avatar"; import { VerifyForm } from "@/components/verify-form"; import { sendEmailCode, sendInviteEmailCode } from "@/lib/server/verify"; @@ -14,7 +15,6 @@ export default async function Page(props: { searchParams: Promise }) { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "verify" }); - const tError = await getTranslations({ locale, namespace: "error" }); const { userId, loginName, code, organization, requestId, invite, send } = searchParams; @@ -130,7 +130,9 @@ export default async function Page(props: { searchParams: Promise }) {

{t("verify.description")}

- {tError("unknownContext")} + + +
)} diff --git a/apps/login/src/app/global-error.tsx b/apps/login/src/app/global-error.tsx index 0fea5d0117..32a8ce824f 100644 --- a/apps/login/src/app/global-error.tsx +++ b/apps/login/src/app/global-error.tsx @@ -25,7 +25,9 @@ export default function GlobalError({ Error: {error?.message}
- +
diff --git a/apps/login/src/components/translated.tsx b/apps/login/src/components/translated.tsx new file mode 100644 index 0000000000..172c5b7af0 --- /dev/null +++ b/apps/login/src/components/translated.tsx @@ -0,0 +1,20 @@ +import { useTranslations } from "next-intl"; + +export function Translated({ + i18nKey, + children, + namespace, + ...props +}: { + i18nKey: string; + children?: React.ReactNode; + namespace?: string; +} & React.HTMLAttributes) { + const t = useTranslations(namespace); + + return ( + + {t(i18nKey)} + + ); +}