Merge branch 'main' into saimuelbr/main

This commit is contained in:
tapframe 2026-02-25 00:31:17 +05:30
commit e6faa7c59f
30 changed files with 21611 additions and 20166 deletions

View file

@ -768,7 +768,17 @@ const AndroidVideoPlayer: React.FC = () => {
onProgress={handleProgress}
onSeek={(data) => {
playerState.isSeeking.current = false;
if (data.currentTime) traktAutosync.handleProgressUpdate(data.currentTime, playerState.duration, true);
if (data.currentTime) {
if (id && type && playerState.duration > 0) {
void storageService.setWatchProgress(id, type, {
currentTime: data.currentTime,
duration: playerState.duration,
lastUpdated: Date.now(),
addonId: currentStreamProvider
}, episodeId);
}
traktAutosync.handleProgressUpdate(data.currentTime, playerState.duration, true);
}
}}
onEnd={() => {
if (modals.showEpisodeStreamsModal) return;

View file

@ -48,6 +48,7 @@ import { useTraktAutosync } from '../../hooks/useTraktAutosync';
import { useMetadata } from '../../hooks/useMetadata';
import { usePlayerGestureControls } from '../../hooks/usePlayerGestureControls';
import stremioService from '../../services/stremioService';
import { storageService } from '../../services/storageService';
import { logger } from '../../utils/logger';
// Utils
@ -227,7 +228,15 @@ const KSPlayerCore: React.FC = () => {
currentTime,
duration,
isSeeking,
isMounted
isMounted,
onSeekComplete: (timeInSeconds) => {
if (!id || !type || duration <= 0) return;
void storageService.setWatchProgress(id, type, {
currentTime: timeInSeconds,
duration,
lastUpdated: Date.now()
}, episodeId);
}
});
const watchProgress = useWatchProgress(

View file

@ -17,6 +17,7 @@ interface PlayerControlsConfig {
duration: number;
isSeeking: MutableRefObject<boolean>;
isMounted: MutableRefObject<boolean>;
onSeekComplete?: (timeInSeconds: number) => void;
}
export const usePlayerControls = (config: PlayerControlsConfig) => {
@ -27,7 +28,8 @@ export const usePlayerControls = (config: PlayerControlsConfig) => {
currentTime,
duration,
isSeeking,
isMounted
isMounted,
onSeekComplete
} = config;
// iOS seeking helpers
@ -54,6 +56,7 @@ export const usePlayerControls = (config: PlayerControlsConfig) => {
// Actually perform the seek
playerRef.current.seek(timeInSeconds);
onSeekComplete?.(timeInSeconds);
// Debounce the seeking state reset
seekTimeoutRef.current = setTimeout(() => {
@ -62,7 +65,7 @@ export const usePlayerControls = (config: PlayerControlsConfig) => {
}
}, 500);
}
}, [duration, paused, playerRef, isSeeking, isMounted]);
}, [duration, paused, playerRef, isSeeking, isMounted, onSeekComplete]);
const skip = useCallback((seconds: number) => {
seekToTime(currentTime + seconds);

View file

@ -1,5 +1,5 @@
import { useState, useEffect, useRef } from 'react';
import { AppState, AppStateStatus } from 'react-native';
import { AppState } from 'react-native';
import { storageService } from '../../../services/storageService';
import { logger } from '../../../utils/logger';
import { useSettings } from '../../../hooks/useSettings';
@ -19,10 +19,9 @@ export const useWatchProgress = (
const [savedDuration, setSavedDuration] = useState<number | null>(null);
const [initialPosition, setInitialPosition] = useState<number | null>(null);
const [showResumeOverlay, setShowResumeOverlay] = useState(false);
const [progressSaveInterval, setProgressSaveInterval] = useState<NodeJS.Timeout | null>(null);
const { settings: appSettings } = useSettings();
const initialSeekTargetRef = useRef<number | null>(null);
const wasPausedRef = useRef<boolean>(paused);
// Values refs for unmount cleanup
const currentTimeRef = useRef(currentTime);
@ -126,22 +125,16 @@ export const useWatchProgress = (
}
};
// Save Interval
useEffect(() => {
if (id && type && !paused && duration > 0) {
if (progressSaveInterval) clearInterval(progressSaveInterval);
const interval = setInterval(() => {
saveWatchProgress();
}, 10000);
setProgressSaveInterval(interval);
return () => {
clearInterval(interval);
setProgressSaveInterval(null);
};
if (wasPausedRef.current !== paused) {
const becamePaused = paused;
wasPausedRef.current = paused;
if (becamePaused) {
void saveWatchProgress();
}
}
}, [id, type, paused, currentTime, duration]);
}, [paused]);
// Unmount Save - deferred to allow navigation to complete first
useEffect(() => {

View file

@ -759,7 +759,65 @@
},
"clear_data_desc": "سيؤدي هذا إلى إعادة تعيين كل الإعدادات ومسح كل البيانات المخزنة مؤقتاً. هل أنت متأكد؟",
"app_updates": "تحديثات التطبيق",
"about_nuvio": "حول Nuvio"
"about_nuvio": "حول 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": "الخصوصية والبيانات",

View file

@ -764,7 +764,65 @@
},
"clear_data_desc": "Това ще нулира всички настройки и ще изчисти всички кеширани данни. Сигурни ли сте?",
"app_updates": "Обновявания на приложението",
"about_nuvio": "Относно Nuvio"
"about_nuvio": "Относно 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": "Поверителност и данни",

View file

@ -765,7 +765,65 @@
},
"clear_data_desc": "Això restablirà tota la configuració i esborrarà totes les dades en memòria cau. Estàs segur?",
"app_updates": "Actualitzacions de l'aplicació",
"about_nuvio": "Quant a Nuvio"
"about_nuvio": "Quant a 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": "Privadesa i dades",

View file

@ -754,7 +754,65 @@
},
"clear_data_desc": "Tímto dojde k resetování všech nastavení a vymazání všech dat v mezipaměti. Jste si jisti?",
"app_updates": "Aktualizace aplikace",
"about_nuvio": "O aplikaci Nuvio"
"about_nuvio": "O aplikaci 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": "Soukromí a data",

View file

@ -759,7 +759,65 @@
},
"clear_data_desc": "Dies setzt alle Einstellungen zurück und löscht alle zwischengespeicherten Daten. Sind Sie sicher?",
"app_updates": "App-Updates",
"about_nuvio": "Über Nuvio"
"about_nuvio": "Über 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": "Datenschutz & Daten",

View file

@ -765,65 +765,65 @@
},
"clear_data_desc": "This will reset all settings and clear all cached data. Are you sure?",
"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"
"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",

View file

@ -759,7 +759,65 @@
},
"clear_data_desc": "Esto restablecerá todos los ajustes y borrará todos los datos almacenados en caché. ¿Estás seguro?",
"app_updates": "Actualizaciones de la app",
"about_nuvio": "Acerca de Nuvio"
"about_nuvio": "Acerca de 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": "Privacidad y Datos",

View file

@ -764,7 +764,65 @@
},
"clear_data_desc": "I-re-reset nito ang lahat ng settings at buburahin ang lahat ng cached data. Sigurado ka ba?",
"app_updates": "Mga Update ng App",
"about_nuvio": "Tungkol sa Nuvio"
"about_nuvio": "Tungkol sa 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 at Data",

View file

