Checklist a fasi (stringhe, hub/sheet, wizard, broadcast, bump versione) allineata al rilascio sul telefono. Co-authored-by: Cursor <cursoragent@cursor.com>
8.6 KiB
Gap Android → iOS: allineamento app nativa
Documento operativo per continuare su Mac lo sviluppo iOS e rilasciare un’app allineata ad Android 2.0.4-native.
Aggiornato: 24 luglio 2026
Riferimento Android (produzione / telefono): 2.0.4-native (versionCode 25), API https://www.matchlivetv.it
Stato iOS attuale: marketing 2.0.0, build 21 — i18n solo Login parziale
Obiettivo iOS: stessa copertura lingua di Android (Login, hub, sheet/dialog, wizard, broadcast) + bump versione.
Contesto
Su Android (rilasciato) la lingua scelta dall’utente vale su tutta l’app usabile:
- Persistenza + apply (
AppLocale/ SharedPreferencesmltv_locale+ recreate) - Icona globo su Login 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 esistono già AppLanguage + LanguagePickerView + Login localizzato, ma Matches/sheet/wizard/broadcast restano in italiano hardcoded. Va replicato il lavoro Android in SwiftUI.
API produzione: entrambe le app puntano già a https://www.matchlivetv.it — nessun gap di endpoint.
Stato a confronto (target = Android 2.0.4)
| Area | Android 2.0.4 | iOS oggi | Da fare su iOS |
|---|---|---|---|
| Persistenza lingua | SharedPreferences + wrap + recreate | UserDefaults + notification | Verificare refresh UI su tutte le schermate (non solo Login/Matches root) |
| Picker Login | Icona globo top-right | Testo / picker presente | Allineare a icona globo come Android |
| Picker Matches | Icona globo top bar | Presente | OK se già icona; altrimenti allineare |
| Login stringhe | Sì | Sì (L10n) |
OK |
| Slogan wordmark | app_slogan |
Chiave app.slogan non usata |
Collegare L10n.t("app.slogan") |
| Hub Matches | Sì | Quasi tutto IT fisso | Localizzare con chiavi matches.* |
| Sheet/dialog Matches | Sì (sheet_*) |
IT fisso | Localizzare (priorità: scegli squadra) |
| Status badge partita | match_status_* |
IT | Localizzare |
| Snackbar hub | matches_msg_* |
IT | Localizzare |
| Wizard 3 step | Sì (wizard_*) |
IT | Localizzare |
| Branding / color picker | Sì | IT | Localizzare |
| Broadcast + score dialog | Sì (broadcast_*, score_*) |
IT | Localizzare |
| Catalogo stringhe | values + values-en/fr/de/es (~230 chiavi) |
~14 chiavi in AppLanguage.swift |
Espandere L10n (o migrare a Localizable.xcstrings) |
| Logout UI | Icona | Testo | Icona SF Symbol |
| Versione | 2.0.4-native / 25 |
2.0.0 / 21 |
Bump a 2.0.4 / 25 (o build successiva se 22–25 già usati su TestFlight) |
| RTMP ingest | RtmpIngestUrl.kt |
MediaUrl.swift |
OK in prod; allineare solo semantica dev se serve |
File di riferimento
Android (sorgente di verità — già fatto)
| Ruolo | Path |
|---|---|
| Locale | native/android/.../core/AppLocale.kt |
| Picker | native/android/.../ui/components/LanguagePickerDialog.kt |
| Activity | native/android/.../MainActivity.kt |
| Stringhe | native/android/app/src/main/res/values/strings.xml + values-{en,fr,de,es}/ |
| Login | .../ui/login/LoginScreen.kt |
| Hub | .../ui/matches/MatchesScreen.kt |
| Sheet/dialog | .../ui/matches/MatchSheets.kt |
| Wizard | .../ui/wizard/*.kt |
| Broadcast | .../ui/broadcast/*.kt |
| Versione | native/android/app/build.gradle.kts |
iOS (da aggiornare)
| Ruolo | Path |
|---|---|
| Lingua + L10n | native/ios/MatchLiveTv/Core/AppLanguage.swift |
| Login | native/ios/MatchLiveTv/UI/Login/LoginScreen.swift |
| Hub | native/ios/MatchLiveTv/UI/Matches/MatchesScreen.swift |
| Sheet/dialog Matches | file sheet/alert equivalenti sotto UI/Matches/ (cercare stringhe IT) |
| Wizard | UI/Wizard/ (o path equivalente) |
| Broadcast | UI/Broadcast/ (o path equivalente) |
| Wordmark | native/ios/MatchLiveTv/UI/Components/MatchLiveWordmark.swift |
| Versioni | generate_xcodeproj.py, project.pbxproj, Info.plist |
| Build | scripts/build_ios_release.sh |
Piano di lavoro iOS (replicare Android — ordine obbligato)
Fase A — Infrastruttura stringhe (prima di tutto)
- Aprire Android
values/strings.xmlevalues-en|fr|de|es/strings.xmlcome catalogo. - Portare in
L10n.table(o meglioLocalizable.xcstrings) tutte le chiavi usate da:matches_*,sheet_*,match_status_*,matches_msg_*wizard_*,wizard_color_huebroadcast_*,score_*login_*,language_*,action_*,app_slogan,common_*se presenti
- Convenzione chiavi iOS:
matches.hello↔ Androidmatches_hello(punto al posto di_). - Placeholder: Android
%1$s→ Swift"Ciao, \(name)"oString(format: L10n.t("matches.hello"), name).
Fase B — Login + wordmark (rapido)
- Login: icona globo in alto a destra (come Android), non solo testo.
MatchLiveWordmark:L10n.t("app.slogan").- Verificare che al cambio lingua Login si ricrei/rinfreschi (notification già presente).
Fase C — Hub Matches + sheet/dialog (priorità UX — screenshot «Scegli squadra»)
MatchesScreen.swift: ogniText("…")hardcoded →L10n.t(...).- Sheet/dialog equivalenti a
MatchSheets.kt:- scegli squadra →
sheet.choose_team - nuova partita / programma / avvia subito
- scegli partita, badge BOZZA/PROGRAMMATA
- riprendi diretta, continua setup
- configura ora?, elimina partita
- scegli squadra →
- Snackbar/alert hub →
matches.msg_*. - Badge status riga partita →
match.status_*. - Assicurare
.id(languageTick)(o environment) su root Matches e sheet presentati.
Fase D — Wizard
- Localizzare step Partita / Trasmissione / Test rete + branding editor + color hue (
wizard.*). - Errori validazione e CTA AVANTI/INDIETRO/INIZIA.
Fase E — Broadcast
- Overlay controlli, contentDescription, snackbar pausa/ripresa/regia.
- Dialog termina diretta, set concluso, chiudi set, partita terminata (
broadcast.*,score.*).
Fase F — Versione e release
- Bump
MARKETING_VERSION→2.0.4,CURRENT_PROJECT_VERSION→25(o successivo se conflitto TestFlight). - Aggiornare
generate_xcodeproj.pyeInfo.plist, poipython3 generate_xcodeproj.py. ./scripts/build_ios_release.sh(API default già produzione).
Mapping chiavi — gruppi da copiare da Android
Sorgente: native/android/app/src/main/res/values*/strings.xml.
| Prefisso Android | Uso | Priorità |
|---|---|---|
language_*, login_*, app_slogan, action_* |
Login / chrome | Alta |
matches_* |
Hub | Alta |
sheet_*, match_status_*, matches_msg_* |
Sheet/dialog hub | Alta (bug «Scegli squadra» in EN) |
wizard_* |
Wizard | Alta (stessa sessione utente dopo hub) |
broadcast_*, score_* |
Diretta | Alta |
streaming_notification_* |
Solo Android FGS | N/A su iOS |
Non lasciare fuori scope wizard/broadcast: su Android sono già tradotti; iOS deve seguirli per parità.
Verifica manuale su Mac (acceptance)
cd native/ios && python3 generate_xcodeproj.py- Build simulatore; login produzione.
- Login: globo → English → label/errori/slogan in EN.
- Matches: saluto, CTA, empty state in EN.
- Apri «Change» / scegli squadra: titolo «Choose team» (non «Scegli squadra»).
- Nuova partita / programma / elimina: tutto EN.
- Wizard 3 step in EN.
- (Se possibile) overlay diretta: dialog/termina in EN.
- Kill app → riapri: lingua persistita.
- Spot-check FR/DE/ES.
- Release:
./scripts/build_ios_release.sh
Test:
cd native/ios
python3 generate_xcodeproj.py
xcodebuild -project MatchLiveTv.xcodeproj -scheme MatchLiveTv \
-destination 'platform=iOS Simulator,name=iPhone 17' \
-derivedDataPath build/DerivedData \
ONLY_ACTIVE_ARCH=YES ARCHS=arm64 EXCLUDED_ARCHS=x86_64 \
test -only-testing:MatchLiveTvTests
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.
Sintesi priorità (ordine di esecuzione)
- A Catalogo stringhe completo (copiare da Android
values*) - C Hub + sheet/dialog (fix «Scegli squadra» in EN)
- B Slogan + globo Login
- D Wizard
- E Broadcast
- F Versione
2.0.4/25+ build release
Quando A–F sono chiusi, iOS è allineato ad Android 2.0.4-native per UX multilingua e versioning store.