diff --git a/composeApp/src/commonMain/composeResources/values-fr/strings.xml b/composeApp/src/commonMain/composeResources/values-fr/strings.xml index 287403fae..42a36ae84 100644 --- a/composeApp/src/commonMain/composeResources/values-fr/strings.xml +++ b/composeApp/src/commonMain/composeResources/values-fr/strings.xml @@ -20,6 +20,7 @@ Réessayer Enregistrer Enregistrement… + Changer Valider Installation en cours Addons @@ -32,6 +33,11 @@ Indisponible Configurer l’addon Supprimer l’addon + Connectez votre propre serveur multimédia pour parcourir et lire depuis votre bibliothèque personnelle. + Ajoutez une URL de serveur ci-dessus pour que Nuvio affiche votre bibliothèque privée. + Aucune bibliothèque personnelle connectée. + URL du serveur + Ajouter Ajoutez une URL de manifeste pour commencer à charger des catalogues, métadonnées, streams ou sous-titres dans Nuvio. Aucun addon installé. Saisissez une URL d’addon. @@ -311,6 +317,8 @@ S’inscrire Vos données seront uniquement stockées localement Regardez tout, partout + En m’inscrivant, j’accepte les + Conditions d’utilisation Bon retour Bibliothèque Bibliothèque Trakt @@ -524,9 +532,13 @@ Statut Anonyme Connecté + Backend de synchronisation + Changer de backend ? + Basculer vers %1$s et se déconnecter ? Vous pourrez vous reconnecter sur le backend sélectionné. Noir AMOLED Utilise des fonds noirs purs pour les écrans OLED. Langue de l’application + Langue de l’appareil Choisir la langue Afficher, masquer et ajuster le bandeau Continuer à regarder. Liquid Glass @@ -621,6 +633,7 @@ ACCUEIL SOURCES Installez, supprimez, mettez à jour et ordonnez vos sources de contenu. + Connectez des sources multimédias personnelles et gérez l’accès à votre propre bibliothèque. Installez des dépôts de scrapers JavaScript et testez des fournisseurs en interne. Contrôle quels catalogues apparaissent à l’accueil et dans quel ordre. Désactivez des sections de détails et réorganisez tout sous le Hero. @@ -768,6 +781,10 @@ Notification de test Communauté Découvrez les personnes qui construisent et soutiennent Nuvio sur Mobile, TV et Web. + Serveur et maintenance de ce mois-ci + Couvert. Le soutien supplémentaire va désormais au développement. + Au-delà de 100 %%, le soutien supplémentaire va au développement. + Chargement de la progression du financement… L’API des supporters n’est pas configurée. Ajoutez DONATIONS_BASE_URL dans local.properties. Contributeurs Supporters @@ -830,6 +847,8 @@ Ouvre les nouvelles lectures avec le lecteur installé sélectionné. Transmettre les sous-titres au lecteur externe Récupère les sous-titres d’addons dans votre langue préférée et les transmet au lecteur externe. + Envoyer les horodatages d’intro et d’outro + Transmet les horodatages de saut d’intro et d’outro résolus au lecteur externe pour le saut automatique. Ne fonctionne que dans les lecteurs compatibles ; les autres l’ignorent. Aucun lecteur externe compatible n’est installé Lecteur Interne @@ -851,6 +870,8 @@ Non défini Par défaut Langue de l’appareil + Langue originale + Nécessite l’activation de l’enrichissement TMDB Forcé Aucun Tous les sous-titres @@ -894,6 +915,16 @@ Langue audio secondaire Langue des sous-titres secondaire DÉCODEUR + Moteur de lecture + Utiliser d’abord ExoPlayer et basculer sur libmpv si la lecture échoue. + Utiliser ExoPlayer et les décodeurs Android Media3. + Utiliser libmpv pour la lecture Android. + Moteur de rendu libmpv + Moteur de rendu libmpv + Décodage matériel libmpv + Utiliser le décodage matériel mpv quand il est disponible. + Compatibilité YUV420P libmpv + Forcer la sortie YUV420P pour les appareils ayant des problèmes de rendu ou de couleur. ÉPISODE SUIVANT LECTEUR PASSER LES SEGMENTS @@ -1280,6 +1311,7 @@ Récupération… Recherche de la source… Chargement des sous-titres depuis les addons… + Chargement des segments à passer… Recherche des streams… Lien du stream copié Aucun lien direct du stream disponible @@ -1349,7 +1381,7 @@ Aperçu de l’alerte de sortie d’épisode. Impossible d’envoyer une notification de test. Notification de test envoyée pour %1$s. - Moteur de lecture MPV indisponible. Reconstruis l’app. + Moteur de lecture MPV indisponible. Reconstruisez l’app. Impossible de lire ce stream. Le code PIN de ce profil a changé. Connectez-vous une fois pour mettre à jour le verrouillage sur cet appareil. Impossible de supprimer le verrouillage PIN. Réessayez. @@ -1422,8 +1454,10 @@ Reprendre %1$s Le JSON est vide. La collection %1$d a un ID vide. + L’identifiant de collection « %1$s » est utilisé plusieurs fois. La collection « %1$s » a un titre vide. Le dossier %1$d dans « %2$s » a un ID vide. + L’identifiant de dossier « %1$s » est utilisé plusieurs fois dans « %2$s ». Le dossier « %1$s » dans « %2$s » a un titre vide. La source %1$d dans le dossier « %2$s » a des champs vides. La source %1$d dans le dossier « %2$s » n’a pas d’ID de liste Trakt. @@ -1784,7 +1818,7 @@ Vérifiez votre connexion et réessayez. Échec de la requête (HTTP %1$d) %1$s (%2$s) - Moteur de lecture MPV indisponible. Reconstruis l’app. + Moteur de lecture MPV indisponible. Reconstruisez l’app. Impossible de lire ce stream. Plugins désactivés Plugins activés @@ -1895,4 +1929,19 @@ Démarrage du moteur P2P… Impossible de démarrer le torrent : %1$s Erreur de torrent : %1$s + + Naissance + Lieu de naissance + Crédits + Biographie + Pays + Type + Catalogue + À propos + Chargement des sous-titres depuis les addons… + Téléchargement des sous-titres… + + %d titre + %d titres + diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml index 68ef9347f..6c7761556 100644 --- a/composeApp/src/commonMain/composeResources/values/strings.xml +++ b/composeApp/src/commonMain/composeResources/values/strings.xml @@ -1926,4 +1926,19 @@ Starting P2P engine… Failed to start torrent: %1$s Torrent error: %1$s + + Born + Place of birth + Credits + Biography + Country + Type + Catalogue + About + Loading subtitles from addons... + Downloading subtitles... + + %d title + %d titles + diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/PersonDetailScreen.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/PersonDetailScreen.kt index 5da68dc8d..179f94b04 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/PersonDetailScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/PersonDetailScreen.kt @@ -523,15 +523,15 @@ private fun PersonIdentitySidebar( Column(verticalArrangement = Arrangement.spacedBy(15.dp)) { person.birthday?.let { birthday -> PersonSidebarFact( - label = "Born", + label = stringResource(Res.string.person_detail_born), value = personBirthLine(birthday = birthday, deathday = person.deathday), ) } person.placeOfBirth?.takeIf { it.isNotBlank() }?.let { place -> - PersonSidebarFact(label = "Place of birth", value = place) + PersonSidebarFact(label = stringResource(Res.string.person_detail_place_of_birth), value = place) } if (creditSummary.isNotBlank()) { - PersonSidebarFact(label = "Credits", value = creditSummary) + PersonSidebarFact(label = stringResource(Res.string.person_detail_credits), value = creditSummary) } } @@ -543,7 +543,7 @@ private fun PersonIdentitySidebar( .background(MaterialTheme.colorScheme.outline.copy(alpha = 0.30f)), ) Column(verticalArrangement = Arrangement.spacedBy(9.dp)) { - SidebarLabel(text = "Biography") + SidebarLabel(text = stringResource(Res.string.person_detail_biography)) Text( text = biography, style = MaterialTheme.typography.bodyMedium.copy(lineHeight = 22.sp), diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/TmdbEntityBrowseScreen.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/TmdbEntityBrowseScreen.kt index 38d10fe34..5d6316fa9 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/TmdbEntityBrowseScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/TmdbEntityBrowseScreen.kt @@ -49,6 +49,7 @@ import androidx.compose.ui.unit.sp import androidx.lifecycle.compose.collectAsStateWithLifecycle import coil3.compose.AsyncImage import nuvio.composeapp.generated.resources.* +import org.jetbrains.compose.resources.pluralStringResource import org.jetbrains.compose.resources.stringResource import com.nuvio.app.core.ui.landscapePosterHeightForWidth import com.nuvio.app.core.ui.landscapePosterWidth @@ -404,15 +405,15 @@ private fun EntityIdentitySidebar( Column(verticalArrangement = Arrangement.spacedBy(15.dp)) { header.originCountry?.takeIf { it.isNotBlank() }?.let { country -> - EntitySidebarFact(label = "Country", value = country) + EntitySidebarFact(label = stringResource(Res.string.entity_browse_country), value = country) } header.secondaryLabel?.takeIf { it.isNotBlank() }?.let { label -> - EntitySidebarFact(label = "Type", value = label) + EntitySidebarFact(label = stringResource(Res.string.entity_browse_type), value = label) } if (catalogueCount > 0) { EntitySidebarFact( - label = "Catalogue", - value = "$catalogueCount ${if (catalogueCount == 1) "title" else "titles"}", + label = stringResource(Res.string.entity_browse_catalogue), + value = pluralStringResource(Res.plurals.entity_browse_title_count, catalogueCount, catalogueCount), ) } } @@ -425,7 +426,7 @@ private fun EntityIdentitySidebar( .background(MaterialTheme.colorScheme.outline.copy(alpha = 0.30f)), ) Column(verticalArrangement = Arrangement.spacedBy(9.dp)) { - EntitySidebarLabel(text = "About") + EntitySidebarLabel(text = stringResource(Res.string.entity_browse_about)) Text( text = description, style = MaterialTheme.typography.bodyMedium.copy(lineHeight = 22.sp), diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/ExternalPlayerLaunchCoordinator.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/ExternalPlayerLaunchCoordinator.kt index 4fe5ff08a..5024ef945 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/ExternalPlayerLaunchCoordinator.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/ExternalPlayerLaunchCoordinator.kt @@ -11,6 +11,10 @@ import kotlinx.coroutines.withTimeoutOrNull import kotlinx.serialization.json.addJsonObject import kotlinx.serialization.json.buildJsonArray import kotlinx.serialization.json.put +import nuvio.composeapp.generated.resources.Res +import nuvio.composeapp.generated.resources.player_external_downloading_subtitles +import nuvio.composeapp.generated.resources.player_external_loading_subtitles +import org.jetbrains.compose.resources.getString private const val SkipSegmentResolveTimeoutMs = 4_000L @@ -39,7 +43,7 @@ suspend fun prepareExternalPlayerLaunch( val subtitlesDeferred = if (forwardSubtitles && !preferredLanguage.equals(SubtitleLanguageOption.NONE, ignoreCase = true)) { async { - onOverlayMessage("Loading subtitles from addons...") + onOverlayMessage(getString(Res.string.player_external_loading_subtitles)) val subtitles = SubtitleForwarder.fetchForExternalPlayer( type = type, @@ -49,7 +53,7 @@ suspend fun prepareExternalPlayerLaunch( ) if (subtitles != null) { - onOverlayMessage("Downloading subtitles...") + onOverlayMessage(getString(Res.string.player_external_downloading_subtitles)) val cachedSubtitles = SubtitleCacheProvider.cacheForExternalPlayer(subtitles) // Fallback: use original URLs if caching fails cachedSubtitles ?: subtitles