Auth Screen Localization Patch

This commit is contained in:
cyberalby2 2026-03-16 12:07:59 +01:00
parent 6a7a7b0f38
commit 08605e613f
3 changed files with 67 additions and 22 deletions

View file

@ -1567,5 +1567,27 @@
"auto_sync_desc":"Automatically add items from your MAL 'Watching' list to your Nuvio Library.", "auto_sync_desc":"Automatically add items from your MAL 'Watching' list to your Nuvio Library.",
"allow_nsfw":"Include NSFW Content", "allow_nsfw":"Include NSFW Content",
"allow_nsfw_desc":"Allow NSFW entries to be returned when fetching your MAL list." "allow_nsfw_desc":"Allow NSFW entries to be returned when fetching your MAL list."
},
"auth_screen":{
"invalid_email":"Invalid Email",
"invalid_email_desc":"Enter a valid email address",
"pw_short":"Password Too Short",
"pw_short_desc":"Password must be at least 6 characters",
"pw_no_match":"Passwords do not match",
"auth_failed":"Authentication Failed",
"login_success":"Logged in successfully",
"sign_up_success":"Sign up successful",
"welcome_back":"Welcome Back",
"create_account":"Create your account",
"sign_in_desc":"Sync your addons, progress and settings across devices",
"sign_in":"Sign In",
"sign_up":"Sign Up",
"email_address_placeholder":"Email address",
"password_placeholder":"Password (min 6 characters)",
"forgot_password":"Forgot password?",
"confirm_password":"Confirm password",
"dont_have_account":"Dont't have an account?",
"already_have_account":"Already have an account?",
"continue_without_account":"Continue without an account"
} }
} }

View file

@ -1551,5 +1551,27 @@
"auto_sync_desc":"Aggiungi elementi dalla tua lista 'Watching' di MAL verso la tua libreria di Nuvio.", "auto_sync_desc":"Aggiungi elementi dalla tua lista 'Watching' di MAL verso la tua libreria di Nuvio.",
"allow_nsfw":"Includi Contenuti NSFW", "allow_nsfw":"Includi Contenuti NSFW",
"allow_nsfw_desc":"Consenti contenuti NSFW quando aggiorni i dati dalle tue liste MAL." "allow_nsfw_desc":"Consenti contenuti NSFW quando aggiorni i dati dalle tue liste MAL."
},
"auth_screen":{
"invalid_email":"Email non valida",
"invalid_email_desc":"Inserisci un indirizzo email valido",
"pw_short":"Password troppo corta",
"pw_short_desc":"La password deve avere almeno 6 caratteri",
"pw_no_match":"Le password non coincidono",
"auth_failed":"Autenticazione fallita",
"login_success":"Login effettuato con successo",
"sign_up_success":"Registrazione effetuata con successo",
"welcome_back":"Bentornato",
"create_account":"Crea il tuo account",
"sign_in_desc":"Sincronizza i tuoi addon, il progresso e le impostazioni fra i dispositivi",
"sign_in":"Accedi",
"sign_up":"Registrati",
"email_address_placeholder":"Indirizzo Email",
"password_placeholder":"Password (min 6 caratteri)",
"forgot_password":"Password dimenticata?",
"confirm_password":"Conferma password",
"dont_have_account":"Non hai un account?",
"already_have_account":"Hai un account?",
"continue_without_account":"Continua senza account"
} }
} }

View file

