diff --git a/apps/login/locales/de.json b/apps/login/locales/de.json index 55a635512..834325f07 100644 --- a/apps/login/locales/de.json +++ b/apps/login/locales/de.json @@ -35,6 +35,29 @@ }, "required": { "loginName": "Dieses Feld ist erforderlich" + }, + "errors": { + "internalError": "Ein interner Fehler ist aufgetreten", + "couldNotGetLoginSettings": "Anmeldeeinstellungen konnten nicht abgerufen werden", + "couldNotSearchUsers": "Benutzer konnten nicht durchsucht werden", + "couldNotGetDomain": "Domain konnte nicht abgerufen werden", + "couldNotGetHost": "Host konnte nicht abgerufen werden", + "couldNotStartIDPFlow": "IDP-Ablauf konnte nicht gestartet werden", + "moreThanOneUserFound": "Mehr als ein Benutzer gefunden. Bitte geben Sie einen eindeutigen Identifikator an.", + "userNotFound": "Benutzer im System nicht gefunden", + "couldNotCreateSession": "Sitzung für Benutzer konnte nicht erstellt werden", + "initialUserNotSupported": "Initialer Benutzer wird nicht unterstützt", + "usernamePasswordNotAllowed": "Benutzername und Passwort nicht zulässig! Wenden Sie sich für weitere Informationen an Ihren Administrator.", + "passkeysNotAllowed": "Passkeys nicht zulässig! Wenden Sie sich für weitere Informationen an Ihren Administrator.", + "couldNotFindIdentityProvider": "Identitätsanbieter konnte nicht gefunden werden.", + "userNotActive": "Das Benutzerkonto ist inaktiv. Wenden Sie sich für weitere Informationen an Ihren Administrator." + } + }, + "zitadel": { + "errors": { + "errorOccured": "Ein Fehler ist aufgetreten", + "multipleUsersFound": "Mehrere Benutzer gefunden", + "userNotFound": "Benutzer im System nicht gefunden" } }, "password": { @@ -48,6 +71,13 @@ }, "required": { "password": "Dieses Feld ist erforderlich" + }, + "errors": { + "couldNotVerifyPassword": "Passwort konnte nicht verifiziert werden", + "couldNotResetPassword": "Passwort konnte nicht zurückgesetzt werden" + }, + "info": { + "passwordResetSent": "Passwort wurde zurückgesetzt. Bitte prüfen Sie Ihre E-Mails" } }, "set": { @@ -66,6 +96,11 @@ "code": "Dieses Feld ist erforderlich", "newPassword": "Bitte geben Sie ein Passwort ein!", "confirmPassword": "Dieses Feld ist erforderlich" + }, + "errors": { + "couldNotSetPassword": "Passwort konnte nicht gesetzt werden", + "couldNotResetPassword": "Passwort konnte nicht zurückgesetzt werden", + "couldNotVerifyPassword": "Passwort konnte nicht verifiziert werden" } }, "change": { @@ -79,7 +114,40 @@ "required": { "newPassword": "Bitte geben Sie ein neues Passwort ein!", "confirmPassword": "Dieses Feld ist erforderlich" + }, + "errors": { + "couldNotChangePassword": "Passwort konnte nicht geändert werden", + "couldNotVerifyPassword": "Passwort konnte nicht verifiziert werden", + "unknownError": "Unbekannter Fehler" } + }, + "complexity": { + "length": "Muss mindestens {minLength} Zeichen lang sein.", + "hasSymbol": "Muss ein Symbol enthalten.", + "hasNumber": "Muss eine Zahl enthalten.", + "hasUppercase": "Muss einen Großbuchstaben enthalten.", + "hasLowercase": "Muss einen Kleinbuchstaben enthalten.", + "equals": "Passwortbestätigung stimmt überein.", + "matches": "Stimmt überein", + "doesNotMatch": "Stimmt nicht überein" + }, + "errors": { + "noHostFound": "Kein Host gefunden", + "couldNotSendResetLink": "Passwort-Zurücksetzungslink konnte nicht gesendet werden", + "couldNotCreateSessionForUser": "Sitzung für Benutzer konnte nicht erstellt werden", + "couldNotVerifyPassword": "Passwort konnte nicht verifiziert werden", + "failedToAuthenticate": "Authentifizierung fehlgeschlagen. Sie haben {failedAttempts} von {maxPasswordAttempts} Passwortversuchen.{lockoutMessage}", + "failedToAuthenticateNoLimit": "Authentifizierung fehlgeschlagen.", + "accountLockedContactAdmin": " Kontaktieren Sie Ihren Administrator, um Ihr Konto zu entsperren", + "userNotFound": "Benutzer nicht im System gefunden", + "initialUserNotSupported": "Initialbenutzer wird nicht unterstützt", + "userInitialStateNotSupported": "Anfangszustand des Benutzers wird nicht unterstützt", + "codeOrVerificationRequired": "Sie müssen einen Code angeben oder eine gültige Benutzerverifizierung durchführen", + "verificationRequired": "Die Benutzerverifizierung muss durchgeführt werden", + "couldNotLoadSession": "Sitzung konnte nicht geladen werden", + "couldNotLoadAuthMethods": "Authentifizierungsmethoden konnten nicht geladen werden", + "failedPrecondition": "Vorbedingung fehlgeschlagen", + "sessionNotValid": "Sitzung ist nicht gültig" } }, "idp": { @@ -244,6 +312,13 @@ "firstname": "Dieses Feld ist erforderlich", "lastname": "Dieses Feld ist erforderlich", "email": "Dieses Feld ist erforderlich" + }, + "errors": { + "couldNotCreateUser": "Benutzer konnte nicht erstellt werden", + "couldNotCreateSession": "Sitzung konnte nicht erstellt werden", + "userNotFound": "Benutzer nicht im System gefunden", + "couldNotLinkIDP": "IDP konnte nicht mit dem Benutzer verknüpft werden", + "couldNotRegisterUser": "Benutzer konnte nicht registriert werden" } }, "invite": { @@ -287,6 +362,19 @@ "required": { "code": "Dieses Feld ist erforderlich" } + }, + "errors": { + "couldNotResendEmail": "E-Mail konnte nicht erneut gesendet werden", + "couldNotVerifyUser": "Benutzer konnte nicht verifiziert werden", + "couldNotVerifyInvite": "Einladung konnte nicht verifiziert werden", + "couldNotVerifyEmail": "E-Mail konnte nicht verifiziert werden", + "couldNotVerify": "Konnte nicht verifizieren", + "couldNotLoadUser": "Benutzer konnte nicht geladen werden", + "couldNotLoadAuthenticators": "Mögliche Authentifikatoren konnten nicht geladen werden", + "couldNotCreateSession": "Sitzung konnte nicht erstellt werden", + "noHostFound": "Kein Host gefunden", + "userAlreadyVerified": "Benutzer ist bereits verifiziert!", + "couldNotResendInvite": "Einladung konnte nicht erneut gesendet werden" } }, "authenticator": { diff --git a/apps/login/locales/en.json b/apps/login/locales/en.json index 8d8c11ec3..3a2ebcbee 100644 --- a/apps/login/locales/en.json +++ b/apps/login/locales/en.json @@ -35,6 +35,29 @@ }, "required": { "loginName": "This field is required" + }, + "errors": { + "internalError": "An internal error occurred", + "couldNotGetLoginSettings": "Could not get login settings", + "couldNotSearchUsers": "Could not search users", + "couldNotGetDomain": "Could not get domain", + "couldNotGetHost": "Could not get host", + "couldNotStartIDPFlow": "Could not start IDP flow", + "moreThanOneUserFound": "More than one user found. Provide a unique identifier.", + "userNotFound": "User not found in the system", + "couldNotCreateSession": "Could not create session for user", + "initialUserNotSupported": "Initial User not supported", + "usernamePasswordNotAllowed": "Username Password not allowed! Contact your administrator for more information.", + "passkeysNotAllowed": "Passkeys not allowed! Contact your administrator for more information.", + "couldNotFindIdentityProvider": "Could not find identity provider.", + "userNotActive": "User is not active. Contact your administrator for more information." + } + }, + "zitadel": { + "errors": { + "errorOccured": "An error occurred", + "multipleUsersFound": "Multiple users found", + "userNotFound": "User not found in the system" } }, "password": { @@ -48,6 +71,13 @@ }, "required": { "password": "This field is required" + }, + "errors": { + "couldNotVerifyPassword": "Could not verify password", + "couldNotResetPassword": "Could not reset password" + }, + "info": { + "passwordResetSent": "Password was reset. Please check your email" } }, "set": { @@ -66,6 +96,11 @@ "code": "This field is required", "newPassword": "You have to provide a password!", "confirmPassword": "This field is required" + }, + "errors": { + "couldNotSetPassword": "Could not set password", + "couldNotResetPassword": "Could not reset password", + "couldNotVerifyPassword": "Could not verify password" } }, "change": { @@ -79,7 +114,40 @@ "required": { "newPassword": "You have to provide a new password!", "confirmPassword": "This field is required" + }, + "errors": { + "couldNotChangePassword": "Could not change password", + "couldNotVerifyPassword": "Could not verify password", + "unknownError": "Unknown error" } + }, + "complexity": { + "length": "Must be at least {minLength} characters long.", + "hasSymbol": "Must include a symbol.", + "hasNumber": "Must include a number.", + "hasUppercase": "Must include an uppercase letter.", + "hasLowercase": "Must include a lowercase letter.", + "equals": "Password confirmation matched.", + "matches": "Matches", + "doesNotMatch": "Doesn't match" + }, + "errors": { + "noHostFound": "No host found", + "couldNotSendResetLink": "Could not send Password Reset Link", + "couldNotCreateSessionForUser": "Could not create session for user", + "couldNotVerifyPassword": "Could not verify password", + "failedToAuthenticate": "Failed to authenticate. You had {failedAttempts} of {maxPasswordAttempts} password attempts.{lockoutMessage}", + "failedToAuthenticateNoLimit": "Failed to authenticate.", + "accountLockedContactAdmin": " Contact your administrator to unlock your account", + "userNotFound": "User not found in the system", + "initialUserNotSupported": "Initial User not supported", + "userInitialStateNotSupported": "User Initial State is not supported", + "codeOrVerificationRequired": "You have to provide a code or have a valid User Verification Check", + "verificationRequired": "User Verification Check has to be done", + "couldNotLoadSession": "Could not load session", + "couldNotLoadAuthMethods": "Could not load auth methods", + "failedPrecondition": "Failed precondition", + "sessionNotValid": "Session is not valid" } }, "idp": { @@ -244,6 +312,13 @@ "firstname": "This field is required", "lastname": "This field is required", "email": "This field is required" + }, + "errors": { + "couldNotCreateUser": "Could not create user", + "couldNotCreateSession": "Could not create session", + "userNotFound": "User not found in the system", + "couldNotLinkIDP": "Could not link IDP to user", + "couldNotRegisterUser": "Could not register user" } }, "invite": { @@ -287,6 +362,19 @@ "required": { "code": "This field is required" } + }, + "errors": { + "couldNotResendEmail": "Could not resend email", + "couldNotVerifyUser": "Could not verify user", + "couldNotVerifyInvite": "Could not verify invite", + "couldNotVerifyEmail": "Could not verify email", + "couldNotVerify": "Could not verify", + "couldNotLoadUser": "Could not load user", + "couldNotLoadAuthenticators": "Could not load possible authenticators", + "couldNotCreateSession": "Could not create session", + "noHostFound": "No host found", + "userAlreadyVerified": "User is already verified!", + "couldNotResendInvite": "Could not resend invite" } }, "authenticator": { diff --git a/apps/login/locales/es.json b/apps/login/locales/es.json index 82f1e9335..e38923f98 100644 --- a/apps/login/locales/es.json +++ b/apps/login/locales/es.json @@ -35,6 +35,29 @@ }, "required": { "loginName": "Este campo es obligatorio" + }, + "errors": { + "internalError": "Se produjo un error interno", + "couldNotGetLoginSettings": "No se pudieron obtener los ajustes de inicio de sesión", + "couldNotSearchUsers": "No se pudieron buscar usuarios", + "couldNotGetDomain": "No se pudo obtener el dominio", + "couldNotGetHost": "No se pudo obtener el host", + "couldNotStartIDPFlow": "No se pudo iniciar el flujo de IDP", + "moreThanOneUserFound": "Se encontró más de un usuario. Proporcione un identificador único.", + "userNotFound": "Usuario no encontrado en el sistema", + "couldNotCreateSession": "No se pudo crear la sesión para el usuario", + "initialUserNotSupported": "Usuario inicial no admitido", + "usernamePasswordNotAllowed": "El inicio de sesión con usuario y contraseña no está permitido. Contacte con su administrador para más información.", + "passkeysNotAllowed": "Las passkeys no están permitidas. Contacte con su administrador para más información.", + "couldNotFindIdentityProvider": "No se pudo encontrar el proveedor de identidad.", + "userNotActive": "El usuario no está activo. Contacte con su administrador para más información." + } + }, + "zitadel": { + "errors": { + "errorOccured": "Ocurrió un error", + "multipleUsersFound": "Se encontraron varios usuarios", + "userNotFound": "Usuario no encontrado en el sistema" } }, "password": { @@ -48,6 +71,13 @@ }, "required": { "password": "Este campo es obligatorio" + }, + "errors": { + "couldNotVerifyPassword": "No se pudo verificar la contraseña", + "couldNotResetPassword": "No se pudo restablecer la contraseña" + }, + "info": { + "passwordResetSent": "Se restableció la contraseña. Por favor, revise su correo electrónico" } }, "set": { @@ -66,6 +96,11 @@ "code": "Este campo es obligatorio", "newPassword": "¡Debes proporcionar una contraseña!", "confirmPassword": "Este campo es obligatorio" + }, + "errors": { + "couldNotSetPassword": "No se pudo establecer la contraseña", + "couldNotResetPassword": "No se pudo restablecer la contraseña", + "couldNotVerifyPassword": "No se pudo verificar la contraseña" } }, "change": { @@ -79,7 +114,40 @@ "required": { "newPassword": "¡Debes proporcionar una nueva contraseña!", "confirmPassword": "Este campo es obligatorio" + }, + "errors": { + "couldNotChangePassword": "No se pudo cambiar la contraseña", + "couldNotVerifyPassword": "No se pudo verificar la contraseña", + "unknownError": "Error desconocido" } + }, + "complexity": { + "length": "Debe tener al menos {minLength} caracteres de longitud.", + "hasSymbol": "Debe incluir un símbolo.", + "hasNumber": "Debe incluir un número.", + "hasUppercase": "Debe incluir una letra mayúscula.", + "hasLowercase": "Debe incluir una letra minúscula.", + "equals": "La confirmación de la contraseña coincide.", + "matches": "Coincide", + "doesNotMatch": "No coincide" + }, + "errors": { + "noHostFound": "No se encontró el host", + "couldNotSendResetLink": "No se pudo enviar el enlace de restablecimiento de contraseña", + "couldNotCreateSessionForUser": "No se pudo crear la sesión para el usuario", + "couldNotVerifyPassword": "No se pudo verificar la contraseña", + "failedToAuthenticate": "Error al autenticar. Tuvo {failedAttempts} de {maxPasswordAttempts} intentos de contraseña.{lockoutMessage}", + "failedToAuthenticateNoLimit": "Error al autenticar.", + "accountLockedContactAdmin": " Comuníquese con su administrador para desbloquear su cuenta", + "userNotFound": "Usuario no encontrado en el sistema", + "initialUserNotSupported": "Usuario inicial no compatible", + "userInitialStateNotSupported": "El estado inicial del usuario no es compatible", + "codeOrVerificationRequired": "Debe proporcionar un código o tener una verificación de usuario válida", + "verificationRequired": "Se debe realizar la verificación de usuario", + "couldNotLoadSession": "No se pudo cargar la sesión", + "couldNotLoadAuthMethods": "No se pudieron cargar los métodos de autenticación", + "failedPrecondition": "Precondición fallida", + "sessionNotValid": "La sesión no es válida" } }, "idp": { @@ -244,6 +312,13 @@ "firstname": "Este campo es obligatorio", "lastname": "Este campo es obligatorio", "email": "Este campo es obligatorio" + }, + "errors": { + "couldNotCreateUser": "No se pudo crear el usuario", + "couldNotCreateSession": "No se pudo crear la sesión", + "userNotFound": "Usuario no encontrado en el sistema", + "couldNotLinkIDP": "No se pudo vincular el IdP al usuario", + "couldNotRegisterUser": "No se pudo registrar el usuario" } }, "invite": { @@ -287,6 +362,19 @@ "required": { "code": "Este campo es obligatorio" } + }, + "errors": { + "couldNotResendEmail": "No se pudo reenviar el correo electrónico", + "couldNotVerifyUser": "No se pudo verificar al usuario", + "couldNotVerifyInvite": "No se pudo verificar la invitación", + "couldNotVerifyEmail": "No se pudo verificar el correo electrónico", + "couldNotVerify": "No se pudo verificar", + "couldNotLoadUser": "No se pudo cargar al usuario", + "couldNotLoadAuthenticators": "No se pudieron cargar los autenticadores posibles", + "couldNotCreateSession": "No se pudo crear la sesión", + "noHostFound": "No se encontró el host", + "userAlreadyVerified": "¡El usuario ya está verificado!", + "couldNotResendInvite": "No se pudo reenviar la invitación" } }, "authenticator": { diff --git a/apps/login/locales/it.json b/apps/login/locales/it.json index 815efb5a3..8d29c5170 100644 --- a/apps/login/locales/it.json +++ b/apps/login/locales/it.json @@ -35,6 +35,29 @@ }, "required": { "loginName": "Questo campo è obbligatorio" + }, + "errors": { + "internalError": "Si è verificato un errore interno", + "couldNotGetLoginSettings": "Impossibile ottenere le impostazioni di accesso", + "couldNotSearchUsers": "Impossibile cercare gli utenti", + "couldNotGetDomain": "Impossibile ottenere il dominio", + "couldNotGetHost": "Impossibile ottenere l'host", + "couldNotStartIDPFlow": "Impossibile avviare il flusso IDP", + "moreThanOneUserFound": "È stato trovato più di un utente. Fornisci un identificatore univoco.", + "userNotFound": "Utente non trovato nel sistema", + "couldNotCreateSession": "Impossibile creare la sessione per l'utente", + "initialUserNotSupported": "Utente iniziale non supportato", + "usernamePasswordNotAllowed": "Nome utente e password non consentiti! Contatta l'amministratore per maggiori informazioni.", + "passkeysNotAllowed": "Passkey non consentite! Contatta l'amministratore per maggiori informazioni.", + "couldNotFindIdentityProvider": "Impossibile trovare il provider di identità.", + "userNotActive": "L'utente non è attivo. Contatta l'amministratore per maggiori informazioni." + } + }, + "zitadel": { + "errors": { + "errorOccured": "Si è verificato un errore", + "multipleUsersFound": "Trovati più utenti", + "userNotFound": "Utente non trovato nel sistema" } }, "password": { @@ -48,6 +71,13 @@ }, "required": { "password": "Questo campo è obbligatorio" + }, + "errors": { + "couldNotVerifyPassword": "Impossibile verificare la password", + "couldNotResetPassword": "Impossibile reimpostare la password" + }, + "info": { + "passwordResetSent": "La password è stata reimpostata. Controlla la tua e-mail" } }, "set": { @@ -66,6 +96,11 @@ "code": "Questo campo è obbligatorio", "newPassword": "Devi fornire una password!", "confirmPassword": "Questo campo è obbligatorio" + }, + "errors": { + "couldNotSetPassword": "Impossibile impostare la password", + "couldNotResetPassword": "Impossibile reimpostare la password", + "couldNotVerifyPassword": "Impossibile verificare la password" } }, "change": { @@ -79,7 +114,40 @@ "required": { "newPassword": "Devi fornire una nuova password!", "confirmPassword": "Questo campo è obbligatorio" + }, + "errors": { + "couldNotChangePassword": "Impossibile modificare la password", + "couldNotVerifyPassword": "Impossibile verificare la password", + "unknownError": "Errore sconosciuto" } + }, + "complexity": { + "length": "Deve contenere almeno {minLength} caratteri.", + "hasSymbol": "Deve includere un simbolo.", + "hasNumber": "Deve includere un numero.", + "hasUppercase": "Deve includere una lettera maiuscola.", + "hasLowercase": "Deve includere una lettera minuscola.", + "equals": "La conferma della password corrisponde.", + "matches": "Corrisponde", + "doesNotMatch": "Non corrisponde" + }, + "errors": { + "noHostFound": "Nessun host trovato", + "couldNotSendResetLink": "Impossibile inviare il link per il ripristino della password", + "couldNotCreateSessionForUser": "Impossibile creare una sessione per l'utente", + "couldNotVerifyPassword": "Impossibile verificare la password", + "failedToAuthenticate": "Autenticazione non riuscita. Hai effettuato {failedAttempts} di {maxPasswordAttempts} tentativi di password.{lockoutMessage}", + "failedToAuthenticateNoLimit": "Autenticazione non riuscita.", + "accountLockedContactAdmin": " Contatta l'amministratore per sbloccare il tuo account", + "userNotFound": "Utente non trovato nel sistema", + "initialUserNotSupported": "Utente iniziale non supportato", + "userInitialStateNotSupported": "Lo stato iniziale dell'utente non è supportato", + "codeOrVerificationRequired": "Devi fornire un codice o avere una verifica utente valida", + "verificationRequired": "È necessario effettuare la verifica utente", + "couldNotLoadSession": "Impossibile caricare la sessione", + "couldNotLoadAuthMethods": "Impossibile caricare i metodi di autenticazione", + "failedPrecondition": "Precondizione non soddisfatta", + "sessionNotValid": "La sessione non è valida" } }, "idp": { @@ -244,6 +312,13 @@ "firstname": "Questo campo è obbligatorio", "lastname": "Questo campo è obbligatorio", "email": "Questo campo è obbligatorio" + }, + "errors": { + "couldNotCreateUser": "Impossibile creare l'utente", + "couldNotCreateSession": "Impossibile creare la sessione", + "userNotFound": "Utente non trovato nel sistema", + "couldNotLinkIDP": "Impossibile collegare l'IDP all'utente", + "couldNotRegisterUser": "Impossibile registrare l'utente" } }, "invite": { @@ -287,6 +362,19 @@ "required": { "code": "Questo campo è obbligatorio" } + }, + "errors": { + "couldNotResendEmail": "Impossibile reinviare l'email", + "couldNotVerifyUser": "Impossibile verificare l'utente", + "couldNotVerifyInvite": "Impossibile verificare l'invito", + "couldNotVerifyEmail": "Impossibile verificare l'email", + "couldNotVerify": "Impossibile verificare", + "couldNotLoadUser": "Impossibile caricare l'utente", + "couldNotLoadAuthenticators": "Impossibile caricare gli autenticatori possibili", + "couldNotCreateSession": "Impossibile creare la sessione", + "noHostFound": "Nessun host trovato", + "userAlreadyVerified": "L'utente è già verificato!", + "couldNotResendInvite": "Impossibile reinviare l'invito" } }, "authenticator": { diff --git a/apps/login/locales/pl.json b/apps/login/locales/pl.json index ae81ba7f3..3113f8805 100644 --- a/apps/login/locales/pl.json +++ b/apps/login/locales/pl.json @@ -35,6 +35,29 @@ }, "required": { "loginName": "To pole jest wymagane" + }, + "errors": { + "internalError": "Wystąpił błąd wewnętrzny", + "couldNotGetLoginSettings": "Nie udało się pobrać ustawień logowania", + "couldNotSearchUsers": "Nie udało się wyszukać użytkowników", + "couldNotGetDomain": "Nie udało się pobrać domeny", + "couldNotGetHost": "Nie udało się pobrać hosta", + "couldNotStartIDPFlow": "Nie udało się rozpocząć procesu IDP", + "moreThanOneUserFound": "Znaleziono więcej niż jednego użytkownika. Podaj unikalny identyfikator.", + "userNotFound": "Użytkownik nie został znaleziony w systemie", + "couldNotCreateSession": "Nie udało się utworzyć sesji dla użytkownika", + "initialUserNotSupported": "Użytkownik inicjalny nie jest obsługiwany", + "usernamePasswordNotAllowed": "Logowanie przy użyciu nazwy użytkownika i hasła jest niedozwolone! Skontaktuj się z administratorem, aby uzyskać więcej informacji.", + "passkeysNotAllowed": "Klucze dostępu są niedozwolone! Skontaktuj się z administratorem, aby uzyskać więcej informacji.", + "couldNotFindIdentityProvider": "Nie udało się znaleźć dostawcy tożsamości.", + "userNotActive": "Użytkownik jest nieaktywny. Skontaktuj się z administratorem, aby uzyskać więcej informacji." + } + }, + "zitadel": { + "errors": { + "errorOccured": "Wystąpił błąd", + "multipleUsersFound": "Znaleziono wielu użytkowników", + "userNotFound": "Użytkownik nie został znaleziony w systemie" } }, "password": { @@ -48,6 +71,13 @@ }, "required": { "password": "To pole jest wymagane" + }, + "errors": { + "couldNotVerifyPassword": "Nie można zweryfikować hasła", + "couldNotResetPassword": "Nie można zresetować hasła" + }, + "info": { + "passwordResetSent": "Hasło zostało zresetowane. Sprawdź swoją pocztę e-mail" } }, "set": { @@ -66,6 +96,11 @@ "code": "To pole jest wymagane", "newPassword": "Musisz podać hasło!", "confirmPassword": "To pole jest wymagane" + }, + "errors": { + "couldNotSetPassword": "Nie można ustawić hasła", + "couldNotResetPassword": "Nie można zresetować hasła", + "couldNotVerifyPassword": "Nie można zweryfikować hasła" } }, "change": { @@ -79,7 +114,40 @@ "required": { "newPassword": "Musisz podać nowe hasło!", "confirmPassword": "To pole jest wymagane" + }, + "errors": { + "couldNotChangePassword": "Nie można zmienić hasła", + "couldNotVerifyPassword": "Nie można zweryfikować hasła", + "unknownError": "Nieznany błąd" } + }, + "complexity": { + "length": "Musi zawierać co najmniej {minLength} znaków.", + "hasSymbol": "Musi zawierać symbol.", + "hasNumber": "Musi zawierać numer.", + "hasUppercase": "Musi zawierać dużą literę.", + "hasLowercase": "Musi zawierać małą literę.", + "equals": "Potwierdzenie hasła pasuje.", + "matches": "Pasuje", + "doesNotMatch": "Nie pasuje" + }, + "errors": { + "noHostFound": "Nie znaleziono hosta", + "couldNotSendResetLink": "Nie można wysłać linku do resetowania hasła", + "couldNotCreateSessionForUser": "Nie można utworzyć sesji dla użytkownika", + "couldNotVerifyPassword": "Nie można zweryfikować hasła", + "failedToAuthenticate": "Uwierzytelnianie nie powiodło się. Wykorzystałeś {failedAttempts} z {maxPasswordAttempts} prób wprowadzenia hasła.{lockoutMessage}", + "failedToAuthenticateNoLimit": "Uwierzytelnianie nie powiodło się.", + "accountLockedContactAdmin": " Skontaktuj się z administratorem, aby odblokować konto", + "userNotFound": "Użytkownik nie został znaleziony w systemie", + "initialUserNotSupported": "Użytkownik początkowy nie jest obsługiwany", + "userInitialStateNotSupported": "Początkowy stan użytkownika nie jest obsługiwany", + "codeOrVerificationRequired": "Musisz podać kod lub mieć ważną weryfikację użytkownika", + "verificationRequired": "Wymagana jest weryfikacja użytkownika", + "couldNotLoadSession": "Nie można załadować sesji", + "couldNotLoadAuthMethods": "Nie można załadować metod uwierzytelniania", + "failedPrecondition": "Nie spełniono warunków wstępnych", + "sessionNotValid": "Sesja jest nieważna" } }, "idp": { @@ -244,6 +312,13 @@ "firstname": "To pole jest wymagane", "lastname": "To pole jest wymagane", "email": "To pole jest wymagane" + }, + "errors": { + "couldNotCreateUser": "Nie udało się utworzyć użytkownika", + "couldNotCreateSession": "Nie udało się utworzyć sesji", + "userNotFound": "Nie znaleziono użytkownika w systemie", + "couldNotLinkIDP": "Nie udało się powiązać IDP z użytkownikiem", + "couldNotRegisterUser": "Nie udało się zarejestrować użytkownika" } }, "invite": { @@ -287,6 +362,19 @@ "required": { "code": "To pole jest wymagane" } + }, + "errors": { + "couldNotResendEmail": "Nie udało się ponownie wysłać wiadomości e-mail", + "couldNotVerifyUser": "Nie udało się zweryfikować użytkownika", + "couldNotVerifyInvite": "Nie udało się zweryfikować zaproszenia", + "couldNotVerifyEmail": "Nie udało się zweryfikować adresu e-mail", + "couldNotVerify": "Nie udało się zweryfikować", + "couldNotLoadUser": "Nie udało się załadować użytkownika", + "couldNotLoadAuthenticators": "Nie udało się wczytać dostępnych metod uwierzytelniania", + "couldNotCreateSession": "Nie udało się utworzyć sesji", + "noHostFound": "Nie znaleziono hosta", + "userAlreadyVerified": "Użytkownik jest już zweryfikowany!", + "couldNotResendInvite": "Nie udało się ponownie wysłać zaproszenia" } }, "authenticator": { diff --git a/apps/login/locales/ru.json b/apps/login/locales/ru.json index f5e91066d..03ea8a7f5 100644 --- a/apps/login/locales/ru.json +++ b/apps/login/locales/ru.json @@ -35,6 +35,29 @@ }, "required": { "loginName": "Это поле обязательно для заполнения" + }, + "errors": { + "internalError": "Произошла внутренняя ошибка", + "couldNotGetLoginSettings": "Не удалось получить настройки входа", + "couldNotSearchUsers": "Не удалось выполнить поиск пользователей", + "couldNotGetDomain": "Не удалось получить домен", + "couldNotGetHost": "Не удалось получить хост", + "couldNotStartIDPFlow": "Не удалось запустить поток IDP", + "moreThanOneUserFound": "Найдено более одного пользователя. Укажите уникальный идентификатор.", + "userNotFound": "Пользователь не найден в системе", + "couldNotCreateSession": "Не удалось создать сессию для пользователя", + "initialUserNotSupported": "Начальный пользователь не поддерживается", + "usernamePasswordNotAllowed": "Использование имени пользователя и пароля не разрешено! Обратитесь к администратору за дополнительной информацией.", + "passkeysNotAllowed": "Ключи доступа не разрешены! Обратитесь к администратору за дополнительной информацией.", + "couldNotFindIdentityProvider": "Не удалось найти поставщика удостоверений.", + "userNotActive": "Пользователь неактивен. Обратитесь к администратору за дополнительной информацией." + } + }, + "zitadel": { + "errors": { + "errorOccured": "Произошла ошибка", + "multipleUsersFound": "Найдено несколько пользователей", + "userNotFound": "Пользователь не найден в системе" } }, "password": { @@ -48,6 +71,13 @@ }, "required": { "password": "Это поле обязательно для заполнения" + }, + "errors": { + "couldNotVerifyPassword": "Не удалось проверить пароль", + "couldNotResetPassword": "Не удалось сбросить пароль" + }, + "info": { + "passwordResetSent": "Пароль был сброшен. Пожалуйста, проверьте свою электронную почту" } }, "set": { @@ -66,6 +96,11 @@ "code": "Это поле обязательно для заполнения", "newPassword": "Вы должны указать пароль!", "confirmPassword": "Это поле обязательно для заполнения" + }, + "errors": { + "couldNotSetPassword": "Не удалось установить пароль", + "couldNotResetPassword": "Не удалось сбросить пароль", + "couldNotVerifyPassword": "Не удалось проверить пароль" } }, "change": { @@ -79,7 +114,40 @@ "required": { "newPassword": "Вы должны указать новый пароль!", "confirmPassword": "Это поле обязательно для заполнения" + }, + "errors": { + "couldNotChangePassword": "Не удалось изменить пароль", + "couldNotVerifyPassword": "Не удалось проверить пароль", + "unknownError": "Неизвестная ошибка" } + }, + "complexity": { + "length": "Минимум {minLength} символов.", + "hasSymbol": "Должен содержать специальный символ.", + "hasNumber": "Должен содержать цифру.", + "hasUppercase": "Должен содержать заглавную букву.", + "hasLowercase": "Должен содержать строчную букву.", + "equals": "Пароли должны совпадать.", + "matches": "Совпадает", + "doesNotMatch": "Не совпадает" + }, + "errors": { + "noHostFound": "Хост не найден", + "couldNotSendResetLink": "Не удалось отправить ссылку для сброса пароля", + "couldNotCreateSessionForUser": "Не удалось создать сессию для пользователя", + "couldNotVerifyPassword": "Не удалось проверить пароль", + "failedToAuthenticate": "Не удалось пройти аутентификацию. У вас было {failedAttempts} из {maxPasswordAttempts} попыток ввода пароля.{lockoutMessage}", + "failedToAuthenticateNoLimit": "Не удалось пройти аутентификацию.", + "accountLockedContactAdmin": " Свяжитесь с администратором, чтобы разблокировать вашу учетную запись", + "userNotFound": "Пользователь не найден в системе", + "initialUserNotSupported": "Первичный пользователь не поддерживается", + "userInitialStateNotSupported": "Начальное состояние пользователя не поддерживается", + "codeOrVerificationRequired": "Вы должны предоставить код или иметь действительную проверку пользователя", + "verificationRequired": "Необходимо выполнить проверку пользователя", + "couldNotLoadSession": "Не удалось загрузить сессию", + "couldNotLoadAuthMethods": "Не удалось загрузить методы аутентификации", + "failedPrecondition": "Нарушено предварительное условие", + "sessionNotValid": "Сессия недействительна" } }, "idp": { @@ -244,7 +312,14 @@ "firstname": "Это поле обязательно для заполнения", "lastname": "Это поле обязательно для заполнения", "email": "Это поле обязательно для заполнения" - } + }, + "errors": { + "couldNotCreateUser": "Не удалось создать пользователя", + "couldNotCreateSession": "Не удалось создать сессию", + "userNotFound": "Пользователь не найден в системе", + "couldNotLinkIDP": "Не удалось привязать IDP к пользователю", + "couldNotRegisterUser": "Не удалось зарегистрировать пользователя" + } }, "invite": { "title": "Пригласить пользователя", @@ -287,6 +362,19 @@ "required": { "code": "Это поле обязательно для заполнения" } + }, + "errors": { + "couldNotResendEmail": "Не удалось повторно отправить электронное письмо", + "couldNotVerifyUser": "Не удалось подтвердить пользователя", + "couldNotVerifyInvite": "Не удалось подтвердить приглашение", + "couldNotVerifyEmail": "Не удалось подтвердить электронную почту", + "couldNotVerify": "Не удалось подтвердить", + "couldNotLoadUser": "Не удалось загрузить пользователя", + "couldNotLoadAuthenticators": "Не удалось загрузить доступные средства аутентификации", + "couldNotCreateSession": "Не удалось создать сеанс", + "noHostFound": "Хост не найден", + "userAlreadyVerified": "Пользователь уже подтверждён!", + "couldNotResendInvite": "Не удалось повторно отправить приглашение" } }, "authenticator": { diff --git a/apps/login/locales/zh.json b/apps/login/locales/zh.json index 3ec2ec31e..4d0d259e3 100644 --- a/apps/login/locales/zh.json +++ b/apps/login/locales/zh.json @@ -35,6 +35,29 @@ }, "required": { "loginName": "此字段为必填项" + }, + "errors": { + "internalError": "发生内部错误", + "couldNotGetLoginSettings": "无法获取登录设置", + "couldNotSearchUsers": "无法搜索用户", + "couldNotGetDomain": "无法获取域名", + "couldNotGetHost": "无法获取主机", + "couldNotStartIDPFlow": "无法启动身份提供者流程", + "moreThanOneUserFound": "找到多个用户。请提供唯一标识符。", + "userNotFound": "系统中未找到用户", + "couldNotCreateSession": "无法为用户创建会话", + "initialUserNotSupported": "不支持初始用户", + "usernamePasswordNotAllowed": "不允许使用用户名和密码!请联系管理员了解更多信息。", + "passkeysNotAllowed": "不允许使用 Passkey!请联系管理员了解更多信息。", + "couldNotFindIdentityProvider": "找不到身份提供者。", + "userNotActive": "用户未激活。请联系管理员了解更多信息。" + } + }, + "zitadel": { + "errors": { + "errorOccured": "发生错误", + "multipleUsersFound": "找到多个用户", + "userNotFound": "系统中未找到用户" } }, "password": { @@ -48,6 +71,13 @@ }, "required": { "password": "此字段为必填项" + }, + "errors": { + "couldNotVerifyPassword": "无法验证密码", + "couldNotResetPassword": "无法重置密码" + }, + "info": { + "passwordResetSent": "密码已重置。请检查您的电子邮件" } }, "set": { @@ -66,6 +96,11 @@ "code": "此字段为必填项", "newPassword": "必须提供密码!", "confirmPassword": "此字段为必填项" + }, + "errors": { + "couldNotSetPassword": "无法设置密码", + "couldNotResetPassword": "无法重置密码", + "couldNotVerifyPassword": "无法验证密码" } }, "change": { @@ -79,7 +114,40 @@ "required": { "newPassword": "必须提供新密码!", "confirmPassword": "此字段为必填项" + }, + "errors": { + "couldNotChangePassword": "无法更改密码", + "couldNotVerifyPassword": "无法验证密码", + "unknownError": "未知错误" } + }, + "complexity": { + "length": "必须至少有 {minLength} 个字符。", + "hasSymbol": "必须包含一个符号。", + "hasNumber": "必须包含一个数字。", + "hasUppercase": "必须包含一个大写字母。", + "hasLowercase": "必须包含一个小写字母。", + "equals": "密码确认匹配。", + "matches": "匹配", + "doesNotMatch": "不匹配" + }, + "errors": { + "noHostFound": "未找到主机", + "couldNotSendResetLink": "无法发送密码重置链接", + "couldNotCreateSessionForUser": "无法为用户创建会话", + "couldNotVerifyPassword": "无法验证密码", + "failedToAuthenticate": "身份验证失败。您已尝试输入密码 {failedAttempts} 次,共允许 {maxPasswordAttempts} 次。{lockoutMessage}", + "failedToAuthenticateNoLimit": "身份验证失败。", + "accountLockedContactAdmin": " 请联系管理员以解锁您的账户", + "userNotFound": "系统中未找到用户", + "initialUserNotSupported": "不支持初始用户", + "userInitialStateNotSupported": "不支持用户初始状态", + "codeOrVerificationRequired": "您必须提供验证码或通过有效的用户验证", + "verificationRequired": "必须完成用户验证", + "couldNotLoadSession": "无法加载会话", + "couldNotLoadAuthMethods": "无法加载验证方法", + "failedPrecondition": "前置条件失败", + "sessionNotValid": "会话无效" } }, "idp": { @@ -244,6 +312,13 @@ "firstname": "此字段为必填项", "lastname": "此字段为必填项", "email": "此字段为必填项" + }, + "errors": { + "couldNotCreateUser": "无法创建用户", + "couldNotCreateSession": "无法创建会话", + "userNotFound": "系统中未找到用户", + "couldNotLinkIDP": "无法将 IDP 关联到用户", + "couldNotRegisterUser": "无法注册用户" } }, "invite": { @@ -287,6 +362,19 @@ "required": { "code": "此字段为必填项" } + }, + "errors": { + "couldNotResendEmail": "无法重新发送邮件", + "couldNotVerifyUser": "无法验证用户", + "couldNotVerifyInvite": "无法验证邀请", + "couldNotVerifyEmail": "无法验证邮箱", + "couldNotVerify": "无法验证", + "couldNotLoadUser": "无法加载用户", + "couldNotLoadAuthenticators": "无法加载可用的身份验证器", + "couldNotCreateSession": "无法创建会话", + "noHostFound": "未找到主机", + "userAlreadyVerified": "用户已验证!", + "couldNotResendInvite": "无法重新发送邀请" } }, "authenticator": { diff --git a/apps/login/src/components/change-password-form.tsx b/apps/login/src/components/change-password-form.tsx index 394d0a663..0381e78d3 100644 --- a/apps/login/src/components/change-password-form.tsx +++ b/apps/login/src/components/change-password-form.tsx @@ -70,7 +70,7 @@ export function ChangePasswordForm({ password: values.password, }) .catch(() => { - setError("Could not change password"); + setError(t("change.errors.couldNotChangePassword")); return; }) .finally(() => { @@ -81,13 +81,13 @@ export function ChangePasswordForm({ setError( typeof changeResponse.error === "string" ? changeResponse.error - : "Unknown error", + : t("change.errors.unknownError") ); return; } if (!changeResponse) { - setError("Could not change password"); + setError(t("change.errors.couldNotChangePassword")); return; } @@ -102,7 +102,7 @@ export function ChangePasswordForm({ requestId, }) .catch(() => { - setError("Could not verify password"); + setError(t("change.errors.couldNotVerifyPassword")); return; }) .finally(() => { diff --git a/apps/login/src/components/password-complexity.test.tsx b/apps/login/src/components/password-complexity.test.tsx index 090c95d39..c563730e8 100644 --- a/apps/login/src/components/password-complexity.test.tsx +++ b/apps/login/src/components/password-complexity.test.tsx @@ -1,64 +1,148 @@ -import { - cleanup, - render, - screen, - waitFor, - within, -} from "@testing-library/react"; -import { afterEach, beforeEach, describe, expect, test } from "vitest"; +import { cleanup, render, screen } from "@testing-library/react"; +import { afterEach, describe, expect, test } from "vitest"; import { PasswordComplexity } from "./password-complexity"; - -const matchesTitle = `Matches`; -const doesntMatchTitle = `Doesn't match`; +import { NextIntlClientProvider } from "next-intl"; describe("", () => { - describe.each` - settingsMinLength | password | expectSVGTitle - ${5} | ${"Password1!"} | ${matchesTitle} - ${30} | ${"Password1!"} | ${doesntMatchTitle} - ${0} | ${"Password1!"} | ${matchesTitle} - ${undefined} | ${"Password1!"} | ${false} - `( - `With settingsMinLength=$settingsMinLength, password=$password, expectSVGTitle=$expectSVGTitle`, - ({ settingsMinLength, password, expectSVGTitle }) => { - const feedbackElementLabel = /password length/i; - beforeEach(() => { - render( - { + render( + + , - ); - }); - afterEach(cleanup); + resourceOwnerType: 0, + } as any + } + /> + , + ); - if (expectSVGTitle === false) { - test(`should not render the feedback element`, async () => { - await waitFor(() => { - expect( - screen.queryByText(feedbackElementLabel), - ).not.toBeInTheDocument(); - }); - }); - } else { - test(`Should show one SVG with title ${expectSVGTitle}`, async () => { - await waitFor(async () => { - const svg = within( - screen.getByText(feedbackElementLabel) - .parentElement as HTMLElement, - ).findByRole("img"); - expect(await svg).toHaveTextContent(expectSVGTitle); - }); - }); - } - }, - ); + const lengthCheck = screen.getByTestId("length-check"); + expect(lengthCheck).toBeInTheDocument(); + expect(lengthCheck.querySelector("svg")).toBeInTheDocument(); + }); + + test("should not render length check when minLength is undefined", () => { + render( + + + , + ); + + expect(screen.queryByTestId("length-check")).toBeInTheDocument(); + }); + + test("should render check icon when password meets length requirement", () => { + render( + + + , + ); + + const lengthCheck = screen.getByTestId("length-check"); + const svg = lengthCheck.querySelector("svg"); + expect(svg).toHaveClass("text-green-500"); + }); + + test("should render cross icon when password does not meet length requirement", () => { + render( + + + , + ); + + const lengthCheck = screen.getByTestId("length-check"); + const svg = lengthCheck.querySelector("svg"); + expect(svg).toHaveClass("text-warn-light-500"); + }); + + test("should render all complexity checks", () => { + render( + + + , + ); + + expect(screen.getByTestId("length-check")).toBeInTheDocument(); + expect(screen.getByTestId("symbol-check")).toBeInTheDocument(); + expect(screen.getByTestId("number-check")).toBeInTheDocument(); + expect(screen.getByTestId("uppercase-check")).toBeInTheDocument(); + expect(screen.getByTestId("lowercase-check")).toBeInTheDocument(); + }); }); diff --git a/apps/login/src/components/password-complexity.tsx b/apps/login/src/components/password-complexity.tsx index 4f0b460c7..25f53820f 100644 --- a/apps/login/src/components/password-complexity.tsx +++ b/apps/login/src/components/password-complexity.tsx @@ -5,6 +5,8 @@ import { upperCaseValidator, } from "@/helpers/validators"; import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb"; +import { useTranslations } from "next-intl"; +import { Translated } from "@/components/translated"; type Props = { passwordComplexitySettings: PasswordComplexitySettings; @@ -12,42 +14,55 @@ type Props = { equals: boolean; }; -const check = ( - - Matches - - -); -const cross = ( - - Doesn't match - - -); +function CheckIcon({ title }: { title: string }) { + return ( + + {title} + + + ); +} + +function CrossIcon({ title }: { title: string }) { + return ( + + {title} + + + ); +} + +function renderIcon(matched: boolean, t: ReturnType) { + return matched ? ( + + ) : ( + + ); +} const desc = "text-14px leading-4 text-input-light-label dark:text-input-dark-label"; @@ -56,6 +71,7 @@ export function PasswordComplexity({ password, equals, }: Props) { + const t = useTranslations("password"); const hasMinLength = password?.length >= passwordComplexitySettings.minLength; const hasSymbol = symbolValidator(password); const hasNumber = numberValidator(password); @@ -66,33 +82,47 @@ export function PasswordComplexity({
{passwordComplexitySettings.minLength != undefined ? (
- {hasMinLength ? check : cross} + {renderIcon(hasMinLength, t)} - Password length {passwordComplexitySettings.minLength.toString()} +
) : ( )}
- {hasSymbol ? check : cross} - has Symbol + {renderIcon(hasSymbol, t)} + + +
- {hasNumber ? check : cross} - has Number + {renderIcon(hasNumber, t)} + + +
- {hasUppercase ? check : cross} - has uppercase + {renderIcon(hasUppercase, t)} + + +
- {hasLowercase ? check : cross} - has lowercase + {renderIcon(hasLowercase, t)} + + +
- {equals ? check : cross} - equals + {renderIcon(equals, t)} + + +
); diff --git a/apps/login/src/components/password-form.tsx b/apps/login/src/components/password-form.tsx index 1b4c73b95..9f4b27fe8 100644 --- a/apps/login/src/components/password-form.tsx +++ b/apps/login/src/components/password-form.tsx @@ -52,9 +52,8 @@ export function PasswordForm({ loginSettings, loginName, organization, requestId }), requestId, }) - .catch((error) => { - setError("Could not verify password"); - console.error("Error verifying password:", error); + .catch(() => { + setError(t("verify.errors.couldNotVerifyPassword")); return; }) .finally(() => { @@ -82,7 +81,7 @@ export function PasswordForm({ loginSettings, loginName, organization, requestId requestId, }) .catch(() => { - setError("Could not reset password"); + setError(t("verify.errors.couldNotResetPassword")); return; }) .finally(() => { @@ -94,7 +93,7 @@ export function PasswordForm({ loginSettings, loginName, organization, requestId return; } - setInfo("Password was reset. Please check your email."); + setInfo(t("verify.info.passwordResetSent")); const params = new URLSearchParams({ loginName: loginName, diff --git a/apps/login/src/components/register-form.tsx b/apps/login/src/components/register-form.tsx index a8f8b0962..968424c79 100644 --- a/apps/login/src/components/register-form.tsx +++ b/apps/login/src/components/register-form.tsx @@ -72,7 +72,7 @@ export function RegisterForm({ requestId: requestId, }) .catch(() => { - setError("Could not register user"); + setError(t("errors.couldNotRegisterUser")); return; }) .finally(() => { diff --git a/apps/login/src/components/set-password-form.tsx b/apps/login/src/components/set-password-form.tsx index ab09c9c19..3c6783fcd 100644 --- a/apps/login/src/components/set-password-form.tsx +++ b/apps/login/src/components/set-password-form.tsx @@ -77,7 +77,7 @@ export function SetPasswordForm({ requestId, }) .catch(() => { - setError("Could not reset password"); + setError(t("set.errors.couldNotResetPassword")); return; }) .finally(() => { @@ -104,7 +104,7 @@ export function SetPasswordForm({ const changeResponse = await changePassword(payload) .catch(() => { - setError("Could not set password"); + setError(t("set.errors.couldNotSetPassword")); return; }) .finally(() => { @@ -117,7 +117,7 @@ export function SetPasswordForm({ } if (!changeResponse) { - setError("Could not set password"); + setError(t("set.errors.couldNotSetPassword")); return; } @@ -141,7 +141,7 @@ export function SetPasswordForm({ requestId, }) .catch(() => { - setError("Could not verify password"); + setError(t("set.errors.couldNotVerifyPassword")); return; }) .finally(() => { diff --git a/apps/login/src/components/set-register-password-form.tsx b/apps/login/src/components/set-register-password-form.tsx index 8d17f1dfc..eedebc495 100644 --- a/apps/login/src/components/set-register-password-form.tsx +++ b/apps/login/src/components/set-register-password-form.tsx @@ -71,7 +71,7 @@ export function SetRegisterPasswordForm({ password: values.password, }) .catch(() => { - setError("Could not register user"); + setError(t("errors.couldNotRegisterUser")); return; }) .finally(() => { diff --git a/apps/login/src/components/username-form.tsx b/apps/login/src/components/username-form.tsx index f5a8a721d..78ae33ad4 100644 --- a/apps/login/src/components/username-form.tsx +++ b/apps/login/src/components/username-form.tsx @@ -60,7 +60,7 @@ export function UsernameForm({ suffix, }) .catch(() => { - setError("An internal error occurred"); + setError(t("errors.internalError")); return; }) .finally(() => { diff --git a/apps/login/src/components/verify-form.tsx b/apps/login/src/components/verify-form.tsx index 575f401e3..eac265924 100644 --- a/apps/login/src/components/verify-form.tsx +++ b/apps/login/src/components/verify-form.tsx @@ -57,7 +57,7 @@ export function VerifyForm({ isInvite: isInvite, }) .catch(() => { - setError("Could not resend email"); + setError(t("errors.couldNotResendEmail")); return; }) .finally(() => { @@ -87,7 +87,7 @@ export function VerifyForm({ requestId: requestId, }) .catch(() => { - setError("Could not verify user"); + setError(t("errors.couldNotVerifyUser")); return; }) .finally(() => { diff --git a/apps/login/src/lib/server/loginname.test.ts b/apps/login/src/lib/server/loginname.test.ts index a394e4805..b483aa0d7 100644 --- a/apps/login/src/lib/server/loginname.test.ts +++ b/apps/login/src/lib/server/loginname.test.ts @@ -42,6 +42,11 @@ vi.mock("./host", () => ({ getOriginalHost: vi.fn(), })); +// this returns the key itself that can be checked not the translated value +vi.mock("next-intl/server", () => ({ + getTranslations: vi.fn(() => (key: string) => key), +})); + describe("sendLoginname", () => { // Mock modules let mockHeaders: any; @@ -116,7 +121,7 @@ describe("sendLoginname", () => { loginName: "user@example.com", }); - expect(result).toEqual({ error: "Could not get login settings" }); + expect(result).toEqual({ error: "errors.couldNotGetLoginSettings" }); }); test("should return error when user search fails", async () => { @@ -138,7 +143,7 @@ describe("sendLoginname", () => { loginName: "user@example.com", }); - expect(result).toEqual({ error: "Could not search users" }); + expect(result).toEqual({ error: "errors.couldNotSearchUsers" }); }); test("should return error when more than one user found", async () => { @@ -154,7 +159,7 @@ describe("sendLoginname", () => { loginName: "user@example.com", }); - expect(result).toEqual({ error: "More than one user found. Provide a unique identifier." }); + expect(result).toEqual({ error: "errors.moreThanOneUserFound" }); }); }); @@ -250,7 +255,7 @@ describe("sendLoginname", () => { }); expect(result).toEqual({ - error: "Username Password not allowed! Contact your administrator for more information.", + error: "errors.usernamePasswordNotAllowed", }); }); @@ -282,7 +287,7 @@ describe("sendLoginname", () => { }); expect(result).toEqual({ - error: "Passkeys not allowed! Contact your administrator for more information.", + error: "errors.passkeysNotAllowed", }); }); @@ -374,7 +379,7 @@ describe("sendLoginname", () => { }); expect(result).toEqual({ - error: "Username Password not allowed! Contact your administrator for more information.", + error: "errors.usernamePasswordNotAllowed", }); }); }); @@ -450,7 +455,7 @@ describe("sendLoginname", () => { loginName: "user@example.com", }); - expect(result).toEqual({ error: "User not found in the system" }); + expect(result).toEqual({ error: "errors.userNotFound" }); }); }); @@ -473,7 +478,7 @@ describe("sendLoginname", () => { loginName: "user@example.com", }); - expect(result).toEqual({ error: "Could not create session for user" }); + expect(result).toEqual({ error: "errors.couldNotCreateSession" }); }); test("should handle initial user state", async () => { @@ -504,7 +509,7 @@ describe("sendLoginname", () => { loginName: "user@example.com", }); - expect(result).toEqual({ error: "Initial User not supported" }); + expect(result).toEqual({ error: "errors.initialUserNotSupported" }); }); test("should handle organization parameter in all redirects", async () => { diff --git a/apps/login/src/lib/server/loginname.ts b/apps/login/src/lib/server/loginname.ts index 9f243a86d..b56bedc77 100644 --- a/apps/login/src/lib/server/loginname.ts +++ b/apps/login/src/lib/server/loginname.ts @@ -3,6 +3,7 @@ import { create } from "@zitadel/client"; import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb"; import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb"; +import { getTranslations } from "next-intl/server"; import { headers } from "next/headers"; import { idpTypeToIdentityProviderType, idpTypeToSlug } from "../idp"; @@ -36,13 +37,15 @@ export async function sendLoginname(command: SendLoginnameCommand) { const _headers = await headers(); const { serviceUrl } = getServiceUrlFromHeaders(_headers); + const t = await getTranslations("loginname"); + const loginSettingsByContext = await getLoginSettings({ serviceUrl, organization: command.organization, }); if (!loginSettingsByContext) { - return { error: "Could not get login settings" }; + return { error: t("errors.couldNotGetLoginSettings") }; } let searchUsersRequest: SearchUsersCommand = { @@ -60,7 +63,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { } if (!("result" in searchResult)) { - return { error: "Could not search users" }; + return { error: t("errors.couldNotSearchUsers") }; } const { result: potentialUsers } = searchResult; @@ -108,7 +111,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { }); if (!url) { - return { error: "Could not start IDP flow" }; + return { error: t("errors.couldNotStartIDPFlow") }; } return { redirect: url }; @@ -138,7 +141,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { const idpType = idp?.type; if (!idp || !idpType) { - throw new Error("Could not find identity provider"); + throw new Error(t("errors.couldNotFindIdentityProvider")); } const identityProviderType = idpTypeToIdentityProviderType(idpType); @@ -170,7 +173,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { }); if (!url) { - return { error: "Could not start IDP flow" }; + return { error: t("errors.couldNotStartIDPFlow") }; } return { redirect: url }; @@ -178,7 +181,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { }; if (potentialUsers.length > 1) { - return { error: "More than one user found. Provide a unique identifier." }; + return { error: t("errors.moreThanOneUserFound") }; } else if (potentialUsers.length == 1 && potentialUsers[0].userId) { const user = potentialUsers[0]; const userId = potentialUsers[0].userId; @@ -196,15 +199,15 @@ export async function sendLoginname(command: SendLoginnameCommand) { // recheck login settings after user discovery, as the search might have been done without org scope if (userLoginSettings?.disableLoginWithEmail && userLoginSettings?.disableLoginWithPhone) { if (user.preferredLoginName !== concatLoginname) { - return { error: "User not found in the system!" }; + return { error: t("errors.userNotFound") }; } } else if (userLoginSettings?.disableLoginWithEmail) { if (user.preferredLoginName !== concatLoginname || humanUser?.phone?.phone !== command.loginName) { - return { error: "User not found in the system!" }; + return { error: t("errors.userNotFound") }; } } else if (userLoginSettings?.disableLoginWithPhone) { if (user.preferredLoginName !== concatLoginname || humanUser?.email?.email !== command.loginName) { - return { error: "User not found in the system!" }; + return { error: t("errors.userNotFound") }; } } @@ -212,18 +215,29 @@ export async function sendLoginname(command: SendLoginnameCommand) { user: { search: { case: "userId", value: userId } }, }); - const session = await createSessionAndUpdateCookie({ + const sessionOrError = await createSessionAndUpdateCookie({ checks, requestId: command.requestId, + }).catch((error) => { + if (error?.rawMessage === "Errors.User.NotActive (SESSION-Gj4ko)") { + return { error: t("errors.userNotActive") }; + } + throw error; }); + if ("error" in sessionOrError) { + return sessionOrError; + } + + const session = sessionOrError; + if (!session.factors?.user?.id) { - return { error: "Could not create session for user" }; + return { error: t("errors.couldNotCreateSession") }; } // TODO: check if handling of userstate INITIAL is needed if (user.state === UserState.INITIAL) { - return { error: "Initial User not supported" }; + return { error: t("errors.initialUserNotSupported") }; } const methods = await listAuthenticationMethodTypes({ @@ -262,7 +276,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { } return { - error: "Username Password not allowed! Contact your administrator for more information.", + error: t("errors.usernamePasswordNotAllowed"), }; } @@ -287,7 +301,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { case AuthenticationMethodType.PASSKEY: // AuthenticationMethodType.AUTHENTICATION_METHOD_TYPE_PASSKEY if (userLoginSettings?.passkeysType === PasskeysType.NOT_ALLOWED) { return { - error: "Passkeys not allowed! Contact your administrator for more information.", + error: t("errors.passkeysNotAllowed"), }; } @@ -366,7 +380,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { if (resp) { return resp; } - return { error: "User not found in the system" }; + return { error: t("errors.userNotFound") }; } else if (loginSettingsByContext?.allowRegister && loginSettingsByContext?.allowUsernamePassword) { let orgToRegisterOn: string | undefined = command.organization; @@ -429,5 +443,5 @@ export async function sendLoginname(command: SendLoginnameCommand) { // fallbackToPassword - return { error: "User not found in the system" }; + return { error: t("errors.userNotFound") }; } diff --git a/apps/login/src/lib/server/password.ts b/apps/login/src/lib/server/password.ts index 166a11d5f..a9b4d29c6 100644 --- a/apps/login/src/lib/server/password.ts +++ b/apps/login/src/lib/server/password.ts @@ -31,6 +31,7 @@ import { checkUserVerification, } from "../verify-helper"; import { createServerTransport } from "../zitadel"; +import { getTranslations } from "next-intl/server"; type ResetPasswordCommand = { loginName: string; @@ -42,6 +43,8 @@ export async function resetPassword(command: ResetPasswordCommand) { const _headers = await headers(); const { serviceUrl } = getServiceUrlFromHeaders(_headers); + const t = await getTranslations("password"); + // Get the original host that the user sees with protocol const hostWithProtocol = await getOriginalHostWithProtocol(); @@ -52,7 +55,7 @@ export async function resetPassword(command: ResetPasswordCommand) { }); if (!users.details || users.details.totalResult !== BigInt(1) || !users.result[0].userId) { - return { error: "Could not send Password Reset Link" }; + return { error: t("errors.couldNotSendResetLink") }; } const userId = users.result[0].userId; @@ -77,6 +80,7 @@ export type UpdateSessionCommand = { export async function sendPassword(command: UpdateSessionCommand): Promise<{ error: string } | { redirect: string }> { const _headers = await headers(); const { serviceUrl } = getServiceUrlFromHeaders(_headers); + const t = await getTranslations("password"); let sessionCookie = await getSessionCookieByLoginName({ loginName: command.loginName, @@ -122,20 +126,28 @@ export async function sendPassword(command: UpdateSessionCommand): Promise<{ err orgId: command.organization, }); + const hasLimit = + lockoutSettings?.maxPasswordAttempts !== undefined && lockoutSettings?.maxPasswordAttempts > BigInt(0); + const locked = hasLimit && error.failedAttempts >= lockoutSettings?.maxPasswordAttempts; + const messageKey = hasLimit ? "errors.failedToAuthenticate" : "errors.failedToAuthenticateNoLimit"; + return { - error: - `Failed to authenticate. You had ${error.failedAttempts} of ${lockoutSettings?.maxPasswordAttempts} password attempts.` + - (lockoutSettings?.maxPasswordAttempts && error.failedAttempts >= lockoutSettings?.maxPasswordAttempts - ? "Contact your administrator to unlock your account" - : ""), + error: t(messageKey, { + failedAttempts: error.failedAttempts, + maxPasswordAttempts: hasLimit ? (lockoutSettings?.maxPasswordAttempts).toString() : "?", + lockoutMessage: locked ? t("errors.accountLockedContactAdmin") : "", + }), }; } - return { error: "Could not create session for user" }; + return { error: t("errors.couldNotCreateSessionForUser") }; } } else { // this is a fake error message to hide that the user does not even exist return { error: "Could not verify password" }; } + + // this is a fake error message to hide that the user does not even exist + return { error: t("errors.couldNotVerifyPassword") }; } else { loginSettings = await getLoginSettings({ serviceUrl, @@ -170,19 +182,24 @@ export async function sendPassword(command: UpdateSessionCommand): Promise<{ err orgId: command.organization, }); + const hasLimit = + lockoutSettings?.maxPasswordAttempts !== undefined && lockoutSettings?.maxPasswordAttempts > BigInt(0); + const locked = hasLimit && error.failedAttempts >= lockoutSettings?.maxPasswordAttempts; + const messageKey = hasLimit ? "errors.failedToAuthenticate" : "errors.failedToAuthenticateNoLimit"; + return { - error: - `Failed to authenticate. You had ${error.failedAttempts} of ${lockoutSettings?.maxPasswordAttempts} password attempts.` + - (lockoutSettings?.maxPasswordAttempts && error.failedAttempts >= lockoutSettings?.maxPasswordAttempts - ? " Contact your administrator to unlock your account" - : ""), + error: t(messageKey, { + failedAttempts: error.failedAttempts, + maxPasswordAttempts: hasLimit ? (lockoutSettings?.maxPasswordAttempts).toString() : "?", + lockoutMessage: locked ? t("errors.accountLockedContactAdmin") : "", + }), }; } throw error; } if (!session?.factors?.user?.id) { - return { error: "Could not create session for user" }; + return { error: t("errors.couldNotCreateSessionForUser") }; } const userResponse = await getUserByID({ @@ -191,7 +208,7 @@ export async function sendPassword(command: UpdateSessionCommand): Promise<{ err }); if (!userResponse.user) { - return { error: "User not found in the system" }; + return { error: t("errors.userNotFound") }; } user = userResponse.user; @@ -204,8 +221,8 @@ export async function sendPassword(command: UpdateSessionCommand): Promise<{ err }); } - if (!session?.factors?.user?.id) { - return { error: "Could not create session for user" }; + if (!session?.factors?.user?.id || !sessionCookie) { + return { error: t("errors.couldNotCreateSessionForUser") }; } const humanUser = user.type.case === "human" ? user.type.value : undefined; @@ -230,7 +247,7 @@ export async function sendPassword(command: UpdateSessionCommand): Promise<{ err // throw error if user is in initial state here and do not continue if (user.state === UserState.INITIAL) { - return { error: "Initial User not supported" }; + return { error: t("errors.initialUserNotSupported") }; } // check to see if user was verified @@ -253,7 +270,7 @@ export async function sendPassword(command: UpdateSessionCommand): Promise<{ err } if (!authMethods) { - return { error: "Could not verify password!" }; + return { error: t("errors.couldNotVerifyPassword") }; } const mfaFactorCheck = await checkMFAFactors( @@ -315,6 +332,7 @@ export async function sendPassword(command: UpdateSessionCommand): Promise<{ err export async function changePassword(command: { code?: string; userId: string; password: string }) { const _headers = await headers(); const { serviceUrl } = getServiceUrlFromHeaders(_headers); + const t = await getTranslations("password"); // check for init state const { user } = await getUserByID({ @@ -323,12 +341,12 @@ export async function changePassword(command: { code?: string; userId: string; p }); if (!user || user.userId !== command.userId) { - return { error: "Could not send Password Reset Link" }; + return { error: t("errors.couldNotSendResetLink") }; } const userId = user.userId; if (user.state === UserState.INITIAL) { - return { error: "User Initial State is not supported" }; + return { error: t("errors.userInitialStateNotSupported") }; } // check if the user has no password set in order to set a password @@ -341,7 +359,7 @@ export async function changePassword(command: { code?: string; userId: string; p // if the user has no authmethods set, we need to check if the user was verified if (authmethods.authMethodTypes.length !== 0) { return { - error: "You have to provide a code or have a valid User Verification Check", + error: t("errors.codeOrVerificationRequired"), }; } @@ -349,7 +367,7 @@ export async function changePassword(command: { code?: string; userId: string; p const hasValidUserVerificationCheck = await checkUserVerification(user.userId); if (!hasValidUserVerificationCheck) { - return { error: "User Verification Check has to be done" }; + return { error: t("errors.verificationRequired") }; } } @@ -369,6 +387,7 @@ type CheckSessionAndSetPasswordCommand = { export async function checkSessionAndSetPassword({ sessionId, password }: CheckSessionAndSetPasswordCommand) { const _headers = await headers(); const { serviceUrl } = getServiceUrlFromHeaders(_headers); + const t = await getTranslations("password"); let sessionCookie; try { @@ -392,7 +411,7 @@ export async function checkSessionAndSetPassword({ sessionId, password }: CheckS } if (!session || !session.factors?.user?.id) { - return { error: "Could not load session" }; + return { error: t("errors.couldNotLoadSession") }; } const payload = create(SetPasswordRequestSchema, { @@ -415,7 +434,7 @@ export async function checkSessionAndSetPassword({ sessionId, password }: CheckS } if (!authmethods) { - return { error: "Could not load auth methods" }; + return { error: t("errors.couldNotLoadAuthMethods") }; } let loginSettings; @@ -437,7 +456,7 @@ export async function checkSessionAndSetPassword({ sessionId, password }: CheckS return setPassword({ serviceUrl, payload }).catch((error) => { // throw error if failed precondition (ex. User is not yet initialized) if (error.code === 9 && error.message) { - return { error: "Failed precondition" }; + return { error: t("errors.failedPrecondition") }; } return { error: "Could not set password" }; }); @@ -464,7 +483,7 @@ export async function checkSessionAndSetPassword({ sessionId, password }: CheckS .catch((error: ConnectError) => { console.log(error); if (error.code === 7) { - return { error: "Session is not valid." }; + return { error: t("errors.sessionNotValid") }; } return { error: "Could not set the password" }; }); diff --git a/apps/login/src/lib/server/register.ts b/apps/login/src/lib/server/register.ts index 74647a387..fb6656f9d 100644 --- a/apps/login/src/lib/server/register.ts +++ b/apps/login/src/lib/server/register.ts @@ -6,11 +6,12 @@ import { create } from "@zitadel/client"; import { Factors } from "@zitadel/proto/zitadel/session/v2/session_pb"; import { ChecksJson, ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb"; import { cookies, headers } from "next/headers"; -import crypto from "crypto"; -import { completeFlowOrGetUrl } from "../client"; +import { getTranslations } from "next-intl/server"; import { getServiceUrlFromHeaders } from "../service-url"; import { checkEmailVerification, checkMFAFactors } from "../verify-helper"; import { getOrSetFingerprintId } from "../fingerprint"; +import crypto from "crypto"; +import { completeFlowOrGetUrl } from "../client"; type RegisterUserCommand = { email: string; @@ -27,6 +28,7 @@ export type RegisterUserResponse = { factors: Factors | undefined; }; export async function registerUser(command: RegisterUserCommand) { + const t = await getTranslations("register"); const _headers = await headers(); const { serviceUrl } = getServiceUrlFromHeaders(_headers); @@ -40,7 +42,7 @@ export async function registerUser(command: RegisterUserCommand) { }); if (!addResponse) { - return { error: "Could not create user" }; + return { error: t("errors.couldNotCreateUser") }; } const loginSettings = await getLoginSettings({ @@ -68,7 +70,7 @@ export async function registerUser(command: RegisterUserCommand) { }); if (!session || !session.factors?.user) { - return { error: "Could not create session" }; + return { error: t("errors.couldNotCreateSession") }; } if (!command.password) { @@ -104,7 +106,7 @@ export async function registerUser(command: RegisterUserCommand) { }); if (!userResponse.user) { - return { error: "User not found in the system" }; + return { error: t("errors.userNotFound") }; } const humanUser = userResponse.user.type.case === "human" ? userResponse.user.type.value : undefined; @@ -157,6 +159,8 @@ export type registerUserAndLinkToIDPResponse = { factors: Factors | undefined; }; export async function registerUserAndLinkToIDP(command: RegisterUserAndLinkToIDPommand) { + const t = await getTranslations("register"); + const _headers = await headers(); const { serviceUrl } = getServiceUrlFromHeaders(_headers); @@ -169,7 +173,7 @@ export async function registerUserAndLinkToIDP(command: RegisterUserAndLinkToIDP }); if (!addUserResponse) { - return { error: "Could not create user" }; + return { error: t("errors.couldNotCreateUser") }; } const loginSettings = await getLoginSettings({ @@ -188,7 +192,7 @@ export async function registerUserAndLinkToIDP(command: RegisterUserAndLinkToIDP }); if (!idpLink) { - return { error: "Could not link IDP to user" }; + return { error: t("errors.couldNotLinkIDP") }; } const session = await createSessionForIdpAndUpdateCookie({ @@ -199,7 +203,7 @@ export async function registerUserAndLinkToIDP(command: RegisterUserAndLinkToIDP }); if (!session || !session.factors?.user) { - return { error: "Could not create session" }; + return { error: t("errors.couldNotCreateSession") }; } // const userResponse = await getUserByID({ diff --git a/apps/login/src/lib/server/verify.ts b/apps/login/src/lib/server/verify.ts index 8326c428d..3fb450666 100644 --- a/apps/login/src/lib/server/verify.ts +++ b/apps/login/src/lib/server/verify.ts @@ -25,6 +25,7 @@ import { loadMostRecentSession } from "../session"; import { checkMFAFactors } from "../verify-helper"; import { createSessionAndUpdateCookie } from "./cookie"; import { getOriginalHostWithProtocol } from "./host"; +import { getTranslations } from "next-intl/server"; export async function verifyTOTP(code: string, loginName?: string, organization?: string) { const _headers = await headers(); @@ -59,6 +60,7 @@ type VerifyUserByEmailCommand = { }; export async function sendVerification(command: VerifyUserByEmailCommand) { + const t = await getTranslations("verify"); const _headers = await headers(); const { serviceUrl } = getServiceUrlFromHeaders(_headers); @@ -69,7 +71,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) { verificationCode: command.code, }).catch((error) => { console.warn(error); - return { error: "Could not verify invite" }; + return { error: t("errors.couldNotVerifyInvite") }; }) : await verifyEmail({ serviceUrl, @@ -77,7 +79,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) { verificationCode: command.code, }).catch((error) => { console.warn(error); - return { error: "Could not verify email" }; + return { error: t("errors.couldNotVerifyEmail") }; }); if ("error" in verifyResponse) { @@ -85,7 +87,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) { } if (!verifyResponse) { - return { error: "Could not verify" }; + return { error: t("errors.couldNotVerify") }; } let session: Session | undefined; @@ -95,7 +97,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) { }); if (!userResponse || !userResponse.user) { - return { error: "Could not load user" }; + return { error: t("errors.couldNotLoadUser") }; } const user = userResponse.user; @@ -126,7 +128,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) { }); if (!authMethodResponse || !authMethodResponse.authMethodTypes) { - return { error: "Could not load possible authenticators" }; + return { error: t("errors.couldNotLoadAuthenticators") }; } // if no authmethods are found on the user, redirect to set one up @@ -148,7 +150,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) { } if (!session) { - return { error: "Could not create session" }; + return { error: t("errors.couldNotCreateSession") }; } const params = new URLSearchParams({ @@ -249,6 +251,7 @@ type resendVerifyEmailCommand = { }; export async function resendVerification(command: resendVerifyEmailCommand) { + const t = await getTranslations("verify"); const _headers = await headers(); const { serviceUrl } = getServiceUrlFromHeaders(_headers); const hostWithProtocol = await getOriginalHostWithProtocol(); @@ -264,9 +267,9 @@ export async function resendVerification(command: resendVerifyEmailCommand) { (command.requestId ? `&requestId=${command.requestId}` : ""), }).catch((error) => { if (error.code === 9) { - return { error: "User is already verified!" }; + return { error: t("errors.userAlreadyVerified") }; } - return { error: "Could not resend invite" }; + return { error: t("errors.couldNotResendInvite") }; }) : zitadelSendEmailCode({ userId: command.userId, diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index ae2a12770..b289fc3cf 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -30,6 +30,7 @@ import { VerifyU2FRegistrationRequest, } from "@zitadel/proto/zitadel/user/v2/user_service_pb"; import { unstable_cacheLife as cacheLife } from "next/cache"; +import { getTranslations } from "next-intl/server"; import { getUserAgent } from "./fingerprint"; import { setSAMLFormCookie } from "./saml"; import { createServiceForHost } from "./service"; @@ -614,6 +615,8 @@ const EmailQuery = (searchValue: string) => export async function searchUsers({ serviceUrl, searchValue, loginSettings, organizationId, suffix }: SearchUsersCommand) { const queries: SearchQuery[] = []; + const t = await getTranslations("zitadel"); + // if a suffix is provided, we search for the userName concatenated with the suffix if (suffix) { const searchValueWithSuffix = `${searchValue}@${suffix}`; @@ -642,11 +645,11 @@ export async function searchUsers({ serviceUrl, searchValue, loginSettings, orga const loginNameResult = await userService.listUsers({ queries }); if (!loginNameResult || !loginNameResult.details) { - return { error: "An error occurred." }; + return { error: t("errors.errorOccured") }; } if (loginNameResult.result.length > 1) { - return { error: "Multiple users found" }; + return { error: t("errors.multipleUsersFound") }; } if (loginNameResult.result.length == 1) { @@ -655,7 +658,7 @@ export async function searchUsers({ serviceUrl, searchValue, loginSettings, orga const emailAndPhoneQueries: SearchQuery[] = []; if (loginSettings.disableLoginWithEmail && loginSettings.disableLoginWithPhone) { - return { error: "User not found in the system" }; + return { error: t("errors.userNotFound") }; } else if (loginSettings.disableLoginWithEmail && searchValue.length <= 20) { const phoneQuery = PhoneQuery(searchValue); emailAndPhoneQueries.push(phoneQuery); @@ -704,18 +707,18 @@ export async function searchUsers({ serviceUrl, searchValue, loginSettings, orga }); if (!emailOrPhoneResult || !emailOrPhoneResult.details) { - return { error: "An error occurred." }; + return { error: t("errors.errorOccured") }; } if (emailOrPhoneResult.result.length > 1) { - return { error: "Multiple users found." }; + return { error: t("errors.multipleUsersFound") }; } if (emailOrPhoneResult.result.length == 1) { return emailOrPhoneResult; } - return { error: "User not found in the system" }; + return { error: t("errors.userNotFound") }; } export async function getDefaultOrg({ serviceUrl }: { serviceUrl: string }): Promise {