Skip to content

i18n(fr): backfill 80 missing translations + extract 26 hardcoded strings#1239

Open
foXaCe wants to merge 2 commits into
NuvioMedia:cmp-rewritefrom
foXaCe:feat/extract-hardcoded-strings-pass5
Open

i18n(fr): backfill 80 missing translations + extract 26 hardcoded strings#1239
foXaCe wants to merge 2 commits into
NuvioMedia:cmp-rewritefrom
foXaCe:feat/extract-hardcoded-strings-pass5

Conversation

@foXaCe

@foXaCe foXaCe commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR brings the French localization back to full parity (1825 ↔ 1825) and extracts 26 hardcoded user-facing strings that were introduced via recent merges. Two complementary passes in one commit:

Backfill (80 missing FR translations) for keys integrated upstream via PRs #1167, #1173, #1180, #1201 and the Indonesian localization series: Compose player UI (Auto Sync, Bold, Capture, Reset…), P2P consent dialog incl. legal body, Player torrent UI (peer info/stats/status/errors), Subtitle styling (Bold/Background/Outline/Size/Vertical Offset), Fusion badge settings, Stream badge settings, P2P settings, Addon subtitle startup, Player preference (Internal/External), External player forward subs, CW countdown, Card style, Original format, Streams loading.

Extract (26 hardcoded strings → 25 new EN keys) found by targeted scan over the 611 commits added since pass 4:

  • StreamBadgeSettingsRepository: URL validation, import limit, error fallback (4 sites)
  • StreamBadgeRules: JSON parsing errors (3 sites)
  • PlayerScreen: subtitle auto-sync errors (2 sites)
  • ExternalPlayerLaunchCoordinator: now uses existing streams_loading_subtitles (1 site)
  • TraktLibraryRepository: 8 sites — errorMessageForStatus converted to suspend fun to allow getString(); existing callers were already suspend
  • P2pStreamingEngine.android: 7 sites (torrent + TorrServer errors). The absolute binary path was removed from the user-facing exception message but kept in Log.e(TAG, …) for debug
  • P2pStreamingEngine.ios: 1 site (platform unsupported stub)