@ -9,6 +9,7 @@ import { useNavigation, useRoute } from '@react-navigation/native';
import * as Haptics from 'expo-haptics'; import * as Haptics from 'expo-haptics';
import { useToast } from '../contexts/ToastContext'; import { useToast } from '../contexts/ToastContext';
import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useTranslation } from 'react-i18next';
const EMAIL_CONFIRMATION_REQUIRED_PREFIX = '__EMAIL_CONFIRMATION__'; const EMAIL_CONFIRMATION_REQUIRED_PREFIX = '__EMAIL_CONFIRMATION__';
const AUTH_BG_GRADIENT = ['#07090F', '#0D1020', '#140B24'] as const; const AUTH_BG_GRADIENT = ['#07090F', '#0D1020', '#140B24'] as const;
@ -51,7 +52,7 @@ const AuthScreen: React.FC = () => {
const safeTopInset = Math.max(insets.top, Platform.OS === 'android' ? (StatusBar.currentHeight || 0) : 0); const safeTopInset = Math.max(insets.top, Platform.OS === 'android' ? (StatusBar.currentHeight || 0) : 0);
const backButtonTop = safeTopInset + 8; const backButtonTop = safeTopInset + 8;
const { showError, showSuccess } = useToast(); const { showError, showSuccess } = useToast();
const {t} = useTranslation();
const [email, setEmail] = useState(''); const [email, setEmail] = useState('');
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState('');
@ -161,23 +162,23 @@ const AuthScreen: React.FC = () => {
if (loading) return; if (loading) return;
if (!isEmailValid) { if (!isEmailValid) {
const msg = 'Enter a valid email address'; const msg = t('auth_screen.invalid_email_desc');
setError(msg); setError(msg);
showError('Invalid Email', 'Enter a valid email address'); showError(t('auth_screen.invalid_email'), t('auth_screen.invalid_email_desc'));
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error).catch(() => {}); Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error).catch(() => {});
return; return;
} }
if (!isPasswordValid) { if (!isPasswordValid) {
const msg = 'Password must be at least 6 characters'; const msg = t('auth_screen.pw_short_desc');
setError(msg); setError(msg);
showError('Password Too Short', 'Password must be at least 6 characters'); showError(t('auth_screen.pw_short'), t('auth_screen.pw_short_desc'));
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error).catch(() => {}); Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error).catch(() => {});
return; return;
} }
if (mode === 'signup' && !passwordsMatch) { if (mode === 'signup' && !passwordsMatch) {
const msg = 'Passwords do not match'; const msg = t('auth_screen.pw_no_match');
setError(msg); setError(msg);
showError('Passwords Don\'t Match', 'Passwords do not match'); showError(t('auth_screen.pw_no_match'),t('auth_screen.pw_no_match'));
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error).catch(() => {}); Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error).catch(() => {});
return; return;
} }
@ -197,11 +198,11 @@ const AuthScreen: React.FC = () => {
const cleanError = normalizeAuthErrorMessage(err); const cleanError = normalizeAuthErrorMessage(err);
setError(cleanError); setError(cleanError);
showError('Authentication Failed', cleanError); showError(t('auth_screen.auth_failed'), cleanError);
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error).catch(() => {}); Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error).catch(() => {});
} else { } else {
const msg = mode === 'signin' ? 'Logged in successfully' : 'Sign up successful'; const msg = mode === 'signin' ? t('auth_screen.login_success') : t('auth_screen.sign_up_success');
showSuccess('Success', msg); showSuccess(t('common.success'), msg);
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success).catch(() => {}); Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success).catch(() => {});
// Navigate to main tabs after successful authentication // Navigate to main tabs after successful authentication
@ -285,11 +286,11 @@ const AuthScreen: React.FC = () => {
]} ]}
> >
<Animated.Text style={[styles.heading, { color: currentTheme.colors.white, opacity: titleOpacity, transform: [{ translateY: titleTranslateY }] }]}> <Animated.Text style={[styles.heading, { color: currentTheme.colors.white, opacity: titleOpacity, transform: [{ translateY: titleTranslateY }] }]}>
{mode === 'signin' ? 'Welcome back' : 'Create your account'} {mode === 'signin' ? t('auth_screen.welcome_back') : t('auth_screen.create_account')}
</Animated.Text> </Animated.Text>
{keyboardHeight === 0 && ( {keyboardHeight === 0 && (
<Text style={[styles.subheading, { color: currentTheme.colors.textMuted }]}> <Text style={[styles.subheading, { color: currentTheme.colors.textMuted }]}>
Sync your addons, progress and settings across devices {t('auth_screen.sign_in_desc')}
</Text> </Text>
)} )}
</Animated.View> </Animated.View>
@ -339,7 +340,7 @@ const AuthScreen: React.FC = () => {
activeOpacity={0.8} activeOpacity={0.8}
> >
<Text style={[styles.switchText, { color: mode === 'signin' ? '#fff' : currentTheme.colors.textMuted }]}> <Text style={[styles.switchText, { color: mode === 'signin' ? '#fff' : currentTheme.colors.textMuted }]}>
Sign In {t('auth_screen.sign_in')}
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity <TouchableOpacity
@ -353,7 +354,7 @@ const AuthScreen: React.FC = () => {
color: mode === 'signup' ? '#fff' : currentTheme.colors.textMuted color: mode === 'signup' ? '#fff' : currentTheme.colors.textMuted
} }
]}> ]}>
Sign Up {t('auth_screen.sign_up')}
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
@ -373,7 +374,7 @@ const AuthScreen: React.FC = () => {
/> />
</View> </View>
<TextInput <TextInput
placeholder="Email address" placeholder={t('auth_screen.email_address_placeholder')}
placeholderTextColor="rgba(255,255,255,0.4)" placeholderTextColor="rgba(255,255,255,0.4)"
style={[styles.input, { color: currentTheme.colors.white }]} style={[styles.input, { color: currentTheme.colors.white }]}
autoCapitalize="none" autoCapitalize="none"
@ -403,7 +404,7 @@ const AuthScreen: React.FC = () => {
/> />
</View> </View>
<TextInput <TextInput
placeholder="Password (min 6 characters)" placeholder={t('auth_screen.password_placeholder')}
placeholderTextColor="rgba(255,255,255,0.4)" placeholderTextColor="rgba(255,255,255,0.4)"
style={[styles.input, { color: currentTheme.colors.white }]} style={[styles.input, { color: currentTheme.colors.white }]}
autoCapitalize="none" autoCapitalize="none"
@ -432,7 +433,7 @@ const AuthScreen: React.FC = () => {
activeOpacity={0.75} activeOpacity={0.75}
style={styles.forgotPasswordButton} style={styles.forgotPasswordButton}
> >
<Text style={[styles.forgotPasswordText, { color: currentTheme.colors.textMuted }]}>Forgot password?</Text> <Text style={[styles.forgotPasswordText, { color: currentTheme.colors.textMuted }]}>{t('auth_screen.forgot_password')}</Text>
</TouchableOpacity> </TouchableOpacity>
)} )}
@ -452,7 +453,7 @@ const AuthScreen: React.FC = () => {
/> />
</View> </View>
<TextInput <TextInput
placeholder="Confirm password" placeholder={t('auth_screen.confirm_password')}
placeholderTextColor="rgba(255,255,255,0.4)" placeholderTextColor="rgba(255,255,255,0.4)"
style={[styles.input, { color: currentTheme.colors.white }]} style={[styles.input, { color: currentTheme.colors.white }]}
autoCapitalize="none" autoCapitalize="none"
@ -523,7 +524,7 @@ const AuthScreen: React.FC = () => {
<ActivityIndicator color="#fff" size="small" /> <ActivityIndicator color="#fff" size="small" />
) : ( ) : (
<Animated.Text style={[styles.ctaText, { opacity: ctaTextOpacity, transform: [{ translateY: ctaTextTranslateY }] }]}> <Animated.Text style={[styles.ctaText, { opacity: ctaTextOpacity, transform: [{ translateY: ctaTextTranslateY }] }]}>
{mode === 'signin' ? 'Sign In' : 'Create Account'} {mode === 'signin' ? t('auth_screen.sign_in') : t('auth_screen.create_account')}
</Animated.Text> </Animated.Text>
)} )}
</TouchableOpacity> </TouchableOpacity>
@ -536,9 +537,9 @@ const AuthScreen: React.FC = () => {
style={{ marginTop: 16 }} style={{ marginTop: 16 }}
> >
<Text style={[styles.switchModeText, { color: currentTheme.colors.textMuted }]}> <Text style={[styles.switchModeText, { color: currentTheme.colors.textMuted }]}>
{mode === 'signin' ? "Don't have an account? " : 'Already have an account? '} {mode === 'signin' ? t('auth_screen.dont_have_account') : t('auth_screen.already_have_account')}
<Text style={{ color: currentTheme.colors.primary, fontWeight: '600' }}> <Text style={{ color: currentTheme.colors.primary, fontWeight: '600' }}>
{mode === 'signin' ? 'Sign up' : 'Sign in'} {mode === 'signin' ? t('auth_screen.sign_up') : t('auth_screen.sign_in')}
</Text> </Text>
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
@ -563,7 +564,7 @@ const AuthScreen: React.FC = () => {
textAlign: 'center', textAlign: 'center',
fontWeight: fromOnboarding ? '700' : '500', fontWeight: fromOnboarding ? '700' : '500',
}}> }}>
Continue without an account {t('auth_screen.continue_without_account')}
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
</Animated.View> </Animated.View>