Creates the app skeleton and the seam everything else in the project hangs off: region-specific data lives in an asset file, not in code, so adding a region later is a new JSON file rather than a refactor. Notable choices: - applicationId and namespace are it.nuvolari.app rather than the doubled it.nuvolari.nuvolari that `flutter create` produces, with the Kotlin package and the iOS bundle identifiers moved to match. - SDK levels are pinned instead of inherited from `flutter.*`. Google Play requires API 36, and that is a release blocker rather than something to let a Flutter upgrade change silently. minSdk 24 is the highest floor the planned dependencies impose. - Riverpod and Dio-free for now, no code generation: see docs/stack-decisions.md. - Italian is the l10n source language, so app_it.arb is the template rather than a translation of an English original. The region parser rejects rather than repairs. An inverted bounding box, a map centre outside its own bounds, an unknown adapter name, a duplicate zone code or an empty attribution list all throw with the offending field named. Each of those would otherwise fail silently and visibly wrong: a swapped latitude and longitude renders the radar in the wrong place, an unknown adapter falling back to mock would show demo frames where live data was expected, and a missing attribution is a licence violation rather than a cosmetic gap. Tests run against the asset that actually ships and against a captured copy of the live ARPA CAP feed, so the eleven zone codes in the config are checked against the eleven the feed really emits rather than against a list retyped from documentation. Verified: dart format clean, flutter analyze 0 issues, 50 tests passing, flutter build appbundle --debug produces an AAB with applicationId it.nuvolari.app, minSdk 24, targetSdk 36. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
68 lines
2.3 KiB
Plaintext
68 lines
2.3 KiB
Plaintext
{
|
|
"@@locale": "it",
|
|
|
|
"appTitle": "Nuvolari",
|
|
"@appTitle": {
|
|
"description": "Application name, shown in the task switcher and the app bar"
|
|
},
|
|
|
|
"navRadar": "Radar",
|
|
"@navRadar": {
|
|
"description": "Bottom navigation label for the radar map"
|
|
},
|
|
"navForecast": "Previsioni",
|
|
"@navForecast": {
|
|
"description": "Bottom navigation label for the forecast"
|
|
},
|
|
"navAlerts": "Allerte",
|
|
"@navAlerts": {
|
|
"description": "Bottom navigation label for the official weather alerts"
|
|
},
|
|
|
|
"sourcesTitle": "Fonti e licenze",
|
|
"@sourcesTitle": {
|
|
"description": "Title of the screen listing data sources, licenses and the disclaimer"
|
|
},
|
|
"sourcesDisclaimerTitle": "App non ufficiale",
|
|
"@sourcesDisclaimerTitle": {
|
|
"description": "Heading of the disclaimer stating the app is independent"
|
|
},
|
|
"sourcesDisclaimerBody": "Nuvolari è un'app indipendente. Non è affiliata, approvata o gestita da Arpa Piemonte o dal Dipartimento della Protezione Civile. Per la protezione civile fanno sempre fede i canali ufficiali.",
|
|
"@sourcesDisclaimerBody": {
|
|
"description": "Disclaimer text. Must never be shortened in a way that drops the independence statement or the primacy of official channels."
|
|
},
|
|
|
|
"regionPiemonte": "Piemonte",
|
|
"@regionPiemonte": {
|
|
"description": "Display name of the Piedmont region"
|
|
},
|
|
|
|
"demoModeBanner": "Modalità dimostrativa: i dati radar sono di esempio",
|
|
"@demoModeBanner": {
|
|
"description": "Banner shown when the app runs on the mock radar source instead of live data"
|
|
},
|
|
"dataUnavailable": "Dati non disponibili",
|
|
"@dataUnavailable": {
|
|
"description": "Banner title shown when the radar manifest or frames cannot be loaded"
|
|
},
|
|
"dataAgeMinutes": "{minutes, plural, =0{Aggiornato ora} one{Aggiornato 1 minuto fa} other{Aggiornato {minutes} minuti fa}}",
|
|
"@dataAgeMinutes": {
|
|
"description": "How old the newest displayed radar frame is. Always shown next to radar imagery so stale data is never presented as current.",
|
|
"placeholders": {
|
|
"minutes": {
|
|
"type": "int",
|
|
"example": "12"
|
|
}
|
|
}
|
|
},
|
|
|
|
"loading": "Caricamento…",
|
|
"@loading": {
|
|
"description": "Generic loading indicator label"
|
|
},
|
|
"retry": "Riprova",
|
|
"@retry": {
|
|
"description": "Button label to retry a failed operation"
|
|
}
|
|
}
|