@ -759,7 +759,65 @@
},
"clear_data_desc": "Cela réinitialisera tous les paramètres et effacera toutes les données en cache. Êtes-vous sûr ?",
"app_updates": "Mises à jour de l'application",
"about_nuvio": "À propos de Nuvio"
"about_nuvio": "À propos de 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": "Confidentialité et Données",

View file

@ -764,7 +764,65 @@
},
"clear_data_desc": "פעולה זו תאפס את כל ההגדרות ותנקה את כל המידע השמור. האם אתם בטוחים?",
"app_updates": "עדכוני אפליקציה",
"about_nuvio": "אודות Nuvio"
"about_nuvio": "אודות 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": "פרטיות ומידע",

View file

@ -759,7 +759,65 @@
},
"clear_data_desc": "यह सभी सेटिंग्स को रीसेट कर देगा और सभी कैश किए गए डेटा को साफ़ कर देगा। क्या आप सुनिश्चित हैं?",
"app_updates": "ऐप अपडेट",
"about_nuvio": "Nuvio के बारे में"
"about_nuvio": "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": "गोपनीयता और डेटा",

View file

@ -747,7 +747,65 @@
},
"clear_data_desc": "Ovo će resetirati sve postavke i obrisati sve privremene podatke. Jeste li sigurni?",
"app_updates": "Ažuriranja aplikacije",
"about_nuvio": "O Nuviju"
"about_nuvio": "O Nuviju",
"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": "Privatnost i Podaci",

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -764,7 +764,65 @@
},
"clear_data_desc": "Dit zal alle instellingen resetten en alle gecachte gegevens wissen. Weet je het zeker?",
"app_updates": "App Updates",
"about_nuvio": "Over Nuvio"
"about_nuvio": "Over 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 & Gegevens",

View file

@ -764,7 +764,65 @@
},
"clear_data_desc": "To zresetuje wszystkie ustawienia i wyczyści pamięć podręczną. Czy na pewno?",
"app_updates": "Aktualizacje aplikacji",
"about_nuvio": "O Nuvio"
"about_nuvio": "O 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": "Prywatność i Dane",

View file

@ -773,65 +773,65 @@
},
"clear_data_desc": "Isso redefinirá todas as configurações e limpará todos os dados em cache. Você tem certeza?",
"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"
"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",

View file

@ -771,7 +771,65 @@
},
"clear_data_desc": "Isso redefinirá todas as configurações e limpará todos os dados em cache. Tens a certeza?",
"app_updates": "Atualizações da App",
"about_nuvio": "Sobre o Nuvio"
"about_nuvio": "Sobre o 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": "Privacidade e Dados",

View file

@ -764,7 +764,65 @@
},
"clear_data_desc": "Această acțiune va reseta toate setările și va șterge toate datele cache. Ești sigur?",
"app_updates": "Actualizări aplicație",
"about_nuvio": "Despre Nuvio"
"about_nuvio": "Despre 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": "Confidențialitate și Date",

View file

@ -764,7 +764,65 @@
},
"clear_data_desc": "Это сбросит все настройки и очистит кэш. Вы уверены?",
"app_updates": "Обновления приложения",
"about_nuvio": "О Nuvio"
"about_nuvio": "О 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": "Конфиденциальность",

View file

@ -764,7 +764,65 @@
},
"clear_data_desc": "To bo ponastavilo vse nastavitve in počistilo predpomnilnik. Ste prepričani?",
"app_updates": "Posodobitve aplikacije",
"about_nuvio": "O Nuvio"
"about_nuvio": "O 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": "Zasebnost in podatki",

View file

@ -764,7 +764,65 @@
},
"clear_data_desc": "Kjo do të rikthejë të gjitha cilësimet dhe do të fshijë të gjithë cache-in. Jeni të sigurt?",
"app_updates": "Përditësimet e Aplikacionit",
"about_nuvio": "Rreth Nuvio"
"about_nuvio": "Rreth 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": "Privatësia & Të dhënat",

View file

