Files
MatchLiveTv/docs/IOS_ANDROID_I18N_GAP.md

7.0 KiB
Raw Permalink Blame History

Gap Android → iOS: allineamento app nativa

Documento operativo per continuare su Mac lo sviluppo iOS e rilasciare unapp allineata ad Android.

Aggiornato: 12 agosto 2026
Riferimento Android (produzione / telefono / Play): 2.0.10-native (versionCode 31), API https://www.matchlivetv.it
Stato iOS attuale: marketing 2.0.10, build 31 — i18n allineato (Login, hub, sheet/dialog, wizard, broadcast, account/forgot)

Nuovo (branch feature/stream-audio-mute): mute microfono in diretta. Codice iOS già nel branch; verifica su Mac in IOS_STREAM_AUDIO_MUTE.md.

Obiettivo iOS: stessa copertura lingua di Android (Login, hub, sheet/dialog, wizard, broadcast, account) + bump versione, senza i bug di sessione/crash già risolti su Android.


Contesto

Su Android (rilasciato) la lingua scelta dallutente vale su tutta lapp usabile:

  • Persistenza + apply live (AppLocale / SharedPreferences mltv_locale + ProvideAppLocale)
  • Icona globo su Login (TopAppBar) e Matches
  • Hub Partite localizzato
  • Bottom sheet e dialog Matches (es. «Choose team», nuova partita, programma, elimina, riprendi)
  • Wizard 3 step + branding colori
  • Broadcast overlay, snackbar, dialog fine set/partita
  • ~230+ chiavi × 5 lingue in res/values*

Su iOS: AppLanguage + L10n (~225 chiavi × 5 lingue) + LanguagePickerView; Login/Matches/Wizard/Broadcast usano L10n.t(...). Refresh UI via NotificationCenter + .id(languageTick) senza reset sessione/nav.

API produzione: entrambe le app puntano già a https://www.matchlivetv.itnessun gap di endpoint.


Lezioni Android 2.0.5 (obbligatorie su iOS)

Queste sono regressioni/bug già visti su Android; non ripeterli su iOS.

Problema Sintomo Fix Android (da replicare in spirito) Stato iOS
Recreate Activity al cambio lingua Torna al Login / perde nav Niente recreate obbligatorio: aggiorna UI via stato lingua + refresh stringhe OK — languageTick / notification
Context “nudo” per le stringhe Crash wizard: picker foto Mantieni Activity come host OK — SwiftUI host invariato
Globe sotto lo scroll del form Login Tap ignorato Globe in toolbar/top bar OK — globo in top bar Login
Splash che richiede rete per restare loggato Dopo cambio lingua → Login se API lenta Se token locale presente → resta autenticato OK — validateOrRefresh restituisce sessione locale su errore rete

Stato a confronto (target = Android 2.0.5)

Area Android 2.0.5 iOS oggi Da fare su iOS
Persistenza lingua SharedPreferences + ProvideAppLocale UserDefaults + notification Fatto
Picker Login Icona globo in TopAppBar Icona globo top bar Fatto
Picker Matches Icona globo top bar Icona globo + logout icon Fatto
Login stringhe Sì (L10n) Fatto
Slogan wordmark app_slogan L10n.t("app.slogan") Fatto
Hub Matches matches.* Fatto
Sheet/dialog Matches Sì (sheet_*) sheet.* Fatto
Status badge partita match_status_* match.status.* Fatto
Snackbar hub matches_msg_* matches.msg.* Fatto
Wizard 3 step Sì (wizard_*) wizard.* Fatto
Branding / color picker wizard.branding.* / wizard.color.hue Fatto
Broadcast + score dialog broadcast.* / score.* Fatto
Catalogo stringhe values* (~230) AppLanguage.swift L10n (~225, no FGS) Fatto
Logout UI Icona Icona SF Symbol Fatto
Versione 2.0.10-native / 31 2.0.10 / 31 Fatto
RTMP ingest RtmpIngestUrl.kt MediaUrl.swift OK

Residui fuori scope Android (opzionali)

Nessuno per messaggi utente: tutte le stringhe UI/errori/termiche/API/overlay usano L10n.
Permission dialog di sistema localizzati via Resources/{it,en,fr,de,es}.lproj/InfoPlist.strings.

Brand fissi lasciati intenzionalmente invariati: MATCH / LIVE / TV, Match Live TV, YouTube Live.


File di riferimento

Android (sorgente di verità)

Ruolo Path
Locale + ProvideAppLocale native/android/.../core/AppLocale.kt
Stringhe native/android/app/src/main/res/values/strings.xml + values-{en,fr,de,es}/
UI Login / Matches / MatchSheets / Wizard / Broadcast

iOS (allineato)

Ruolo Path
Lingua + L10n native/ios/MatchLiveTv/Core/AppLanguage.swift
Login native/ios/MatchLiveTv/UI/Login/LoginScreen.swift
Hub + sheet native/ios/MatchLiveTv/UI/Matches/MatchesScreen.swift
Status badge native/ios/MatchLiveTv/Domain/MatchHubFilter.swift (MatchPresentation)
Wizard native/ios/MatchLiveTv/UI/Wizard/*.swift
Broadcast native/ios/MatchLiveTv/UI/Broadcast/*.swift
Wordmark native/ios/MatchLiveTv/UI/Components/MatchLiveWordmark.swift
Versioni generate_xcodeproj.py, Info.plist, project.pbxproj

Convenzione chiavi

  • Android matches_hello → iOS matches.hello (ogni _.)
  • Placeholder: %1$s / %1$d%1$@ / %1$d con L10n.t("key", args...)
  • Catalogo generato da values*/strings.xml (escluse streaming_notification_*, solo Android FGS)

Verifica manuale su Mac (acceptance)

  1. cd native/ios && python3 generate_xcodeproj.py
  2. Build simulatore; login produzione.
  3. Login: globo → English → label/errori/slogan in EN.
  4. Loggato: cambio lingua da Matches → resti su Matches, testi EN (niente ritorno al Login).
  5. Matches: saluto, CTA, empty state in EN.
  6. Apri «Change» / scegli squadra: titolo «Choose team» (non «Scegli squadra»).
  7. Nuova partita → Avvia ora → wizard si apre senza crash; step in EN.
  8. Wizard 3 step in EN; logo picker funziona.
  9. (Se possibile) overlay diretta: dialog/termina in EN.
  10. Kill app → riapri: lingua persistita e sessione resta se token valido.
  11. Spot-check FR/DE/ES.
  12. Release: ./scripts/build_ios_release.sh
cd native/ios
python3 generate_xcodeproj.py
xcodebuild -project MatchLiveTv.xcodeproj -scheme MatchLiveTv \
  -destination 'generic/platform=iOS Simulator' \
  -derivedDataPath build/DerivedData \
  ONLY_ACTIVE_ARCH=YES ARCHS=arm64 EXCLUDED_ARCHS=x86_64 \
  build

Note API / produzione

Android iOS
Default BuildConfig / -PAPI_BASE_URL API_BASE_URL → Info.plist
Fallback https://www.matchlivetv.it idem
REST / Cable /api/v1, wss://…/cable idem

Nessuna modifica server richiesta.

Versione store target: 2.0.10 / build 31 (parità con Android 2.0.10-native / versionCode 31).


Sintesi

Fasi AF del piano originale sono chiuse. Tutti i messaggi utente (UI, errori API/RTMP, termica, overlay, permission system) passano da L10n / InfoPlist.strings in IT/EN/FR/DE/ES.