diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 4b413c6f..46f89c38 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -767,6 +767,64 @@ "app_updates": "App Updates", "about_nuvio": "About Nuvio" }, + "cloud_sync": { + "title": "Nuvio Sync", + "description": "Sync data across your Nuvio devices", + "hero_title": "Cloud Sync", + "hero_subtitle": "Keep your addons, progress, and library aligned across all devices.", + "auth": { + "account": "Account", + "not_configured": "Supabase not configured", + "not_authenticated": "Not authenticated", + "email_session": "Email session", + "signed_in_as": "Signed in as {{email}}", + "not_signed_in": "Not signed in", + "effective_owner": "Effective owner: {{id}}" + }, + "stats": { + "title": "Database Statistics", + "plugins": "Plugins", + "addons": "Addons", + "watch_progress": "Watch Progress", + "library_items": "Library Items", + "watched_items": "Watched Items", + "signin_required": "Sign in to load remote data counts." + }, + "actions": { + "title": "Actions", + "description": "Pull to update this device from the cloud, or push from this device as the latest source.", + "pull_btn": "Pull from Cloud", + "push_btn": "Push from Device", + "manage_account": "Manage Account", + "sign_out": "Sign Out", + "sign_in_up": "Sign In / Up" + }, + "alerts": { + "pull_success_title": "Cloud Data Pulled", + "pull_success_msg": "The latest cloud data has been downloaded to this device.", + "pull_failed_title": "Pull Failed", + "pull_failed_msg": "Failed to download data from the cloud", + "push_success_title": "Push Completed", + "push_success_msg": "Device data has been uploaded to the cloud.", + "push_failed_title": "Push Failed", + "push_failed_msg": "Failed to upload local data", + "sign_out_failed": "Sign Out Failed", + "sign_out_failed_title": "Logout Error" + }, + "external_sync": { + "title": "External Sync Priority", + "active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.", + "inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database." + }, + "pre_auth": { + "title": "Before Syncing", + "description": "Sign in to start cloud sync and keep your data consistent across devices.", + "point_1": "• Addons and plugins settings", + "point_2": "• Watch progress and library", + "env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync." + }, + "connection": "Connection" + }, "privacy": { "title": "Privacy & Data", "settings_desc": "Control telemetry and data collection", diff --git a/src/i18n/locales/pt-BR.json b/src/i18n/locales/pt-BR.json index 8ac6a0bb..736840c6 100644 --- a/src/i18n/locales/pt-BR.json +++ b/src/i18n/locales/pt-BR.json @@ -775,6 +775,64 @@ "app_updates": "Atualizações do App", "about_nuvio": "Sobre o Nuvio" }, + "cloud_sync": { + "title": "Nuvio Sync", + "description": "Sincronize dados entre seus dispositivos Nuvio", + "hero_title": "Sincronização na Nuvem", + "hero_subtitle": "Mantenha seus addons, progresso e biblioteca alinhados em todos os dispositivos.", + "auth": { + "account": "Conta", + "not_configured": "Supabase não configurado", + "not_authenticated": "Não autenticado", + "email_session": "Sessão de email", + "signed_in_as": "Logado como {{email}}", + "not_signed_in": "Não logado", + "effective_owner": "Proprietário efetivo: {{id}}" + }, + "stats": { + "title": "Estatísticas do Banco de Dados", + "plugins": "Plugins", + "addons": "Addons", + "watch_progress": "Progresso", + "library_items": "Itens na Biblioteca", + "watched_items": "Itens Assistidos", + "signin_required": "Faça login para carregar contagens de dados remotos." + }, + "actions": { + "title": "Ações", + "description": "Baixe para atualizar este dispositivo a partir da nuvem, ou envie deste dispositivo como a fonte mais recente.", + "pull_btn": "Baixar da Nuvem", + "push_btn": "Enviar deste Dispositivo", + "manage_account": "Gerenciar Conta", + "sign_out": "Sair", + "sign_in_up": "Entrar / Cadastrar" + }, + "alerts": { + "pull_success_title": "Dados da Nuvem Baixados", + "pull_success_msg": "Os dados mais recentes da nuvem foram baixados para este dispositivo.", + "pull_failed_title": "Falha ao Baixar", + "pull_failed_msg": "Falha ao baixar dados da nuvem", + "push_success_title": "Envio Concluído", + "push_success_msg": "Os dados deste dispositivo foram enviados para a nuvem.", + "push_failed_title": "Falha ao Enviar", + "push_failed_msg": "Falha ao enviar dados locais", + "sign_out_failed": "Falha ao Sair", + "sign_out_failed_title": "Erro de Saida" + }, + "external_sync": { + "title": "Prioridade de Sincronização Externa", + "active_msg": "{{services}} está ativo. O progresso e atualizações da biblioteca são gerenciados por esses serviços em vez do banco de dados Nuvio.", + "inactive_msg": "Se a sincronização do Trakt ou Simkl estiver ativada, o progresso e a biblioteca usarão esses serviços em vez do banco de dados Nuvio." + }, + "pre_auth": { + "title": "Antes de Sincronizar", + "description": "Faça login para iniciar a sincronização na nuvem e manter seus dados consistentes entre dispositivos.", + "point_1": "• Configurações de addons e plugins", + "point_2": "• Progresso de exibição e biblioteca", + "env_warning": "Defina EXPO_PUBLIC_SUPABASE_URL e EXPO_PUBLIC_SUPABASE_ANON_KEY para habilitar a sincronização." + }, + "connection": "Conexão" + }, "privacy": { "title": "Privacidade e Dados", "settings_desc": "Controle a telemetria e coleta de dados", diff --git a/src/screens/SettingsScreen.tsx b/src/screens/SettingsScreen.tsx index cd545c8f..b2bb71a2 100644 --- a/src/screens/SettingsScreen.tsx +++ b/src/screens/SettingsScreen.tsx @@ -381,8 +381,8 @@ const SettingsScreen: React.FC = () => { {showCloudSyncItem && ( { (title: string, message: string, actions?: Array<{ label: string; onPress: () => void; style?: object }>) => { setAlertTitle(title); setAlertMessage(message); - setAlertActions(actions && actions.length > 0 ? actions : [{ label: 'OK', onPress: () => {} }]); + setAlertActions(actions && actions.length > 0 ? actions : [{ label: 'OK', onPress: () => { } }]); setAlertVisible(true); }, [] @@ -64,7 +64,7 @@ const SyncSettingsScreen: React.FC = () => { const stats = await supabaseSyncService.getRemoteStats(); setRemoteStats(stats); } catch (error: any) { - openAlert('Sync Error', error?.message || 'Failed to load sync state'); + openAlert(t('common.error'), error?.message || t('settings.cloud_sync.auth.not_authenticated')); } finally { setLoading(false); } @@ -77,19 +77,19 @@ const SyncSettingsScreen: React.FC = () => { ); const authLabel = useMemo(() => { - if (!supabaseSyncService.isConfigured()) return 'Supabase not configured'; - if (!sessionUser) return 'Not authenticated'; - return `Email session${sessionUser.email ? ` (${sessionUser.email})` : ''}`; + if (!supabaseSyncService.isConfigured()) return t('settings.cloud_sync.auth.not_configured'); + if (!sessionUser) return t('settings.cloud_sync.auth.not_authenticated'); + return `${t('settings.cloud_sync.auth.email_session')} ${sessionUser.email ? `(${sessionUser.email})` : ''}`; }, [sessionUser]); const statItems = useMemo(() => { if (!remoteStats) return []; return [ - { label: 'Plugins', value: remoteStats.plugins }, - { label: 'Addons', value: remoteStats.addons }, - { label: 'Watch Progress', value: remoteStats.watchProgress }, - { label: 'Library Items', value: remoteStats.libraryItems }, - { label: 'Watched Items', value: remoteStats.watchedItems }, + { label: t('settings.cloud_sync.stats.plugins'), value: remoteStats.plugins }, + { label: t('settings.cloud_sync.stats.addons'), value: remoteStats.addons }, + { label: t('settings.cloud_sync.stats.watch_progress'), value: remoteStats.watchProgress }, + { label: t('settings.cloud_sync.stats.library_items'), value: remoteStats.libraryItems }, + { label: t('settings.cloud_sync.stats.watched_items'), value: remoteStats.watchedItems }, ]; }, [remoteStats]); const isSignedIn = Boolean(user); @@ -106,10 +106,10 @@ const SyncSettingsScreen: React.FC = () => { setSyncCodeLoading(true); try { await supabaseSyncService.pullAllToLocal(); - openAlert('Cloud Data Pulled', 'Latest cloud data was pulled to this device.'); + openAlert(t('settings.cloud_sync.alerts.pull_success_title'), t('settings.cloud_sync.alerts.pull_success_msg')); await loadSyncState(); } catch (error: any) { - openAlert('Pull Failed', error?.message || 'Failed to pull cloud data'); + openAlert(t('settings.cloud_sync.alerts.pull_failed_title'), error?.message || t('settings.cloud_sync.alerts.pull_failed_msg')); } finally { setSyncCodeLoading(false); } @@ -119,10 +119,10 @@ const SyncSettingsScreen: React.FC = () => { setSyncCodeLoading(true); try { await supabaseSyncService.pushAllLocalData(); - openAlert('Upload Complete', 'This device data has been uploaded to cloud.'); + openAlert(t('settings.cloud_sync.alerts.push_success_title'), t('settings.cloud_sync.alerts.push_success_msg')); await loadSyncState(); } catch (error: any) { - openAlert('Upload Failed', error?.message || 'Failed to upload local data'); + openAlert(t('settings.cloud_sync.alerts.push_failed_title'), error?.message || t('settings.cloud_sync.alerts.push_failed_msg')); } finally { setSyncCodeLoading(false); } @@ -134,14 +134,14 @@ const SyncSettingsScreen: React.FC = () => { await signOut(); await loadSyncState(); } catch (error: any) { - openAlert('Sign Out Failed', error?.message || 'Failed to sign out'); + openAlert(t('settings.cloud_sync.alerts.sign_out_failed_title'), error?.message || t('settings.cloud_sync.alerts.sign_out_failed_msg')); } finally { setSyncCodeLoading(false); } }; return ( - + navigation.goBack()} style={styles.backButton}> @@ -150,176 +150,181 @@ const SyncSettingsScreen: React.FC = () => { - Nuvio Sync + {t('settings.cloud_sync.title')} {loading ? ( ) : ( - <> + <> - - - - - Cloud Sync - - Keep your addons, progress and library aligned across devices. - - - - - - - - - External Sync Priority - - - {externalSyncActive - ? `${externalSyncServices.join(' + ')} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.` - : 'If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database.'} - - - - - - - Account - - - {user?.email ? `Signed in as ${user.email}` : 'Not signed in'} - - - {!isSignedIn ? ( - navigation.navigate('Account')} - > - Sign In / Sign Up - - ) : ( - <> - navigation.navigate('AccountManage')} - > - Manage Account - - - Sign Out - - - )} - - - - {!isSignedIn ? ( - - - - Before You Sync - - - Sign in to start cloud sync and keep your data consistent across devices. - - - • Addons and plugin settings - • Watch progress and library - - {!supabaseSyncService.isConfigured() && ( - - Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync. - - )} - - ) : ( - <> - - - - Connection - - {authLabel} - - Effective owner: {ownerId || 'Unavailable'} - - {!supabaseSyncService.isConfigured() && ( - - Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync. - - )} - - - - - - Database Stats - - {!remoteStats ? ( - - Sign in to load remote data counts. - - ) : ( - - {statItems.map((item) => ( - - {item.value} - {item.label} - - ))} + + + + + {t('settings.cloud_sync.hero_title')} + + {t('settings.cloud_sync.hero_subtitle')} + - )} + + + + + + + {t('settings.cloud_sync.external_sync.title')} + + + {externalSyncActive + ? t('settings.cloud_sync.external_sync.active_msg', { + services: externalSyncServices.join(' + ') + }) + : t('settings.cloud_sync.external_sync.inactive_msg')} + - - Actions + + {t('settings.cloud_sync.auth.account')} - Pull to refresh this device from cloud, or upload this device as the latest source. + {user?.email + ? t('settings.cloud_sync.auth.signed_in_as', { email: user.email }) + : t('settings.cloud_sync.auth.not_signed_in') + } - - {syncCodeLoading ? ( - - ) : ( - Pull From Cloud - )} - - - Upload This Device - + {!isSignedIn ? ( + navigation.navigate('Account')} + > + {t('settings.cloud_sync.actions.sign_in_up')} + + ) : ( + <> + navigation.navigate('AccountManage')} + > + {t('settings.cloud_sync.actions.manage_account')} + + + {t('settings.cloud_sync.actions.sign_out')} + + + )} - - )} - - + + {!isSignedIn ? ( + + + + {t('settings.cloud_sync.pre_auth.title')} + + + {t('settings.cloud_sync.pre_auth.description')} + + + {t('settings.cloud_sync.pre_auth.point_1')} + {t('settings.cloud_sync.pre_auth.point_2')} + + {!supabaseSyncService.isConfigured() && ( + + {t('settings.cloud_sync.pre_auth.env_warning')} + + )} + + ) : ( + <> + + + + {t('settings.cloud_sync.connection')} + + {authLabel} + + {t('settings.cloud_sync.auth.effective_owner', { id: ownerId || 'Unavailable' })} + + {!supabaseSyncService.isConfigured() && ( + + {t('settings.cloud_sync.pre_auth.env_warning')} + + )} + + + + + + {t('settings.cloud_sync.stats.title')} + + {!remoteStats ? ( + + {t('settings.cloud_sync.stats.signin_required')} + + ) : ( + + {statItems.map((item) => ( + + {item.value} + {item.label} + + ))} + + )} + + + + + + {t('settings.cloud_sync.actions.title')} + + + {t('settings.cloud_sync.actions.description')} + + + + {syncCodeLoading ? ( + + ) : ( + {t('settings.cloud_sync.actions.pull_btn')} + )} + + + {t('settings.cloud_sync.actions.push_btn')} + + + + + )} + + )}