Conventions: stream, addon, torrent, P2P, Fusion, buffer kept in English (project convention). lecteur / sous-titres / sources / pairs / contour / aperçu translated. Tutoiement consistent throughout (0 vouvoiement, 0 mixed forms, aligned with #1171). Typography: only typographic apostrophes (), no mojibake, UTF-8.

PR type

  • Reproducible bug fix
  • UI glitch/bug fix
  • Behavior bug/regression fix
  • Small maintenance only, with no UI or behavior change
  • Docs accuracy fix
  • Translation/localization only
  • Approved larger or directional change

Why

Two recent waves of upstream work added 80 string keys without FR translations and 26 newly-hardcoded user-facing strings (mostly in the new P2P / TorrServer engine, Stream badges, Trakt library mutations, and player subtitle auto-sync). Without this PR, French users see the EN fallback for those strings, and the new hardcoded errors cannot ever be localized. Bringing the file back to 100% parity preserves the editorial choice made in #1171 (informal tu, aligned with Nuvio TV and the standard for French media apps).

Issue or approval

No linked issue: regular translation maintenance + small hardcoded-strings extraction (same pattern already approved in #1171, #1029, #1025, #943).

UI / behavior impact

  • No UI change
  • No behavior change
  • UI changed only to fix a documented glitch/bug
  • Behavior changed only to fix a documented bug/regression
  • UI change has explicit maintainer approval
  • Behavior change has explicit maintainer approval

The only Kotlin behavior change is the TorrServer binary not found exception message: the absolute filesystem path is no longer exposed to end users (kept in Log.e() for debug). This avoids leaking app-internal paths in UI surfaces.

Policy check

  • I have read and understood CONTRIBUTING.md.
  • This PR is small, focused, and limited to one problem.
  • This PR is not cosmetic-only.
  • Any UI change fixes a linked glitch/bug and includes visual proof, or this PR has no UI change.
  • Any behavior change fixes a linked bug/regression or has explicit approval, or this PR has no behavior change.
  • This PR does not bundle unrelated refactors, cleanups, formatting, or drive-by changes.
  • This PR does not add dependencies, architecture changes, migrations, or product-direction changes without explicit approval.
  • I listed the testing performed below.

Scope boundaries

Limited to:

  • composeApp/src/commonMain/composeResources/values/strings.xml (25 new EN keys, no edits to existing strings)
  • composeApp/src/commonMain/composeResources/values-fr/strings.xml (105 new FR translations)
  • 7 Kotlin files containing the 26 hardcoded-string call sites (StreamBadgeSettingsRepository, StreamBadgeRules, PlayerScreen, ExternalPlayerLaunchCoordinator, TraktLibraryRepository, P2pStreamingEngine.android, P2pStreamingEngine.ios)

No refactor, no dependency change, no other locale touched (the new EN keys will fall back to EN on the 10 other languages via Compose Resources default-locale fallback until each values-XX/strings.xml is updated separately, same as the PR #1173 pattern).

Testing

  • ./gradlew :composeApp:compileFullDebugKotlinAndroid → BUILD SUCCESSFUL in 1m27s
  • ./gradlew :composeApp:compilePlaystoreDebugKotlinAndroid → BUILD SUCCESSFUL (covers androidPlaystore source set)
  • ./gradlew :composeApp:compileFullDebugUnitTestKotlinAndroid → BUILD SUCCESSFUL (covers StreamBadgeRulesParser test which exercises the modified parse() function)
  • xmllint --noout on both values/strings.xml and values-fr/strings.xml → OK
  • ✓ Key parity: 1825 EN ↔ 1825 FR strings, 2 ↔ 2 plurals (0 missing, 0 orphans)
  • ✓ Re-scan of the 19 extracted hardcoded patterns confirms 0 occurrences remain in .kt files (outside tests)
  • ✓ Placeholder alignment check: all %1$s, %1$d, %1$s %2$d preserved between EN and FR
  • ✓ FR linguistic audit: 0 mojibake, 0 unescaped majuscules (EtatÉtat), 0 vouvoiement residue, 0 imperative -ez verbs in the new strings, 100% typographic apostrophes ()
  • iOS / desktop targets: not testable on Linux host (Kotlin/Native iOS requires macOS). Patterns are strictly identical to validated Android paths (runBlocking { getString(Res.string.X) } for non-suspend, getString(...) in suspend functions, mirroring DownloadsPlatformDownloader.ios.kt).

Screenshots / Video

Not a UI change.

Breaking changes

None. The only signature change is TraktLibraryRepository.errorMessageForStatus going from private fun to private suspend fun. All call sites are already inside suspend fun (getRaw, postJson, addToWatchlist, addToPersonalList) — verified by grep over the codebase.

Linked issues

No linked issue — translation/localization maintenance.

…ings (pass 5)

Backfill (80 FR translations for keys integrated via upstream PRs NuvioMedia#1167/NuvioMedia#1173/NuvioMedia#1180/NuvioMedia#1201):
- Compose player UI (Auto Sync, Bold, Capture, Reset, etc.) : 10
- P2P consent dialog (legal body + Cancel/Enable/Title) : 4
- Player torrent UI (peer info, stats, status, errors) : 8
- Subtitle styling (Bold/Background/Outline/Size/Vertical Offset/etc.) : 13
- Fusion badge settings (URL, preview, group, etc.) : 13
- Stream badge settings (URLs, size badges, Fusion style) : 6
- P2P settings (hide stats, allow torrent) : 4
- Addon subtitle startup (All/Fast/Preferred + descriptions) : 7
- Player preference (Internal/External + descriptions) : 4
- External player forward subs : 2
- CW countdown / Card style / Original format / Streams loading : 9

Extract (26 hardcoded strings, 25 new EN keys):
- StreamBadgeSettingsRepository : 4 sites (URL validation, import limit, fallback)
- StreamBadgeRules : 3 sites (JSON parsing errors)
- PlayerScreen : 2 sites (subtitle auto-sync errors)
- ExternalPlayerLaunchCoordinator : 1 site (uses existing streams_loading_subtitles)
- TraktLibraryRepository : 8 sites (errorMessageForStatus converted to suspend,
  defaultMessages, list fallback for slug-only IDs)
- P2pStreamingEngine.android : 7 sites (torrent + TorrServer errors;
  binary path removed from UI, kept in Log.e for debug)
- P2pStreamingEngine.ios : 1 site (platform unsupported)

Conventions: stream/addon/torrent/P2P/Fusion/buffer preserved EN.
lecteur/sous-titres/sources/pairs/contour/aperçu translated.
Tutoiement consistent (0 vouvoiement, 0 mixed verbs).
Typography: ' typographic only, no mojibake, UTF-8.

Parity EN ↔ FR: 1825 / 1825 strings, 2 / 2 plurals.
Builds: composeApp:compileFullDebugKotlinAndroid + UnitTestKotlinAndroid SUCCESSFUL.
xmllint OK on both XML files.
@D4rk56

D4rk56 commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Nice !!

…e (pass 5 follow-up)

Quality audit follow-up on the 1825 FR strings — 17 corrections found by terminology
script + linguistic sub-agent. No bugs (grammar/orthography clean), only style and
cross-key consistency.

Block A — Project terminology (sources → seeds): 3 strings
- player_torrent_peer_info, player_torrent_stats, settings_p2p_hide_stats_subtitle
- "sources" conflicted with "source de stream" used elsewhere (compose_player_sources);
  "seeds" is the unambiguous BitTorrent term

Block B — Style polish on pass 5 new strings: 9 corrections
- p2p_consent_body : "visible des" → "visible par" (modern usage)
- p2p_consent_body : "de l'utilisation" → "découlant de ton utilisation" (preserves
  "arising from your use" possessive, legally clearer)
- settings_p2p_subtitle : "Autoriser" → "Autorise" (consistency with sibling
  settings_p2p_hide_stats_subtitle "Masque...")
- settings_playback_subtitle_use_forced_description : "paramètres" → "préférences"
  (less heavy)
- 4 Fusion badge strings : "style Fusion" → "au style Fusion" (less calqué from
  English "Fusion-style")
- settings_fusion_badge_url_status_summary : commas → "·" separator (consistent
  with player_torrent_stats)

Block C — Cross-key consistency (same EN, diverging FR): 8 strings, 5 groups
- 3× "Request failed with HTTP %d" → "Échec de la requête (HTTP %d)" (was mixed
  with "La requête a échoué avec HTTP %d")
- collections_tmdb_discover_no_data : add missing "La" (grammar)
- 4× "TMDB Discover" → "Découverte TMDB" (was mixed with EN-preserved)
- downloads_error_finalize_failed : "fichier téléchargé" → "fichier de téléchargement"
  (semantic: file being written, not already downloaded)
- collections_editor_trakt_input_required : reorder to match
  collections_editor_trakt_enter_name_url_or_id

Parity preserved: EN 1825 ↔ FR 1825 strings, 2 ↔ 2 plurals.
xmllint OK. compileCommonMainKotlinMetadata SUCCESSFUL.
0 vouvoiement residue, 0 mojibake, 0 faux ami trivial.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants