Files
zitadel/apps/login/locales/ru.json
Max Peintner 9dc127ddb5 fix(login): Prevent double execution of IDP callback token and improve architecture (#10948)
Closes #10828 

# Which Problems Are Solved

The IDP callback flow was calling retrieveIDPIntent() twice, causing
single-use token failures with error: "Intent Token is invalid". This
occurred due to Next.js 15's dynamicIO feature triggering double renders

# How the Problems Are Solved

Completely refactored the IDP callback architecture to ensure single-use
tokens are consumed exactly once:

- Centralized Business Logic: Moved all IDP callback logic into a single
server action (processIDPCallback) that:
   - Consumes the token once
- Handles all 6 business scenarios (login, linking, auto-linking,
auto-creation, manual registration, account not found)
   - Integrates session creation in the same action
- Returns `{ redirect?: string; error?: string }` for client-side
navigation
- Client Component Invocation: Created `IdpProcessHandler` client
component that:
- Calls the server action from browser context (enables cookie
modification)
   - Prevents double execution with useRef
   - Handles loading states and error display
- Clean Architecture:
   - Removed 403-line success page with complex logic
   - Removed component files from `/components/idps/pages/` folder
   - Moved all UI directly into server pages
   - Created dedicated result pages with minimal params

# Additional Changes

- Added translations to all 8 supported languages

---------

Co-authored-by: Ramon <mail@conblem.me>
2025-10-27 14:34:39 +01:00

441 lines
24 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"common": {
"back": "Назад",
"title": "Войти с Zitadel"
},
"accounts": {
"title": "Аккаунты",
"description": "Выберите аккаунт, который хотите использовать.",
"addAnother": "Добавить другой аккаунт",
"noResults": "Аккаунты не найдены",
"verified": "проверенный",
"expired": "истёк"
},
"logout": {
"title": "Выход",
"description": "Выберите аккаунт, который хотите удалить",
"noResults": "Аккаунты не найдены",
"clear": "Удалить сессию",
"verifiedAt": "Последняя активность: {time}",
"success": {
"title": "Выход выполнен успешно",
"description": "Вы успешно вышли из системы."
}
},
"loginname": {
"title": "С возвращением!",
"description": "Введите свои данные для входа.",
"register": "Зарегистрировать нового пользователя",
"submit": "Продолжить",
"labels": {
"loginname": "Логин",
"username": "Имя пользователя",
"usernameOrPhoneNumber": "Имя пользователя или номер телефона",
"usernameOrEmail": "Имя пользователя или электронная почта"
},
"required": {
"loginName": "Это поле обязательно для заполнения"
},
"errors": {
"internalError": "Произошла внутренняя ошибка",
"couldNotGetLoginSettings": "Не удалось получить настройки входа",
"couldNotSearchUsers": "Не удалось выполнить поиск пользователей",
"couldNotGetDomain": "Не удалось получить домен",
"couldNotGetHost": "Не удалось получить хост",
"couldNotStartIDPFlow": "Не удалось запустить поток IDP",
"moreThanOneUserFound": "Найдено более одного пользователя. Укажите уникальный идентификатор.",
"userNotFound": "Пользователь не найден в системе",
"couldNotCreateSession": "Не удалось создать сессию для пользователя",
"initialUserNotSupported": "Начальный пользователь не поддерживается",
"usernamePasswordNotAllowed": "Использование имени пользователя и пароля не разрешено! Обратитесь к администратору за дополнительной информацией.",
"passkeysNotAllowed": "Ключи доступа не разрешены! Обратитесь к администратору за дополнительной информацией.",
"couldNotFindIdentityProvider": "Не удалось найти поставщика удостоверений.",
"userNotActive": "Пользователь неактивен. Обратитесь к администратору за дополнительной информацией."
}
},
"zitadel": {
"errors": {
"errorOccured": "Произошла ошибка",
"multipleUsersFound": "Найдено несколько пользователей",
"userNotFound": "Пользователь не найден в системе"
}
},
"password": {
"verify": {
"title": "Пароль",
"description": "Введите ваш пароль.",
"resetPassword": "Сбросить пароль",
"submit": "Продолжить",
"labels": {
"password": "Пароль"
},
"required": {
"password": "Это поле обязательно для заполнения"
},
"errors": {
"couldNotVerifyPassword": "Не удалось проверить пароль",
"couldNotResetPassword": "Не удалось сбросить пароль"
},
"info": {
"passwordResetSent": "Пароль был сброшен. Пожалуйста, проверьте свою электронную почту"
}
},
"set": {
"title": "Установить пароль",
"description": "Установите пароль для вашего аккаунта",
"codeSent": "Код отправлен на ваш адрес электронной почты.",
"noCodeReceived": "Не получили код?",
"resend": "Отправить код повторно",
"submit": "Продолжить",
"labels": {
"code": "Код",
"newPassword": "Новый пароль",
"confirmPassword": "Подтвердите пароль"
},
"required": {
"code": "Это поле обязательно для заполнения",
"newPassword": "Вы должны указать пароль!",
"confirmPassword": "Это поле обязательно для заполнения"
},
"errors": {
"couldNotSetPassword": "Не удалось установить пароль",
"couldNotResetPassword": "Не удалось сбросить пароль",
"couldNotVerifyPassword": "Не удалось проверить пароль"
}
},
"change": {
"title": "Изменить пароль",
"description": "Установите пароль для вашего аккаунта",
"submit": "Продолжить",
"labels": {
"newPassword": "Новый пароль",
"confirmPassword": "Подтвердите пароль"
},
"required": {
"newPassword": "Вы должны указать новый пароль!",
"confirmPassword": "Это поле обязательно для заполнения"
},
"errors": {
"couldNotChangePassword": "Не удалось изменить пароль",
"couldNotVerifyPassword": "Не удалось проверить пароль",
"unknownError": "Неизвестная ошибка"
}
},
"complexity": {
"length": "Минимум {minLength} символов.",
"hasSymbol": "Должен содержать специальный символ.",
"hasNumber": "Должен содержать цифру.",
"hasUppercase": "Должен содержать заглавную букву.",
"hasLowercase": "Должен содержать строчную букву.",
"equals": "Пароли должны совпадать.",
"matches": "Совпадает",
"doesNotMatch": "Не совпадает"
},
"errors": {
"noHostFound": "Хост не найден",
"couldNotSendResetLink": "Не удалось отправить ссылку для сброса пароля",
"couldNotCreateSessionForUser": "Не удалось создать сессию для пользователя",
"couldNotVerifyPassword": "Не удалось проверить пароль",
"failedToAuthenticate": "Не удалось пройти аутентификацию. У вас было {failedAttempts} из {maxPasswordAttempts} попыток ввода пароля.{lockoutMessage}",
"failedToAuthenticateNoLimit": "Не удалось пройти аутентификацию.",
"accountLockedContactAdmin": " Свяжитесь с администратором, чтобы разблокировать вашу учетную запись",
"userNotFound": "Пользователь не найден в системе",
"initialUserNotSupported": "Первичный пользователь не поддерживается",
"userInitialStateNotSupported": "Начальное состояние пользователя не поддерживается",
"codeOrVerificationRequired": "Вы должны предоставить код или иметь действительную проверку пользователя",
"verificationRequired": "Необходимо выполнить проверку пользователя",
"couldNotLoadSession": "Не удалось загрузить сессию",
"couldNotLoadAuthMethods": "Не удалось загрузить методы аутентификации",
"failedPrecondition": "Нарушено предварительное условие",
"sessionNotValid": "Сессия недействительна"
}
},
"idp": {
"title": "Войти через SSO",
"description": "Выберите одного из провайдеров для входа",
"orSignInWith": "или войти через",
"signInWithApple": "Войти через Apple",
"signInWithGoogle": "Войти через Google",
"signInWithAzureAD": "Войти через AzureAD",
"signInWithGithub": "Войти через GitHub",
"signInWithGitlab": "Войти через GitLab",
"loginError": {
"title": "Ошибка входа",
"description": "Произошла ошибка при попытке входа."
},
"linkingError": {
"title": "Ошибка привязки аккаунта",
"description": "Произошла ошибка при попытке привязать аккаунт."
},
"completeRegister": {
"title": "Завершите регистрацию",
"description": "Завершите регистрацию вашего аккаунта."
},
"accountNotFound": {
"title": "Аккаунт не найден",
"description": "Мы не смогли найти аккаунт, связанный с учетными данными вашего провайдера идентификации.",
"info": "Существующий аккаунт не найден. Пожалуйста, войдите с существующим аккаунтом или обратитесь к администратору за помощью.",
"backToLogin": "Вернуться к входу"
},
"registrationFailed": {
"title": "Регистрация недоступна",
"description": "Мы не смогли завершить процесс регистрации.",
"info": "Не удалось определить организацию для регистрации. Пожалуйста, обратитесь к администратору за помощью.",
"backToLogin": "Вернуться к входу"
},
"processing": {
"message": "Обработка аутентификации...",
"noRedirect": "Не получено перенаправления или ошибки от сервера",
"unexpectedError": "Произошла неожиданная ошибка"
},
"errors": {
"missingParameters": "Отсутствуют обязательные параметры",
"missingIdpInfo": "Отсутствует информация IDP",
"idpNotFound": "Провайдер идентификации не найден",
"linkingNotAllowed": "Связывание не разрешено для этого провайдера идентификации",
"linkingFailed": "Не удалось связать провайдера идентификации с учетной записью",
"autoLinkingFailed": "Не удалось автоматически связать учетную запись",
"userCreationFailed": "Не удалось создать учетную запись пользователя",
"orgResolutionFailed": "Не удалось определить организацию для регистрации",
"sessionCreationFailed": "Не удалось создать сеанс или определить перенаправление",
"unknownError": "Произошла неизвестная ошибка"
}
},
"ldap": {
"title": "Войти через LDAP",
"description": "Введите ваши учетные данные LDAP.",
"submit": "Продолжить",
"labels": {
"username": "Имя пользователя",
"password": "Пароль"
},
"required": {
"username": "Это поле обязательно для заполнения",
"password": "Это поле обязательно для заполнения"
}
},
"mfa": {
"verify": {
"title": "Подтвердите вашу личность",
"description": "Выберите один из следующих факторов.",
"noResults": "Нет доступных методов двухфакторной аутентификации"
},
"set": {
"title": "Настройка двухфакторной аутентификации",
"description": "Выберите один из следующих методов.",
"skip": "Пропустить"
}
},
"otp": {
"verify": {
"title": "Подтверждение 2FA",
"totpDescription": "Введите код из приложения-аутентификатора.",
"smsDescription": "Введите код, полученный по SMS.",
"emailDescription": "Введите код, полученный по email.",
"noCodeReceived": "Не получили код?",
"resendCode": "Отправить код повторно",
"submit": "Продолжить",
"labels": {
"code": "Код"
},
"required": {
"code": "Это поле обязательно для заполнения"
}
},
"set": {
"title": "Настройка двухфакторной аутентификации",
"totpDescription": "Отсканируйте QR-код в приложении-аутентификаторе.",
"smsDescription": "Введите номер телефона для получения кода по SMS.",
"emailDescription": "Введите email для получения кода.",
"totpRegisterDescription": "Отсканируйте QR-код или перейдите по ссылке вручную.",
"submit": "Продолжить",
"labels": {
"code": "Код"
},
"required": {
"code": "Это поле обязательно для заполнения"
}
}
},
"passkey": {
"verify": {
"title": "Аутентификация с помощью пасскей",
"description": "Устройство запросит отпечаток пальца, лицо или экранный замок",
"usePassword": "Использовать пароль",
"submit": "Продолжить"
},
"set": {
"title": "Настройка пасскей",
"description": "Устройство запросит отпечаток пальца, лицо или экранный замок",
"info": {
"description": "Пасскей — метод аутентификации через устройство (отпечаток пальца, Apple FaceID и аналоги).",
"link": "Аутентификация без пароля"
},
"skip": "Пропустить",
"submit": "Продолжить"
}
},
"u2f": {
"verify": {
"title": "Подтверждение 2FA",
"description": "Подтвердите аккаунт с помощью устройства."
},
"set": {
"title": "Настройка двухфакторной аутентификации",
"description": "Настройте устройство как второй фактор.",
"submit": "Продолжить"
}
},
"register": {
"methods": {
"passkey": "Пасскей",
"password": "Пароль"
},
"disabled": {
"title": "Регистрация отключена",
"description": "Регистрация недоступна. Обратитесь к администратору."
},
"missingdata": {
"title": "Недостаточно данных",
"description": "Укажите email, имя и фамилию для регистрации."
},
"title": "Регистрация",
"description": "Создайте свой аккаунт ZITADEL.",
"noMethodAvailableWarning": "Нет доступных методов аутентификации. Обратитесь к администратору.",
"selectMethod": "Выберите метод аутентификации",
"agreeTo": "Для регистрации необходимо принять условия:",
"termsOfService": "Условия использования",
"privacyPolicy": "Политика конфиденциальности",
"submit": "Продолжить",
"password": {
"title": "Установить пароль",
"description": "Установите пароль для вашего аккаунта",
"submit": "Продолжить",
"labels": {
"password": "Пароль",
"confirmPassword": "Подтвердите пароль"
},
"required": {
"password": "Вы должны указать пароль!",
"confirmPassword": "Это поле обязательно для заполнения"
}
},
"labels": {
"firstname": "Имя",
"lastname": "Фамилия",
"email": "Электронная почта"
},
"required": {
"firstname": "Это поле обязательно для заполнения",
"lastname": "Это поле обязательно для заполнения",
"email": "Это поле обязательно для заполнения"
},
"errors": {
"couldNotCreateUser": "Не удалось создать пользователя",
"couldNotCreateSession": "Не удалось создать сессию",
"userNotFound": "Пользователь не найден в системе",
"couldNotLinkIDP": "Не удалось привязать IDP к пользователю",
"couldNotRegisterUser": "Не удалось зарегистрировать пользователя"
}
},
"invite": {
"title": "Пригласить пользователя",
"description": "Укажите email и имя пользователя для приглашения.",
"info": "Пользователь получит email с инструкциями.",
"notAllowed": "Ваши настройки не позволяют приглашать пользователей.",
"submit": "Продолжить",
"success": {
"title": "Пользователь приглашён",
"description": "Письмо успешно отправлено.",
"verified": "Пользователь приглашён и уже подтвердил email.",
"notVerifiedYet": "Пользователь приглашён. Он получит email с инструкциями.",
"submit": "Пригласить другого пользователя"
}
},
"signedin": {
"title": "Добро пожаловать, {user}!",
"description": "Вы вошли в систему.",
"continue": "Продолжить",
"error": {
"title": "Ошибка",
"description": "Не удалось войти в систему. Проверьте свои данные и попробуйте снова."
}
},
"verify": {
"userIdMissing": "Не указан userId!",
"successTitle": "Пользователь подтверждён",
"successDescription": "Пользователь успешно подтверждён.",
"setupAuthenticator": "Настроить аутентификатор",
"verify": {
"title": "Подтверждение пользователя",
"description": "Введите код из письма подтверждения.",
"noCodeReceived": "Не получили код?",
"resendCode": "Отправить код повторно",
"codeSent": "Код отправлен на ваш email.",
"submit": "Продолжить",
"labels": {
"code": "Код"
},
"required": {
"code": "Это поле обязательно для заполнения"
}
},
"errors": {
"couldNotResendEmail": "Не удалось повторно отправить электронное письмо",
"couldNotVerifyUser": "Не удалось подтвердить пользователя",
"couldNotVerifyInvite": "Не удалось подтвердить приглашение",
"couldNotVerifyEmail": "Не удалось подтвердить электронную почту",
"couldNotVerify": "Не удалось подтвердить",
"couldNotLoadUser": "Не удалось загрузить пользователя",
"couldNotLoadAuthenticators": "Не удалось загрузить доступные средства аутентификации",
"couldNotCreateSession": "Не удалось создать сеанс",
"noHostFound": "Хост не найден",
"userAlreadyVerified": "Пользователь уже подтверждён!",
"couldNotResendInvite": "Не удалось повторно отправить приглашение",
"inviteSendFailed": "Не удалось отправить письмо с приглашением",
"emailSendFailed": "Не удалось отправить письмо с подтверждением"
}
},
"authenticator": {
"title": "Выбор метода аутентификации",
"description": "Выберите предпочитаемый метод аутентификации",
"noMethodsAvailable": "Нет доступных методов аутентификации",
"allSetup": "Аутентификатор уже настроен!",
"linkWithIDP": "или привязать через Identity Provider"
},
"device": {
"usercode": {
"title": "Код устройства",
"description": "Введите код.",
"submit": "Продолжить",
"labels": {
"code": "Код"
},
"required": {
"code": "Это поле обязательно для заполнения"
}
},
"request": {
"title": "{appName} хочет подключиться:",
"description": "{appName} получит доступ к:",
"disclaimer": "Нажимая «Разрешить», вы разрешаете этому приложению и Zitadel использовать вашу информацию в соответствии с их условиями использования и политиками конфиденциальности. Вы можете отозвать этот доступ в любое время.",
"submit": "Разрешить",
"deny": "Запретить"
},
"scope": {
"openid": "Проверка вашей личности.",
"email": "Доступ к вашему адресу электронной почты.",
"profile": "Доступ к полной информации вашего профиля.",
"offline_access": "Разрешить офлайн-доступ к вашему аккаунту."
}
},
"error": {
"noUserCode": "Не указан код пользователя!",
"noDeviceRequest": "Не найдена ни одна заявка на устройство.",
"unknownContext": "Не удалось получить контекст пользователя. Укажите имя пользователя или loginName в параметрах поиска.",
"sessionExpired": "Ваша сессия истекла. Войдите снова.",
"failedLoading": "Ошибка загрузки данных. Попробуйте ещё раз.",
"tryagain": "Попробовать снова"
}
}