diff --git a/src/components/auth/LoginForm.tsx b/src/components/auth/LoginForm.tsx index af18291..3e4b4d3 100644 --- a/src/components/auth/LoginForm.tsx +++ b/src/components/auth/LoginForm.tsx @@ -33,7 +33,8 @@ export default function LoginForm() { const timeToReset = Math.ceil(rateLimiter.getTimeToReset(clientIp) / 1000 / 60); setIsLockedOut(true); setLockoutMinutes(timeToReset); - throw new Error(`Too many attempts. Please try again in ${timeToReset} minutes.`); + const unit = timeToReset === 1 ? t('rateLimit.locked.minute') : t('rateLimit.locked.minutes'); + throw new Error(t('rateLimit.locked.message', { minutes: timeToReset, unit })); } const supabase = createClient(); @@ -69,9 +70,12 @@ export default function LoginForm() {
-

Account temporarily locked

+

{t('rateLimit.locked.title')}

- Too many failed login attempts. Please try again in {lockoutMinutes} {lockoutMinutes === 1 ? 'minute' : 'minutes'}. + {t('rateLimit.locked.message', { + minutes: lockoutMinutes, + unit: lockoutMinutes === 1 ? t('rateLimit.locked.minute') : t('rateLimit.locked.minutes') + })}

@@ -85,7 +89,10 @@ export default function LoginForm() { {remainingAttempts !== null && remainingAttempts > 0 && (

- {remainingAttempts} {remainingAttempts === 1 ? 'attempt' : 'attempts'} remaining before temporary lockout. + {t('rateLimit.warning.message', { + attempts: remainingAttempts, + unit: remainingAttempts === 1 ? t('rateLimit.warning.attempt') : t('rateLimit.warning.attempts') + })}

)} diff --git a/src/i18n/locales-old/de/pages/login.ts b/src/i18n/locales-old/de/pages/login.ts index 5b36150..f8235c3 100644 --- a/src/i18n/locales-old/de/pages/login.ts +++ b/src/i18n/locales-old/de/pages/login.ts @@ -50,5 +50,19 @@ export const login = { security: { secureConnection: 'Sichere Verbindung', privacyNote: 'Ihre Daten werden verschlüsselt übertragen' + }, + // Ratenbegrenzung + rateLimit: { + locked: { + title: 'Konto vorübergehend gesperrt', + message: 'Zu viele fehlgeschlagene Anmeldeversuche. Bitte versuchen Sie es in {minutes} {unit} erneut.', + minute: 'Minute', + minutes: 'Minuten' + }, + warning: { + message: '{attempts} {unit} verbleibend vor vorübergehender Sperrung.', + attempt: 'Versuch', + attempts: 'Versuche' + } } }; diff --git a/src/i18n/locales-old/en/pages/login.ts b/src/i18n/locales-old/en/pages/login.ts index 017161a..da44315 100644 --- a/src/i18n/locales-old/en/pages/login.ts +++ b/src/i18n/locales-old/en/pages/login.ts @@ -50,5 +50,19 @@ export const login = { security: { secureConnection: 'Secure Connection', privacyNote: 'Your data is transmitted encrypted' + }, + // Rate limiting + rateLimit: { + locked: { + title: 'Account temporarily locked', + message: 'Too many failed login attempts. Please try again in {minutes} {unit}.', + minute: 'minute', + minutes: 'minutes' + }, + warning: { + message: '{attempts} {unit} remaining before temporary lockout.', + attempt: 'attempt', + attempts: 'attempts' + } } }; diff --git a/src/i18n/locales-old/sr/pages/login.ts b/src/i18n/locales-old/sr/pages/login.ts index 708fed2..eb06259 100644 --- a/src/i18n/locales-old/sr/pages/login.ts +++ b/src/i18n/locales-old/sr/pages/login.ts @@ -50,5 +50,19 @@ export const login = { security: { secureConnection: 'Bezbedna veza', privacyNote: 'Vaši podaci se prenose u šifrovanom obliku' + }, + // Ograničenje broja pokušaja + rateLimit: { + locked: { + title: 'Nalog privremeno zaključan', + message: 'Previše neuspešnih pokušaja prijave. Molimo pokušajte ponovo za {minutes} {unit}.', + minute: 'minut', + minutes: 'minuta' + }, + warning: { + message: '{attempts} {unit} preostalo pre privremenog zaključavanja.', + attempt: 'pokušaj', + attempts: 'pokušaja' + } } };