diff --git a/composeApp/src/androidMain/kotlin/com/nuvio/app/features/player/ExternalPlayerPlatform.android.kt b/composeApp/src/androidMain/kotlin/com/nuvio/app/features/player/ExternalPlayerPlatform.android.kt index 3f101118..2cd6dec2 100644 --- a/composeApp/src/androidMain/kotlin/com/nuvio/app/features/player/ExternalPlayerPlatform.android.kt +++ b/composeApp/src/androidMain/kotlin/com/nuvio/app/features/player/ExternalPlayerPlatform.android.kt @@ -6,6 +6,10 @@ import android.content.Intent import android.net.Uri import android.os.Bundle import androidx.core.content.FileProvider +import kotlinx.coroutines.runBlocking +import nuvio.composeapp.generated.resources.Res +import nuvio.composeapp.generated.resources.external_player_android_system +import org.jetbrains.compose.resources.getString import java.io.File import java.net.URI @@ -21,7 +25,12 @@ internal actual object ExternalPlayerPlatform { actual fun defaultPlayerId(): String? = AndroidSystemPlayerId actual fun availablePlayers(): List = - listOf(ExternalPlayerApp(AndroidSystemPlayerId, "Android system player")) + listOf( + ExternalPlayerApp( + AndroidSystemPlayerId, + runBlocking { getString(Res.string.external_player_android_system) }, + ), + ) actual fun open( request: ExternalPlayerPlaybackRequest, diff --git a/composeApp/src/androidPlaystore/kotlin/com/nuvio/app/features/plugins/PluginRepository.android.kt b/composeApp/src/androidPlaystore/kotlin/com/nuvio/app/features/plugins/PluginRepository.android.kt index 6139ed02..4fcefb8b 100644 --- a/composeApp/src/androidPlaystore/kotlin/com/nuvio/app/features/plugins/PluginRepository.android.kt +++ b/composeApp/src/androidPlaystore/kotlin/com/nuvio/app/features/plugins/PluginRepository.android.kt @@ -3,6 +3,9 @@ package com.nuvio.app.features.plugins import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import nuvio.composeapp.generated.resources.Res +import nuvio.composeapp.generated.resources.plugins_error_unavailable_build +import org.jetbrains.compose.resources.getString actual object PluginRepository { private val disabledState = MutableStateFlow(PluginsUiState(pluginsEnabled = false)) @@ -18,7 +21,7 @@ actual object PluginRepository { actual suspend fun pullFromServer(profileId: Int) = Unit actual suspend fun addRepository(rawUrl: String): AddPluginRepositoryResult = - AddPluginRepositoryResult.Error("Plugins are not available in this build.") + AddPluginRepositoryResult.Error(getString(Res.string.plugins_error_unavailable_build)) actual fun removeRepository(manifestUrl: String) = Unit @@ -35,7 +38,7 @@ actual object PluginRepository { actual fun getEnabledScrapersForType(type: String): List = emptyList() actual suspend fun testScraper(scraperId: String): Result> = - Result.failure(UnsupportedOperationException("Plugins are not available in this build.")) + Result.failure(UnsupportedOperationException(getString(Res.string.plugins_error_unavailable_build))) actual suspend fun executeScraper( scraper: PluginScraper, @@ -44,5 +47,5 @@ actual object PluginRepository { season: Int?, episode: Int?, ): Result> = - Result.failure(UnsupportedOperationException("Plugins are not available in this build.")) + Result.failure(UnsupportedOperationException(getString(Res.string.plugins_error_unavailable_build))) } \ No newline at end of file diff --git a/composeApp/src/androidPlaystore/kotlin/com/nuvio/app/features/updater/AppUpdaterPlatform.android.kt b/composeApp/src/androidPlaystore/kotlin/com/nuvio/app/features/updater/AppUpdaterPlatform.android.kt index 01acbee9..6b06204e 100644 --- a/composeApp/src/androidPlaystore/kotlin/com/nuvio/app/features/updater/AppUpdaterPlatform.android.kt +++ b/composeApp/src/androidPlaystore/kotlin/com/nuvio/app/features/updater/AppUpdaterPlatform.android.kt @@ -1,5 +1,10 @@ package com.nuvio.app.features.updater +import kotlinx.coroutines.runBlocking +import nuvio.composeapp.generated.resources.Res +import nuvio.composeapp.generated.resources.updates_not_available +import org.jetbrains.compose.resources.getString + actual object AppUpdaterPlatform { actual val isSupported: Boolean = false @@ -13,12 +18,12 @@ actual object AppUpdaterPlatform { assetUrl: String, assetName: String, onProgress: (downloadedBytes: Long, totalBytes: Long?) -> Unit, - ): Result = Result.failure(IllegalStateException("In-app updates are unavailable on this build.")) + ): Result = Result.failure(IllegalStateException(getString(Res.string.updates_not_available))) actual fun canRequestPackageInstalls(): Boolean = false actual fun openUnknownSourcesSettings() = Unit actual fun installDownloadedApk(path: String): Result = - Result.failure(IllegalStateException("In-app updates are unavailable on this build.")) + Result.failure(IllegalStateException(runBlocking { getString(Res.string.updates_not_available) })) } \ No newline at end of file diff --git a/composeApp/src/commonMain/composeResources/values-fr/strings.xml b/composeApp/src/commonMain/composeResources/values-fr/strings.xml index 6b4f604f..d96c24bc 100644 --- a/composeApp/src/commonMain/composeResources/values-fr/strings.xml +++ b/composeApp/src/commonMain/composeResources/values-fr/strings.xml @@ -30,13 +30,13 @@ Actualisation %1$d ressources Indisponible - Configurer l'addon - Supprimer l'addon + Configurer l’addon + Supprimer l’addon Ajoute une URL de manifeste pour commencer à charger des catalogues, métadonnées, streams ou sous-titres dans Nuvio. Aucun addon installé. - Saisis une URL d'addon. - URL de l'addon - Installer l'addon + Saisis une URL d’addon. + URL de l’addon + Installer l’addon Chargement des détails du manifeste… Validation de l’URL du manifeste et chargement des détails de l’addon avant installation. Vérification de l’addon @@ -62,7 +62,7 @@ Ajouter un catalogue Ajouter un dossier Tous les genres - Ajoute des catalogues depuis tes addons installés pour définir ce qu'affiche ce dossier. + Ajoute des catalogues depuis tes addons installés pour définir ce qu’affiche ce dossier. Aucune source de catalogue Choisir Emoji @@ -73,7 +73,7 @@ Terminé Modifier la collection Modifier le dossier - Configure l'identité, la présentation et les sources de catalogue du dossier avec la même structure que l'éditeur principal de collections. + Configure l’identité, la présentation et les sources de catalogue du dossier avec la même structure que l’éditeur principal de collections. Ajoutes-en un pour commencer. Aucun dossier Dossiers @@ -92,7 +92,7 @@ Apparence Informations de base Sources de catalogue - Choisis les catalogues d'addon que ce dossier doit regrouper. + Choisis les catalogues d’addon que ce dossier doit regrouper. Sélectionner des catalogues Sélectionner un genre %1$d sélectionné(s) @@ -118,14 +118,14 @@ Personne Réalisateur Personnalisé - Choisis une source prédéfinie. Tu peux la modifier ou la supprimer après l'avoir ajoutée. - Colle une URL de liste publique TMDB ou uniquement le numéro de l'URL. + Choisis une source prédéfinie. Tu peux la modifier ou la supprimer après l’avoir ajoutée. + Colle une URL de liste publique TMDB ou uniquement le numéro de l’URL. Cherche par nom de studio, ou colle un ID/URL de société TMDB et ajoute-le directement. Saisis un ID de chaîne. Les chaînes courantes sont disponibles dans les préréglages et les filtres rapides. - Cherche le nom d'une collection de films ou colle l'ID de collection TMDB. + Cherche le nom d’une collection de films ou colle l’ID de collection TMDB. Saisis un ID ou une URL de personne TMDB pour créer une ligne à partir des crédits de casting. Saisis un ID ou une URL de personne TMDB pour créer une ligne à partir des crédits de réalisation. - Crée une ligne TMDB dynamique avec des filtres optionnels. Laisse les champs vides si tu n'as pas besoin de ce filtre. + Crée une ligne TMDB dynamique avec des filtres optionnels. Laisse les champs vides si tu n’as pas besoin de ce filtre. Liste publique TMDB ID de chaîne ID de collection @@ -158,7 +158,7 @@ Les deux Tri Filtres - Laisse les champs vides si tu n'as pas besoin de ce filtre. + Laisse les champs vides si tu n’as pas besoin de ce filtre. Genres rapides Langues rapides Pays rapides @@ -168,7 +168,7 @@ ID de genre Utilise des numéros de genre TMDB. Sépare plusieurs valeurs par des virgules pour ET, ou des barres verticales pour OU. Date de sortie ou de diffusion depuis - Date de sortie ou de diffusion jusqu'au + Date de sortie ou de diffusion jusqu’au Utilise le format AAAA-MM-JJ, ex. 2024-01-01. Note minimale Note maximale @@ -179,7 +179,7 @@ Utilise ceci pour éviter les titres peu connus avec peu de votes. Exemple : 100. Langue originale Utilise des codes de langue à deux lettres, ex. en, ko, ja, hi. - Pays d'origine + Pays d’origine Utilise des codes de pays à deux lettres, ex. US, KR, JP, IN. ID de mots-clés Utilise des numéros de mots-clés TMDB. Les puces rapides remplissent des exemples courants. @@ -263,7 +263,7 @@ Code pays ISO 3166-1 où le titre est disponible. Exemple : US, GB. Régions rapides ID des fournisseurs de visionnage - Utilise les ID de fournisseurs de visionnage TMDB. Sépare-les par des virgules pour ET, ou par des pipes pour OU. + Utilise les ID de fournisseurs de visionnage TMDB. Sépare-les par des virgules pour ET, ou par des barres verticales pour OU. 8|337|350 Fournisseurs rapides Netflix @@ -298,7 +298,7 @@ Activé Pause Recharger - Tu as déjà un compte ? + Tu as déjà un compte ? Continuer sans compte Créer un compte Pas encore de compte ? @@ -308,7 +308,7 @@ Connecte-toi pour accéder à ta bibliothèque et ta progression Se connecter Inscris-toi pour synchroniser tes données entre appareils - S'inscrire + S’inscrire Tes données seront uniquement stockées localement Regarde tout, partout Bon retour @@ -377,7 +377,7 @@ Aucun addon actif Les catalogues installés n’ont retourné aucun résultat pour cette requête. Aucun résultat trouvé - Tes addons installés n'exposent pas de catalogue de recherche. + Tes addons installés n’exposent pas de catalogue de recherche. Aucun catalogue de recherche Rechercher des films, séries… Recherches récentes @@ -390,7 +390,7 @@ Contenu et découverte Continuer à regarder Services connectés - Écran d'accueil + Écran d’accueil Intégrations Licences et attributions Notes MDBList @@ -406,15 +406,15 @@ À PROPOS Gère ton compte, déconnecte-toi ou supprime-le. COMPTE - Ajuste la présentation de l'accueil et les préférences visuelles. - Rechercher de nouvelles versions de l'application. + Ajuste la présentation de l’accueil et les préférences visuelles. + Rechercher de nouvelles versions de l’application. Vérifier les mises à jour Gère les addons et sources de découverte. Gère tes films et épisodes téléchargés. Téléchargements GÉNÉRAL Connecte les services TMDB et MDBList. - Gère les alertes de sortie d'épisodes et envoie une notification de test. + Gère les alertes de sortie d’épisodes et envoie une notification de test. Basculer vers un profil différent. Changer de profil Connecte Trakt, synchronise des listes et enregistre des titres directement dans Trakt. @@ -495,7 +495,7 @@ Adresse e-mail Non connecté Se déconnecter - Tu seras redirigé vers l'écran de connexion. + Tu seras redirigé vers l’écran de connexion. Se déconnecter ? Statut Anonyme @@ -513,11 +513,11 @@ THÈME Collection • %1$s Nom affiché - Installe un addon avec des catalogues compatibles avec les tableaux pour configurer les lignes de l'écran d'accueil. - Aucun catalogue d'accueil + Installe un addon avec des catalogues compatibles avec les tableaux pour configurer les lignes de l’écran d’accueil. + Aucun catalogue d’accueil Source Hero Masqué - Garder l’accueil en focus + Garder le focus sur l’accueil %1$s • Limite atteinte (max. %2$d) Aucune source Hero sélectionnée Absent du Hero @@ -532,7 +532,7 @@ SOURCES HERO %1$d sur %2$d sélectionnés Afficher le Hero - Afficher un carrousel Hero en vedette en haut de l'accueil. Choisis jusqu'à 2 catalogues sources ci-dessous. + Afficher un carrousel Hero en vedette en haut de l’accueil. Choisis jusqu’à 2 catalogues sources ci-dessous. Masquer le contenu non sorti Masque les films et séries qui ne sont pas encore sortis. Masquer le soulignement des catalogues @@ -548,7 +548,7 @@ Personnalisé Ajuste la largeur des cartes et le rayon des coins. Masquer les étiquettes - Mode paysage pour les affiches dans les rayons + Affiches en mode paysage Aperçu en direct %1$s (%2$s) Rayon de coin : %1$ddp @@ -566,11 +566,11 @@ Grand Standard Afficher la valeur - Afficher une invite pour reprendre là où tu en étais à l'ouverture de l'application après avoir quitté le lecteur. + Afficher une invite pour reprendre là où tu en étais à l’ouverture de l’application après avoir quitté le lecteur. Invite de reprise au démarrage Floute les vignettes du prochain épisode dans Continuer à regarder pour éviter les spoilers. Flouter le contenu non vu dans Continuer à regarder - Inclut les épisodes à venir dans Continuer à regarder avant leur diffusion. + Inclus les épisodes à venir dans Continuer à regarder avant leur diffusion. Afficher les épisodes à venir non diffusés ORDRE DE TRI Ordre de tri @@ -578,7 +578,7 @@ Trier tous les éléments par récence Style streaming Éléments sortis d’abord, à venir à la fin - STYLE DE CARTE D'AFFICHE + STYLE DE CARTE D’AFFICHE AU DÉMARRAGE COMPORTEMENT DE LA SUITE VISIBILITÉ @@ -588,25 +588,25 @@ Carte d’affiche centrée sur la couverture Large Carte horizontale riche en informations - Quand activé, La suite reprend toujours depuis l'épisode le plus avancé vu. Quand désactivé, suit l'épisode le plus récemment visionné. Utile si tu revois des épisodes précédents. - La suite depuis l'épisode le plus avancé + Quand activé, La suite reprend toujours depuis l’épisode le plus avancé vu. Quand désactivé, suit l’épisode le plus récemment visionné. Utile si tu revois des épisodes précédents. + La suite depuis l’épisode le plus avancé Préfère les vignettes d’épisode quand elles sont disponibles. Préférer les vignettes d’épisode dans Continuer à regarder ACCUEIL SOURCES Installe, supprime, mets à jour et ordonne tes sources de contenu. Installe des dépôts de scrapers JavaScript et teste des fournisseurs en interne. - Contrôlez quels catalogues apparaissent à l'accueil et dans quel ordre. + Contrôle quels catalogues apparaissent à l’accueil et dans quel ordre. Désactive des sections de détails et réorganise tout sous le Hero. - Crée des regroupements de catalogues personnalisés avec des dossiers affichés à l'accueil. + Crée des regroupements de catalogues personnalisés avec des dossiers affichés à l’accueil. INTÉGRATIONS - Enrichissez les pages de détails avec de l'art, des crédits, des métadonnées d'épisodes et plus depuis TMDB. - Ajoute des notes externes d'IMDb, Rotten Tomatoes, Metacritic et d'autres aux pages de détails. + Enrichis les pages de détails avec de l’art, des crédits, des métadonnées d’épisodes et plus depuis TMDB. + Ajoute des notes externes d’IMDb, Rotten Tomatoes, Metacritic et d’autres aux pages de détails. Connecte des comptes pour les liens et l’accès à la bibliothèque Services connectés Ces intégrations sont expérimentales et peuvent être conservées, modifiées ou supprimées plus tard. Cloud library - Parcoure et lis les fichiers déjà présents dans tes comptes connectés. + Parcours et lis les fichiers déjà présents dans tes comptes connectés. Résoudre les liens lisibles Demande à un service connecté des liens lisibles quand un résultat le nécessite. Cela peut ajouter l’élément à ce service. Résoudre avec @@ -648,7 +648,7 @@ Restaurer la mise en forme par défaut des résultats. Clé API validée. Impossible de valider cette clé API. - Ajoute ta clé API MDBList ci-dessous avant d'activer les notes. + Ajoute ta clé API MDBList ci-dessous avant d’activer les notes. Obtiens une clé sur https://mdblist.com/preferences et colle-la ici. Clé API Clé API MDBList @@ -658,7 +658,7 @@ FOURNISSEURS DE NOTES MDBLIST Actions - Contrôles de lecture et d'enregistrement. + Contrôles de lecture et d’enregistrement. Casting Liste principale du casting. Fond cinématographique @@ -669,18 +669,18 @@ Section de commentaires Trakt. Détails Durée, statut, date de sortie, langue et informations associées. - Cartes d'épisodes - Choisis comment les épisodes sont affichés sur l'écran de métadonnées. + Cartes d’épisodes + Choisis comment les épisodes sont affichés sur l’écran de métadonnées. Horizontal Cartes en ligne style fond Liste Cartes empilées centrées sur les détails Épisodes - Saisons et liste d'épisodes pour les séries. + Saisons et liste d’épisodes pour les séries. Flouter les épisodes non vus Floute les vignettes d’épisodes jusqu’à leur visionnage pour éviter les spoilers. Groupe %1$d - Plus comme ceci + À voir aussi Visuels de recommandations TMDB sur la page de détail. Aucun Aperçu @@ -695,8 +695,8 @@ Bandes-annonces Rayon de bandes-annonces et raccourcis de lecture. Les notifications sont actuellement désactivées dans Nuvio. - Alertes de sortie d'épisodes - Programmez des notifications locales lorsqu'un nouvel épisode d'une série sauvegardée est disponible. + Alertes de sortie d’épisodes + Programme des notifications locales lorsqu’un nouvel épisode d’une série sauvegardée est disponible. Les notifications système sont désactivées pour Nuvio. Active-les pour recevoir des alertes et des notifications de test. Il y a actuellement %1$d alertes de sortie programmées sur cet appareil. ALERTES @@ -704,11 +704,11 @@ Envoyer une notification de test Envoi de la notification de test… Envoyer une notification locale de test pour %1$s. - Sauvegarde d'abord une série dans ta bibliothèque pour tester les notifications. + Enregistre d’abord une série dans ta bibliothèque pour tester les notifications. Notification de test Communauté Découvre les personnes qui construisent et soutiennent Nuvio sur Mobile, TV et Web. - L'API des supporters n'est pas configurée. Ajoute DONATIONS_BASE_URL dans local.properties. + L’API des supporters n’est pas configurée. Ajoute DONATIONS_BASE_URL dans local.properties. Contributeurs Supporters Ouvrir GitHub @@ -730,8 +730,8 @@ Mar Avr Mai - Jun - Jul + Juin + Juil. Aoû Sep Oct @@ -775,10 +775,10 @@ Modèle regex invalide Durée du cache du dernier lien Mapper DV7 vers HEVC - Utiliser Dolby Vision Profil 7 vers HEVC comme alternative pour les appareils non compatibles. + Convertir Dolby Vision Profil 7 en HEVC standard pour les appareils non compatibles. Minutes avant la fin Afficher la carte de l’épisode suivant ce nombre de minutes avant la fin. - %1$d min + %1$s min Aucun élément disponible Non défini Par défaut @@ -855,16 +855,16 @@ Pourcentage Pourcentage de seuil Afficher la carte de l’épisode suivant lorsque la lecture atteint ce pourcentage. - %1$d% + %1$s % Instantané %1$ds Illimité Lecture tunnelisée Active la lecture tunnelisée pour une latence réduite dans la synchronisation audio/vidéo. - Ajoute ta propre clé API TMDB ci-dessous avant d'activer l'enrichissement. + Ajoute ta propre clé API TMDB ci-dessous avant d’activer l’enrichissement. Clé API TMDB - Activer l'enrichissement TMDB - Utiliser ta clé API TMDB pour enrichir les métadonnées de l'addon sur l'écran de détails lorsqu'un ID TMDB ou IMDb est disponible. + Activer l’enrichissement TMDB + Utiliser ta clé API TMDB pour enrichir les métadonnées de l’addon sur l’écran de détails lorsqu’un ID TMDB ou IMDb est disponible. Saisis ta clé API v3 TMDB. Code de langue Visuels @@ -879,7 +879,7 @@ Utiliser les informations de sortie, durée, classification, statut, pays et langue de TMDB. Épisodes Utiliser les titres, miniatures, descriptions et durées des épisodes de TMDB pour les séries. - Plus comme ceci + À voir aussi Visuels de recommandations TMDB sur la page de détail. Chaînes Utiliser les métadonnées des chaînes TMDB pour les titres TV. @@ -910,8 +910,8 @@ Suis ce que tu regardes, enregistre dans ta liste ou tes listes personnalisées et garde ta bibliothèque synchronisée avec Trakt. Identifiants Trakt manquants dans local.properties (TRAKT_CLIENT_ID / TRAKT_CLIENT_SECRET). Ouvrir la connexion Trakt - Tes actions d'enregistrement peuvent maintenant cibler la watchlist Trakt et tes listes personnelles. - Connecte-toi avec Trakt pour activer la sauvegarde basée sur les listes et le mode bibliothèque Trakt. + Tes actions d’enregistrement peuvent maintenant cibler la watchlist Trakt et tes listes personnelles. + Connecte-toi à Trakt pour activer l’enregistrement par liste et le mode bibliothèque Trakt. Source de la bibliothèque Choisis quelle bibliothèque utiliser pour enregistrer et consulter ta collection Source de la bibliothèque @@ -1045,19 +1045,19 @@ Non Mettre à jour Oui - Veux-tu quitter l'application ? - Quitter l'application - Ce catalogue n'a renvoyé aucun élément. + Veux-tu quitter l’application ? + Quitter l’application + Ce catalogue n’a renvoyé aucun élément. Aucun titre trouvé Vérifie ta connexion Wi‑Fi ou données mobiles et réessaie. Réalisateur Échec du chargement À voir aussi Saisons - Cet addon a renvoyé des vidéos pour la série, mais aucune n'incluait de numéros de saison ou d'épisode. - Cet addon n'a fourni aucune métadonnée d'épisode pour cette série. - Cet addon n'a pas encore publié d'épisodes. - Ton appareil est en ligne, mais Nuvio n'a pas pu se connecter aux serveurs nécessaires. + Cet addon a renvoyé des vidéos pour la série, mais aucune n’incluait de numéros de saison ou d’épisode. + Cet addon n’a fourni aucune métadonnée d’épisode pour cette série. + Cet addon n’a pas encore publié d’épisodes. + Ton appareil est en ligne, mais Nuvio n’a pas pu se connecter aux serveurs nécessaires. Afficher moins Afficher plus ▾ Scénariste @@ -1070,7 +1070,7 @@ Aucun catalogue de découverte Le catalogue et les filtres sélectionnés n’ont retourné aucun élément. Aucun titre trouvé - Installe et valide au moins un addon avant d'explorer les catalogues dans Découvrir. + Installe et valide au moins un addon avant d’explorer les catalogues dans Découvrir. Sélectionner un catalogue Sélectionner un genre Sélectionner un type @@ -1084,11 +1084,11 @@ Marquer comme vu À suivre %1$s vu - Installe et valide au moins un addon avant de charger des lignes de catalogue à l'accueil. - Les addons installés n'exposent actuellement aucun catalogue compatible avec le tableau sans extras requis. - Aucune ligne d'accueil disponible + Installe et valide au moins un addon avant de charger des lignes de catalogue à l’accueil. + Les addons installés n’exposent actuellement aucun catalogue compatible avec le tableau sans extras requis. + Aucune ligne d’accueil disponible Voir les détails - Contrôles de lecture et d'enregistrement. + Contrôles de lecture et d’enregistrement. Actions Liste principale du casting. Rayon de collection ou de franchise associée. @@ -1125,7 +1125,7 @@ Code PIN oublié ? Code PIN incorrect Bloqué. Réessaie dans %1$ds - Les options d'avatar apparaîtront ici une fois le catalogue chargé. + Les options d’avatar apparaîtront ici une fois le catalogue chargé. Avatar : %1$s Saisis une URL d’image http:// ou https:// valide. Choisir un avatar @@ -1152,7 +1152,7 @@ Supprimer le verrouillage PIN Enregistrement… Sécurité - Ajoute un code PIN si tu souhaites que ce profil soit verrouillé avant d'y accéder. + Ajoute un code PIN si tu souhaites que ce profil soit verrouillé avant d’y accéder. Ce profil est protégé par un code PIN. Sélectionne un avatar pour ce profil. Configurer le verrouillage PIN @@ -1168,12 +1168,12 @@ Télécharger le fichier Ouvrir dans le lecteur externe Ouvrir dans le lecteur interne - Les addons de streams installés n'ont pas renvoyé de réponse valide. + Les addons de streams installés n’ont pas renvoyé de réponse valide. Impossible de charger les streams - Installe d'abord un addon pour charger les streams de ce titre. + Installe d’abord un addon pour charger les streams de ce titre. Tes addons installés ne fournissent pas de streams pour ce type de titre. Aucun addon de streams disponible - Aucun de tes addons installés n'a renvoyé de stream pour ce titre. + Aucun de tes addons installés n’a renvoyé de stream pour ce titre. S%1$d E%2$d Épisode S%1$dE%2$d - %3$s @@ -1203,9 +1203,9 @@ Échec de la vérification des mises à jour Échec du téléchargement Téléchargement %1$d % - Impossible de démarrer l'installation + Impossible de démarrer l’installation Tu utilises la version la plus récente. - Active l'installation d'applications pour Nuvio puis reviens pour continuer. + Active l’installation d’applications pour Nuvio puis reviens pour continuer. Téléchargement de la mise à jour… Aucune mise à jour trouvée. Une nouvelle version est prête à être installée. @@ -1216,7 +1216,7 @@ Mise à jour disponible Statut de la mise à jour Cet addon est déjà installé. - Saisis une URL d'addon valide + Saisis une URL d’addon valide Impossible de charger le manifeste Nuvio Impossible de supprimer le compte @@ -1228,7 +1228,7 @@ À suivre • S%1$dE%2$d Logo de %1$s Impossible de charger les commentaires - Impossible de charger les détails depuis aucun addon. + Impossible de charger les détails depuis les addons disponibles. Chaînes Aucun addon ne fournit de métadonnées pour ce contenu. Échec du téléchargement @@ -1253,7 +1253,7 @@ Le code PIN de ce profil a changé. Connecte-toi une fois pour mettre à jour le verrouillage sur cet appareil. Impossible de supprimer le verrouillage PIN. Réessaie. Connecte-toi à Internet pour supprimer le verrouillage PIN. - Ce code PIN ne peut pas encore être vérifié hors ligne sur cet appareil. Connecte-toi une fois et déverrouille-le en ligne d'abord. + Ce code PIN ne peut pas encore être vérifié hors ligne sur cet appareil. Connecte-toi une fois et déverrouille-le en ligne d’abord. Impossible de définir le code PIN. Réessaie. Connecte-toi à Internet pour définir un code PIN. Ce profil utilise les addons principaux. @@ -1278,7 +1278,7 @@ ID de liste Trakt manquant La liste Trakt n’inclut pas d’ID numérique Liste Trakt introuvable ou non publique - Limite de débit Trakt atteinte + Limite de requêtes Trakt atteinte Échec de la requête Trakt Impossible de terminer la connexion Trakt Utilisateur Trakt @@ -1300,7 +1300,7 @@ ID de personne TMDB manquant Chaîne TMDB %1$d Chaîne TMDB introuvable - Crédits de personne TMDB introuvables + Crédits TMDB de la personne introuvables Personne TMDB %1$d Personne TMDB introuvable Bande-annonce @@ -1337,8 +1337,8 @@ Mar Avr Mai - Jun - Jul + Juin + Juil. Aoû Sep Oct @@ -1425,7 +1425,7 @@ %1$s • %2$s est maintenant disponible Un nouvel épisode est maintenant disponible %1$s est maintenant disponible - Sorties d'épisodes + Sorties d’épisodes Alcool/Drogues Effrayant Nudité @@ -1470,7 +1470,7 @@ SDR tone mapped Blancs et noirs plus prévisibles sur une sortie de type SDR. Compatibilité - Au plus proche de l’ancien comportement MPV iOS. + Au plus près de l’ancien comportement MPV iOS. Personnalisé Utilise tes valeurs avancées ci-dessous. Désactivé @@ -1479,7 +1479,7 @@ Décodeur matériel Plage dynamique étendue Mode de sortie Metal par défaut pour les nouvelles sessions de lecture. - Indice de couleur d’affichage + Indication de couleur d’affichage Permettre à mpv de cibler par défaut l’espace colorimétrique de l’écran actif. Primaires cibles Transfert cible @@ -1502,7 +1502,7 @@ Par défaut Plus gros d’abord - Plus petit d’abord + Plus petits d’abord Meilleur audio d’abord Langue d’abord @@ -1629,7 +1629,7 @@ Production TMDB %1$s Impossible de charger la source TMDB ID %1$s - Ajoute une clé API TMDB dans les Paramètres pour utiliser les sources TMDB. + Ajoute une clé API TMDB dans les paramètres pour utiliser les sources TMDB. Collection TMDB introuvable Société TMDB introuvable Découverte TMDB n’a retourné aucune donnée @@ -1666,7 +1666,7 @@ Échec de la requête (HTTP %1$d) %1$s (%2$s) Moteur de lecture MPV indisponible. Reconstruis l’app. - Impossible de lire ce flux. + Impossible de lire ce stream. Plugins désactivés Plugins activés %1$d fournisseurs @@ -1756,4 +1756,7 @@ Nouvel épisode Nouvelle saison + + Liste Trakt %1$s + Lecteur système Android diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml index 911b00d6..bd8d548b 100644 --- a/composeApp/src/commonMain/composeResources/values/strings.xml +++ b/composeApp/src/commonMain/composeResources/values/strings.xml @@ -1752,4 +1752,7 @@ New Episode New Season + + Trakt List %1$s + Android system player diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/addons/AddonRepository.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/addons/AddonRepository.kt index 3e69411d..f430f3ed 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/addons/AddonRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/addons/AddonRepository.kt @@ -16,6 +16,7 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -497,7 +498,7 @@ private fun ensureManifestSuffix(url: String): String { private fun normalizeManifestUrl(rawUrl: String): String { val trimmed = rawUrl.trim() - require(trimmed.isNotEmpty()) { "Enter an addon URL." } + require(trimmed.isNotEmpty()) { runBlocking { getString(Res.string.addons_error_enter_url) } } val normalizedScheme = when { trimmed.startsWith("http://") || trimmed.startsWith("https://") -> trimmed diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/collection/CollectionEditorRepository.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/collection/CollectionEditorRepository.kt index c7f299f4..c3843bdd 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/collection/CollectionEditorRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/collection/CollectionEditorRepository.kt @@ -15,11 +15,18 @@ import nuvio.composeapp.generated.resources.Res import nuvio.composeapp.generated.resources.collections_editor_media_movies_suffix import nuvio.composeapp.generated.resources.collections_editor_media_series_suffix import nuvio.composeapp.generated.resources.collections_editor_resolved_trakt_list +import nuvio.composeapp.generated.resources.collections_editor_tmdb_collection_title_format +import nuvio.composeapp.generated.resources.collections_editor_tmdb_director_title_format import nuvio.composeapp.generated.resources.collections_editor_tmdb_discover import nuvio.composeapp.generated.resources.collections_editor_tmdb_invalid_id_error +import nuvio.composeapp.generated.resources.collections_editor_tmdb_list_title_format import nuvio.composeapp.generated.resources.collections_editor_tmdb_load_error +import nuvio.composeapp.generated.resources.collections_editor_tmdb_network_title_format +import nuvio.composeapp.generated.resources.collections_editor_tmdb_person_title_format +import nuvio.composeapp.generated.resources.collections_editor_tmdb_production_title_format import nuvio.composeapp.generated.resources.collections_editor_trakt_id_url_required import nuvio.composeapp.generated.resources.collections_editor_trakt_input_required +import nuvio.composeapp.generated.resources.collections_editor_trakt_list_title_format import nuvio.composeapp.generated.resources.collections_editor_trakt_load_error import nuvio.composeapp.generated.resources.collections_editor_trakt_no_lists_found import org.jetbrains.compose.resources.getString @@ -423,7 +430,7 @@ object CollectionEditorRepository { listOf( TraktPublicListSearchResult( traktListId = id, - title = metadata.title ?: "Trakt List $id", + title = metadata.title ?: getString(Res.string.collections_editor_trakt_list_title_format, id), subtitle = getString(Res.string.collections_editor_resolved_trakt_list), coverImageUrl = metadata.coverImageUrl, ), @@ -654,12 +661,12 @@ object CollectionEditorRepository { val seriesSuffix = getString(Res.string.collections_editor_media_series_suffix) val baseTitle = state.tmdbTitleInput.ifBlank { when (sourceType) { - TmdbCollectionSourceType.LIST -> "TMDB List ${id ?: ""}".trim() - TmdbCollectionSourceType.COLLECTION -> "TMDB Collection ${id ?: ""}".trim() - TmdbCollectionSourceType.COMPANY -> "TMDB Production ${id ?: ""}".trim() - TmdbCollectionSourceType.NETWORK -> "TMDB Network ${id ?: ""}".trim() - TmdbCollectionSourceType.PERSON -> "TMDB Person ${id ?: ""}".trim() - TmdbCollectionSourceType.DIRECTOR -> "TMDB Director ${id ?: ""}".trim() + TmdbCollectionSourceType.LIST -> getString(Res.string.collections_editor_tmdb_list_title_format, id ?: "").trim() + TmdbCollectionSourceType.COLLECTION -> getString(Res.string.collections_editor_tmdb_collection_title_format, id ?: "").trim() + TmdbCollectionSourceType.COMPANY -> getString(Res.string.collections_editor_tmdb_production_title_format, id ?: "").trim() + TmdbCollectionSourceType.NETWORK -> getString(Res.string.collections_editor_tmdb_network_title_format, id ?: "").trim() + TmdbCollectionSourceType.PERSON -> getString(Res.string.collections_editor_tmdb_person_title_format, id ?: "").trim() + TmdbCollectionSourceType.DIRECTOR -> getString(Res.string.collections_editor_tmdb_director_title_format, id ?: "").trim() TmdbCollectionSourceType.DISCOVER -> getString(Res.string.collections_editor_tmdb_discover) } } @@ -747,7 +754,7 @@ object CollectionEditorRepository { return@launch } - val title = state.traktTitleInput.ifBlank { resolved.title ?: "Trakt List $listId" } + val title = state.traktTitleInput.ifBlank { resolved.title ?: getString(Res.string.collections_editor_trakt_list_title_format, listId) } addTraktSourcesToFolder( sources = selectedTraktMediaTypes(state).map { mediaType -> CollectionSource( diff --git a/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/updater/AppUpdaterPlatform.desktop.kt b/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/updater/AppUpdaterPlatform.desktop.kt index 01acbee9..6b06204e 100644 --- a/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/updater/AppUpdaterPlatform.desktop.kt +++ b/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/updater/AppUpdaterPlatform.desktop.kt @@ -1,5 +1,10 @@ package com.nuvio.app.features.updater +import kotlinx.coroutines.runBlocking +import nuvio.composeapp.generated.resources.Res +import nuvio.composeapp.generated.resources.updates_not_available +import org.jetbrains.compose.resources.getString + actual object AppUpdaterPlatform { actual val isSupported: Boolean = false @@ -13,12 +18,12 @@ actual object AppUpdaterPlatform { assetUrl: String, assetName: String, onProgress: (downloadedBytes: Long, totalBytes: Long?) -> Unit, - ): Result = Result.failure(IllegalStateException("In-app updates are unavailable on this build.")) + ): Result = Result.failure(IllegalStateException(getString(Res.string.updates_not_available))) actual fun canRequestPackageInstalls(): Boolean = false actual fun openUnknownSourcesSettings() = Unit actual fun installDownloadedApk(path: String): Result = - Result.failure(IllegalStateException("In-app updates are unavailable on this build.")) + Result.failure(IllegalStateException(runBlocking { getString(Res.string.updates_not_available) })) } \ No newline at end of file diff --git a/composeApp/src/fullCommonMain/kotlin/com/nuvio/app/features/plugins/PluginRepository.kt b/composeApp/src/fullCommonMain/kotlin/com/nuvio/app/features/plugins/PluginRepository.kt index 85bdad69..88439c51 100644 --- a/composeApp/src/fullCommonMain/kotlin/com/nuvio/app/features/plugins/PluginRepository.kt +++ b/composeApp/src/fullCommonMain/kotlin/com/nuvio/app/features/plugins/PluginRepository.kt @@ -27,6 +27,9 @@ import kotlinx.serialization.json.buildJsonObject import kotlinx.serialization.json.encodeToJsonElement import kotlinx.serialization.json.put import nuvio.composeapp.generated.resources.Res +import nuvio.composeapp.generated.resources.plugins_error_enter_repo_url +import nuvio.composeapp.generated.resources.plugins_error_enter_valid_url +import nuvio.composeapp.generated.resources.plugins_error_provider_not_found import nuvio.composeapp.generated.resources.plugins_repository_already_installed import nuvio.composeapp.generated.resources.plugins_repository_install_failed import nuvio.composeapp.generated.resources.plugins_repository_refresh_failed @@ -151,7 +154,7 @@ actual object PluginRepository { val manifestUrl = try { normalizeManifestUrl(rawUrl) } catch (error: IllegalArgumentException) { - return AddPluginRepositoryResult.Error(error.message ?: "Enter a valid plugin URL") + return AddPluginRepositoryResult.Error(error.message ?: getString(Res.string.plugins_error_enter_valid_url)) } if (_uiState.value.repositories.any { it.manifestUrl == manifestUrl }) { @@ -300,7 +303,7 @@ actual object PluginRepository { actual suspend fun testScraper(scraperId: String): Result> { initialize() val scraper = _uiState.value.scrapers.find { it.id == scraperId } - ?: return Result.failure(IllegalArgumentException("Provider not found")) + ?: return Result.failure(IllegalArgumentException(getString(Res.string.plugins_error_provider_not_found))) val mediaType = if (scraper.supportsType("movie")) "movie" else "tv" val season = if (mediaType == "tv") 1 else null @@ -570,7 +573,7 @@ actual object PluginRepository { private fun normalizeManifestUrl(rawUrl: String): String { val trimmed = rawUrl.trim() - require(trimmed.isNotEmpty()) { "Enter a plugin repository URL." } + require(trimmed.isNotEmpty()) { runBlocking { getString(Res.string.plugins_error_enter_repo_url) } } val normalizedScheme = when { trimmed.startsWith("http://") || trimmed.startsWith("https://") -> trimmed diff --git a/composeApp/src/iosAppStore/kotlin/com/nuvio/app/features/plugins/PluginRepository.ios.kt b/composeApp/src/iosAppStore/kotlin/com/nuvio/app/features/plugins/PluginRepository.ios.kt index 6139ed02..4fcefb8b 100644 --- a/composeApp/src/iosAppStore/kotlin/com/nuvio/app/features/plugins/PluginRepository.ios.kt +++ b/composeApp/src/iosAppStore/kotlin/com/nuvio/app/features/plugins/PluginRepository.ios.kt @@ -3,6 +3,9 @@ package com.nuvio.app.features.plugins import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import nuvio.composeapp.generated.resources.Res +import nuvio.composeapp.generated.resources.plugins_error_unavailable_build +import org.jetbrains.compose.resources.getString actual object PluginRepository { private val disabledState = MutableStateFlow(PluginsUiState(pluginsEnabled = false)) @@ -18,7 +21,7 @@ actual object PluginRepository { actual suspend fun pullFromServer(profileId: Int) = Unit actual suspend fun addRepository(rawUrl: String): AddPluginRepositoryResult = - AddPluginRepositoryResult.Error("Plugins are not available in this build.") + AddPluginRepositoryResult.Error(getString(Res.string.plugins_error_unavailable_build)) actual fun removeRepository(manifestUrl: String) = Unit @@ -35,7 +38,7 @@ actual object PluginRepository { actual fun getEnabledScrapersForType(type: String): List = emptyList() actual suspend fun testScraper(scraperId: String): Result> = - Result.failure(UnsupportedOperationException("Plugins are not available in this build.")) + Result.failure(UnsupportedOperationException(getString(Res.string.plugins_error_unavailable_build))) actual suspend fun executeScraper( scraper: PluginScraper, @@ -44,5 +47,5 @@ actual object PluginRepository { season: Int?, episode: Int?, ): Result> = - Result.failure(UnsupportedOperationException("Plugins are not available in this build.")) + Result.failure(UnsupportedOperationException(getString(Res.string.plugins_error_unavailable_build))) } \ No newline at end of file diff --git a/composeApp/src/iosMain/kotlin/com/nuvio/app/features/updater/AppUpdaterPlatform.ios.kt b/composeApp/src/iosMain/kotlin/com/nuvio/app/features/updater/AppUpdaterPlatform.ios.kt index 01acbee9..6b06204e 100644 --- a/composeApp/src/iosMain/kotlin/com/nuvio/app/features/updater/AppUpdaterPlatform.ios.kt +++ b/composeApp/src/iosMain/kotlin/com/nuvio/app/features/updater/AppUpdaterPlatform.ios.kt @@ -1,5 +1,10 @@ package com.nuvio.app.features.updater +import kotlinx.coroutines.runBlocking +import nuvio.composeapp.generated.resources.Res +import nuvio.composeapp.generated.resources.updates_not_available +import org.jetbrains.compose.resources.getString + actual object AppUpdaterPlatform { actual val isSupported: Boolean = false @@ -13,12 +18,12 @@ actual object AppUpdaterPlatform { assetUrl: String, assetName: String, onProgress: (downloadedBytes: Long, totalBytes: Long?) -> Unit, - ): Result = Result.failure(IllegalStateException("In-app updates are unavailable on this build.")) + ): Result = Result.failure(IllegalStateException(getString(Res.string.updates_not_available))) actual fun canRequestPackageInstalls(): Boolean = false actual fun openUnknownSourcesSettings() = Unit actual fun installDownloadedApk(path: String): Result = - Result.failure(IllegalStateException("In-app updates are unavailable on this build.")) + Result.failure(IllegalStateException(runBlocking { getString(Res.string.updates_not_available) })) } \ No newline at end of file