Files
MatchLiveTv/docs/IOS_ANDROID_I18N_GAP.md
T
eminuxandCursor 97af398654 Aggiorna il gap iOS per replicare i18n Android 2.0.4 completo.
Checklist a fasi (stringhe, hub/sheet, wizard, broadcast, bump versione) allineata al rilascio sul telefono.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 08:48:55 +02:00

204 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Gap Android → iOS: allineamento app nativa
Documento operativo per continuare su **Mac** lo sviluppo iOS e rilasciare unapp **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 dallutente vale su **tutta lapp** usabile:
- Persistenza + apply (`AppLocale` / SharedPreferences `mltv_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 2225 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)
1. Aprire Android `values/strings.xml` e `values-en|fr|de|es/strings.xml` come catalogo.
2. Portare in `L10n.table` (o meglio `Localizable.xcstrings`) **tutte** le chiavi usate da:
- `matches_*`, `sheet_*`, `match_status_*`, `matches_msg_*`
- `wizard_*`, `wizard_color_hue`
- `broadcast_*`, `score_*`
- `login_*`, `language_*`, `action_*`, `app_slogan`, `common_*` se presenti
3. Convenzione chiavi iOS: `matches.hello` ↔ Android `matches_hello` (punto al posto di `_`).
4. Placeholder: Android `%1$s` → Swift `"Ciao, \(name)"` o `String(format: L10n.t("matches.hello"), name)`.
### Fase B — Login + wordmark (rapido)
5. Login: icona globo in alto a destra (come Android), non solo testo.
6. `MatchLiveWordmark`: `L10n.t("app.slogan")`.
7. Verificare che al cambio lingua Login si ricrei/rinfreschi (notification già presente).
### Fase C — Hub Matches + sheet/dialog (priorità UX — screenshot «Scegli squadra»)
8. `MatchesScreen.swift`: ogni `Text("…")` hardcoded → `L10n.t(...)`.
9. 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
10. Snackbar/alert hub → `matches.msg_*`.
11. Badge status riga partita → `match.status_*`.
12. Assicurare `.id(languageTick)` (o environment) su root Matches **e** sheet presentati.
### Fase D — Wizard
13. Localizzare step Partita / Trasmissione / Test rete + branding editor + color hue (`wizard.*`).
14. Errori validazione e CTA AVANTI/INDIETRO/INIZIA.
### Fase E — Broadcast
15. Overlay controlli, contentDescription, snackbar pausa/ripresa/regia.
16. Dialog termina diretta, set concluso, chiudi set, partita terminata (`broadcast.*`, `score.*`).
### Fase F — Versione e release
17. Bump `MARKETING_VERSION``2.0.4`, `CURRENT_PROJECT_VERSION``25` (o successivo se conflitto TestFlight).
18. Aggiornare `generate_xcodeproj.py` **e** `Info.plist`, poi `python3 generate_xcodeproj.py`.
19. `./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)
1. `cd native/ios && python3 generate_xcodeproj.py`
2. Build simulatore; login produzione.
3. Login: globo → English → label/errori/slogan in EN.
4. Matches: saluto, CTA, empty state in EN.
5. Apri «Change» / scegli squadra: titolo **«Choose team»** (non «Scegli squadra»).
6. Nuova partita / programma / elimina: tutto EN.
7. Wizard 3 step in EN.
8. (Se possibile) overlay diretta: dialog/termina in EN.
9. Kill app → riapri: lingua persistita.
10. Spot-check FR/DE/ES.
11. Release: `./scripts/build_ios_release.sh`
Test:
```bash
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)
1. **A** Catalogo stringhe completo (copiare da Android `values*`)
2. **C** Hub + sheet/dialog (fix «Scegli squadra» in EN)
3. **B** Slogan + globo Login
4. **D** Wizard
5. **E** Broadcast
6. **F** Versione `2.0.4` / `25` + build release
Quando AF sono chiusi, iOS è allineato ad Android **2.0.4-native** per UX multilingua e versioning store.