@ -1,426 +1,426 @@
{
"common": {
"loading": "Учитавање...",
"cancel": "Одустани",
"save": "Сачувај",
"delete": "Обриши",
"edit": "Уреди",
"search": "Претражи",
"error": "Грешка",
"success": "Успех",
"ok": "У реду",
"unknown": "Непознато",
"retry": "Покушај поново",
"try_again": "Покушај поново",
"go_back": "Иди назад",
"settings": "Подешавања",
"close": "Затвори",
"enable": "Омогући",
"disable": "Искључи",
"show_more": "Прикажи више",
"show_less": "Прикажи мање",
"load_more": "Учитај више",
"unknown_date": "Непознат датум",
"anonymous_user": "Анонимни корисник",
"time": {
"now": "Управо сада",
"minutes_ago": "пре {{count}} мин",
"hours_ago": "пре {{count}} ч",
"days_ago": "пре {{count}} д"
"common": {
"loading": "Учитавање...",
"cancel": "Одустани",
"save": "Сачувај",
"delete": "Обриши",
"edit": "Уреди",
"search": "Претражи",
"error": "Грешка",
"success": "Успех",
"ok": "У реду",
"unknown": "Непознато",
"retry": "Покушај поново",
"try_again": "Покушај поново",
"go_back": "Иди назад",
"settings": "Подешавања",
"close": "Затвори",
"enable": "Омогући",
"disable": "Искључи",
"show_more": "Прикажи више",
"show_less": "Прикажи мање",
"load_more": "Учитај више",
"unknown_date": "Непознат датум",
"anonymous_user": "Анонимни корисник",
"time": {
"now": "Управо сада",
"minutes_ago": "пре {{count}} мин",
"hours_ago": "пре {{count}} ч",
"days_ago": "пре {{count}} д"
},
"days_short": {
"sun": "Нед",
"mon": "Пон",
"tue": "Уто",
"wed": "Сре",
"thu": "Чет",
"fri": "Пет",
"sat": "Суб"
},
"email": "Е-пошта",
"status": "Статус"
},
"days_short": {
"sun": "Нед",
"mon": "Пон",
"tue": "Уто",
"wed": "Сре",
"thu": "Чет",
"fri": "Пет",
"sat": "Суб"
"home": {
"categories": {
"movies": "Филмови",
"series": "Серије",
"channels": "Канали"
},
"movies": "Филмови",
"tv_shows": "Cерије",
"load_more_catalogs": "Учитај више каталога",
"no_content": "Садржај није доступан",
"add_catalogs": "Додај каталоге",
"sign_in_available": "Пријава доступна",
"sign_in_desc": "Можете се пријавити било када у Подешавања → Налог",
"view_all": "Види све",
"this_week": "Ове недеље",
"upcoming": "Надолазеће",
"recently_released": "Недавно објављено",
"no_scheduled_episodes": "Серије без заказаних епизода",
"check_back_later": "Проверите касније",
"continue_watching": "Настави са гледањем",
"up_next": "Следеће на реду",
"up_next_caps": "СЛЕДЕЋЕ",
"released": "Објављено",
"new": "Ново",
"tba": "Биће објављено",
"new_episodes": "{{count}} нове епизоде",
"season_short": "С{{season}}",
"episode_short": "Е{{episode}}",
"season": "Сезона {{season}}",
"episode": "Епизода {{episode}}",
"movie": "Филм",
"series": "Серија",
"tv_show": "Cерија",
"percent_watched": "{{percent}}% одгледано",
"view_details": "Види детаље",
"remove": "Уклони",
"play": "Пусти",
"play_now": "Пусти одмах",
"resume": "Настави",
"info": "Инфо",
"more_info": "Више информација",
"my_list": "Моја листа",
"save": "Сачувај",
"saved": "Сачувано",
"retry": "Покушај поново",
"install_addons": "Инсталирај додатке",
"settings": "Подешавања",
"no_featured_content": "Нема истакнутог садржаја",
"couldnt_load_featured": "Учитавање истакнутог садржаја није успело",
"no_featured_desc": "Инсталирајте додатке са каталозима или промените извор садржаја у подешавањима.",
"load_error_desc": "Дошло је до проблема при преузимању садржаја. Проверите везу и покушајте поново.",
"no_featured_available": "Нема доступног истакнутог садржаја",
"no_description": "Опис није доступан"
},
"email": "Е-пошта",
"status": "Статус"
},
"home": {
"categories": {
"movies": "Филмови",
"series": "Серије",
"channels": "Канали"
"navigation": {
"home": "Почетна",
"library": "Библиотека",
"search": "Претрага",
"downloads": "Преузимања",
"settings": "Подешавања"
},
"movies": "Филмови",
"tv_shows": "Cерије",
"load_more_catalogs": "Учитај више каталога",
"no_content": "Садржај није доступан",
"add_catalogs": "Додај каталоге",
"sign_in_available": "Пријава доступна",
"sign_in_desc": "Можете се пријавити било када у Подешавања → Налог",
"view_all": "Види све",
"this_week": "Ове недеље",
"upcoming": "Надолазеће",
"recently_released": "Недавно објављено",
"no_scheduled_episodes": "Серије без заказаних епизода",
"check_back_later": "Проверите касније",
"continue_watching": "Настави са гледањем",
"up_next": "Следеће на реду",
"up_next_caps": "СЛЕДЕЋЕ",
"released": "Објављено",
"new": "Ново",
"tba": "Биће објављено",
"new_episodes": "{{count}} нове епизоде",
"season_short": "С{{season}}",
"episode_short": "Е{{episode}}",
"season": "Сезона {{season}}",
"episode": "Епизода {{episode}}",
"movie": "Филм",
"series": "Серија",
"tv_show": "Cерија",
"percent_watched": "{{percent}}% одгледано",
"view_details": "Види детаље",
"remove": "Уклони",
"play": "Пусти",
"play_now": "Пусти одмах",
"resume": "Настави",
"info": "Инфо",
"more_info": "Више информација",
"my_list": "Моја листа",
"save": "Сачувај",
"saved": "Сачувано",
"retry": "Покушај поново",
"install_addons": "Инсталирај додатке",
"settings": "Подешавања",
"no_featured_content": "Нема истакнутог садржаја",
"couldnt_load_featured": "Учитавање истакнутог садржаја није успело",
"no_featured_desc": "Инсталирајте додатке са каталозима или промените извор садржаја у подешавањима.",
"load_error_desc": "Дошло је до проблема при преузимању садржаја. Проверите везу и покушајте поново.",
"no_featured_available": "Нема доступног истакнутог садржаја",
"no_description": "Опис није доступан"
},
"navigation": {
"home": "Почетна",
"library": "Библиотека",
"search": "Претрага",
"downloads": "Преузимања",
"settings": "Подешавања"
},
"search": {
"title": "Претрага",
"recent_searches": "Недавне претраге",
"discover": "Откриј",
"movies": "Филмови",
"tv_shows": "Cерије",
"select_catalog": "Изабери каталог",
"all_genres": "Сви жанрови",
"discovering": "Откривање садржаја...",
"show_more": "Прикажи више ({{count}})",
"no_content_found": "Садржај није пронађен",
"try_different": "Покушајте други жанр или каталог",
"select_catalog_desc": "Изаберите каталог за истраживање",
"tap_catalog_desc": "Додирните дугме каталога изнад за почетак",
"placeholder": "Претражи филмове, серије...",
"keep_typing": "Наставите са куцањем...",
"type_characters": "Упишите најмање 2 знака за претрагу",
"no_results": "Нема резултата",
"try_keywords": "Покушајте са другим кључним речима",
"select_type": "Изабери тип",
"browse_movies": "Прегледај каталоге филмова",
"browse_tv": "Прегледај каталоге cерија",
"select_genre": "Изабери жанр",
"show_all_content": "Прикажи сав садржај",
"genres_count": "{{count}} жанрова"
},
"library": {
"title": "Библиотека",
"watched": "Одгледано",
"continue": "Настави",
"watchlist": "Листа за гледање",
"collection": "Колекција",
"rated": "Оцењено",
"items": "ставки",
"trakt_collections": "Trakt колекције",
"trakt_collection": "Trakt колекција",
"no_trakt": "Нема Trakt колекција",
"no_trakt_desc": "Ваше Trakt колекције ће се појавити овде након коришћења Trakt-а",
"load_collections": "Учитај колекције",
"empty_folder": "Нема садржаја у {{folder}}",
"empty_folder_desc": "Ова колекција је празна",
"refresh": "Освежи",
"no_movies": "Још нема филмова",
"no_series": "Још нема cерија",
"no_content": "Још нема садржаја",
"add_content_desc": "Додајте садржај у своју библиотеку да бисте га видели овде",
"find_something": "Пронађи нешто за гледање",
"removed_from_library": "Уклоњено из библиотеке",
"item_removed": "Ставка је уклоњена из ваше библиотеке",
"failed_update_library": "Ажурирање библиотеке није успело",
"unable_remove": "Неуспело уклањање ставке из библиотеке",
"marked_watched": "Означено као одгледано",
"marked_unwatched": "Означено као неодгледано",
"item_marked_watched": "Ставка је означена као одгледана",
"item_marked_unwatched": "Ставка је означена као неодгледана",
"failed_update_watched": "Ажурирање статуса гледања није успело",
"unable_update_watched": "Неуспело ажурирање статуса гледања",
"added_to_library": "Додато у библиотеку",
"item_added": "Додато у вашу локалну библиотеку",
"add_to_library": "Додај у библиотеку",
"remove_from_library": "Уклони из библиотеке",
"mark_watched": "Означи као одгледано",
"mark_unwatched": "Означи као неодгледано",
"share": "Подели",
"add_to_watchlist": "Додај на Trakt листу гледања",
"remove_from_watchlist": "Уклони са Trakt листе гледања",
"added_to_watchlist": "Додато на листу гледања",
"added_to_watchlist_desc": "Додато на вашу Trakt листу гледања",
"removed_from_watchlist": "Уклоњено са листе гледања",
"removed_from_watchlist_desc": "Уклоњено са ваше Trakt листе гледања",
"add_to_collection": "Додај у Trakt колекцију",
"remove_from_collection": "Уклони из Trakt колекције",
"added_to_collection": "Додато у колекцију",
"added_to_collection_desc": "Додато у вашу Trakt колекцију",
"removed_from_collection": "Уклоњено из колекције",
"removed_from_collection_desc": "Уклоњено из ваше Trakt колекције"
},
"metadata": {
"unable_to_load": "Учитавање садржаја није успело",
"error_code": "Код грешке: {{code}}",
"content_not_found": "Садржај није пронађен",
"content_not_found_desc": "Овај садржај не постоји или је можда уклоњен.",
"server_error": "Грешка сервера",
"server_error_desc": "Сервер је привремено недоступан. Покушајте касније.",
"bad_gateway": "Лош gateway",
"bad_gateway_desc": "Сервер има потешкоћа. Покушајте касније.",
"service_unavailable": "Услуга недоступна",
"service_unavailable_desc": "Услуга је тренутно недоступна због одржавања.",
"too_many_requests": "Превише захтева",
"too_many_requests_desc": "Шаљете превише захтева. Молимо сачекајте тренутак.",
"request_timeout": "Истек захтева",
"request_timeout_desc": "Захтев је трајао предуго. Покушајте поново.",
"network_error": "Мрежна грешка",
"network_error_desc": "Проверите интернет везу и покушајте поново.",
"auth_error": "Грешка у аутентификацији",
"auth_error_desc": "Проверите подешавања налога и покушајте поново.",
"access_denied": "Приступ одбијен",
"access_denied_desc": "Немате дозволу за приступ овом садржају.",
"connection_error": "Грешка у вези",
"streams_unavailable": "Стримови недоступни",
"streams_unavailable_desc": "Извори за стримовање су тренутно недоступни.",
"unknown_error": "Непозната грешка",
"something_went_wrong": "Нешто је пошло по злу. Покушајте поново.",
"cast": "Глумачка постава",
"more_like_this": "Слично овоме",
"collection": "Колекција",
"episodes": "Епизоде",
"seasons": "Сезоне",
"posters": "Постери",
"banners": "Банери",
"specials": "Специјали",
"season_number": "Сезона {{number}}",
"episode_count": "{{count}} епизода",
"episode_count_plural": "{{count}} епизода",
"no_episodes": "Нема доступних епизода",
"no_episodes_for_season": "Нема доступних епизода за сезону {{season}}",
"episodes_not_released": "Епизоде можда још нису објављене",
"no_description": "Опис није доступан",
"episode_label": "ЕПИЗОДА {{number}}",
"watch_again": "Гледај поново",
"completed": "Завршено",
"play_episode": "Пусти С{{season}}Е{{episode}}",
"play": "Пусти",
"watched": "Одгледано",
"watched_on_trakt": "Одгледано на Trakt-у",
"synced_with_trakt": "Синхронизовано са Trakt-ом",
"saved": "Сачувано",
"director": "Режисер",
"directors": "Режисери",
"creator": "Креатор",
"creators": "Креатори",
"production": "Продукција",
"network": "Мрежа",
"mark_watched": "Означи као одгледано",
"mark_unwatched": "Означи као неодгледано",
"marking": "Означавање...",
"removing": "Уклањање...",
"unmark_season": "Одозначи сезону {{season}}",
"mark_season": "Означи сезону {{season}}",
"resume": "Настави",
"spoiler_warning": "Упозорење о спојлерима",
"spoiler_warning_desc": "Овај коментар садржи спојлере. Да ли сте сигурни да желите да га откријете?",
"cancel": "Одустани",
"reveal_spoilers": "Откриј спојлере",
"movie_details": "Детаљи о филму",
"show_details": "Детаљи о серији",
"tagline": "Слоган",
"status": "Статус",
"release_date": "Датум објаве",
"runtime": "Трајање",
"budget": "Буџет",
"revenue": "Приход",
"origin_country": "Земља порекла",
"original_language": "Оригинални језик",
"first_air_date": "Прво емитовање",
"last_air_date": "Последње емитовање",
"total_episodes": "Укупно епизода",
"episode_runtime": "Трајање епизоде",
"created_by": "Креирао",
"backdrop_gallery": "Галерија позадина",
"loading_episodes": "Учитавање епизода...",
"no_episodes_available": "Нема доступних епизода",
"play_next": "Пусти С{{season}}Е{{episode}}",
"play_next_episode": "Пусти следећу епизоду",
"save": "Сачувај",
"percent_watched_trakt": "{{percent}}% одгледано ({{traktPercent}}% на Trakt-у)",
"synced_with_trakt_progress": "Синхронизовано са Trakt-ом",
"using_trakt_progress": "Користи се Trakt напредак",
"added_to_collection_hero": "Додато у колекцију",
"added_to_collection_desc_hero": "Додато у вашу Trakt колекцију",
"removed_from_collection_hero": "Уклоњено из колекције",
"removed_from_collection_desc_hero": "Уклоњено из ваше Trakt колекције",
"mark_as_watched": "Означи као одгледано",
"mark_as_unwatched": "Означи као неодгледано"
},
"cast": {
"biography": "Биографија",
"known_for": "Познат по",
"personal_info": "Лични подаци",
"born_in": "Рођен у {{place}}",
"filmography": "Филмографија",
"also_known_as": "Познат и као",
"no_info_available": "Додатне информације нису доступне",
"as_character": "као {{character}}",
"loading_details": "Учитавање детаља...",
"years_old": "{{age}} година",
"view_filmography": "Види филмографију",
"filter": "Филтер",
"sort_by": "Сортирај по",
"sort_popular": "Популарно",
"sort_latest": "Најновије",
"sort_upcoming": "Надолазеће",
"upcoming_badge": "НАДОЛАЗЕЋЕ",
"coming_soon": "Ускоро стиже",
"filmography_count": "Филмографија • {{count}} наслова",
"loading_filmography": "Учитавање филмографије...",
"load_more_remaining": "Учитај још ({{count}} преостало)",
"alert_error_title": "Грешка",
"alert_error_message": "Неуспело учитавање \"{{title}}\". Покушајте касније.",
"alert_ok": "У реду",
"no_upcoming": "Нема надолазећих објава за овог глумца",
"no_content": "Нема доступног садржаја за овог глумца",
"no_movies": "Нема доступних филмова за овог глумца",
"no_tv": "Нема доступних серија за овог глумца"
},
"comments": {
"title": "Trakt коментари",
"spoiler_warning": "⚠️ Овај коментар садржи спојлере. Додирните да откријете.",
"spoiler": "Спојлер",
"contains_spoilers": "Садржи спојлере",
"reveal": "Откриј",
"vip": "VIP",
"unavailable": "Коментари недоступни",
"no_comments": "Још нема коментара на Trakt-у",
"not_in_database": "Овај садржај можда још није у Trakt бази података",
"check_trakt": "Провери Trakt"
},
"trailers": {
"title": "Трејлери",
"official_trailers": "Званични трејлери",
"official_trailer": "Званични трејлер",
"teasers": "Тизери",
"teaser": "Тизер",
"clips_scenes": "Клипови и сцене",
"clip": "Клип",
"featurettes": "Кратки филмови о снимању",
"featurette": "Кратки филм о снимању",
"behind_the_scenes": "Иза кулиса",
"no_trailers": "Нема доступних трејлера",
"unavailable": "Трејлер недоступан",
"unavailable_desc": "Овај трејлер није могуће учитати тренутно.",
"unable_to_play": "Није могуће пустити трејлер. Покушајте поново.",
"watch_on_youtube": "Гледај на YouTube-у"
},
"catalog": {
"no_content_found": "Садржај није пронађен",
"no_content_filters": "Нема садржаја за изабране филтере",
"loading_content": "Учитавање садржаја...",
"back": "Назад",
"in_theaters": "У биоскопима",
"all": "Све",
"failed_tmdb": "Неуспело учитавање садржаја са TMDB",
"movies": "Филмови",
"tv_shows": "Cерије",
"channels": "Канали"
},
"streams": {
"back_to_episodes": "Назад на епизоде",
"back_to_info": "Назад на инфо",
"fetching_from": "Преузимање са:",
"no_sources_available": "Нема доступних извора за стримовање",
"add_sources_desc": "Молимо додајте изворе у подешавањима",
"add_sources": "Додај изворе",
"finding_streams": "Проналажење доступних стримова...",
"finding_best_stream": "Проналажење најбољег стрима за аутоматско пуштање...",
"still_fetching": "Преузимање стримова је још у току...",
"no_streams_available": "Нема доступних стримова",
"starting_best_stream": "Покретање најбољег стрима...",
"loading_more_sources": "Учитавање додатних извора..."
},
"player_ui": {
"via": "преко {{name}}",
"audio_tracks": "Аудио траке",
"no_audio_tracks": "Нема доступних аудио трака",
"playback_speed": "Брзина репродукције",
"on_hold": "На чекању",
"playback_error": "Грешка при репродукцији",
"unknown_error": "Дошло је до непознате грешке током репродукције.",
"copy_error": "Копирај детаље о грешци",
"copied_to_clipboard": "Копирано у привремени меморију",
"dismiss": "Одбаци",
"continue_watching": "Настави са гледањем",
"start_over": "Крени испочетка",
"resume": "Настави",
"change_source": "Промени извор",
"switching_source": "Промена извора...",
"no_sources_found": "Извори нису пронађени",
"sources": "Извори",
"finding_sources": "Проналажење извора...",
"unknown_source": "Непознат извор",
"sources_limited": "Извори могу бити ограничени због грешака провајдера.",
"episodes": "Епизоде",
"specials": "Специјали",
"season": "Сезона {{season}}",
"stream": "Стрим {{number}}",
"subtitles": "Титлови",
"built_in": "Уграђени",
"addons": "Додаци",
"style": "Стил",
"none": "Ниједан",
"search_online_subtitles": "Претражи титлове на мрежи",
"preview": "Преглед",
"quick_presets": "Брза подешавања",
"default": "Подразумевано",
"yellow": "Жуто",
"high_contrast": "Висок контраст",
"large": "Велико",
"core": "Језгро",
"font_size": "Величина фонта",
"show_background": "Прикажи позадину",
"advanced": "Напредно",
"position": "Позиција",
"text_color": "Боја текста",
"align": "Поравнање",
"bottom_offset": "Размак од дна",
"background_opacity": "Провидност позадине",
"text_shadow": "Сенка текста",
"on": "Укључено",
"off": "Искључено",
"outline_color": "Боја оквира",
"outline": "Оквир",
"outline_width": "Ширина оквира",
"letter_spacing": "Размак између слова",
"line_height": "Висина линије",
"timing_offset": "Временски помак (с)",
"visual_sync": "Визуелна синхронизација",
"timing_hint": "Померите титлове раније (-) или касније (+) за синхронизацију.",
"reset_defaults": "Врати на подразумевано"
},
"downloads": {
"search": {
"title": "Претрага",
"recent_searches": "Недавне претраге",
"discover": "Откриј",
"movies": "Филмови",
"tv_shows": "Cерије",
"select_catalog": "Изабери каталог",
"all_genres": "Сви жанрови",
"discovering": "Откривање садржаја...",
"show_more": "Прикажи више ({{count}})",
"no_content_found": "Садржај није пронађен",
"try_different": "Покушајте други жанр или каталог",
"select_catalog_desc": "Изаберите каталог за истраживање",
"tap_catalog_desc": "Додирните дугме каталога изнад за почетак",
"placeholder": "Претражи филмове, серије...",
"keep_typing": "Наставите са куцањем...",
"type_characters": "Упишите најмање 2 знака за претрагу",
"no_results": "Нема резултата",
"try_keywords": "Покушајте са другим кључним речима",
"select_type": "Изабери тип",
"browse_movies": "Прегледај каталоге филмова",
"browse_tv": "Прегледај каталоге cерија",
"select_genre": "Изабери жанр",
"show_all_content": "Прикажи сав садржај",
"genres_count": "{{count}} жанрова"
},
"library": {
"title": "Библиотека",
"watched": "Одгледано",
"continue": "Настави",
"watchlist": "Листа за гледање",
"collection": "Колекција",
"rated": "Оцењено",
"items": "ставки",
"trakt_collections": "Trakt колекције",
"trakt_collection": "Trakt колекција",
"no_trakt": "Нема Trakt колекција",
"no_trakt_desc": "Ваше Trakt колекције ће се појавити овде након коришћења Trakt-а",
"load_collections": "Учитај колекције",
"empty_folder": "Нема садржаја у {{folder}}",
"empty_folder_desc": "Ова колекција је празна",
"refresh": "Освежи",
"no_movies": "Још нема филмова",
"no_series": "Још нема cерија",
"no_content": "Још нема садржаја",
"add_content_desc": "Додајте садржај у своју библиотеку да бисте га видели овде",
"find_something": "Пронађи нешто за гледање",
"removed_from_library": "Уклоњено из библиотеке",
"item_removed": "Ставка је уклоњена из ваше библиотеке",
"failed_update_library": "Ажурирање библиотеке није успело",
"unable_remove": "Неуспело уклањање ставке из библиотеке",
"marked_watched": "Означено као одгледано",
"marked_unwatched": "Означено као неодгледано",
"item_marked_watched": "Ставка је означена као одгледана",
"item_marked_unwatched": "Ставка је означена као неодгледана",
"failed_update_watched": "Ажурирање статуса гледања није успело",
"unable_update_watched": "Неуспело ажурирање статуса гледања",
"added_to_library": "Додато у библиотеку",
"item_added": "Додато у вашу локалну библиотеку",
"add_to_library": "Додај у библиотеку",
"remove_from_library": "Уклони из библиотеке",
"mark_watched": "Означи као одгледано",
"mark_unwatched": "Означи као неодгледано",
"share": "Подели",
"add_to_watchlist": "Додај на Trakt листу гледања",
"remove_from_watchlist": "Уклони са Trakt листе гледања",
"added_to_watchlist": "Додато на листу гледања",
"added_to_watchlist_desc": "Додато на вашу Trakt листу гледања",
"removed_from_watchlist": "Уклоњено са листе гледања",
"removed_from_watchlist_desc": "Уклоњено са ваше Trakt листе гледања",
"add_to_collection": "Додај у Trakt колекцију",
"remove_from_collection": "Уклони из Trakt колекције",
"added_to_collection": "Додато у колекцију",
"added_to_collection_desc": "Додато у вашу Trakt колекцију",
"removed_from_collection": "Уклоњено из колекције",
"removed_from_collection_desc": "Уклоњено из ваше Trakt колекције"
},
"metadata": {
"unable_to_load": "Учитавање садржаја није успело",
"error_code": "Код грешке: {{code}}",
"content_not_found": "Садржај није пронађен",
"content_not_found_desc": "Овај садржај не постоји или је можда уклоњен.",
"server_error": "Грешка сервера",
"server_error_desc": "Сервер је привремено недоступан. Покушајте касније.",
"bad_gateway": "Лош gateway",
"bad_gateway_desc": "Сервер има потешкоћа. Покушајте касније.",
"service_unavailable": "Услуга недоступна",
"service_unavailable_desc": "Услуга је тренутно недоступна због одржавања.",
"too_many_requests": "Превише захтева",
"too_many_requests_desc": "Шаљете превише захтева. Молимо сачекајте тренутак.",
"request_timeout": "Истек захтева",
"request_timeout_desc": "Захтев је трајао предуго. Покушајте поново.",
"network_error": "Мрежна грешка",
"network_error_desc": "Проверите интернет везу и покушајте поново.",
"auth_error": "Грешка у аутентификацији",
"auth_error_desc": "Проверите подешавања налога и покушајте поново.",
"access_denied": "Приступ одбијен",
"access_denied_desc": "Немате дозволу за приступ овом садржају.",
"connection_error": "Грешка у вези",
"streams_unavailable": "Стримови недоступни",
"streams_unavailable_desc": "Извори за стримовање су тренутно недоступни.",
"unknown_error": "Непозната грешка",
"something_went_wrong": "Нешто је пошло по злу. Покушајте поново.",
"cast": "Глумачка постава",
"more_like_this": "Слично овоме",
"collection": "Колекција",
"episodes": "Епизоде",
"seasons": "Сезоне",
"posters": "Постери",
"banners": "Банери",
"specials": "Специјали",
"season_number": "Сезона {{number}}",
"episode_count": "{{count}} епизода",
"episode_count_plural": "{{count}} епизода",
"no_episodes": "Нема доступних епизода",
"no_episodes_for_season": "Нема доступних епизода за сезону {{season}}",
"episodes_not_released": "Епизоде можда још нису објављене",
"no_description": "Опис није доступан",
"episode_label": "ЕПИЗОДА {{number}}",
"watch_again": "Гледај поново",
"completed": "Завршено",
"play_episode": "Пусти С{{season}}Е{{episode}}",
"play": "Пусти",
"watched": "Одгледано",
"watched_on_trakt": "Одгледано на Trakt-у",
"synced_with_trakt": "Синхронизовано са Trakt-ом",
"saved": "Сачувано",
"director": "Режисер",
"directors": "Режисери",
"creator": "Креатор",
"creators": "Креатори",
"production": "Продукција",
"network": "Мрежа",
"mark_watched": "Означи као одгледано",
"mark_unwatched": "Означи као неодгледано",
"marking": "Означавање...",
"removing": "Уклањање...",
"unmark_season": "Одозначи сезону {{season}}",
"mark_season": "Означи сезону {{season}}",
"resume": "Настави",
"spoiler_warning": "Упозорење о спојлерима",
"spoiler_warning_desc": "Овај коментар садржи спојлере. Да ли сте сигурни да желите да га откријете?",
"cancel": "Одустани",
"reveal_spoilers": "Откриј спојлере",
"movie_details": "Детаљи о филму",
"show_details": "Детаљи о серији",
"tagline": "Слоган",
"status": "Статус",
"release_date": "Датум објаве",
"runtime": "Трајање",
"budget": "Буџет",
"revenue": "Приход",
"origin_country": "Земља порекла",
"original_language": "Оригинални језик",
"first_air_date": "Прво емитовање",
"last_air_date": "Последње емитовање",
"total_episodes": "Укупно епизода",
"episode_runtime": "Трајање епизоде",
"created_by": "Креирао",
"backdrop_gallery": "Галерија позадина",
"loading_episodes": "Учитавање епизода...",
"no_episodes_available": "Нема доступних епизода",
"play_next": "Пусти С{{season}}Е{{episode}}",
"play_next_episode": "Пусти следећу епизоду",
"save": "Сачувај",
"percent_watched_trakt": "{{percent}}% одгледано ({{traktPercent}}% на Trakt-у)",
"synced_with_trakt_progress": "Синхронизовано са Trakt-ом",
"using_trakt_progress": "Користи се Trakt напредак",
"added_to_collection_hero": "Додато у колекцију",
"added_to_collection_desc_hero": "Додато у вашу Trakt колекцију",
"removed_from_collection_hero": "Уклоњено из колекције",
"removed_from_collection_desc_hero": "Уклоњено из ваше Trakt колекције",
"mark_as_watched": "Означи као одгледано",
"mark_as_unwatched": "Означи као неодгледано"
},
"cast": {
"biography": "Биографија",
"known_for": "Познат по",
"personal_info": "Лични подаци",
"born_in": "Рођен у {{place}}",
"filmography": "Филмографија",
"also_known_as": "Познат и као",
"no_info_available": "Додатне информације нису доступне",
"as_character": "као {{character}}",
"loading_details": "Учитавање детаља...",
"years_old": "{{age}} година",
"view_filmography": "Види филмографију",
"filter": "Филтер",
"sort_by": "Сортирај по",
"sort_popular": "Популарно",
"sort_latest": "Најновије",
"sort_upcoming": "Надолазеће",
"upcoming_badge": "НАДОЛАЗЕЋЕ",
"coming_soon": "Ускоро стиже",
"filmography_count": "Филмографија • {{count}} наслова",
"loading_filmography": "Учитавање филмографије...",
"load_more_remaining": "Учитај још ({{count}} преостало)",
"alert_error_title": "Грешка",
"alert_error_message": "Неуспело учитавање \"{{title}}\". Покушајте касније.",
"alert_ok": "У реду",
"no_upcoming": "Нема надолазећих објава за овог глумца",
"no_content": "Нема доступног садржаја за овог глумца",
"no_movies": "Нема доступних филмова за овог глумца",
"no_tv": "Нема доступних серија за овог глумца"
},
"comments": {
"title": "Trakt коментари",
"spoiler_warning": "⚠️ Овај коментар садржи спојлере. Додирните да откријете.",
"spoiler": "Спојлер",
"contains_spoilers": "Садржи спојлере",
"reveal": "Откриј",
"vip": "VIP",
"unavailable": "Коментари недоступни",
"no_comments": "Још нема коментара на Trakt-у",
"not_in_database": "Овај садржај можда још није у Trakt бази података",
"check_trakt": "Провери Trakt"
},
"trailers": {
"title": "Трејлери",
"official_trailers": "Званични трејлери",
"official_trailer": "Званични трејлер",
"teasers": "Тизери",
"teaser": "Тизер",
"clips_scenes": "Клипови и сцене",
"clip": "Клип",
"featurettes": "Кратки филмови о снимању",
"featurette": "Кратки филм о снимању",
"behind_the_scenes": "Иза кулиса",
"no_trailers": "Нема доступних трејлера",
"unavailable": "Трејлер недоступан",
"unavailable_desc": "Овај трејлер није могуће учитати тренутно.",
"unable_to_play": "Није могуће пустити трејлер. Покушајте поново.",
"watch_on_youtube": "Гледај на YouTube-у"
},
"catalog": {
"no_content_found": "Садржај није пронађен",
"no_content_filters": "Нема садржаја за изабране филтере",
"loading_content": "Учитавање садржаја...",
"back": "Назад",
"in_theaters": "У биоскопима",
"all": "Све",
"failed_tmdb": "Неуспело учитавање садржаја са TMDB",
"movies": "Филмови",
"tv_shows": "Cерије",
"channels": "Канали"
},
"streams": {
"back_to_episodes": "Назад на епизоде",
"back_to_info": "Назад на инфо",
"fetching_from": "Преузимање са:",
"no_sources_available": "Нема доступних извора за стримовање",
"add_sources_desc": "Молимо додајте изворе у подешавањима",
"add_sources": "Додај изворе",
"finding_streams": "Проналажење доступних стримова...",
"finding_best_stream": "Проналажење најбољег стрима за аутоматско пуштање...",
"still_fetching": "Преузимање стримова је још у току...",
"no_streams_available": "Нема доступних стримова",
"starting_best_stream": "Покретање најбољег стрима...",
"loading_more_sources": "Учитавање додатних извора..."
},
"player_ui": {
"via": "преко {{name}}",
"audio_tracks": "Аудио траке",
"no_audio_tracks": "Нема доступних аудио трака",
"playback_speed": "Брзина репродукције",
"on_hold": "На чекању",
"playback_error": "Грешка при репродукцији",
"unknown_error": "Дошло је до непознате грешке током репродукције.",
"copy_error": "Копирај детаље о грешци",
"copied_to_clipboard": "Копирано у привремени меморију",
"dismiss": "Одбаци",
"continue_watching": "Настави са гледањем",
"start_over": "Крени испочетка",
"resume": "Настави",
"change_source": "Промени извор",
"switching_source": "Промена извора...",
"no_sources_found": "Извори нису пронађени",
"sources": "Извори",
"finding_sources": "Проналажење извора...",
"unknown_source": "Непознат извор",
"sources_limited": "Извори могу бити ограничени због грешака провајдера.",
"episodes": "Епизоде",
"specials": "Специјали",
"season": "Сезона {{season}}",
"stream": "Стрим {{number}}",
"subtitles": "Титлови",
"built_in": "Уграђени",
"addons": "Додаци",
"style": "Стил",
"none": "Ниједан",
"search_online_subtitles": "Претражи титлове на мрежи",
"preview": "Преглед",
"quick_presets": "Брза подешавања",
"default": "Подразумевано",
"yellow": "Жуто",
"high_contrast": "Висок контраст",
"large": "Велико",
"core": "Језгро",
"font_size": "Величина фонта",
"show_background": "Прикажи позадину",
"advanced": "Напредно",
"position": "Позиција",
"text_color": "Боја текста",
"align": "Поравнање",
"bottom_offset": "Размак од дна",
"background_opacity": "Провидност позадине",
"text_shadow": "Сенка текста",
"on": "Укључено",
"off": "Искључено",
"outline_color": "Боја оквира",
"outline": "Оквир",
"outline_width": "Ширина оквира",
"letter_spacing": "Размак између слова",
"line_height": "Висина линије",
"timing_offset": "Временски помак (с)",
"visual_sync": "Визуелна синхронизација",
"timing_hint": "Померите титлове раније (-) или касније (+) за синхронизацију.",
"reset_defaults": "Врати на подразумевано"
},
"downloads": {
"title": "Преузимања",
"no_downloads": "Још нема преузимања",
"no_downloads_desc": "Преузети садржај ће се појавити овде за гледање ван мреже",
@ -758,7 +758,65 @@
},
"clear_data_desc": "Ово ће ресетовати сва подешавања и обрисати кеш. Да ли сте сигурни?",
"app_updates": "Ажурирања апликације",
"about_nuvio": "О Nuvio апликацији"
"about_nuvio": "О 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": "Приватност и Подаци",

View file

@ -764,7 +764,65 @@
},
"clear_data_desc": "Bu işlem tüm ayarları sıfırlayacak ve tüm önbelleği temizleyecektir. Emin misiniz?",
"app_updates": "Uygulama Güncellemeleri",
"about_nuvio": "Nuvio Hakkında"
"about_nuvio": "Nuvio Hakkında",
"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": "Gizlilik ve Veri",

View file

@ -759,7 +759,65 @@
},
"clear_data_desc": "这将重置所有设置并清除所有缓存数据。您确定吗?",
"app_updates": "应用更新",
"about_nuvio": "关于 Nuvio"
"about_nuvio": "关于 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": "隐私和数据",

View file

@ -7,6 +7,7 @@ import { catalogService, StreamingContent } from './catalogService';
import { storageService } from './storageService';
import { watchedService, LocalWatchedItem } from './watchedService';
import { TraktService } from './traktService';
import { SimklService } from './simklService';
const SUPABASE_SESSION_KEY = '@supabase:session';
const DEFAULT_SYNC_DEBOUNCE_MS = 2000;
@ -123,6 +124,7 @@ class SupabaseSyncService {
private readonly foregroundPullCooldownMs = 30000;
private pendingWatchProgressDeleteKeys = new Set<string>();
private watchProgressDeleteTimer: ReturnType<typeof setTimeout> | null = null;
private watchProgressPushedSignatures = new Map<string, string>();
private pendingPushTimers: Record<PushTarget, ReturnType<typeof setTimeout> | null> = {
plugins: null,
@ -236,6 +238,7 @@ class SupabaseSyncService {
}
this.session = null;
this.watchProgressPushedSignatures.clear();
await mmkvStorage.removeItem(SUPABASE_SESSION_KEY);
}
@ -277,13 +280,15 @@ class SupabaseSyncService {
await this.pushPluginsFromLocal();
await this.pushAddonsFromLocal();
const traktConnected = await this.isTraktConnected();
if (traktConnected) {
await this.pushLibraryFromLocal();
const externalProgressSyncConnected = await this.isExternalProgressSyncConnected();
if (externalProgressSyncConnected) {
logger.log('[SupabaseSyncService] External sync (Trakt/Simkl) is connected; skipping watch progress/watched-items push, keeping library sync.');
logger.log('[SupabaseSyncService] pushAllLocalData: complete');
return;
}
await this.pushWatchProgressFromLocal();
await this.pushLibraryFromLocal();
await this.pushWatchedItemsFromLocal();
logger.log('[SupabaseSyncService] pushAllLocalData: complete');
}
@ -296,13 +301,14 @@ class SupabaseSyncService {
await this.pullPluginsToLocal();
await this.pullAddonsToLocal();
const traktConnected = await this.isTraktConnected();
if (traktConnected) {
await this.pullLibraryToLocal();
const externalProgressSyncConnected = await this.isExternalProgressSyncConnected();
if (externalProgressSyncConnected) {
logger.log('[SupabaseSyncService] External sync (Trakt/Simkl) is connected; skipping watch progress/watched-items pull, keeping library sync.');
return;
}
await this.pullWatchProgressToLocal();
await this.pullLibraryToLocal();
await this.pullWatchedItemsToLocal();
});
logger.log('[SupabaseSyncService] pullAllToLocal: complete');
@ -493,9 +499,18 @@ class SupabaseSyncService {
logger.warn('[SupabaseSyncService] runStartupSync: one or more pull steps failed; skipped startup push-by-design');
}
const traktConnected = await this.isTraktConnected();
if (traktConnected) {
logger.log('[SupabaseSyncService] Trakt is connected; skipping progress/library/watched Supabase sync.');
const libraryPullOk = await this.safeRun('pull_library', async () => {
await this.withSuppressedPushes(async () => {
await this.pullLibraryToLocal();
});
});
const externalProgressSyncConnected = await this.isExternalProgressSyncConnected();
if (externalProgressSyncConnected) {
logger.log('[SupabaseSyncService] External sync (Trakt/Simkl) is connected; skipping watch progress/watched-items Supabase sync (library still synced).');
if (!libraryPullOk) {
logger.warn('[SupabaseSyncService] runStartupSync: library pull failed while external sync priority is active');
}
return;
}
@ -505,12 +520,6 @@ class SupabaseSyncService {
});
});
const libraryPullOk = await this.safeRun('pull_library', async () => {
await this.withSuppressedPushes(async () => {
await this.pullLibraryToLocal();
});
});
const watchedPullOk = await this.safeRun('pull_watched_items', async () => {
await this.withSuppressedPushes(async () => {
await this.pullWatchedItemsToLocal();
@ -629,8 +638,8 @@ class SupabaseSyncService {
return;
}
const traktConnected = await this.isTraktConnected();
if (traktConnected) return;
const externalProgressSyncConnected = await this.isExternalProgressSyncConnected();
if (externalProgressSyncConnected) return;
try {
logger.log(`[SupabaseSyncService] flushWatchProgressDeletes: deleting ${keys.length} keys`);
@ -700,12 +709,12 @@ class SupabaseSyncService {
return;
}
const traktConnected = await this.isTraktConnected();
if (traktConnected) {
return;
}
if (target === 'watch_progress') {
const externalProgressSyncConnected = await this.isExternalProgressSyncConnected();
if (externalProgressSyncConnected) {
logger.log('[SupabaseSyncService] executeScheduledPush: skipping watch_progress due to external sync priority (Trakt/Simkl)');
return;
}
await this.pushWatchProgressFromLocal();
logger.log(`[SupabaseSyncService] executeScheduledPush: target=${target}:done`);
return;
@ -716,6 +725,12 @@ class SupabaseSyncService {
return;
}
const externalProgressSyncConnected = await this.isExternalProgressSyncConnected();
if (externalProgressSyncConnected) {
logger.log('[SupabaseSyncService] executeScheduledPush: skipping watched_items due to external sync priority (Trakt/Simkl)');
return;
}
await this.pushWatchedItemsFromLocal();
logger.log(`[SupabaseSyncService] executeScheduledPush: target=${target}:done`);
}
@ -745,6 +760,8 @@ class SupabaseSyncService {
}
private async setSession(session: SupabaseSession): Promise<void> {
// Reset per-entry push cache on session changes to avoid cross-account state bleed.
this.watchProgressPushedSignatures.clear();
this.session = session;
await mmkvStorage.setItem(SUPABASE_SESSION_KEY, JSON.stringify(session));
}
@ -775,6 +792,7 @@ class SupabaseSyncService {
} catch (error) {
logger.error('[SupabaseSyncService] Failed to refresh session:', error);
this.session = null;
this.watchProgressPushedSignatures.clear();
await mmkvStorage.removeItem(SUPABASE_SESSION_KEY);
return false;
}
@ -791,6 +809,7 @@ class SupabaseSyncService {
} catch (error) {
logger.error('[SupabaseSyncService] Token refresh failed:', error);
this.session = null;
this.watchProgressPushedSignatures.clear();
await mmkvStorage.removeItem(SUPABASE_SESSION_KEY);
return null;
}
@ -997,6 +1016,22 @@ class SupabaseSyncService {
};
}
private getWatchProgressEntrySignature(value: { currentTime?: number; duration?: number; lastUpdated?: number }): string {
return [
Number(value.currentTime || 0),
Number(value.duration || 0),
Number(value.lastUpdated || 0),
].join('|');
}
private buildLocalWatchProgressKey(
contentType: 'movie' | 'series',
contentId: string,
episodeId?: string
): string {
return `${contentType}:${contentId}${episodeId ? `:${episodeId}` : ''}`;
}
private toStreamingContent(item: LibraryRow): StreamingContent {
const type = item.content_type === 'movie' ? 'movie' : 'series';
const posterShape = (item.poster_shape || 'POSTER').toLowerCase() as 'poster' | 'square' | 'landscape';
@ -1037,6 +1072,19 @@ class SupabaseSyncService {
}
}
private async isSimklConnected(): Promise<boolean> {
try {
return await SimklService.getInstance().isAuthenticated();
} catch {
return false;
}
}
private async isExternalProgressSyncConnected(): Promise<boolean> {
if (await this.isTraktConnected()) return true;
return await this.isSimklConnected();
}
private async pullPluginsToLocal(): Promise<void> {
const token = await this.getValidAccessToken();
if (!token) return;
@ -1254,11 +1302,10 @@ class SupabaseSyncService {
const type = row.content_type === 'movie' ? 'movie' : 'series';
const season = row.season == null ? null : Number(row.season);
const episode = row.episode == null ? null : Number(row.episode);
remoteSet.add(`${type}:${row.content_id}:${season ?? ''}:${episode ?? ''}`);
const episodeId = type === 'series' && season != null && episode != null
? `${row.content_id}:${season}:${episode}`
: undefined;
remoteSet.add(this.buildLocalWatchProgressKey(type, row.content_id, episodeId));
const local = await storageService.getWatchProgress(row.content_id, type, episodeId);
const remoteLastWatched = this.normalizeEpochMs(row.last_watched);
@ -1284,15 +1331,46 @@ class SupabaseSyncService {
);
}
logger.log(`[SupabaseSyncService] pullWatchProgressToLocal: merged ${(rows || []).length} remote entries (no local prune)`);
// Remote-first continue watching: remove local entries that no longer exist remotely.
// This intentionally treats the successful remote pull as authoritative.
const allLocal = await storageService.getAllWatchProgress();
let pruned = 0;
for (const [localKey] of Object.entries(allLocal)) {
if (remoteSet.has(localKey)) continue;
const parsed = this.parseWatchProgressKey(localKey);
if (!parsed) continue;
const episodeId = parsed.videoId && parsed.videoId !== parsed.contentId ? parsed.videoId : undefined;
await storageService.removeWatchProgress(parsed.contentId, parsed.contentType, episodeId);
this.watchProgressPushedSignatures.delete(localKey);
pruned += 1;
}
logger.log(`[SupabaseSyncService] pullWatchProgressToLocal: merged=${(rows || []).length} prunedLocalMissing=${pruned}`);
}
private async pushWatchProgressFromLocal(): Promise<void> {
const all = await storageService.getAllWatchProgress();
const entries: WatchProgressRow[] = Object.entries(all).reduce<WatchProgressRow[]>((acc, [key, value]) => {
const nextSeenKeys = new Set<string>();
const changedEntries: Array<{ key: string; row: WatchProgressRow; signature: string }> = [];
for (const [key, value] of Object.entries(all)) {
nextSeenKeys.add(key);
const signature = this.getWatchProgressEntrySignature(value);
if (this.watchProgressPushedSignatures.get(key) === signature) {
continue;
}
const parsed = this.parseWatchProgressKey(key);
if (!parsed) return acc;
acc.push({
if (!parsed) {
continue;
}
changedEntries.push({
key,
signature,
row: {
content_id: parsed.contentId,
content_type: parsed.contentType,
video_id: parsed.videoId,
@ -1302,11 +1380,30 @@ class SupabaseSyncService {
duration: this.secondsToMsLong(value.duration),
last_watched: this.normalizeEpochMs(value.lastUpdated || Date.now()),
progress_key: parsed.progressKey,
},
});
return acc;
}, []);
}
await this.callRpc<void>('sync_push_watch_progress', { p_entries: entries });
// Prune signatures for entries no longer present locally (deletes are handled separately).
for (const existingKey of Array.from(this.watchProgressPushedSignatures.keys())) {
if (!nextSeenKeys.has(existingKey)) {
this.watchProgressPushedSignatures.delete(existingKey);
}
}
if (changedEntries.length === 0) {
logger.log('[SupabaseSyncService] pushWatchProgressFromLocal: no changed entries; skipping push');
return;
}
await this.callRpc<void>('sync_push_watch_progress', {
p_entries: changedEntries.map((entry) => entry.row),
});
for (const entry of changedEntries) {
this.watchProgressPushedSignatures.set(entry.key, entry.signature);
}
logger.log(`[SupabaseSyncService] pushWatchProgressFromLocal: pushedChanged=${changedEntries.length} totalLocal=${Object.keys(all).length}`);
}
private async pullLibraryToLocal(): Promise<void> {