From 793c260fc57e152e0002b0dfd6fa41bbc00179c2 Mon Sep 17 00:00:00 2001 From: duckietm Date: Wed, 6 May 2026 08:32:36 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=86=99=20Small=20update=20to=20the=20logi?= =?UTF-8?q?n=20texts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/login/LoginView.tsx | 139 ++++++++++++++++------------- 1 file changed, 75 insertions(+), 64 deletions(-) diff --git a/src/components/login/LoginView.tsx b/src/components/login/LoginView.tsx index e77dac5..ce26fe6 100644 --- a/src/components/login/LoginView.tsx +++ b/src/components/login/LoginView.tsx @@ -15,6 +15,7 @@ import flagTr from '../../assets/images/flag_icon/flag_icon_tr.png'; import { applyTextTranslationLocale } from '../../hooks/translation/useTranslation'; import { NewsWindow } from './components/NewsWindow'; import { TurnstileWidget } from './TurnstileWidget'; +import { t } from './utils/i18n'; type DialogMode = 'login' | 'register' | 'forgot'; type LoginLocale = { code: string; file: string; label: string; flag: string }; @@ -194,8 +195,16 @@ export const LoginView: FC = ({ onAuthenticated, isEntering = fa const [ localeApplying, setLocaleApplying ] = useState(false); const [ localeError, setLocaleError ] = useState(''); const [ loginViewConfig, setLoginViewConfig ] = useState>(() => GetConfigurationValue>('loginview', {})); + const [ , setLocalizationVersion ] = useState(0); const submitTimeRef = useRef(0); + useEffect(() => + { + const refreshLocalization = () => setLocalizationVersion(value => (value + 1)); + window.addEventListener('nitro-localization-updated', refreshLocalization); + return () => window.removeEventListener('nitro-localization-updated', refreshLocalization); + }, []); + const loginImages = useMemo>(() => { const configured = (loginViewConfig?.['images'] as Record) ?? {}; @@ -413,19 +422,19 @@ export const LoginView: FC = ({ onAuthenticated, isEntering = fa if(state.lockedUntil > nowTs) { const remaining = Math.ceil((state.lockedUntil - nowTs) / 1000); - setError(`Too many attempts. Try again in ${ remaining }s.`); + setError(t('nitro.login.error.too_many_attempts', 'Too many attempts. Try again in %seconds%s.', [ 'seconds' ], [ String(remaining) ])); return; } if(!username.trim() || !password) { - setError('Please enter both your Habbo name and password.'); + setError(t('nitro.login.error.missing_credentials', 'Please enter both your Habbo name and password.')); return; } if(turnstileEnabled && !loginTurnstileToken) { - setError('Please complete the security check.'); + setError(t('nitro.login.error.turnstile', 'Please complete the security check.')); return; } @@ -453,14 +462,14 @@ export const LoginView: FC = ({ onAuthenticated, isEntering = fa } recordFailure(); - const message = typeof payload.error === 'string' ? payload.error : 'Invalid Habbo name or password.'; + const message = typeof payload.error === 'string' ? payload.error : t('nitro.login.error.invalid_credentials', 'Invalid Habbo name or password.'); setError(message); resetLoginTurnstile(); } catch(err) { recordFailure(); - setError('Unable to reach the login service. Please try again.'); + setError(t('nitro.login.error.login_unreachable', 'Unable to reach the login service. Please try again.')); resetLoginTurnstile(); } finally @@ -497,7 +506,7 @@ export const LoginView: FC = ({ onAuthenticated, isEntering = fa const { ok, status, payload } = await postJson(checkEmailUrl, { email }); const result = interpretAvailability(ok, status, payload); if(result.available) return { available: true }; - return { available: false, error: result.error || 'This email is already in use.' }; + return { available: false, error: result.error || t('nitro.login.error.email_taken', 'This email is already in use.') }; } catch { @@ -512,7 +521,7 @@ export const LoginView: FC = ({ onAuthenticated, isEntering = fa const { ok, status, payload } = await postJson(checkUsernameUrl, { username }); const result = interpretAvailability(ok, status, payload); if(result.available) return { available: true }; - return { available: false, error: result.error || 'This Habbo name is already taken.' }; + return { available: false, error: result.error || t('nitro.login.error.username_taken', 'This Habbo name is already taken.') }; } catch { @@ -524,7 +533,7 @@ export const LoginView: FC = ({ onAuthenticated, isEntering = fa { if(turnstileEnabled && !body.turnstileToken) { - setError('Please complete the security check.'); + setError(t('nitro.login.error.turnstile', 'Please complete the security check.')); return; } @@ -545,7 +554,7 @@ export const LoginView: FC = ({ onAuthenticated, isEntering = fa if(ok) { - const friendly = `Welcome aboard, ${ body.username }! Your account is ready — log in below with the password you just chose.`; + const friendly = t('nitro.login.register.success', 'Welcome aboard, %username%! Your account is ready — log in below with the password you just chose.', [ 'username' ], [ body.username ]); setInfo(typeof payload.message === 'string' ? payload.message : friendly); setMode('login'); setUsername(body.username); @@ -553,12 +562,12 @@ export const LoginView: FC = ({ onAuthenticated, isEntering = fa return; } - setError(typeof payload.error === 'string' ? payload.error : 'Unable to create your account.'); + setError(typeof payload.error === 'string' ? payload.error : t('nitro.login.error.register_failed', 'Unable to create your account.')); onDialogReset(); } catch { - setError('Unable to reach the registration service.'); + setError(t('nitro.login.error.register_unreachable', 'Unable to reach the registration service.')); onDialogReset(); } finally @@ -571,7 +580,7 @@ export const LoginView: FC = ({ onAuthenticated, isEntering = fa { if(turnstileEnabled && !body.turnstileToken) { - setError('Please complete the security check.'); + setError(t('nitro.login.error.turnstile', 'Please complete the security check.')); return; } @@ -588,18 +597,18 @@ export const LoginView: FC = ({ onAuthenticated, isEntering = fa if(ok) { - const friendly = 'Email sent! If an account matches that address you\'ll find a reset link in your inbox shortly (check spam if it doesn\'t show up within a minute).'; + const friendly = t('nitro.login.forgot.success', 'Email sent! If an account matches that address you\'ll find a reset link in your inbox shortly (check spam if it doesn\'t show up within a minute).'); setInfo(typeof payload.message === 'string' ? payload.message : friendly); setMode('login'); return; } - setError(typeof payload.error === 'string' ? payload.error : 'Unable to send a reset email right now.'); + setError(typeof payload.error === 'string' ? payload.error : t('nitro.login.error.forgot_failed', 'Unable to send a reset email right now.')); onDialogReset(); } catch { - setError('Unable to reach the password reset service.'); + setError(t('nitro.login.error.forgot_unreachable', 'Unable to reach the password reset service.')); onDialogReset(); } finally @@ -655,8 +664,8 @@ export const LoginView: FC = ({ onAuthenticated, isEntering = fa
-
Choose your language
-
+
{ t('nitro.login.language.title', 'Choose your language') }
+
{ LOGIN_LOCALES.map(locale =>
{ localeError.length > 0 &&
{ localeError }
}
-
First time here?
+
{ t('nitro.login.firsttime.title', 'First time here?') }
- Don't have a Habbo yet? - setMode('register') }>You can create one here + { t('nitro.login.firsttime.text', 'Don\'t have a Habbo yet?') } + setMode('register') }>{ t('nitro.login.firsttime.link', 'You can create one here') }
-
What's your Habbo called?
+
{ t('nitro.login.card.title', 'What\'s your Habbo called?') }
- + = ({ onAuthenticated, isEntering = fa />
- + = ({ onAuthenticated, isEntering = fa checked={ rememberMe } onChange={ e => setRememberMe(e.target.checked) } /> - Ricordami + { t('login.remember_me', 'Remember me') } { turnstileEnabled && mode === 'login' && = ({ onAuthenticated, isEntering = fa /> } { loginServerReachable === false &&
- The gameserver isn't running right now. Please try again in a moment. + { t('nitro.login.server.offline.short', 'The gameserver isn\'t running right now. Please try again in a moment.') }
} @@ -744,9 +753,9 @@ export const LoginView: FC = ({ onAuthenticated, isEntering = fa type="submit" className="ok-button" disabled={ submitting || isEntering || isLocked } - >{ isEntering ? 'Entrando…' : loginPingingServer ? 'Checking…' : 'OK' } + >{ isEntering ? t('nitro.login.entering', 'Entering…') : loginPingingServer ? t('nitro.login.server.checking', 'Checking…') : t('login.title', 'Log in') }
- setMode('forgot') }>Forgotten your password? + setMode('forgot') }>{ t('login.forgot_password', 'Forgotten your password?') }
@@ -1097,22 +1106,22 @@ const RegisterDialog: FC = props => if(!email.trim() || !password || !confirm) { - setLocalError('Please fill in every field.'); + setLocalError(t('nitro.login.register.error.missing_fields', 'Please fill in every field.')); return; } if(!EMAIL_REGEX.test(email.trim())) { - setLocalError('Please enter a valid email address.'); + setLocalError(t('nitro.login.register.error.invalid_email', 'Please enter a valid email address.')); return; } if(password.length < 8) { - setLocalError('Your password must be at least 8 characters.'); + setLocalError(t('nitro.login.register.error.password_too_short', 'Your password must be at least 8 characters.')); return; } if(password !== confirm) { - setLocalError('Passwords do not match.'); + setLocalError(t('nitro.login.register.error.password_mismatch', 'Passwords do not match.')); return; } @@ -1122,13 +1131,13 @@ const RegisterDialog: FC = props => const serverOk = await pingServer(); if(!serverOk) { - setLocalError('The gameserver is not running. Please try again later.'); + setLocalError(t('nitro.login.error.server_offline', 'The gameserver is not running. Please try again later.')); return; } const result = await onCheckEmail(email.trim()); if(!result.available) { - setLocalError(result.error || 'This email is already in use.'); + setLocalError(result.error || t('nitro.login.error.email_taken', 'This email is already in use.')); return; } setStep('avatar'); @@ -1207,18 +1216,18 @@ const RegisterDialog: FC = props => const trimmed = username.trim(); if(!trimmed) { - setLocalError('Please choose a Habbo name.'); + setLocalError(t('nitro.login.register.error.username_required', 'Please choose a Habbo name.')); return; } if(trimmed.length < 3 || trimmed.length > 16) { - setLocalError('Habbo name must be 3–16 characters.'); + setLocalError(t('nitro.login.register.error.username_length', 'Habbo name must be 3–16 characters.')); return; } if(turnstileEnabled && !turnstileToken) { - setLocalError('Please complete the security check.'); + setLocalError(t('nitro.login.error.turnstile', 'Please complete the security check.')); return; } @@ -1228,13 +1237,13 @@ const RegisterDialog: FC = props => const serverOk = await pingServer(); if(!serverOk) { - setLocalError('The gameserver is not running. Please try again later.'); + setLocalError(t('nitro.login.error.server_offline', 'The gameserver is not running. Please try again later.')); return; } const result = await onCheckUsername(trimmed); if(!result.available) { - setLocalError(result.error || 'This Habbo name is already taken.'); + setLocalError(result.error || t('nitro.login.error.username_taken', 'This Habbo name is already taken.')); return; } } @@ -1261,35 +1270,35 @@ const RegisterDialog: FC = props =>
- Habbo Details - + { t('nitro.login.register.title', 'Habbo Details') } +
{ step === 'credentials' &&
- Let's create your account. Enter your email and pick a password — we'll check that email isn't already in use. + { t('nitro.login.register.intro.credentials', 'Let\'s create your account. Enter your email and pick a password — we\'ll check that email isn\'t already in use.') }
{ serverOffline &&
- The gameserver isn't running right now, so new accounts can't be created. Please try again in a moment. + { t('nitro.login.register.server.offline', 'The gameserver isn\'t running right now, so new accounts can\'t be created. Please try again in a moment.') }
}
- + setEmail(e.target.value) } />
- + setPassword(e.target.value) } />
- + setConfirm(e.target.value) } />
@@ -1298,7 +1307,7 @@ const RegisterDialog: FC = props =>
1/2
@@ -1307,29 +1316,29 @@ const RegisterDialog: FC = props => { step === 'avatar' &&
- Now it's time to make your own Habbo character! To make your own Habbo, please start by choosing your Habbo Name. + { t('nitro.login.register.intro.avatar', 'Now it\'s time to make your own Habbo character! To make your own Habbo, please start by choosing your Habbo Name.') }
{ serverOffline &&
- The gameserver isn't running right now, so new accounts can't be created. Please try again in a moment. + { t('nitro.login.register.server.offline', 'The gameserver isn\'t running right now, so new accounts can\'t be created. Please try again in a moment.') }
}
- setUsername(e.target.value) } />
@@ -1377,8 +1386,10 @@ const RegisterDialog: FC = props =>
@@ -1395,10 +1406,10 @@ const RegisterDialog: FC = props => { info &&
{ info }
}
- + 2/2
@@ -1436,7 +1447,7 @@ const ForgotDialog: FC = props => if(!email.trim()) { - setLocalError('Please enter your email address.'); + setLocalError(t('nitro.login.forgot.error.email_required', 'Please enter your email address.')); return; } @@ -1448,12 +1459,12 @@ const ForgotDialog: FC = props =>
- Reset password - + { t('nitro.login.forgot.title', 'Reset password') } +
- + setEmail(e.target.value) } />
@@ -1469,7 +1480,7 @@ const ForgotDialog: FC = props => { (localError || error) &&
{ localError || error }
} { info &&
{ info }
}
- +