i18n(fr): extract remaining hardcoded strings to stringResource

- NetworkStatusRepository: titleForEmptyState/messageForEmptyState now @Composable, using existing keys (network_cannot_reach_servers, network_no_internet_connection, details_servers_unreachable, details_check_connection) + 2 new (network_connection_issue, network_please_check_connection)
- LibraryRepository: LOCAL_LIBRARY_LIST_TITLE moved to library_local_tab_title resource; toLibraryDisplayTitle() "Other" fallback uses library_other
- EpisodeReleaseNotificationsRepository: permission-disabled message uses settings_notifications_permission_disabled
- StreamsRepository.fallbackRepositoryLabel: uses streams_plugin_repository_fallback
- PluginRuntime: title fallback "Unknown" uses generic_unknown

4 new keys added (EN + FR with tutoiement, NBSP, apostrophes courbes).
Parity preserved: 1353 keys EN ↔ FR.
This commit is contained in:
Stéphane 2026-05-06 20:23:32 +02:00
parent 31d18869fc
commit af43edcf04
7 changed files with 45 additions and 14 deletions

View file

@ -1400,4 +1400,8 @@
<string name="settings_search_results_section">RÉSULTATS</string>
<string name="streams_open_external_player">Ouvrir dans un lecteur externe</string>
<string name="streams_open_internal_player">Ouvrir dans le lecteur interne</string>
<string name="network_connection_issue">Problème de connexion</string>
<string name="network_please_check_connection">Vérifie ta connexion et réessaie.</string>
<string name="library_local_tab_title">Bibliothèque Nuvio</string>
<string name="streams_plugin_repository_fallback">Dépôt de plugin</string>
</resources>

View file

@ -1399,4 +1399,8 @@
<string name="submit_intro_button_submit">Submit</string>
<string name="submit_intro_capture_button">Capture</string>
<string name="settings_playback_introdb_invalid_key">Invalid API Key or connection failed</string>
<string name="network_connection_issue">Connection issue</string>
<string name="network_please_check_connection">Please check your connection and try again.</string>
<string name="library_local_tab_title">Nuvio Library</string>
<string name="streams_plugin_repository_fallback">Plugin repository</string>
</resources>

View file

