diff --git a/client/src/i18n/translations/ar.ts b/client/src/i18n/translations/ar.ts index 390b05c0..99295939 100644 --- a/client/src/i18n/translations/ar.ts +++ b/client/src/i18n/translations/ar.ts @@ -464,6 +464,8 @@ const ar: Record = { 'login.mfaVerify': 'تحقق', 'login.invalidInviteLink': 'رابط الدعوة غير صالح أو منتهي الصلاحية', 'login.oidcFailed': 'فشل تسجيل الدخول عبر OIDC', + 'login.configLoadError': 'تعذّر تحميل خيارات تسجيل الدخول.', + 'login.configLoadRetry': 'تحديث', 'login.usernameRequired': 'اسم المستخدم مطلوب', 'login.passwordMinLength': 'يجب أن تكون كلمة المرور 8 أحرف على الأقل', 'login.forgotPassword': 'نسيت كلمة المرور؟', diff --git a/client/src/i18n/translations/br.ts b/client/src/i18n/translations/br.ts index 0757c3d2..e23ca5a1 100644 --- a/client/src/i18n/translations/br.ts +++ b/client/src/i18n/translations/br.ts @@ -459,6 +459,8 @@ const br: Record = { 'login.mfaVerify': 'Verificar', 'login.invalidInviteLink': 'Link de convite inválido ou expirado', 'login.oidcFailed': 'Falha no login OIDC', + 'login.configLoadError': 'Não foi possível carregar as opções de login.', + 'login.configLoadRetry': 'Atualizar', 'login.usernameRequired': 'Nome de usuário é obrigatório', 'login.passwordMinLength': 'A senha deve ter pelo menos 8 caracteres', 'login.forgotPassword': 'Esqueceu a senha?', diff --git a/client/src/i18n/translations/cs.ts b/client/src/i18n/translations/cs.ts index a14b633d..cc951bce 100644 --- a/client/src/i18n/translations/cs.ts +++ b/client/src/i18n/translations/cs.ts @@ -459,6 +459,8 @@ const cs: Record = { 'login.mfaVerify': 'Ověřit', 'login.invalidInviteLink': 'Neplatný nebo vypršelý odkaz s pozvánkou', 'login.oidcFailed': 'Přihlášení přes OIDC se nezdařilo', + 'login.configLoadError': 'Nepodařilo se načíst možnosti přihlášení.', + 'login.configLoadRetry': 'Obnovit', 'login.usernameRequired': 'Uživatelské jméno je povinné', 'login.passwordMinLength': 'Heslo musí mít alespoň 8 znaků', 'login.forgotPassword': 'Zapomenuté heslo?', diff --git a/client/src/i18n/translations/de.ts b/client/src/i18n/translations/de.ts index cbb6d153..1aab8743 100644 --- a/client/src/i18n/translations/de.ts +++ b/client/src/i18n/translations/de.ts @@ -464,6 +464,8 @@ const de: Record = { 'login.mfaVerify': 'Bestätigen', 'login.invalidInviteLink': 'Ungültiger oder abgelaufener Einladungslink', 'login.oidcFailed': 'OIDC-Anmeldung fehlgeschlagen', + 'login.configLoadError': 'Anmeldeoptionen konnten nicht geladen werden.', + 'login.configLoadRetry': 'Aktualisieren', 'login.usernameRequired': 'Benutzername ist erforderlich', 'login.passwordMinLength': 'Das Passwort muss mindestens 8 Zeichen lang sein', 'login.forgotPassword': 'Passwort vergessen?', diff --git a/client/src/i18n/translations/en.ts b/client/src/i18n/translations/en.ts index ce8321a6..145c6c5b 100644 --- a/client/src/i18n/translations/en.ts +++ b/client/src/i18n/translations/en.ts @@ -537,6 +537,8 @@ const en: Record = { 'login.mfaVerify': 'Verify', 'login.invalidInviteLink': 'Invalid or expired invite link', 'login.oidcFailed': 'OIDC login failed', + 'login.configLoadError': 'Could not load login options.', + 'login.configLoadRetry': 'Refresh', 'login.usernameRequired': 'Username is required', 'login.passwordMinLength': 'Password must be at least 8 characters', 'login.forgotPassword': 'Forgot password?', diff --git a/client/src/i18n/translations/es.ts b/client/src/i18n/translations/es.ts index a66bdfb6..a4562409 100644 --- a/client/src/i18n/translations/es.ts +++ b/client/src/i18n/translations/es.ts @@ -451,6 +451,8 @@ const es: Record = { 'login.mfaVerify': 'Verificar', 'login.invalidInviteLink': 'Enlace de invitación inválido o expirado', 'login.oidcFailed': 'Error de inicio de sesión OIDC', + 'login.configLoadError': 'No se pudieron cargar las opciones de inicio de sesión.', + 'login.configLoadRetry': 'Actualizar', 'login.usernameRequired': 'El nombre de usuario es obligatorio', 'login.passwordMinLength': 'La contraseña debe tener al menos 8 caracteres', 'login.forgotPassword': '¿Olvidaste tu contraseña?', diff --git a/client/src/i18n/translations/fr.ts b/client/src/i18n/translations/fr.ts index c7cd1605..ef26c1df 100644 --- a/client/src/i18n/translations/fr.ts +++ b/client/src/i18n/translations/fr.ts @@ -452,6 +452,8 @@ const fr: Record = { 'login.mfaVerify': 'Vérifier', 'login.invalidInviteLink': 'Lien d\'invitation invalide ou expiré', 'login.oidcFailed': 'Échec de connexion OIDC', + 'login.configLoadError': 'Impossible de charger les options de connexion.', + 'login.configLoadRetry': 'Actualiser', 'login.usernameRequired': 'Le nom d\'utilisateur est obligatoire', 'login.passwordMinLength': 'Le mot de passe doit comporter au moins 8 caractères', 'login.forgotPassword': 'Mot de passe oublié ?', diff --git a/client/src/i18n/translations/hu.ts b/client/src/i18n/translations/hu.ts index f8046fab..a07397d5 100644 --- a/client/src/i18n/translations/hu.ts +++ b/client/src/i18n/translations/hu.ts @@ -459,6 +459,8 @@ const hu: Record = { 'login.mfaVerify': 'Ellenőrzés', 'login.invalidInviteLink': 'Érvénytelen vagy lejárt meghívólink', 'login.oidcFailed': 'OIDC bejelentkezés sikertelen', + 'login.configLoadError': 'A bejelentkezési lehetőségek betöltése nem sikerült.', + 'login.configLoadRetry': 'Frissítés', 'login.usernameRequired': 'A felhasználónév kötelező', 'login.passwordMinLength': 'A jelszónak legalább 8 karakter hosszúnak kell lennie', 'login.forgotPassword': 'Elfelejtetted a jelszavad?', diff --git a/client/src/i18n/translations/id.ts b/client/src/i18n/translations/id.ts index 112d17fc..f9e51bb3 100644 --- a/client/src/i18n/translations/id.ts +++ b/client/src/i18n/translations/id.ts @@ -521,6 +521,8 @@ const id: Record = { 'login.mfaVerify': 'Verifikasi', 'login.invalidInviteLink': 'Tautan undangan tidak valid atau sudah kedaluwarsa', 'login.oidcFailed': 'Login OIDC gagal', + 'login.configLoadError': 'Gagal memuat opsi login.', + 'login.configLoadRetry': 'Segarkan', 'login.usernameRequired': 'Nama pengguna wajib diisi', 'login.passwordMinLength': 'Kata sandi minimal 8 karakter', 'login.forgotPassword': 'Lupa kata sandi?', diff --git a/client/src/i18n/translations/it.ts b/client/src/i18n/translations/it.ts index 2ac5424f..44bdcfe8 100644 --- a/client/src/i18n/translations/it.ts +++ b/client/src/i18n/translations/it.ts @@ -459,6 +459,8 @@ const it: Record = { 'login.mfaVerify': 'Verifica', 'login.invalidInviteLink': 'Link di invito non valido o scaduto', 'login.oidcFailed': 'Accesso OIDC non riuscito', + 'login.configLoadError': 'Impossibile caricare le opzioni di accesso.', + 'login.configLoadRetry': 'Aggiorna', 'login.usernameRequired': 'Il nome utente è obbligatorio', 'login.passwordMinLength': 'La password deve contenere almeno 8 caratteri', 'login.forgotPassword': 'Password dimenticata?', diff --git a/client/src/i18n/translations/nl.ts b/client/src/i18n/translations/nl.ts index 0cb55bc1..c16c68cb 100644 --- a/client/src/i18n/translations/nl.ts +++ b/client/src/i18n/translations/nl.ts @@ -452,6 +452,8 @@ const nl: Record = { 'login.mfaVerify': 'Verifiëren', 'login.invalidInviteLink': 'Ongeldige of verlopen uitnodigingslink', 'login.oidcFailed': 'OIDC-aanmelding mislukt', + 'login.configLoadError': 'Kan aanmeldingsopties niet laden.', + 'login.configLoadRetry': 'Vernieuwen', 'login.usernameRequired': 'Gebruikersnaam is vereist', 'login.passwordMinLength': 'Wachtwoord moet minimaal 8 tekens bevatten', 'login.forgotPassword': 'Wachtwoord vergeten?', diff --git a/client/src/i18n/translations/pl.ts b/client/src/i18n/translations/pl.ts index 87f768a9..005541ae 100644 --- a/client/src/i18n/translations/pl.ts +++ b/client/src/i18n/translations/pl.ts @@ -426,6 +426,8 @@ const pl: Record = { 'login.mfaVerify': 'Weryfikuj', 'login.invalidInviteLink': 'Nieprawidłowy lub wygasły link zaproszenia', 'login.oidcFailed': 'Logowanie OIDC nie powiodło się', + 'login.configLoadError': 'Nie można załadować opcji logowania.', + 'login.configLoadRetry': 'Odśwież', 'login.usernameRequired': 'Nazwa użytkownika jest wymagana', 'login.passwordMinLength': 'Hasło musi mieć co najmniej 8 znaków', 'login.forgotPassword': 'Nie pamiętasz hasła?', diff --git a/client/src/i18n/translations/ru.ts b/client/src/i18n/translations/ru.ts index f4f23fb8..0f82d22a 100644 --- a/client/src/i18n/translations/ru.ts +++ b/client/src/i18n/translations/ru.ts @@ -452,6 +452,8 @@ const ru: Record = { 'login.mfaVerify': 'Подтвердить', 'login.invalidInviteLink': 'Недействительная или истёкшая ссылка-приглашение', 'login.oidcFailed': 'Ошибка входа через OIDC', + 'login.configLoadError': 'Не удалось загрузить параметры входа.', + 'login.configLoadRetry': 'Обновить', 'login.usernameRequired': 'Имя пользователя обязательно', 'login.passwordMinLength': 'Пароль должен содержать не менее 8 символов', 'login.forgotPassword': 'Забыли пароль?', diff --git a/client/src/i18n/translations/zh.ts b/client/src/i18n/translations/zh.ts index ffa564b6..72e9e9d2 100644 --- a/client/src/i18n/translations/zh.ts +++ b/client/src/i18n/translations/zh.ts @@ -452,6 +452,8 @@ const zh: Record = { 'login.mfaVerify': '验证', 'login.invalidInviteLink': '邀请链接无效或已过期', 'login.oidcFailed': 'OIDC 登录失败', + 'login.configLoadError': '无法加载登录选项。', + 'login.configLoadRetry': '刷新', 'login.usernameRequired': '用户名为必填项', 'login.passwordMinLength': '密码至少需要8个字符', 'login.forgotPassword': '忘记密码?', diff --git a/client/src/i18n/translations/zhTw.ts b/client/src/i18n/translations/zhTw.ts index 331596c5..276a76f6 100644 --- a/client/src/i18n/translations/zhTw.ts +++ b/client/src/i18n/translations/zhTw.ts @@ -511,6 +511,8 @@ const zhTw: Record = { 'login.mfaVerify': '驗證', 'login.invalidInviteLink': '邀請連結無效或已過期', 'login.oidcFailed': 'OIDC 登入失敗', + 'login.configLoadError': '無法載入登入選項。', + 'login.configLoadRetry': '重新整理', 'login.usernameRequired': '使用者名稱為必填', 'login.passwordMinLength': '密碼至少需要8個字元', 'login.forgotPassword': '忘記密碼?', diff --git a/client/src/pages/LoginPage.tsx b/client/src/pages/LoginPage.tsx index 6fa2c192..0104f97e 100644 --- a/client/src/pages/LoginPage.tsx +++ b/client/src/pages/LoginPage.tsx @@ -33,6 +33,7 @@ export default function LoginPage(): React.ReactElement { const [isLoading, setIsLoading] = useState(false) const [error, setError] = useState('') const [appConfig, setAppConfig] = useState(null) + const [configError, setConfigError] = useState(false) const [inviteToken, setInviteToken] = useState('') const [inviteValid, setInviteValid] = useState(false) const exchangeInitiated = useRef(false) @@ -117,15 +118,15 @@ export default function LoginPage(): React.ReactElement { return } - authApi.getAppConfig?.().catch(() => null).then((config: AppConfig | null) => { - if (config) { + authApi.getAppConfig?.() + .then((config: AppConfig) => { setAppConfig(config) if (!config.has_users) setMode('register') if (!config.password_login && config.oidc_login && config.oidc_configured && config.has_users && !invite && !noRedirect) { window.location.href = '/api/auth/oidc/login' } - } - }) + }) + .catch(() => setConfigError(true)) }, [navigate, t, noRedirect]) // Language detection chain (runs once on mount, only if user has no saved preference): @@ -860,6 +861,20 @@ export default function LoginPage(): React.ReactElement { )} + {/* Config load error — shown when /api/auth/app-config fails (e.g. ZT redirect, + network blip). Hides the SSO button; prompt user to refresh. */} + {configError && !appConfig && ( +
+ {t('login.configLoadError')} + +
+ )} + {/* Demo login button */} {appConfig?.demo_mode && (