diff --git a/locales/de.json b/locales/de.json index 55a635512..843d31772 100644 --- a/locales/de.json +++ b/locales/de.json @@ -66,7 +66,13 @@ "code": "Dieses Feld ist erforderlich", "newPassword": "Bitte geben Sie ein Passwort ein!", "confirmPassword": "Dieses Feld ist erforderlich" - } + }, + "minLength": "Mindestens", + "symbol": "Ein Symbol", + "number": "Eine Zahl", + "uppercase": "Ein Großbuchstabe", + "lowercase": "Ein Kleinbuchstabe", + "equals": "Übereinstimmung" }, "change": { "title": "Passwort ändern", @@ -244,7 +250,8 @@ "firstname": "Dieses Feld ist erforderlich", "lastname": "Dieses Feld ist erforderlich", "email": "Dieses Feld ist erforderlich" - } + }, + "orUseIDP": "oder einen Identity Provider verwenden" }, "invite": { "title": "Benutzer einladen", @@ -329,5 +336,102 @@ "sessionExpired": "Ihre aktuelle Sitzung ist abgelaufen. Bitte melden Sie sich erneut an.", "failedLoading": "Daten konnten nicht geladen werden. Bitte versuchen Sie es erneut.", "tryagain": "Erneut versuchen" + }, + "server": { + "common": { + "errors": { + "couldNotGetHost": "Host konnte nicht ermittelt werden", + "couldNotGetDomain": "Domain konnte nicht ermittelt werden", + "couldNotGetHostname": "Hostname konnte nicht ermittelt werden", + "couldNotGetSession": "Sitzung konnte nicht ermittelt werden", + "couldNotCreateSession": "Sitzung konnte nicht erstellt werden", + "noHostFound": "Kein Host gefunden", + "couldNotLoadLoginSettings": "Anmeldeeinstellungen konnten nicht geladen werden", + "failedToAuthenticate": "Authentifizierung fehlgeschlagen. Sie hatten {failedAttempts} Versuche von {maxAttempts} für das Passwort.", + "userNotFoundInSystem": "Benutzer im System nicht gefunden", + "userVerificationCheckRequired": "Benutzerverifizierung erforderlich", + "couldNotFindSession": "Sitzung konnte nicht gefunden werden", + "couldNotUpdateSession": "Sitzung konnte nicht aktualisiert werden", + "couldNotVerify": "Verifizierung nicht möglich", + "couldNotStartIdpFlow": "IDP-Flow konnte nicht gestartet werden", + "initialUserNotSupported": "Initialer Benutzer nicht unterstützt", + "couldNotSetPassword": "Passwort konnte nicht gesetzt werden" + } + }, + "password": { + "errors": { + "couldNotSendPasswordResetLink": "Passwort-Reset-Link konnte nicht gesendet werden", + "couldNotCreateSessionForUser": "Sitzung für Benutzer konnte nicht erstellt werden", + "couldNotVerifyPassword": "Passwort konnte nicht verifiziert werden", + "noPasswordLifetimeProvided": "Keine Passwort-Lebensdauer angegeben, Standard 24 Stunden wird verwendet", + "contactAdministratorToUnlock": "Kontaktieren Sie Ihren Administrator, um Ihr Konto zu entsperren", + "couldNotVerifyPasswordExclamation": "Passwort konnte nicht verifiziert werden!", + "userInitialStateNotSupported": "Benutzer-Initialzustand nicht unterstützt", + "provideCodeOrValidVerification": "Sie müssen einen Code angeben oder eine gültige Benutzerverifizierung haben", + "couldNotLoadSession": "Sitzung konnte nicht geladen werden", + "couldNotLoadAuthMethods": "Authentifizierungsmethoden konnten nicht geladen werden", + "failedPrecondition": "Vorbedingung fehlgeschlagen" + } + }, + "session": { + "errors": { + "sessionNotValid": "Sitzung ist nicht gültig.", + "noLifetimeProvidedForSession": "Keine Lebensdauer für Sitzung angegeben, Standard 24 Stunden wird verwendet", + "couldNotDeleteSession": "Sitzung konnte nicht gelöscht werden" + } + }, + "passkeys": { + "errors": { + "couldNotDetermineUserFromSession": "Benutzer konnte nicht aus Sitzung ermittelt werden", + "authenticateOrValidVerification": "Sie müssen sich authentifizieren oder eine gültige Benutzerverifizierung haben", + "missingCodeInResponse": "Code in Antwort fehlt", + "noPasskeyLifetimeProvided": "Keine Passkey-Lebensdauer angegeben, Standard 24 Stunden wird verwendet", + "noUserIdFoundInSession": "Keine Benutzer-ID in Sitzung gefunden.", + "couldNotCreateRegistrationLink": "Registrierungslink konnte nicht erstellt werden" + } + }, + "verify": { + "errors": { + "couldNotVerifyInvite": "Einladung konnte nicht verifiziert werden", + "couldNotVerifyEmail": "E-Mail konnte nicht verifiziert werden", + "couldNotLoadUser": "Benutzer konnte nicht geladen werden", + "couldNotLoadPossibleAuthenticators": "Mögliche Authentifikatoren konnten nicht geladen werden", + "userAlreadyVerified": "Benutzer bereits verifiziert!", + "couldNotResendInvite": "Einladung konnte nicht erneut gesendet werden" + } + }, + "register": { + "errors": { + "couldNotCreateUser": "Benutzer konnte nicht erstellt werden", + "couldNotLinkIdpToUser": "IDP konnte nicht mit Benutzer verknüpft werden" + } + }, + "loginname": { + "errors": { + "couldNotSearchUsers": "Benutzer konnten nicht gesucht werden", + "couldNotFindIdentityProvider": "Identity Provider konnte nicht gefunden werden", + "moreThanOneUserFound": "Mehr als ein Benutzer gefunden. Geben Sie eine eindeutige Kennung an.", + "usernamePasswordNotAllowed": "Benutzername und Passwort nicht erlaubt! Kontaktieren Sie Ihren Administrator für weitere Informationen.", + "passkeysNotAllowed": "Passkeys nicht erlaubt! Kontaktieren Sie Ihren Administrator für weitere Informationen." + } + }, + "idp": { + "errors": { + "unexpectedResponseFromIdpFlow": "Unerwartete Antwort vom IDP-Flow", + "noUsernameOrPasswordProvided": "Kein Benutzername oder Passwort angegeben", + "couldNotStartLdapIdpFlow": "LDAP Identity Provider Flow konnte nicht gestartet werden" + } + }, + "cookie": { + "errors": { + "noSessionLifetimeProvided": "Keine Sitzungslebensdauer angegeben, Standard 24 Stunden wird verwendet.", + "noIdpSessionLifetimeProvided": "Keine IDP-Sitzungslebensdauer angegeben, Standard 24 Stunden wird verwendet.", + "couldNotGetSessionOrLoginName": "Sitzung konnte nicht abgerufen werden oder Sitzung hat keinen Anmeldenamen", + "couldNotRetrieveSession": "Sitzung konnte nicht abgerufen werden", + "sessionCouldNotBeSet": "Sitzung konnte nicht gesetzt werden", + "failedToAuthenticateAttempts": "Authentifizierung fehlgeschlagen: Sie hatten {failedAttempts} Passwort-Versuche.", + "failedToAuthenticateIdpAttempts": "Authentifizierung fehlgeschlagen: Sie hatten {failedAttempts} Passwort-Versuche." + } + } } } diff --git a/locales/en.json b/locales/en.json index 8d8c11ec3..e8934484d 100644 --- a/locales/en.json +++ b/locales/en.json @@ -66,7 +66,13 @@ "code": "This field is required", "newPassword": "You have to provide a password!", "confirmPassword": "This field is required" - } + }, + "minLength": "Minimum", + "symbol": "A symbol", + "number": "A number", + "uppercase": "An uppercase letter", + "lowercase": "A lowercase letter", + "equals": "Match" }, "change": { "title": "Change Password", @@ -235,6 +241,7 @@ "confirmPassword": "This field is required" } }, + "orUseIDP": "or use an identity provider", "labels": { "firstname": "First name", "lastname": "Last name", @@ -329,5 +336,102 @@ "sessionExpired": "Your current session has expired. Please login again.", "failedLoading": "Failed to load data. Please try again.", "tryagain": "Try Again" + }, + "server": { + "common": { + "errors": { + "couldNotGetHost": "Could not get host", + "couldNotGetDomain": "Could not get domain", + "couldNotGetHostname": "Could not get hostname", + "couldNotGetSession": "Could not get session", + "couldNotCreateSession": "Could not create session", + "noHostFound": "No host found", + "couldNotLoadLoginSettings": "Could not load login settings", + "failedToAuthenticate": "Failed to authenticate. You have had {failedAttempts} attempts out of {maxAttempts} for the password.", + "userNotFoundInSystem": "User not found in system", + "userVerificationCheckRequired": "User verification check required", + "couldNotFindSession": "Could not find session", + "couldNotUpdateSession": "Could not update session", + "couldNotVerify": "Could not verify", + "couldNotStartIdpFlow": "Could not start IDP flow", + "initialUserNotSupported": "Initial user not supported", + "couldNotSetPassword": "Could not set password" + } + }, + "password": { + "errors": { + "couldNotSendPasswordResetLink": "Could not send password reset link", + "couldNotCreateSessionForUser": "Could not create session for user", + "couldNotVerifyPassword": "Could not verify password", + "noPasswordLifetimeProvided": "No password lifetime provided, defaulting to 24 hours", + "contactAdministratorToUnlock": "Contact your administrator to unlock your account", + "couldNotVerifyPasswordExclamation": "Could not verify password!", + "userInitialStateNotSupported": "User initial state not supported", + "provideCodeOrValidVerification": "You must provide a code or have a valid user verification", + "couldNotLoadSession": "Could not load session", + "couldNotLoadAuthMethods": "Could not load authentication methods", + "failedPrecondition": "Failed precondition" + } + }, + "session": { + "errors": { + "sessionNotValid": "Session is not valid.", + "noLifetimeProvidedForSession": "No lifetime provided for session, defaulting to 24 hours", + "couldNotDeleteSession": "Could not delete session" + } + }, + "passkeys": { + "errors": { + "couldNotDetermineUserFromSession": "Could not determine user from session", + "authenticateOrValidVerification": "You must authenticate or have a valid user verification", + "missingCodeInResponse": "Missing code in response", + "noPasskeyLifetimeProvided": "No passkey lifetime provided, defaulting to 24 hours", + "noUserIdFoundInSession": "No user ID found in session.", + "couldNotCreateRegistrationLink": "Could not create registration link" + } + }, + "verify": { + "errors": { + "couldNotVerifyInvite": "Could not verify invite", + "couldNotVerifyEmail": "Could not verify email", + "couldNotLoadUser": "Could not load user", + "couldNotLoadPossibleAuthenticators": "Could not load possible authenticators", + "userAlreadyVerified": "User already verified!", + "couldNotResendInvite": "Could not resend invite" + } + }, + "register": { + "errors": { + "couldNotCreateUser": "Could not create user", + "couldNotLinkIdpToUser": "Could not link IDP to user" + } + }, + "loginname": { + "errors": { + "couldNotSearchUsers": "Could not search users", + "couldNotFindIdentityProvider": "Could not find identity provider", + "moreThanOneUserFound": "More than one user found. Provide a unique identifier.", + "usernamePasswordNotAllowed": "Username and password not allowed! Contact your administrator for more information.", + "passkeysNotAllowed": "Passkeys not allowed! Contact your administrator for more information." + } + }, + "idp": { + "errors": { + "unexpectedResponseFromIdpFlow": "Unexpected response from IDP flow", + "noUsernameOrPasswordProvided": "No username or password provided", + "couldNotStartLdapIdpFlow": "Could not start LDAP identity provider flow" + } + }, + "cookie": { + "errors": { + "noSessionLifetimeProvided": "No session lifetime provided, using default 24 hours.", + "noIdpSessionLifetimeProvided": "No IDP session lifetime provided, using default 24 hours.", + "couldNotGetSessionOrLoginName": "Could not get session or session has no login name", + "couldNotRetrieveSession": "Could not retrieve session", + "sessionCouldNotBeSet": "Session could not be set", + "failedToAuthenticateAttempts": "Failed to authenticate: You have had {failedAttempts} password attempts.", + "failedToAuthenticateIdpAttempts": "Failed to authenticate: You have had {failedAttempts} password attempts." + } + } } } diff --git a/locales/es.json b/locales/es.json index 82f1e9335..fea008c8a 100644 --- a/locales/es.json +++ b/locales/es.json @@ -66,7 +66,13 @@ "code": "Este campo es obligatorio", "newPassword": "¡Debes proporcionar una contraseña!", "confirmPassword": "Este campo es obligatorio" - } + }, + "minLength": "Mínimo", + "symbol": "Un símbolo", + "number": "Un número", + "uppercase": "Una letra mayúscula", + "lowercase": "Una letra minúscula", + "equals": "Coinciden" }, "change": { "title": "Cambiar Contraseña", @@ -244,7 +250,8 @@ "firstname": "Este campo es obligatorio", "lastname": "Este campo es obligatorio", "email": "Este campo es obligatorio" - } + }, + "orUseIDP": "o usar un proveedor de identidad" }, "invite": { "title": "Invitar usuario", @@ -329,5 +336,102 @@ "sessionExpired": "Tu sesión actual ha expirado. Por favor, inicia sesión de nuevo.", "failedLoading": "No se pudieron cargar los datos. Por favor, inténtalo de nuevo.", "tryagain": "Intentar de nuevo" + }, + "server": { + "common": { + "errors": { + "couldNotGetHost": "No se pudo obtener el host", + "couldNotGetDomain": "No se pudo obtener el dominio", + "couldNotGetHostname": "No se pudo obtener el nombre del host", + "couldNotGetSession": "No se pudo obtener la sesión", + "couldNotCreateSession": "No se pudo crear la sesión", + "noHostFound": "No se encontró ningún host", + "couldNotLoadLoginSettings": "No se pudieron cargar las configuraciones de inicio de sesión", + "failedToAuthenticate": "Error de autenticación. Has tenido {failedAttempts} intentos de {maxAttempts} para la contraseña.", + "userNotFoundInSystem": "Usuario no encontrado en el sistema", + "userVerificationCheckRequired": "Se requiere verificación del usuario", + "couldNotFindSession": "No se pudo encontrar la sesión", + "couldNotUpdateSession": "No se pudo actualizar la sesión", + "couldNotVerify": "No se pudo verificar", + "couldNotStartIdpFlow": "No se pudo iniciar el flujo IDP", + "initialUserNotSupported": "Usuario inicial no compatible", + "couldNotSetPassword": "No se pudo establecer la contraseña" + } + }, + "password": { + "errors": { + "couldNotSendPasswordResetLink": "No se pudo enviar el enlace de restablecimiento de contraseña", + "couldNotCreateSessionForUser": "No se pudo crear una sesión para el usuario", + "couldNotVerifyPassword": "No se pudo verificar la contraseña", + "noPasswordLifetimeProvided": "No se proporcionó vida útil de contraseña, por defecto 24 horas", + "contactAdministratorToUnlock": "Contacta a tu administrador para desbloquear tu cuenta", + "couldNotVerifyPasswordExclamation": "¡No se pudo verificar la contraseña!", + "userInitialStateNotSupported": "Estado inicial del usuario no compatible", + "provideCodeOrValidVerification": "Debes proporcionar un código o tener una verificación de usuario válida", + "couldNotLoadSession": "No se pudo cargar la sesión", + "couldNotLoadAuthMethods": "No se pudieron cargar los métodos de autenticación", + "failedPrecondition": "Precondición fallida" + } + }, + "session": { + "errors": { + "sessionNotValid": "La sesión no es válida.", + "noLifetimeProvidedForSession": "No se proporcionó vida útil para la sesión, por defecto 24 horas", + "couldNotDeleteSession": "No se pudo eliminar la sesión" + } + }, + "passkeys": { + "errors": { + "couldNotDetermineUserFromSession": "No se pudo determinar el usuario desde la sesión", + "authenticateOrValidVerification": "Debes autenticarte o tener una verificación de usuario válida", + "missingCodeInResponse": "Código faltante en la respuesta", + "noPasskeyLifetimeProvided": "No se proporcionó vida útil de passkey, por defecto 24 horas", + "noUserIdFoundInSession": "No se encontró ID de usuario en la sesión.", + "couldNotCreateRegistrationLink": "No se pudo crear el enlace de registro" + } + }, + "verify": { + "errors": { + "couldNotVerifyInvite": "No se pudo verificar la invitación", + "couldNotVerifyEmail": "No se pudo verificar el correo electrónico", + "couldNotLoadUser": "No se pudo cargar el usuario", + "couldNotLoadPossibleAuthenticators": "No se pudieron cargar los autenticadores posibles", + "userAlreadyVerified": "¡Usuario ya verificado!", + "couldNotResendInvite": "No se pudo reenviar la invitación" + } + }, + "register": { + "errors": { + "couldNotCreateUser": "No se pudo crear el usuario", + "couldNotLinkIdpToUser": "No se pudo vincular IDP al usuario" + } + }, + "loginname": { + "errors": { + "couldNotSearchUsers": "No se pudieron buscar usuarios", + "couldNotFindIdentityProvider": "No se pudo encontrar el proveedor de identidad", + "moreThanOneUserFound": "Se encontró más de un usuario. Proporciona un identificador único.", + "usernamePasswordNotAllowed": "¡Nombre de usuario y contraseña no permitidos! Contacta a tu administrador para más información.", + "passkeysNotAllowed": "¡Passkeys no permitidos! Contacta a tu administrador para más información." + } + }, + "idp": { + "errors": { + "unexpectedResponseFromIdpFlow": "Respuesta inesperada del flujo IDP", + "noUsernameOrPasswordProvided": "No se proporcionó nombre de usuario o contraseña", + "couldNotStartLdapIdpFlow": "No se pudo iniciar el flujo del proveedor de identidad LDAP" + } + }, + "cookie": { + "errors": { + "noSessionLifetimeProvided": "No se proporcionó vida útil de sesión, usando por defecto 24 horas.", + "noIdpSessionLifetimeProvided": "No se proporcionó vida útil de sesión IDP, usando por defecto 24 horas.", + "couldNotGetSessionOrLoginName": "No se pudo obtener la sesión o la sesión no tiene nombre de inicio de sesión", + "couldNotRetrieveSession": "No se pudo recuperar la sesión", + "sessionCouldNotBeSet": "No se pudo establecer la sesión", + "failedToAuthenticateAttempts": "Error de autenticación: Has tenido {failedAttempts} intentos de contraseña.", + "failedToAuthenticateIdpAttempts": "Error de autenticación: Has tenido {failedAttempts} intentos de contraseña." + } + } } } diff --git a/locales/fr.json b/locales/fr.json new file mode 100644 index 000000000..4a34034f5 --- /dev/null +++ b/locales/fr.json @@ -0,0 +1,441 @@ +{ + "common": { + "back": "Retour", + "title": "Se connecter avec Zitadel" + }, + "accounts": { + "title": "Comptes", + "description": "Sélectionnez le compte que vous souhaitez utiliser.", + "addAnother": "Ajouter un autre compte", + "noResults": "Aucun compte trouvé", + "verified": "vérifié", + "expired": "expiré" + }, + "logout": { + "title": "Déconnexion", + "description": "Cliquez sur un compte pour terminer la session", + "noResults": "Aucun compte trouvé", + "clear": "Terminer la session", + "verifiedAt": "Dernière activité : {time}", + "success": { + "title": "Déconnexion réussie", + "description": "Vous vous êtes déconnecté avec succès." + } + }, + "loginname": { + "title": "Connectez-vous à votre compte", + "description": "Saisissez vos données de connexion.", + "register": "Inscrire un nouvel utilisateur", + "submit": "Continuer", + "labels": { + "loginname": "E-mail", + "username": "Nom d'utilisateur", + "usernameOrPhoneNumber": "Nom d'utilisateur ou numéro de téléphone", + "usernameOrEmail": "Nom d'utilisateur ou adresse e-mail" + }, + "required": { + "loginName": "Ce champ est obligatoire" + } + }, + "password": { + "verify": { + "title": "Mot de passe", + "description": "Saisissez votre mot de passe.", + "resetPassword": "Réinitialiser le mot de passe", + "submit": "Continuer", + "labels": { + "password": "Mot de passe" + }, + "required": { + "password": "Ce champ est obligatoire" + } + }, + "set": { + "title": "Définir le mot de passe", + "description": "Définissez le mot de passe pour votre compte", + "codeSent": "Un code a été envoyé à votre adresse e-mail.", + "noCodeReceived": "Vous n'avez pas reçu de code ?", + "resend": "Renvoyer le code", + "submit": "Continuer", + "labels": { + "code": "Code", + "newPassword": "Nouveau mot de passe", + "confirmPassword": "Confirmer le mot de passe" + }, + "required": { + "code": "Ce champ est obligatoire", + "newPassword": "Vous devez fournir un mot de passe !", + "confirmPassword": "Ce champ est obligatoire" + }, + "newPassword": "Nouveau mot de passe", + "confirmPassword": "Confirmer le mot de passe", + "minLength": "Minimum", + "symbol": "Un symbole", + "number": "Un chiffre", + "uppercase": "Une majuscule", + "lowercase": "Une minuscule", + "equals": "Identiques" + }, + "change": { + "title": "Changer le mot de passe", + "description": "Définissez le mot de passe pour votre compte", + "submit": "Continuer", + "labels": { + "newPassword": "Nouveau mot de passe", + "confirmPassword": "Confirmer le mot de passe" + }, + "required": { + "newPassword": "Vous devez fournir un nouveau mot de passe !", + "confirmPassword": "Ce champ est obligatoire" + } + } + }, + "idp": { + "title": "Se connecter avec SSO", + "description": "Sélectionnez l'un des fournisseurs suivants pour vous connecter", + "orSignInWith": "ou se connecter avec", + "signInWithApple": "Se connecter avec Apple", + "signInWithGoogle": "Se connecter avec Google", + "signInWithAzureAD": "Se connecter avec AzureAD", + "signInWithGithub": "Se connecter avec GitHub", + "signInWithGitlab": "Se connecter avec GitLab", + "loginSuccess": { + "title": "Connexion réussie", + "description": "Vous avez été connecté avec succès !" + }, + "linkingSuccess": { + "title": "Compte lié", + "description": "Vous avez lié votre compte avec succès !" + }, + "registerSuccess": { + "title": "Inscription réussie", + "description": "Vous vous êtes inscrit avec succès !" + }, + "loginError": { + "title": "Échec de la connexion", + "description": "Une erreur s'est produite lors de la tentative de connexion." + }, + "linkingError": { + "title": "Échec de la liaison du compte", + "description": "Une erreur s'est produite lors de la tentative de liaison de votre compte." + }, + "completeRegister": { + "title": "Complétez vos données", + "description": "Vous devez compléter votre inscription en fournissant votre adresse e-mail et votre nom." + } + }, + "ldap": { + "title": "Connexion LDAP", + "description": "Saisissez vos identifiants LDAP.", + "username": "Nom d'utilisateur", + "password": "Mot de passe", + "submit": "Continuer", + "labels": { + "username": "Nom d'utilisateur", + "password": "Mot de passe" + }, + "required": { + "username": "Ce champ est obligatoire", + "password": "Ce champ est obligatoire" + } + }, + "mfa": { + "verify": { + "title": "Vérifiez votre identité", + "description": "Choisissez l'un des facteurs suivants.", + "noResults": "Aucun second facteur disponible à configurer." + }, + "set": { + "title": "Configurer l'authentification à 2 facteurs", + "description": "Choisissez l'un des seconds facteurs suivants.", + "skip": "Ignorer" + } + }, + "otp": { + "verify": { + "title": "Vérifier l'authentification à 2 facteurs", + "totpDescription": "Saisissez le code de votre application d'authentification.", + "smsDescription": "Saisissez le code que vous avez reçu par SMS.", + "emailDescription": "Saisissez le code que vous avez reçu par e-mail.", + "noCodeReceived": "Vous n'avez pas reçu de code ?", + "resendCode": "Renvoyer le code", + "submit": "Continuer", + "labels": { + "code": "Code" + }, + "required": { + "code": "Ce champ est obligatoire" + } + }, + "set": { + "title": "Configurer l'authentification à 2 facteurs", + "totpDescription": "Scannez le code QR avec votre application d'authentification.", + "smsDescription": "Saisissez votre numéro de téléphone pour recevoir un code par SMS.", + "emailDescription": "Saisissez votre adresse e-mail pour recevoir un code par e-mail.", + "totpRegisterDescription": "Scannez le code QR ou naviguez vers l'URL manuellement.", + "submit": "Continuer", + "labels": { + "code": "Code" + }, + "required": { + "code": "Ce champ est obligatoire" + } + } + }, + "passkey": { + "verify": { + "title": "S'authentifier avec une clé d'accès", + "description": "Votre appareil vous demandera votre empreinte digitale, votre visage ou le verrouillage d'écran", + "usePassword": "Utiliser le mot de passe", + "submit": "Continuer" + }, + "set": { + "title": "Configurer une clé d'accès", + "description": "Votre appareil vous demandera votre empreinte digitale, votre visage ou le verrouillage d'écran", + "info": { + "description": "Une clé d'accès est une méthode d'authentification sur un appareil comme votre empreinte digitale, Apple FaceID ou similaire. ", + "link": "Authentification sans mot de passe" + }, + "skip": "Ignorer", + "submit": "Continuer" + } + }, + "u2f": { + "verify": { + "title": "Vérifier l'authentification à 2 facteurs", + "description": "Vérifiez votre compte avec votre appareil." + }, + "set": { + "title": "Configurer l'authentification à 2 facteurs", + "description": "Configurez un appareil comme second facteur.", + "submit": "Continuer" + } + }, + "register": { + "methods": { + "passkey": "Clé d'accès", + "password": "Mot de passe" + }, + "disabled": { + "title": "Inscription désactivée", + "description": "L'inscription est désactivée. Veuillez contacter votre administrateur." + }, + "missingdata": { + "title": "Données manquantes", + "description": "Fournissez l'e-mail, le prénom et le nom de famille pour vous inscrire." + }, + "title": "S'inscrire", + "description": "Créez votre compte ZITADEL.", + "noMethodAvailableWarning": "Aucune méthode d'authentification disponible. Veuillez contacter votre administrateur.", + "selectMethod": "Sélectionnez la méthode avec laquelle vous souhaitez vous authentifier", + "agreeTo": "Pour vous inscrire, vous devez accepter les conditions générales", + "termsOfService": "Conditions d'utilisation", + "privacyPolicy": "Politique de confidentialité", + "submit": "Continuer", + "orUseIDP": "ou utiliser un fournisseur d'identité", + "password": { + "title": "Définir le mot de passe", + "description": "Définissez le mot de passe pour votre compte", + "submit": "Continuer", + "labels": { + "password": "Mot de passe", + "confirmPassword": "Confirmer le mot de passe" + }, + "required": { + "password": "Vous devez fournir un mot de passe !", + "confirmPassword": "Ce champ est obligatoire" + } + }, + "labels": { + "firstname": "Prénom", + "lastname": "Nom de famille", + "email": "E-mail" + }, + "required": { + "firstname": "Ce champ est obligatoire", + "lastname": "Ce champ est obligatoire", + "email": "Ce champ est obligatoire" + } + }, + "invite": { + "title": "Inviter un utilisateur", + "description": "Fournissez l'adresse e-mail et le nom de l'utilisateur que vous souhaitez inviter.", + "info": "L'utilisateur recevra un e-mail avec des instructions supplémentaires.", + "notAllowed": "Vos paramètres ne vous permettent pas d'inviter des utilisateurs.", + "submit": "Continuer", + "success": { + "title": "Utilisateur invité", + "description": "L'e-mail a été envoyé avec succès.", + "verified": "L'utilisateur a été invité et a déjà vérifié son e-mail.", + "notVerifiedYet": "L'utilisateur a été invité. Il recevra un e-mail avec des instructions supplémentaires.", + "submit": "Inviter un autre utilisateur" + } + }, + "signedin": { + "title": "Bienvenue {user} !", + "description": "Vous êtes connecté.", + "continue": "Continuer", + "error": { + "title": "Erreur", + "description": "Une erreur s'est produite lors de la tentative de connexion." + } + }, + "verify": { + "userIdMissing": "Aucun userId fourni !", + "successTitle": "Utilisateur vérifié", + "successDescription": "L'utilisateur a été vérifié avec succès.", + "setupAuthenticator": "Configurer l'authentificateur", + "verify": { + "title": "Vérifier l'utilisateur", + "description": "Saisissez le code fourni dans l'e-mail de vérification.", + "noCodeReceived": "Vous n'avez pas reçu de code ?", + "resendCode": "Renvoyer le code", + "codeSent": "Un code vient d'être envoyé à votre adresse e-mail.", + "submit": "Continuer", + "labels": { + "code": "Code" + }, + "required": { + "code": "Ce champ est obligatoire" + } + } + }, + "authenticator": { + "title": "Choisir la méthode d'authentification", + "description": "Sélectionnez la méthode avec laquelle vous souhaitez vous authentifier", + "noMethodsAvailable": "Aucune méthode d'authentification disponible", + "allSetup": "Vous avez déjà configuré un authentificateur !", + "linkWithIDP": "ou lier avec un fournisseur d'identité" + }, + "device": { + "usercode": { + "title": "Code d'appareil", + "description": "Saisissez le code affiché sur votre application ou appareil.", + "submit": "Continuer", + "labels": { + "code": "Code" + }, + "required": { + "code": "Ce champ est obligatoire" + } + }, + "request": { + "title": "{appName} souhaite se connecter", + "description": "{appName} aura accès à :", + "disclaimer": "En cliquant sur Autoriser, vous autorisez {appName} et Zitadel à utiliser vos informations conformément à leurs conditions d'utilisation et politiques de confidentialité respectives. Vous pouvez révoquer cet accès à tout moment.", + "submit": "Autoriser", + "deny": "Refuser" + }, + "scope": { + "openid": "Vérifier votre identité.", + "email": "Voir votre adresse e-mail.", + "profile": "Voir vos informations de profil complètes.", + "offline_access": "Autoriser l'accès hors ligne à votre compte." + } + }, + "error": { + "noUserCode": "Aucun code utilisateur fourni !", + "noDeviceRequest": "Aucune demande d'appareil trouvée.", + "unknownContext": "Impossible d'obtenir le contexte de l'utilisateur. Assurez-vous de saisir d'abord le nom d'utilisateur ou fournissez un loginName comme searchParam.", + "sessionExpired": "Votre session actuelle a expiré. Veuillez vous reconnecter.", + "failedLoading": "Échec du chargement des données. Veuillez réessayer.", + "tryagain": "Réessayer" + }, + "server": { + "common": { + "errors": { + "couldNotGetHost": "Impossible d'obtenir l'hôte", + "couldNotGetDomain": "Impossible d'obtenir le domaine", + "couldNotGetHostname": "Impossible d'obtenir le nom d'hôte", + "couldNotGetSession": "Impossible d'obtenir la session", + "couldNotCreateSession": "Impossible de créer la session", + "couldNotSetPassword": "Impossible de définir le mot de passe", + "noHostFound": "Aucun hôte trouvé", + "couldNotLoadLoginSettings": "Impossible de charger les paramètres de connexion", + "failedToAuthenticate": "Échec de l'authentification. Vous avez eu {failedAttempts} tentatives sur {maxAttempts} pour le mot de passe.", + "userNotFoundInSystem": "Utilisateur non trouvé dans le système", + "userVerificationCheckRequired": "La vérification de l'utilisateur doit être effectuée", + "couldNotFindSession": "Impossible de trouver la session", + "couldNotUpdateSession": "Impossible de mettre à jour la session", + "couldNotVerify": "Impossible de vérifier", + "couldNotStartIdpFlow": "Impossible de démarrer le flux IDP", + "initialUserNotSupported": "Utilisateur initial non pris en charge" + } + }, + "password": { + "errors": { + "couldNotSendPasswordResetLink": "Impossible d'envoyer le lien de réinitialisation du mot de passe", + "couldNotCreateSessionForUser": "Impossible de créer une session pour l'utilisateur", + "couldNotVerifyPassword": "Impossible de vérifier le mot de passe", + "noPasswordLifetimeProvided": "Aucune durée de vie de mot de passe fournie, par défaut 24 heures", + "contactAdministratorToUnlock": "Contactez votre administrateur pour débloquer votre compte", + "couldNotVerifyPasswordExclamation": "Impossible de vérifier le mot de passe !", + "userInitialStateNotSupported": "État initial de l'utilisateur non pris en charge", + "provideCodeOrValidVerification": "Vous devez fournir un code ou avoir une vérification utilisateur valide", + "couldNotLoadSession": "Impossible de charger la session", + "couldNotLoadAuthMethods": "Impossible de charger les méthodes d'authentification", + "failedPrecondition": "Précondition échouée" + } + }, + "session": { + "errors": { + "sessionNotValid": "La session n'est pas valide.", + "noLifetimeProvidedForSession": "Aucune durée de vie fournie pour la session, par défaut 24 heures", + "couldNotDeleteSession": "Impossible de supprimer la session" + } + }, + "passkeys": { + "errors": { + "couldNotDetermineUserFromSession": "Impossible de déterminer l'utilisateur à partir de la session", + "authenticateOrValidVerification": "Vous devez vous authentifier ou avoir une vérification utilisateur valide", + "missingCodeInResponse": "Code manquant dans la réponse", + "noPasskeyLifetimeProvided": "Aucune durée de vie de clé d'accès fournie, par défaut 24 heures", + "noUserIdFoundInSession": "Aucun ID utilisateur trouvé dans la session.", + "couldNotCreateRegistrationLink": "Impossible de créer le lien d'enregistrement" + } + }, + "verify": { + "errors": { + "couldNotVerifyInvite": "Impossible de vérifier l'invitation", + "couldNotVerifyEmail": "Impossible de vérifier l'e-mail", + "couldNotLoadUser": "Impossible de charger l'utilisateur", + "couldNotLoadPossibleAuthenticators": "Impossible de charger les authentificateurs possibles", + "userAlreadyVerified": "L'utilisateur est déjà vérifié !", + "couldNotResendInvite": "Impossible de renvoyer l'invitation" + } + }, + "register": { + "errors": { + "couldNotCreateUser": "Impossible de créer l'utilisateur", + "couldNotLinkIdpToUser": "Impossible de lier l'IDP à l'utilisateur" + } + }, + "loginname": { + "errors": { + "couldNotSearchUsers": "Impossible de rechercher des utilisateurs", + "couldNotFindIdentityProvider": "Impossible de trouver le fournisseur d'identité", + "moreThanOneUserFound": "Plus d'un utilisateur trouvé. Fournissez un identifiant unique.", + "usernamePasswordNotAllowed": "Nom d'utilisateur et mot de passe non autorisés ! Contactez votre administrateur pour plus d'informations.", + "passkeysNotAllowed": "Clés d'accès non autorisées ! Contactez votre administrateur pour plus d'informations." + } + }, + "idp": { + "errors": { + "unexpectedResponseFromIdpFlow": "Réponse inattendue du flux IDP", + "noUsernameOrPasswordProvided": "Aucun nom d'utilisateur ou mot de passe fourni", + "couldNotStartLdapIdpFlow": "Impossible de démarrer le flux du fournisseur d'identité LDAP" + } + }, + "cookie": { + "errors": { + "noSessionLifetimeProvided": "Aucune durée de vie de session fournie, utilisation de la valeur par défaut de 24 heures.", + "noIdpSessionLifetimeProvided": "Aucune durée de vie de session IDP fournie, utilisation de la valeur par défaut de 24 heures.", + "couldNotGetSessionOrLoginName": "Impossible d'obtenir la session ou la session n'a pas de nom de connexion", + "couldNotRetrieveSession": "Impossible de récupérer la session", + "sessionCouldNotBeSet": "La session n'a pas pu être définie", + "failedToAuthenticateAttempts": "Échec de l'authentification : Vous avez eu {failedAttempts} tentatives de mot de passe.", + "failedToAuthenticateIdpAttempts": "Échec de l'authentification : Vous avez eu {failedAttempts} tentatives de mot de passe." + } + } + } +} \ No newline at end of file diff --git a/locales/it.json b/locales/it.json index 815efb5a3..b470800e7 100644 --- a/locales/it.json +++ b/locales/it.json @@ -66,7 +66,13 @@ "code": "Questo campo è obbligatorio", "newPassword": "Devi fornire una password!", "confirmPassword": "Questo campo è obbligatorio" - } + }, + "minLength": "Minimo", + "symbol": "Un simbolo", + "number": "Un numero", + "uppercase": "Una lettera maiuscola", + "lowercase": "Una lettera minuscola", + "equals": "Corrispondenza" }, "change": { "title": "Cambia Password", @@ -244,7 +250,8 @@ "firstname": "Questo campo è obbligatorio", "lastname": "Questo campo è obbligatorio", "email": "Questo campo è obbligatorio" - } + }, + "orUseIDP": "o usa un provider di identità" }, "invite": { "title": "Invita Utente", @@ -329,5 +336,100 @@ "sessionExpired": "La tua sessione attuale è scaduta. Effettua nuovamente l'accesso.", "failedLoading": "Impossibile caricare i dati. Riprova.", "tryagain": "Riprova" + }, + "server": { + "common": { + "errors": { + "couldNotGetHost": "Impossibile ottenere l'host", + "couldNotGetDomain": "Impossibile ottenere il dominio", + "couldNotGetHostname": "Impossibile ottenere l'hostname", + "couldNotGetSession": "Impossibile ottenere la sessione", + "couldNotCreateSession": "Impossibile creare la sessione", + "noHostFound": "Nessun host trovato", + "couldNotLoadLoginSettings": "Impossibile caricare le impostazioni di accesso", + "failedToAuthenticate": "Autenticazione fallita. Hai avuto {failedAttempts} tentativi su {maxAttempts} per la password.", + "userNotFoundInSystem": "Utente non trovato nel sistema", + "userVerificationCheckRequired": "Verifica utente richiesta", + "couldNotFindSession": "Impossibile trovare la sessione", + "couldNotUpdateSession": "Impossibile aggiornare la sessione", + "couldNotVerify": "Impossibile verificare", + "couldNotStartIdpFlow": "Impossibile avviare il flusso IDP", + "initialUserNotSupported": "Utente iniziale non supportato" + } + }, + "password": { + "errors": { + "couldNotSendPasswordResetLink": "Impossibile inviare il link di reset della password", + "couldNotCreateSessionForUser": "Impossibile creare una sessione per l'utente", + "couldNotVerifyPassword": "Impossibile verificare la password", + "noPasswordLifetimeProvided": "Nessuna durata della password fornita, default 24 ore", + "contactAdministratorToUnlock": "Contatta il tuo amministratore per sbloccare il tuo account", + "couldNotVerifyPasswordExclamation": "Impossibile verificare la password!", + "userInitialStateNotSupported": "Stato iniziale utente non supportato", + "provideCodeOrValidVerification": "Devi fornire un codice o avere una verifica utente valida", + "couldNotLoadSession": "Impossibile caricare la sessione", + "couldNotLoadAuthMethods": "Impossibile caricare i metodi di autenticazione", + "failedPrecondition": "Precondizione fallita" + } + }, + "session": { + "errors": { + "sessionNotValid": "La sessione non è valida.", + "noLifetimeProvidedForSession": "Nessuna durata fornita per la sessione, default 24 ore", + "couldNotDeleteSession": "Impossibile eliminare la sessione" + } + }, + "passkeys": { + "errors": { + "couldNotDetermineUserFromSession": "Impossibile determinare l'utente dalla sessione", + "authenticateOrValidVerification": "Devi autenticarti o avere una verifica utente valida", + "missingCodeInResponse": "Codice mancante nella risposta", + "noPasskeyLifetimeProvided": "Nessuna durata passkey fornita, default 24 ore", + "noUserIdFoundInSession": "Nessun ID utente trovato nella sessione." + } + }, + "verify": { + "errors": { + "couldNotVerifyInvite": "Impossibile verificare l'invito", + "couldNotVerifyEmail": "Impossibile verificare l'email", + "couldNotLoadUser": "Impossibile caricare l'utente", + "couldNotLoadPossibleAuthenticators": "Impossibile caricare gli autenticatori possibili", + "userAlreadyVerified": "Utente già verificato!", + "couldNotResendInvite": "Impossibile reinviare l'invito" + } + }, + "register": { + "errors": { + "couldNotCreateUser": "Impossibile creare l'utente", + "couldNotLinkIdpToUser": "Impossibile collegare IDP all'utente" + } + }, + "loginname": { + "errors": { + "couldNotSearchUsers": "Impossibile cercare utenti", + "couldNotFindIdentityProvider": "Impossibile trovare il provider di identità", + "moreThanOneUserFound": "Più di un utente trovato. Fornisci un identificatore univoco.", + "usernamePasswordNotAllowed": "Nome utente e password non consentiti! Contatta il tuo amministratore per maggiori informazioni.", + "passkeysNotAllowed": "Passkey non consentiti! Contatta il tuo amministratore per maggiori informazioni." + } + }, + "idp": { + "errors": { + "unexpectedResponseFromIdpFlow": "Risposta inaspettata dal flusso IDP", + "noUsernameOrPasswordProvided": "Nessun nome utente o password forniti", + "couldNotStartLdapIdpFlow": "Impossibile avviare il flusso del provider di identità LDAP" + } + }, + "cookie": { + "errors": { + "noSessionLifetimeProvided": "Nessuna durata di sessione fornita, usando default 24 ore.", + "noIdpSessionLifetimeProvided": "Nessuna durata di sessione IDP fornita, usando default 24 ore.", + "couldNotGetSessionOrLoginName": "Impossibile ottenere la sessione o la sessione non ha nome di accesso", + "couldNotRetrieveSession": "Impossibile recuperare la sessione", + "sessionCouldNotBeSet": "Impossibile impostare la sessione", + "failedToAuthenticateAttempts": "Autenticazione fallita: Hai avuto {failedAttempts} tentativi di password.", + "failedToAuthenticateIdpAttempts": "Autenticazione fallita: Hai avuto {failedAttempts} tentativi di password." + } + } } } diff --git a/locales/pl.json b/locales/pl.json index ae81ba7f3..f1734b601 100644 --- a/locales/pl.json +++ b/locales/pl.json @@ -66,7 +66,13 @@ "code": "To pole jest wymagane", "newPassword": "Musisz podać hasło!", "confirmPassword": "To pole jest wymagane" - } + }, + "minLength": "Minimum", + "symbol": "Symbol", + "number": "Cyfra", + "uppercase": "Wielka litera", + "lowercase": "Mała litera", + "equals": "Pasują" }, "change": { "title": "Zmień hasło", @@ -244,7 +250,8 @@ "firstname": "To pole jest wymagane", "lastname": "To pole jest wymagane", "email": "To pole jest wymagane" - } + }, + "orUseIDP": "lub użyj dostawcy tożsamości" }, "invite": { "title": "Zaproś użytkownika", @@ -329,5 +336,102 @@ "sessionExpired": "Twoja sesja wygasła. Zaloguj się ponownie.", "failedLoading": "Nie udało się załadować danych. Spróbuj ponownie.", "tryagain": "Spróbuj ponownie" + }, + "server": { + "common": { + "errors": { + "couldNotGetHost": "Nie można pobrać hosta", + "couldNotGetDomain": "Nie można pobrać domeny", + "couldNotGetHostname": "Nie można pobrać nazwy hosta", + "couldNotGetSession": "Nie można pobrać sesji", + "couldNotCreateSession": "Nie można utworzyć sesji", + "noHostFound": "Nie znaleziono hosta", + "couldNotLoadLoginSettings": "Nie można załadować ustawień logowania", + "failedToAuthenticate": "Uwierzytelnianie nie powiodło się. Miałeś {failedAttempts} prób z {maxAttempts} dla hasła.", + "userNotFoundInSystem": "Użytkownik nie znaleziony w systemie", + "userVerificationCheckRequired": "Wymagana weryfikacja użytkownika", + "couldNotFindSession": "Nie można znaleźć sesji", + "couldNotUpdateSession": "Nie można zaktualizować sesji", + "couldNotVerify": "Nie można zweryfikować", + "couldNotStartIdpFlow": "Nie można uruchomić przepływu IDP", + "initialUserNotSupported": "Użytkownik początkowy nieobsługiwany", + "couldNotSetPassword": "Nie można ustawić hasła" + } + }, + "password": { + "errors": { + "couldNotSendPasswordResetLink": "Nie można wysłać linku resetowania hasła", + "couldNotCreateSessionForUser": "Nie można utworzyć sesji dla użytkownika", + "couldNotVerifyPassword": "Nie można zweryfikować hasła", + "noPasswordLifetimeProvided": "Nie podano czasu życia hasła, domyślnie 24 godziny", + "contactAdministratorToUnlock": "Skontaktuj się z administratorem, aby odblokować konto", + "couldNotVerifyPasswordExclamation": "Nie można zweryfikować hasła!", + "userInitialStateNotSupported": "Stan początkowy użytkownika nieobsługiwany", + "provideCodeOrValidVerification": "Musisz podać kod lub mieć ważną weryfikację użytkownika", + "couldNotLoadSession": "Nie można załadować sesji", + "couldNotLoadAuthMethods": "Nie można załadować metod uwierzytelniania", + "failedPrecondition": "Warunek wstępny nie został spełniony" + } + }, + "session": { + "errors": { + "sessionNotValid": "Sesja jest nieprawidłowa.", + "noLifetimeProvidedForSession": "Nie podano czasu życia sesji, domyślnie 24 godziny", + "couldNotDeleteSession": "Nie można usunąć sesji" + } + }, + "passkeys": { + "errors": { + "couldNotDetermineUserFromSession": "Nie można określić użytkownika z sesji", + "authenticateOrValidVerification": "Musisz się uwierzytelnić lub mieć ważną weryfikację użytkownika", + "missingCodeInResponse": "Brakuje kodu w odpowiedzi", + "noPasskeyLifetimeProvided": "Nie podano czasu życia klucza dostępu, domyślnie 24 godziny", + "noUserIdFoundInSession": "Nie znaleziono ID użytkownika w sesji.", + "couldNotCreateRegistrationLink": "Nie można utworzyć linku rejestracji" + } + }, + "verify": { + "errors": { + "couldNotVerifyInvite": "Nie można zweryfikować zaproszenia", + "couldNotVerifyEmail": "Nie można zweryfikować e-maila", + "couldNotLoadUser": "Nie można załadować użytkownika", + "couldNotLoadPossibleAuthenticators": "Nie można załadować możliwych autentykatorów", + "userAlreadyVerified": "Użytkownik już zweryfikowany!", + "couldNotResendInvite": "Nie można ponownie wysłać zaproszenia" + } + }, + "register": { + "errors": { + "couldNotCreateUser": "Nie można utworzyć użytkownika", + "couldNotLinkIdpToUser": "Nie można połączyć IDP z użytkownikiem" + } + }, + "loginname": { + "errors": { + "couldNotSearchUsers": "Nie można wyszukać użytkowników", + "couldNotFindIdentityProvider": "Nie można znaleźć dostawcy tożsamości", + "moreThanOneUserFound": "Znaleziono więcej niż jednego użytkownika. Podaj unikalny identyfikator.", + "usernamePasswordNotAllowed": "Nazwa użytkownika i hasło niedozwolone! Skontaktuj się z administratorem po więcej informacji.", + "passkeysNotAllowed": "Klucze dostępu niedozwolone! Skontaktuj się z administratorem po więcej informacji." + } + }, + "idp": { + "errors": { + "unexpectedResponseFromIdpFlow": "Nieoczekiwana odpowiedź z przepływu IDP", + "noUsernameOrPasswordProvided": "Nie podano nazwy użytkownika lub hasła", + "couldNotStartLdapIdpFlow": "Nie można uruchomić przepływu dostawcy tożsamości LDAP" + } + }, + "cookie": { + "errors": { + "noSessionLifetimeProvided": "Nie podano czasu życia sesji, używam domyślnych 24 godzin.", + "noIdpSessionLifetimeProvided": "Nie podano czasu życia sesji IDP, używam domyślnych 24 godzin.", + "couldNotGetSessionOrLoginName": "Nie można pobrać sesji lub sesja nie ma nazwy logowania", + "couldNotRetrieveSession": "Nie można pobrać sesji", + "sessionCouldNotBeSet": "Nie można ustawić sesji", + "failedToAuthenticateAttempts": "Uwierzytelnianie nie powiodło się: Miałeś {failedAttempts} prób hasła.", + "failedToAuthenticateIdpAttempts": "Uwierzytelnianie nie powiodło się: Miałeś {failedAttempts} prób hasła." + } + } } } diff --git a/locales/ru.json b/locales/ru.json index f5e91066d..87973743d 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -66,7 +66,13 @@ "code": "Это поле обязательно для заполнения", "newPassword": "Вы должны указать пароль!", "confirmPassword": "Это поле обязательно для заполнения" - } + }, + "minLength": "Минимум", + "symbol": "Символ", + "number": "Цифра", + "uppercase": "Заглавная буква", + "lowercase": "Строчная буква", + "equals": "Совпадение" }, "change": { "title": "Изменить пароль", @@ -244,7 +250,8 @@ "firstname": "Это поле обязательно для заполнения", "lastname": "Это поле обязательно для заполнения", "email": "Это поле обязательно для заполнения" - } + }, + "orUseIDP": "или использовать провайдера идентичности" }, "invite": { "title": "Пригласить пользователя", @@ -329,5 +336,102 @@ "sessionExpired": "Ваша сессия истекла. Войдите снова.", "failedLoading": "Ошибка загрузки данных. Попробуйте ещё раз.", "tryagain": "Попробовать снова" + }, + "server": { + "common": { + "errors": { + "couldNotGetHost": "Не удалось получить хост", + "couldNotGetDomain": "Не удалось получить домен", + "couldNotGetHostname": "Не удалось получить имя хоста", + "couldNotGetSession": "Не удалось получить сессию", + "couldNotCreateSession": "Не удалось создать сессию", + "noHostFound": "Хост не найден", + "couldNotLoadLoginSettings": "Не удалось загрузить настройки входа", + "failedToAuthenticate": "Ошибка аутентификации. У вас было {failedAttempts} попыток из {maxAttempts} для пароля.", + "userNotFoundInSystem": "Пользователь не найден в системе", + "userVerificationCheckRequired": "Требуется проверка пользователя", + "couldNotFindSession": "Не удалось найти сессию", + "couldNotUpdateSession": "Не удалось обновить сессию", + "couldNotVerify": "Не удалось проверить", + "couldNotStartIdpFlow": "Не удалось запустить поток IDP", + "initialUserNotSupported": "Начальный пользователь не поддерживается", + "couldNotSetPassword": "Не удалось установить пароль" + } + }, + "password": { + "errors": { + "couldNotSendPasswordResetLink": "Не удалось отправить ссылку для сброса пароля", + "couldNotCreateSessionForUser": "Не удалось создать сессию для пользователя", + "couldNotVerifyPassword": "Не удалось проверить пароль", + "noPasswordLifetimeProvided": "Не указано время жизни пароля, по умолчанию 24 часа", + "contactAdministratorToUnlock": "Обратитесь к администратору для разблокировки учетной записи", + "couldNotVerifyPasswordExclamation": "Не удалось проверить пароль!", + "userInitialStateNotSupported": "Начальное состояние пользователя не поддерживается", + "provideCodeOrValidVerification": "Вы должны предоставить код или иметь действительную проверку пользователя", + "couldNotLoadSession": "Не удалось загрузить сессию", + "couldNotLoadAuthMethods": "Не удалось загрузить методы аутентификации", + "failedPrecondition": "Не выполнено предварительное условие" + } + }, + "session": { + "errors": { + "sessionNotValid": "Сессия недействительна.", + "noLifetimeProvidedForSession": "Не указано время жизни сессии, по умолчанию 24 часа", + "couldNotDeleteSession": "Не удалось удалить сессию" + } + }, + "passkeys": { + "errors": { + "couldNotDetermineUserFromSession": "Не удалось определить пользователя из сессии", + "authenticateOrValidVerification": "Вы должны аутентифицироваться или иметь действительную проверку пользователя", + "missingCodeInResponse": "Отсутствует код в ответе", + "noPasskeyLifetimeProvided": "Не указано время жизни ключа доступа, по умолчанию 24 часа", + "noUserIdFoundInSession": "ID пользователя не найден в сессии.", + "couldNotCreateRegistrationLink": "Не удалось создать ссылку для регистрации" + } + }, + "verify": { + "errors": { + "couldNotVerifyInvite": "Не удалось проверить приглашение", + "couldNotVerifyEmail": "Не удалось проверить email", + "couldNotLoadUser": "Не удалось загрузить пользователя", + "couldNotLoadPossibleAuthenticators": "Не удалось загрузить возможные аутентификаторы", + "userAlreadyVerified": "Пользователь уже проверен!", + "couldNotResendInvite": "Не удалось повторно отправить приглашение" + } + }, + "register": { + "errors": { + "couldNotCreateUser": "Не удалось создать пользователя", + "couldNotLinkIdpToUser": "Не удалось связать IDP с пользователем" + } + }, + "loginname": { + "errors": { + "couldNotSearchUsers": "Не удалось найти пользователей", + "couldNotFindIdentityProvider": "Не удалось найти провайдера идентичности", + "moreThanOneUserFound": "Найдено более одного пользователя. Укажите уникальный идентификатор.", + "usernamePasswordNotAllowed": "Имя пользователя и пароль не разрешены! Обратитесь к администратору за дополнительной информацией.", + "passkeysNotAllowed": "Ключи доступа не разрешены! Обратитесь к администратору за дополнительной информацией." + } + }, + "idp": { + "errors": { + "unexpectedResponseFromIdpFlow": "Неожиданный ответ от потока IDP", + "noUsernameOrPasswordProvided": "Не указано имя пользователя или пароль", + "couldNotStartLdapIdpFlow": "Не удалось запустить поток провайдера идентичности LDAP" + } + }, + "cookie": { + "errors": { + "noSessionLifetimeProvided": "Не указано время жизни сессии, используется по умолчанию 24 часа.", + "noIdpSessionLifetimeProvided": "Не указано время жизни сессии IDP, используется по умолчанию 24 часа.", + "couldNotGetSessionOrLoginName": "Не удалось получить сессию или у сессии нет имени входа", + "couldNotRetrieveSession": "Не удалось получить сессию", + "sessionCouldNotBeSet": "Не удалось установить сессию", + "failedToAuthenticateAttempts": "Ошибка аутентификации: У вас было {failedAttempts} попыток пароля.", + "failedToAuthenticateIdpAttempts": "Ошибка аутентификации: У вас было {failedAttempts} попыток пароля." + } + } } } diff --git a/locales/zh.json b/locales/zh.json index 3ec2ec31e..786e0d598 100644 --- a/locales/zh.json +++ b/locales/zh.json @@ -66,7 +66,13 @@ "code": "此字段为必填项", "newPassword": "必须提供密码!", "confirmPassword": "此字段为必填项" - } + }, + "minLength": "最少", + "symbol": "符号", + "number": "数字", + "uppercase": "大写字母", + "lowercase": "小写字母", + "equals": "匹配" }, "change": { "title": "更改密码", @@ -244,7 +250,8 @@ "firstname": "此字段为必填项", "lastname": "此字段为必填项", "email": "此字段为必填项" - } + }, + "orUseIDP": "或使用身份提供商" }, "invite": { "title": "邀请用户", @@ -329,5 +336,102 @@ "sessionExpired": "当前会话已过期,请重新登录。", "failedLoading": "加载数据失败,请再试一次。", "tryagain": "重试" + }, + "server": { + "common": { + "errors": { + "couldNotGetHost": "无法获取主机", + "couldNotGetDomain": "无法获取域", + "couldNotGetHostname": "无法获取主机名", + "couldNotGetSession": "无法获取会话", + "couldNotCreateSession": "无法创建会话", + "noHostFound": "未找到主机", + "couldNotLoadLoginSettings": "无法加载登录设置", + "failedToAuthenticate": "身份验证失败。您已尝试密码 {failedAttempts} 次,共 {maxAttempts} 次。", + "userNotFoundInSystem": "系统中未找到用户", + "userVerificationCheckRequired": "需要用户验证检查", + "couldNotFindSession": "无法找到会话", + "couldNotUpdateSession": "无法更新会话", + "couldNotVerify": "无法验证", + "couldNotStartIdpFlow": "无法启动 IDP 流程", + "initialUserNotSupported": "不支持初始用户", + "couldNotSetPassword": "无法设置密码" + } + }, + "password": { + "errors": { + "couldNotSendPasswordResetLink": "无法发送密码重置链接", + "couldNotCreateSessionForUser": "无法为用户创建会话", + "couldNotVerifyPassword": "无法验证密码", + "noPasswordLifetimeProvided": "未提供密码生命周期,默认为 24 小时", + "contactAdministratorToUnlock": "请联系您的管理员解锁您的账户", + "couldNotVerifyPasswordExclamation": "无法验证密码!", + "userInitialStateNotSupported": "不支持用户初始状态", + "provideCodeOrValidVerification": "您必须提供代码或具有有效的用户验证", + "couldNotLoadSession": "无法加载会话", + "couldNotLoadAuthMethods": "无法加载身份验证方法", + "failedPrecondition": "前提条件失败" + } + }, + "session": { + "errors": { + "sessionNotValid": "会话无效。", + "noLifetimeProvidedForSession": "未提供会话生命周期,默认为 24 小时", + "couldNotDeleteSession": "无法删除会话" + } + }, + "passkeys": { + "errors": { + "couldNotDetermineUserFromSession": "无法从会话中确定用户", + "authenticateOrValidVerification": "您必须进行身份验证或具有有效的用户验证", + "missingCodeInResponse": "响应中缺少代码", + "noPasskeyLifetimeProvided": "未提供密钥生命周期,默认为 24 小时", + "noUserIdFoundInSession": "会话中未找到用户 ID。", + "couldNotCreateRegistrationLink": "无法创建注册链接" + } + }, + "verify": { + "errors": { + "couldNotVerifyInvite": "无法验证邀请", + "couldNotVerifyEmail": "无法验证邮箱", + "couldNotLoadUser": "无法加载用户", + "couldNotLoadPossibleAuthenticators": "无法加载可能的身份验证器", + "userAlreadyVerified": "用户已验证!", + "couldNotResendInvite": "无法重新发送邀请" + } + }, + "register": { + "errors": { + "couldNotCreateUser": "无法创建用户", + "couldNotLinkIdpToUser": "无法将 IDP 链接到用户" + } + }, + "loginname": { + "errors": { + "couldNotSearchUsers": "无法搜索用户", + "couldNotFindIdentityProvider": "无法找到身份提供者", + "moreThanOneUserFound": "找到多个用户。请提供唯一标识符。", + "usernamePasswordNotAllowed": "不允许使用用户名和密码!请联系您的管理员获取更多信息。", + "passkeysNotAllowed": "不允许使用密钥!请联系您的管理员获取更多信息。" + } + }, + "idp": { + "errors": { + "unexpectedResponseFromIdpFlow": "IDP 流程的意外响应", + "noUsernameOrPasswordProvided": "未提供用户名或密码", + "couldNotStartLdapIdpFlow": "无法启动 LDAP 身份提供者流程" + } + }, + "cookie": { + "errors": { + "noSessionLifetimeProvided": "未提供会话生命周期,使用默认的 24 小时。", + "noIdpSessionLifetimeProvided": "未提供 IDP 会话生命周期,使用默认的 24 小时。", + "couldNotGetSessionOrLoginName": "无法获取会话或会话没有登录名", + "couldNotRetrieveSession": "无法检索会话", + "sessionCouldNotBeSet": "无法设置会话", + "failedToAuthenticateAttempts": "身份验证失败:您已尝试密码 {failedAttempts} 次。", + "failedToAuthenticateIdpAttempts": "身份验证失败:您已尝试密码 {failedAttempts} 次。" + } + } } } diff --git a/src/components/password-complexity.tsx b/src/components/password-complexity.tsx index 4f0b460c7..682b8160a 100644 --- a/src/components/password-complexity.tsx +++ b/src/components/password-complexity.tsx @@ -5,6 +5,7 @@ import { upperCaseValidator, } from "@/helpers/validators"; import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb"; +import { Translated } from "./translated"; type Props = { passwordComplexitySettings: PasswordComplexitySettings; @@ -68,7 +69,8 @@ export function PasswordComplexity({
{hasMinLength ? check : cross} - Password length {passwordComplexitySettings.minLength.toString()} + {" "} + {passwordComplexitySettings.minLength.toString()}
) : ( @@ -76,23 +78,33 @@ export function PasswordComplexity({ )}
{hasSymbol ? check : cross} - has Symbol + + +
{hasNumber ? check : cross} - has Number + + +
{hasUppercase ? check : cross} - has uppercase + + +
{hasLowercase ? check : cross} - has lowercase + + +
{equals ? check : cross} - equals + + +
); diff --git a/src/lib/i18n.ts b/src/lib/i18n.ts index 780d9a98f..581cdde2d 100644 --- a/src/lib/i18n.ts +++ b/src/lib/i18n.ts @@ -20,6 +20,10 @@ export const LANGS: Lang[] = [ name: "Español", code: "es", }, + { + name: "Français", + code: "fr", + }, { name: "Polski", code: "pl", diff --git a/src/lib/server-translations.ts b/src/lib/server-translations.ts new file mode 100644 index 000000000..dff766678 --- /dev/null +++ b/src/lib/server-translations.ts @@ -0,0 +1,14 @@ +import { getTranslations } from "next-intl/server"; + +/** + * Get server-side translation for a specific key with optional interpolation + */ +export async function getServerTranslation( + base: string, + key: string, + params?: Record, + locale?: string +): Promise { + const t = await getTranslations({ locale, namespace: `server.${base}` }); + return t(key, params); +} \ No newline at end of file diff --git a/src/lib/server/cookie.ts b/src/lib/server/cookie.ts index 551d95db5..04b2a9ba6 100644 --- a/src/lib/server/cookie.ts +++ b/src/lib/server/cookie.ts @@ -15,6 +15,7 @@ import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb"; import { Checks } from "@zitadel/proto/zitadel/session/v2/session_service_pb"; import { headers } from "next/headers"; import { getServiceUrlFromHeaders } from "../service-url"; +import { getServerTranslation } from "../server-translations"; type CustomCookieData = { id: string; @@ -27,13 +28,13 @@ type CustomCookieData = { requestId?: string; // if its linked to an OIDC flow }; -const passwordAttemptsHandler = (error: ConnectError) => { +const passwordAttemptsHandler = async (error: ConnectError) => { const details = error.findDetails(CredentialsCheckErrorSchema); if (details[0] && "failedAttempts" in details[0]) { const failedAttempts = details[0].failedAttempts; throw { - error: `Failed to authenticate: You had ${failedAttempts} password attempts.`, + error: await getServerTranslation("cookie.errors", "failedToAuthenticateAttempts", { failedAttempts }), failedAttempts: failedAttempts, }; } @@ -51,7 +52,7 @@ export async function createSessionAndUpdateCookie(command: { let sessionLifetime = command.lifetime; if (!sessionLifetime) { - console.warn("No session lifetime provided, using default of 24 hours."); + console.warn(await getServerTranslation("cookie.errors","noSessionLifetimeProvided")); sessionLifetime = { seconds: BigInt(24 * 60 * 60), // 24 hours @@ -96,11 +97,11 @@ export async function createSessionAndUpdateCookie(command: { return response.session as Session; } else { - throw "could not get session or session does not have loginName"; + throw new Error(await getServerTranslation("cookie.errors", "couldNotGetSessionOrLoginName")); } }); } else { - throw "Could not create session"; + throw new Error(await getServerTranslation("common.errors", "couldNotCreateSession")); } } @@ -124,7 +125,9 @@ export async function createSessionForIdpAndUpdateCookie({ let sessionLifetime = lifetime; if (!sessionLifetime) { - console.warn("No IDP session lifetime provided, using default of 24 hours."); + console.warn( + await getServerTranslation("cookie.errors", "noIdpSessionLifetimeProvided"), + ); sessionLifetime = { seconds: BigInt(24 * 60 * 60), // 24 hours @@ -137,11 +140,11 @@ export async function createSessionForIdpAndUpdateCookie({ userId, idpIntent, lifetime: sessionLifetime, - }).catch((error: ErrorDetail | CredentialsCheckError) => { + }).catch(async (error: ErrorDetail | CredentialsCheckError) => { console.error("Could not set session", error); if ("failedAttempts" in error && error.failedAttempts) { throw { - error: `Failed to authenticate: You had ${error.failedAttempts} password attempts.`, + error: await getServerTranslation("cookie.errors", "failedToAuthenticateIdpAttempts", { failedAttempts: error.failedAttempts }), failedAttempts: error.failedAttempts, }; } @@ -149,7 +152,7 @@ export async function createSessionForIdpAndUpdateCookie({ }); if (!createdSession) { - throw "Could not create session"; + throw new Error(await getServerTranslation("common.errors", "couldNotCreateSession")); } const { session } = await getSession({ @@ -159,7 +162,7 @@ export async function createSessionForIdpAndUpdateCookie({ }); if (!session || !session.factors?.user?.loginName) { - throw "Could not retrieve session"; + throw new Error(await getServerTranslation("cookie.errors", "couldNotRetrieveSession")); } const sessionCookie: CustomCookieData = { @@ -210,7 +213,7 @@ export async function setSessionAndUpdateCookie(command: { checks: command.checks, lifetime: command.lifetime, }) - .then((updatedSession) => { + .then(async (updatedSession) => { if (updatedSession) { const sessionCookie: CustomCookieData = { id: command.recentCookie.id, @@ -232,8 +235,11 @@ export async function setSessionAndUpdateCookie(command: { sessionId: sessionCookie.id, sessionToken: sessionCookie.token, }).then(async (response) => { - if (!response?.session || !response.session.factors?.user?.loginName) { - throw "could not get session or session does not have loginName"; + if ( + !response?.session || + !response.session.factors?.user?.loginName + ) { + throw new Error(await getServerTranslation("cookie.errors", "couldNotGetSessionOrLoginName")); } const { session } = response; @@ -264,7 +270,7 @@ export async function setSessionAndUpdateCookie(command: { }); }); } else { - throw "Session not be set"; + throw new Error(await getServerTranslation("cookie.errors", "sessionCouldNotBeSet")); } }) .catch(passwordAttemptsHandler); diff --git a/src/lib/server/host.ts b/src/lib/server/host.ts index 9d2d57b8a..8f7cbe5f4 100644 --- a/src/lib/server/host.ts +++ b/src/lib/server/host.ts @@ -1,4 +1,5 @@ import { headers } from "next/headers"; +import { getServerTranslation } from "../server-translations"; /** * Gets the original host that the user sees in their browser URL. @@ -23,7 +24,7 @@ export async function getOriginalHost(): Promise { const host = _headers.get("x-forwarded-host") || _headers.get("x-original-host") || _headers.get("host"); if (!host || typeof host !== "string") { - throw new Error("No host found in headers"); + throw new Error(await getServerTranslation("common.errors", "couldNotGetHost")); } return host; diff --git a/src/lib/server/idp.ts b/src/lib/server/idp.ts index 96773e6f6..a35a11789 100644 --- a/src/lib/server/idp.ts +++ b/src/lib/server/idp.ts @@ -12,9 +12,11 @@ import { redirect } from "next/navigation"; import { completeFlowOrGetUrl } from "../client"; import { getServiceUrlFromHeaders } from "../service-url"; import { checkEmailVerification, checkMFAFactors } from "../verify-helper"; +import { getServerTranslation } from "../server-translations"; import { createSessionForIdpAndUpdateCookie } from "./cookie"; import { getOriginalHost } from "./host"; + export type RedirectToIdpState = { error?: string | null } | undefined; export async function redirectToIdp(prevState: RedirectToIdpState, formData: FormData): Promise { @@ -49,14 +51,14 @@ export async function redirectToIdp(prevState: RedirectToIdpState, formData: For }); if (!response) { - return { error: "Could not start IDP flow" }; + return { error: await getServerTranslation("idp.errors", "couldNotStartIdpFlow") }; } if (response && "redirect" in response && response?.redirect) { redirect(response.redirect); } - return { error: "Unexpected response from IDP flow" }; + return { error: await getServerTranslation("idp.errors","unexpectedResponseFromIdpFlow") }; } export type StartIDPFlowCommand = { @@ -80,7 +82,7 @@ async function startIDPFlow(command: StartIDPFlowCommand) { }); if (!url) { - return { error: "Could not start IDP flow" }; + return { error: await getServerTranslation("idp.errors","couldNotStartIdpFlow") }; } return { redirect: url }; @@ -113,7 +115,7 @@ export async function createNewSessionFromIdpIntent(command: CreateNewSessionCom }); if (!userResponse || !userResponse.user) { - return { error: "User not found in the system" }; + return { error: await getServerTranslation("common.errors", "userNotFoundInSystem") }; } const loginSettings = await getLoginSettings({ @@ -129,7 +131,7 @@ export async function createNewSessionFromIdpIntent(command: CreateNewSessionCom }); if (!session || !session.factors?.user) { - return { error: "Could not create session" }; + return { error: await getServerTranslation("common.errors", "couldNotCreateSession") }; } const humanUser = userResponse.user.type.case === "human" ? userResponse.user.type.value : undefined; @@ -194,7 +196,7 @@ export async function createNewSessionForLDAP(command: createNewSessionForLDAPCo const { serviceUrl } = getServiceUrlFromHeaders(_headers); if (!command.username || !command.password) { - return { error: "No username or password provided" }; + return { error: await getServerTranslation("idp.errors", "noUsernameOrPasswordProvided") }; } const response = await startLDAPIdentityProviderFlow({ @@ -204,8 +206,12 @@ export async function createNewSessionForLDAP(command: createNewSessionForLDAPCo password: command.password, }); - if (!response || response.nextStep.case !== "idpIntent" || !response.nextStep.value) { - return { error: "Could not start LDAP identity provider flow" }; + if ( + !response || + response.nextStep.case !== "idpIntent" || + !response.nextStep.value + ) { + return { error: await getServerTranslation("idp.errors", "couldNotStartLdapIdpFlow") }; } const { userId, idpIntentId, idpIntentToken } = response.nextStep.value; diff --git a/src/lib/server/loginname.ts b/src/lib/server/loginname.ts index 9f243a86d..fed4d54a4 100644 --- a/src/lib/server/loginname.ts +++ b/src/lib/server/loginname.ts @@ -9,6 +9,7 @@ import { idpTypeToIdentityProviderType, idpTypeToSlug } from "../idp"; import { PasskeysType } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb"; import { UserState } from "@zitadel/proto/zitadel/user/v2/user_pb"; import { getServiceUrlFromHeaders } from "../service-url"; +import { getServerTranslation } from "../server-translations"; import { getActiveIdentityProviders, getIDPByID, @@ -42,7 +43,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { }); if (!loginSettingsByContext) { - return { error: "Could not get login settings" }; + return { error: await getServerTranslation("common.errors", "couldNotLoadLoginSettings") }; } let searchUsersRequest: SearchUsersCommand = { @@ -60,7 +61,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { } if (!("result" in searchResult)) { - return { error: "Could not search users" }; + return { error: await getServerTranslation("loginname.errors", "couldNotSearchUsers") }; } const { result: potentialUsers } = searchResult; @@ -108,7 +109,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { }); if (!url) { - return { error: "Could not start IDP flow" }; + return { error: await getServerTranslation("common.errors", "couldNotStartIdpFlow") }; } return { redirect: url }; @@ -138,7 +139,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(await getServerTranslation("loginname.errors", "couldNotFindIdentityProvider")); } const identityProviderType = idpTypeToIdentityProviderType(idpType); @@ -170,7 +171,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { }); if (!url) { - return { error: "Could not start IDP flow" }; + return { error: await getServerTranslation("common.errors", "couldNotStartIdpFlow") }; } return { redirect: url }; @@ -178,7 +179,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { }; if (potentialUsers.length > 1) { - return { error: "More than one user found. Provide a unique identifier." }; + return { error: await getServerTranslation("loginname.errors", "moreThanOneUserFound") }; } else if (potentialUsers.length == 1 && potentialUsers[0].userId) { const user = potentialUsers[0]; const userId = potentialUsers[0].userId; @@ -196,15 +197,21 @@ 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: await getServerTranslation("common.errors", "userNotFoundInSystem") }; } } else if (userLoginSettings?.disableLoginWithEmail) { - if (user.preferredLoginName !== concatLoginname || humanUser?.phone?.phone !== command.loginName) { - return { error: "User not found in the system!" }; + if ( + user.preferredLoginName !== concatLoginname || + humanUser?.phone?.phone !== command.loginName + ) { + return { error: await getServerTranslation("common.errors", "userNotFoundInSystem") }; } } else if (userLoginSettings?.disableLoginWithPhone) { - if (user.preferredLoginName !== concatLoginname || humanUser?.email?.email !== command.loginName) { - return { error: "User not found in the system!" }; + if ( + user.preferredLoginName !== concatLoginname || + humanUser?.email?.email !== command.loginName + ) { + return { error: await getServerTranslation("common.errors", "userNotFoundInSystem") }; } } @@ -218,12 +225,12 @@ export async function sendLoginname(command: SendLoginnameCommand) { }); if (!session.factors?.user?.id) { - return { error: "Could not create session for user" }; + return { error: await getServerTranslation("common.errors", "couldNotCreateSession") }; } // TODO: check if handling of userstate INITIAL is needed if (user.state === UserState.INITIAL) { - return { error: "Initial User not supported" }; + return { error: await getServerTranslation("common.errors", "initialUserNotSupported") }; } const methods = await listAuthenticationMethodTypes({ @@ -262,7 +269,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { } return { - error: "Username Password not allowed! Contact your administrator for more information.", + error: await getServerTranslation("loginname.errors", "usernamePasswordNotAllowed"), }; } @@ -287,7 +294,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: await getServerTranslation("loginname.errors", "passkeysNotAllowed"), }; } @@ -366,8 +373,11 @@ export async function sendLoginname(command: SendLoginnameCommand) { if (resp) { return resp; } - return { error: "User not found in the system" }; - } else if (loginSettingsByContext?.allowRegister && loginSettingsByContext?.allowUsernamePassword) { + return { error: await getServerTranslation("common.errors", "userNotFoundInSystem") }; + } else if ( + loginSettingsByContext?.allowRegister && + loginSettingsByContext?.allowUsernamePassword + ) { let orgToRegisterOn: string | undefined = command.organization; if ( @@ -429,5 +439,5 @@ export async function sendLoginname(command: SendLoginnameCommand) { // fallbackToPassword - return { error: "User not found in the system" }; + return { error: await getServerTranslation("common.errors", "userNotFoundInSystem") }; } diff --git a/src/lib/server/passkeys.ts b/src/lib/server/passkeys.ts index 83a354a27..8b95d7322 100644 --- a/src/lib/server/passkeys.ts +++ b/src/lib/server/passkeys.ts @@ -24,6 +24,7 @@ import { checkEmailVerification, checkUserVerification } from "../verify-helper" import { createSessionAndUpdateCookie, setSessionAndUpdateCookie } from "./cookie"; import { getOriginalHost } from "./host"; import { completeFlowOrGetUrl } from "../client"; +import { getServerTranslation } from "../server-translations"; type VerifyPasskeyCommand = { passkeyId: string; @@ -80,7 +81,7 @@ export async function registerPasskeyLink( }); if (!session?.session?.factors?.user?.id) { - return { error: "Could not determine user from session" }; + return { error: await getServerTranslation("passkeys.errors", "couldNotDetermineUserFromSession") }; } currentUserId = session.session.factors.user.id; @@ -96,16 +97,16 @@ export async function registerPasskeyLink( // 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 authenticate or have a valid User Verification Check", + error: + await getServerTranslation("passkeys.errors","authenticateOrValidVerification"), }; } // check if a verification was done earlier const hasValidUserVerificationCheck = await checkUserVerification(currentUserId); - console.log("hasValidUserVerificationCheck", hasValidUserVerificationCheck); if (!hasValidUserVerificationCheck) { - return { error: "User Verification Check has to be done" }; + return { error: await getServerTranslation("common.errors", "userVerificationCheckRequired") }; } if (!command.code) { @@ -114,9 +115,9 @@ export async function registerPasskeyLink( serviceUrl, userId: currentUserId, }); - + if (!codeResponse?.code?.code) { - return { error: "Could not create registration link" }; + return { error: await getServerTranslation("passkeys.errors", "couldNotCreateRegistrationLink") }; } registerCode = codeResponse.code; @@ -166,11 +167,11 @@ export async function registerPasskeyLink( const [hostname] = host.split(":"); if (!hostname) { - throw new Error("Could not get hostname"); + throw new Error(await getServerTranslation("common.errors", "couldNotGetHostname")); } if (!currentUserId) { - throw new Error("Could not determine user"); + throw new Error(await getServerTranslation("passkeys.errors", "couldNotDetermineUserFromSession")); } return registerPasskey({ @@ -216,7 +217,7 @@ export async function verifyPasskeyRegistration(command: VerifyPasskeyCommand) { const userId = session?.session?.factors?.user?.id; if (!userId) { - throw new Error("Could not get session"); + throw new Error(await getServerTranslation("common.errors", "couldNotGetSession")); } currentUserId = userId; @@ -231,7 +232,7 @@ export async function verifyPasskeyRegistration(command: VerifyPasskeyCommand) { }); if (!userResponse || !userResponse.user) { - throw new Error("User not found"); + throw new Error(await getServerTranslation("common.errors", "userNotFoundInSystem")); } } @@ -265,7 +266,7 @@ export async function sendPasskey(command: SendPasskeyCommand) { if (!recentSession) { return { - error: "Could not find session", + error: await getServerTranslation("common.errors", "couldNotFindSession"), }; } @@ -284,7 +285,7 @@ export async function sendPasskey(command: SendPasskeyCommand) { : undefined; if (!lifetime) { - console.warn("No passkey lifetime provided, defaulting to 24 hours"); + console.warn(await getServerTranslation("passkeys.errors", "noPasskeyLifetimeProvided")); lifetime = { seconds: BigInt(60 * 60 * 24), // default to 24 hours @@ -300,7 +301,7 @@ export async function sendPasskey(command: SendPasskeyCommand) { }); if (!session || !session?.factors?.user?.id) { - return { error: "Could not update session" }; + return { error: await getServerTranslation("common.errors", "couldNotUpdateSession") }; } const userResponse = await getUserByID({ @@ -309,7 +310,7 @@ export async function sendPasskey(command: SendPasskeyCommand) { }); if (!userResponse.user) { - return { error: "User not found in the system" }; + return { error: await getServerTranslation("common.errors", "userNotFoundInSystem") }; } const humanUser = userResponse.user.type.case === "human" ? userResponse.user.type.value : undefined; diff --git a/src/lib/server/password.ts b/src/lib/server/password.ts index 166a11d5f..70770ee1d 100644 --- a/src/lib/server/password.ts +++ b/src/lib/server/password.ts @@ -24,6 +24,7 @@ import { completeFlowOrGetUrl } from "../client"; import { getSessionCookieById, getSessionCookieByLoginName } from "../cookies"; import { getServiceUrlFromHeaders } from "../service-url"; import { getOriginalHostWithProtocol } from "./host"; +import { getServerTranslation } from "../server-translations"; import { checkEmailVerification, checkMFAFactors, @@ -52,10 +53,10 @@ 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: await getServerTranslation("password.errors", "couldNotSendPasswordResetLink") }; } - const userId = users.result[0].userId; + const userId = users.result[0].userId; const basePath = process.env.NEXT_PUBLIC_BASE_PATH ?? ""; return passwordReset({ @@ -124,17 +125,21 @@ export async function sendPassword(command: UpdateSessionCommand): Promise<{ err 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" + await getServerTranslation("common.errors", "failedToAuthenticate", { + failedAttempts: String(error.failedAttempts), + maxAttempts: String(lockoutSettings?.maxPasswordAttempts || 0) + }) + + (lockoutSettings?.maxPasswordAttempts && + error.failedAttempts >= lockoutSettings?.maxPasswordAttempts + ? await getServerTranslation("password.errors", "contactAdministratorToUnlock") : ""), }; } - return { error: "Could not create session for user" }; + return { error: await getServerTranslation("password.errors", "couldNotCreateSessionForUser") }; } } else { // this is a fake error message to hide that the user does not even exist - return { error: "Could not verify password" }; + return { error: await getServerTranslation("password.errors", "couldNotVerifyPassword") }; } } else { loginSettings = await getLoginSettings({ @@ -143,13 +148,13 @@ export async function sendPassword(command: UpdateSessionCommand): Promise<{ err }); if (!loginSettings) { - return { error: "Could not load login settings" }; + return { error: await getServerTranslation("common.errors", "couldNotLoadLoginSettings") }; } let lifetime = loginSettings.passwordCheckLifetime; if (!lifetime) { - console.warn("No password lifetime provided, defaulting to 24 hours"); + console.warn(await getServerTranslation("password.errors", "noPasswordLifetimeProvided")); lifetime = { seconds: BigInt(60 * 60 * 24), // default to 24 hours nanos: 0, @@ -171,18 +176,22 @@ export async function sendPassword(command: UpdateSessionCommand): Promise<{ err }); 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: + await getServerTranslation("common.errors", "failedToAuthenticate", { + failedAttempts: String(error.failedAttempts), + maxAttempts: String(lockoutSettings?.maxPasswordAttempts || 0) + }) + + (lockoutSettings?.maxPasswordAttempts && + error.failedAttempts >= lockoutSettings?.maxPasswordAttempts + ? await getServerTranslation("password.errors", "contactAdministratorToUnlock") + : ""), + }; } throw error; } if (!session?.factors?.user?.id) { - return { error: "Could not create session for user" }; + return { error: await getServerTranslation("password.errors", "couldNotCreateSessionForUser") }; } const userResponse = await getUserByID({ @@ -191,7 +200,7 @@ export async function sendPassword(command: UpdateSessionCommand): Promise<{ err }); if (!userResponse.user) { - return { error: "User not found in the system" }; + return { error: await getServerTranslation("common.errors", "userNotFoundInSystem") }; } user = userResponse.user; @@ -205,7 +214,7 @@ export async function sendPassword(command: UpdateSessionCommand): Promise<{ err } if (!session?.factors?.user?.id) { - return { error: "Could not create session for user" }; + return { error: await getServerTranslation("password.errors", "couldNotCreateSessionForUser") }; } const humanUser = user.type.case === "human" ? user.type.value : undefined; @@ -230,7 +239,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: await getServerTranslation("common.errors", "initialUserNotSupported") }; } // check to see if user was verified @@ -253,7 +262,7 @@ export async function sendPassword(command: UpdateSessionCommand): Promise<{ err } if (!authMethods) { - return { error: "Could not verify password!" }; + return { error: await getServerTranslation("password.errors", "couldNotVerifyPasswordExclamation") }; } const mfaFactorCheck = await checkMFAFactors( @@ -323,12 +332,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: await getServerTranslation("password.errors", "couldNotSendPasswordResetLink") }; } const userId = user.userId; if (user.state === UserState.INITIAL) { - return { error: "User Initial State is not supported" }; + return { error: await getServerTranslation("password.errors", "userInitialStateNotSupported") }; } // check if the user has no password set in order to set a password @@ -341,7 +350,8 @@ 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: + await getServerTranslation("password.errors", "provideCodeOrValidVerification"), }; } @@ -349,7 +359,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: await getServerTranslation("common.errors", "userVerificationCheckRequired") }; } } @@ -392,7 +402,7 @@ export async function checkSessionAndSetPassword({ sessionId, password }: CheckS } if (!session || !session.factors?.user?.id) { - return { error: "Could not load session" }; + return { error: await getServerTranslation("password.errors", "couldNotLoadSession") }; } const payload = create(SetPasswordRequestSchema, { @@ -415,7 +425,7 @@ export async function checkSessionAndSetPassword({ sessionId, password }: CheckS } if (!authmethods) { - return { error: "Could not load auth methods" }; + return { error: await getServerTranslation("password.errors", "couldNotLoadAuthMethods") }; } let loginSettings; @@ -434,12 +444,12 @@ export async function checkSessionAndSetPassword({ sessionId, password }: CheckS // if the user has no MFA but MFA is enforced, we can set a password otherwise we use the token of the user if (forceMfa) { console.log("Set password using service account due to enforced MFA without existing MFA methods"); - return setPassword({ serviceUrl, payload }).catch((error) => { + return setPassword({ serviceUrl, payload }).catch(async (error) => { // throw error if failed precondition (ex. User is not yet initialized) if (error.code === 9 && error.message) { - return { error: "Failed precondition" }; + return { error: await getServerTranslation("password.errors", "failedPrecondition") }; } - return { error: "Could not set password" }; + return { error: await getServerTranslation("common.errors", "couldNotSetPassword") }; }); } else { const transport = async (serviceUrl: string, token: string) => { @@ -461,10 +471,10 @@ export async function checkSessionAndSetPassword({ sessionId, password }: CheckS }, {}, ) - .catch((error: ConnectError) => { + .catch(async (error: ConnectError) => { console.log(error); if (error.code === 7) { - return { error: "Session is not valid." }; + return { error: await getServerTranslation("password.errors", "sessionNotValid") }; } return { error: "Could not set the password" }; }); diff --git a/src/lib/server/register.ts b/src/lib/server/register.ts index 74647a387..70dcdb730 100644 --- a/src/lib/server/register.ts +++ b/src/lib/server/register.ts @@ -11,6 +11,7 @@ import { completeFlowOrGetUrl } from "../client"; import { getServiceUrlFromHeaders } from "../service-url"; import { checkEmailVerification, checkMFAFactors } from "../verify-helper"; import { getOrSetFingerprintId } from "../fingerprint"; +import { getServerTranslation } from "../server-translations"; type RegisterUserCommand = { email: string; @@ -40,7 +41,7 @@ export async function registerUser(command: RegisterUserCommand) { }); if (!addResponse) { - return { error: "Could not create user" }; + return { error: await getServerTranslation("register.errors", "couldNotCreateUser") }; } const loginSettings = await getLoginSettings({ @@ -68,7 +69,7 @@ export async function registerUser(command: RegisterUserCommand) { }); if (!session || !session.factors?.user) { - return { error: "Could not create session" }; + return { error: await getServerTranslation("common.errors", "couldNotCreateSession") }; } if (!command.password) { @@ -104,7 +105,7 @@ export async function registerUser(command: RegisterUserCommand) { }); if (!userResponse.user) { - return { error: "User not found in the system" }; + return { error: await getServerTranslation("common.errors", "userNotFoundInSystem") }; } const humanUser = userResponse.user.type.case === "human" ? userResponse.user.type.value : undefined; @@ -169,7 +170,7 @@ export async function registerUserAndLinkToIDP(command: RegisterUserAndLinkToIDP }); if (!addUserResponse) { - return { error: "Could not create user" }; + return { error: await getServerTranslation("register.errors", "couldNotCreateUser") }; } const loginSettings = await getLoginSettings({ @@ -188,7 +189,7 @@ export async function registerUserAndLinkToIDP(command: RegisterUserAndLinkToIDP }); if (!idpLink) { - return { error: "Could not link IDP to user" }; + return { error: await getServerTranslation("register.errors", "couldNotLinkIdpToUser") }; } const session = await createSessionForIdpAndUpdateCookie({ @@ -199,7 +200,7 @@ export async function registerUserAndLinkToIDP(command: RegisterUserAndLinkToIDP }); if (!session || !session.factors?.user) { - return { error: "Could not create session" }; + return { error: await getServerTranslation("common.errors", "couldNotCreateSession") }; } // const userResponse = await getUserByID({ diff --git a/src/lib/server/session.ts b/src/lib/server/session.ts index 59de5aec5..f1860acc9 100644 --- a/src/lib/server/session.ts +++ b/src/lib/server/session.ts @@ -22,6 +22,7 @@ import { } from "../cookies"; import { getServiceUrlFromHeaders } from "../service-url"; import { getOriginalHost } from "./host"; +import { getServerTranslation } from "../server-translations"; export async function skipMFAAndContinueWithNextUrl({ userId, @@ -119,7 +120,7 @@ export async function updateSession(options: UpdateSessionCommand) { if (!recentSession) { return { - error: "Could not find session", + error: await getServerTranslation("common.errors", "couldNotFindSession"), }; } @@ -128,7 +129,7 @@ export async function updateSession(options: UpdateSessionCommand) { const host = await getOriginalHost(); if (!host) { - return { error: "Could not get host" }; + return { error: await getServerTranslation("common.errors", "couldNotGetHost") }; } if (host && challenges && challenges.webAuthN && !challenges.webAuthN.domain) { @@ -149,7 +150,7 @@ export async function updateSession(options: UpdateSessionCommand) { : undefined; if (!lifetime) { - console.warn("No lifetime provided for session, defaulting to 24 hours"); + console.warn(await getServerTranslation("session.errors", "noLifetimeProvidedForSession")); lifetime = { seconds: BigInt(60 * 60 * 24), // default to 24 hours nanos: 0, @@ -165,7 +166,7 @@ export async function updateSession(options: UpdateSessionCommand) { }); if (!session) { - return { error: "Could not update session" }; + return { error: await getServerTranslation("common.errors", "couldNotUpdateSession") }; } // if password, check if user has MFA methods @@ -210,7 +211,7 @@ export async function clearSession(options: ClearSessionOptions) { const iFrameEnabled = !!securitySettings?.embeddedIframe?.enabled; if (!deleteResponse) { - throw new Error("Could not delete session"); + throw new Error(await getServerTranslation("session.errors", "couldNotDeleteSession")); } return removeSessionFromCookie({ session: sessionCookie, iFrameEnabled }); diff --git a/src/lib/server/u2f.ts b/src/lib/server/u2f.ts index 69d0454e9..076d55beb 100644 --- a/src/lib/server/u2f.ts +++ b/src/lib/server/u2f.ts @@ -8,6 +8,7 @@ import { userAgent } from "next/server"; import { getSessionCookieById } from "../cookies"; import { getServiceUrlFromHeaders } from "../service-url"; import { getOriginalHost } from "./host"; +import { getServerTranslation } from "../server-translations"; type RegisterU2FCommand = { sessionId: string; @@ -30,7 +31,7 @@ export async function addU2F(command: RegisterU2FCommand) { }); if (!sessionCookie) { - return { error: "Could not get session" }; + return { error: await getServerTranslation("common.errors", "couldNotGetSession") }; } const session = await getSession({ @@ -42,13 +43,13 @@ export async function addU2F(command: RegisterU2FCommand) { const [hostname] = host.split(":"); if (!hostname) { - throw new Error("Could not get hostname"); + throw new Error(await getServerTranslation("common.errors", "couldNotGetHostname")); } const userId = session?.session?.factors?.user?.id; if (!session || !userId) { - return { error: "Could not get session" }; + return { error: await getServerTranslation("common.errors", "couldNotGetSession") }; } return registerU2F({ serviceUrl, userId, domain: hostname }); @@ -80,7 +81,7 @@ export async function verifyU2F(command: VerifyU2FCommand) { const userId = session?.session?.factors?.user?.id; if (!userId) { - return { error: "Could not get session" }; + return { error: await getServerTranslation("common.errors", "couldNotGetSession") }; } const request = create(VerifyU2FRegistrationRequestSchema, { diff --git a/src/lib/server/verify.ts b/src/lib/server/verify.ts index 8326c428d..f17adc305 100644 --- a/src/lib/server/verify.ts +++ b/src/lib/server/verify.ts @@ -21,6 +21,7 @@ import { completeFlowOrGetUrl } from "../client"; import { getSessionCookieByLoginName } from "../cookies"; import { getOrSetFingerprintId } from "../fingerprint"; import { getServiceUrlFromHeaders } from "../service-url"; +import { getServerTranslation } from "../server-translations"; import { loadMostRecentSession } from "../session"; import { checkMFAFactors } from "../verify-helper"; import { createSessionAndUpdateCookie } from "./cookie"; @@ -36,7 +37,7 @@ export async function verifyTOTP(code: string, loginName?: string, organization? loginName, organization, }, - }).then((session) => { + }).then(async (session) => { if (session?.factors?.user?.id) { return verifyTOTPRegistration({ serviceUrl, @@ -44,7 +45,7 @@ export async function verifyTOTP(code: string, loginName?: string, organization? userId: session.factors.user.id, }); } else { - throw Error("No user id found in session."); + throw Error(await getServerTranslation("verify.errors", "noUserIdFoundInSession")); } }); } @@ -67,17 +68,17 @@ export async function sendVerification(command: VerifyUserByEmailCommand) { serviceUrl, userId: command.userId, verificationCode: command.code, - }).catch((error) => { + }).catch(async (error) => { console.warn(error); - return { error: "Could not verify invite" }; + return { error: await getServerTranslation("verify.errors", "couldNotVerifyInvite") }; }) : await verifyEmail({ serviceUrl, userId: command.userId, verificationCode: command.code, - }).catch((error) => { + }).catch(async (error) => { console.warn(error); - return { error: "Could not verify email" }; + return { error: await getServerTranslation("verify.errors", "couldNotVerifyEmail") }; }); if ("error" in verifyResponse) { @@ -85,7 +86,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) { } if (!verifyResponse) { - return { error: "Could not verify" }; + return { error: await getServerTranslation("common.errors", "couldNotVerify") }; } let session: Session | undefined; @@ -95,7 +96,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) { }); if (!userResponse || !userResponse.user) { - return { error: "Could not load user" }; + return { error: await getServerTranslation("verify.errors", "couldNotLoadUser") }; } const user = userResponse.user; @@ -126,7 +127,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) { }); if (!authMethodResponse || !authMethodResponse.authMethodTypes) { - return { error: "Could not load possible authenticators" }; + return { error: await getServerTranslation("verify.errors", "couldNotLoadPossibleAuthenticators") }; } // if no authmethods are found on the user, redirect to set one up @@ -148,7 +149,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) { } if (!session) { - return { error: "Could not create session" }; + return { error: await getServerTranslation("common.errors", "couldNotCreateSession") }; } const params = new URLSearchParams({ @@ -262,11 +263,11 @@ export async function resendVerification(command: resendVerifyEmailCommand) { urlTemplate: `${hostWithProtocol}${basePath}/verify?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}&invite=true` + (command.requestId ? `&requestId=${command.requestId}` : ""), - }).catch((error) => { + }).catch(async (error) => { if (error.code === 9) { - return { error: "User is already verified!" }; + return { error: await getServerTranslation("verify.errors", "userAlreadyVerified") }; } - return { error: "Could not resend invite" }; + return { error: await getServerTranslation("verify.errors", "couldNotResendInvite") }; }) : zitadelSendEmailCode({ userId: command.userId,