@ -1,5 +1,6 @@
package com.nuvio.app.core.network
import androidx.compose.runtime.Composable
import com.nuvio.app.features.addons.httpRequestRaw
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -9,6 +10,14 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeoutOrNull
import nuvio.composeapp.generated.resources.Res
import nuvio.composeapp.generated.resources.details_check_connection
import nuvio.composeapp.generated.resources.details_servers_unreachable
import nuvio.composeapp.generated.resources.network_cannot_reach_servers
import nuvio.composeapp.generated.resources.network_connection_issue
import nuvio.composeapp.generated.resources.network_no_internet_connection
import nuvio.composeapp.generated.resources.network_please_check_connection
import org.jetbrains.compose.resources.stringResource
enum class NetworkCondition {
Unknown,
@ -28,18 +37,20 @@ data class NetworkStatusUiState(
get() = condition == NetworkCondition.NoInternet || condition == NetworkCondition.ServersUnreachable
}
@Composable
fun NetworkCondition.titleForEmptyState(): String =
when (this) {
NetworkCondition.ServersUnreachable -> "Cannot reach servers"
NetworkCondition.NoInternet -> "No internet connection"
else -> "Connection issue"
NetworkCondition.ServersUnreachable -> stringResource(Res.string.network_cannot_reach_servers)
NetworkCondition.NoInternet -> stringResource(Res.string.network_no_internet_connection)
else -> stringResource(Res.string.network_connection_issue)
}
@Composable
fun NetworkCondition.messageForEmptyState(): String =
when (this) {
NetworkCondition.ServersUnreachable -> "Your device is online, but Nuvio could not reach required servers."
NetworkCondition.NoInternet -> "Check your Wi-Fi or mobile data connection and try again."
else -> "Please check your connection and try again."
NetworkCondition.ServersUnreachable -> stringResource(Res.string.details_servers_unreachable)
NetworkCondition.NoInternet -> stringResource(Res.string.details_check_connection)
else -> stringResource(Res.string.network_please_check_connection)
}
object NetworkStatusRepository {

View file

@ -13,6 +13,11 @@ import com.nuvio.app.features.trakt.effectiveLibrarySourceMode as resolveEffecti
import com.nuvio.app.features.trakt.shouldUseTraktLibrary
import io.github.jan.supabase.postgrest.postgrest
import io.github.jan.supabase.postgrest.rpc
import kotlinx.coroutines.runBlocking
import nuvio.composeapp.generated.resources.Res
import nuvio.composeapp.generated.resources.library_local_tab_title
import nuvio.composeapp.generated.resources.library_other
import org.jetbrains.compose.resources.getString
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
@ -405,12 +410,11 @@ object LibraryRepository {
}
internal const val LOCAL_LIBRARY_LIST_KEY = "local"
internal const val LOCAL_LIBRARY_LIST_TITLE = "Nuvio Library"
internal fun localLibraryListTab(): TraktListTab =
TraktListTab(
key = LOCAL_LIBRARY_LIST_KEY,
title = LOCAL_LIBRARY_LIST_TITLE,
title = runBlocking { getString(Res.string.library_local_tab_title) },
type = TraktListType.WATCHLIST,
)
@ -461,7 +465,7 @@ private fun LibraryItem.toSyncItem(): LibrarySyncItem = LibrarySyncItem(
internal fun String.toLibraryDisplayTitle(): String {
val normalized = trim()
if (normalized.isBlank()) return "Other"
if (normalized.isBlank()) return runBlocking { getString(Res.string.library_other) }
return normalized
.split('-', '_', ' ')
@ -469,5 +473,5 @@ internal fun String.toLibraryDisplayTitle(): String {
.joinToString(" ") { token ->
token.lowercase().replaceFirstChar { char -> char.uppercase() }
}
.ifBlank { "Other" }
.ifBlank { runBlocking { getString(Res.string.library_other) } }
}

View file

@ -21,6 +21,7 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.sync.withPermit
@ -294,7 +295,7 @@ object EpisodeReleaseNotificationsRepository {
permissionGranted = granted,
testTargetTitle = currentTestTarget()?.name,
errorMessage = when {
_uiState.value.isEnabled && !granted -> "System notifications are currently disabled for Nuvio."
_uiState.value.isEnabled && !granted -> runBlocking { getString(Res.string.settings_notifications_permission_disabled) }
else -> _uiState.value.errorMessage
},
)
@ -362,7 +363,7 @@ object EpisodeReleaseNotificationsRepository {
scheduledCount = 0,
testTargetTitle = currentTestTarget()?.name,
errorMessage = if (_uiState.value.isEnabled && !permissionGranted) {
"System notifications are currently disabled for Nuvio."
runBlocking { getString(Res.string.settings_notifications_permission_disabled) }
} else {
null
},

View file

@ -23,6 +23,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.runBlocking
import nuvio.composeapp.generated.resources.*
import org.jetbrains.compose.resources.getString
import kotlinx.coroutines.launch
@ -596,6 +597,8 @@ private fun String.fallbackRepositoryLabel(): String {
val withoutManifest = withoutQuery.removeSuffix("/manifest.json")
val host = withoutManifest.substringAfter("://", withoutManifest).substringBefore('/')
return host.ifBlank {
withoutManifest.substringAfterLast('/').ifBlank { "Plugin repository" }
withoutManifest.substringAfterLast('/').ifBlank {
runBlocking { getString(Res.string.streams_plugin_repository_fallback) }
}
}
}

View file

@ -22,6 +22,10 @@ import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.intOrNull
import kotlinx.serialization.json.jsonPrimitive
import kotlinx.coroutines.runBlocking
import nuvio.composeapp.generated.resources.Res
import nuvio.composeapp.generated.resources.generic_unknown
import org.jetbrains.compose.resources.getString
import kotlin.random.Random
private const val PLUGIN_TIMEOUT_MS = 60_000L
@ -438,7 +442,7 @@ internal object PluginRuntime {
?.takeIf { it.isNotEmpty() }
PluginRuntimeResult(
title = item.stringOrNull("title") ?: item.stringOrNull("name") ?: "Unknown",
title = item.stringOrNull("title") ?: item.stringOrNull("name") ?: runBlocking { getString(Res.string.generic_unknown) },
name = item.stringOrNull("name"),
url = url,
quality = item.stringOrNull("quality"),