Notrufnummern-Datenbasis, Ländererkennung, State-Management und Lokalisierung (AP1-AP7)
Implementiert den kompletten Kern-Flow der Emergency App gemäß docs/plan.md: - Notrufnummern-Datenbasis für 199 Länder + Modelle/Repository (AP1) - DialerService für tel:-Notrufe ohne Auto-Dial (AP2) - Statisches UI mit Panik-Button-Fallback (AP3) - Priorisierte Ländererkennung: SIM/Netz -> GPS/Geocoding -> Cache (AP4) - EmergencyProvider verdrahtet Repository/LocationService mit der UI (AP5) - Manuelle Länderauswahl als Fallback samt eigener Priorität (AP6) - UI-Lokalisierung (de/en/fr/es), an erkanntes Land gekoppelt (AP7) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"@@locale": "de",
|
||||
"appTitle": "Notruf",
|
||||
"selectCountryButton": "Land manuell wählen",
|
||||
"retryButton": "Erneut versuchen",
|
||||
"errorGeneric": "Unbekannter Fehler beim Laden der Notrufnummern.",
|
||||
"countryUnknownMessage": "Land konnte nicht ermittelt werden.",
|
||||
"countryNotInDatabaseMessage": "Land nicht in der Notrufnummern-Datenbasis hinterlegt. Es steht nur der globale Notruf zur Verfügung.",
|
||||
"pickerTitle": "Land auswählen",
|
||||
"pickerSearchHint": "Land suchen",
|
||||
"pickerNoResults": "Kein Land gefunden.",
|
||||
"emergencyButtonSemanticLabel": "{label}, {number} anrufen"
|
||||
}
|
||||
+49
-1
@@ -1,3 +1,51 @@
|
||||
{
|
||||
"@@locale": "en"
|
||||
"@@locale": "en",
|
||||
"appTitle": "Emergency",
|
||||
"@appTitle": {
|
||||
"description": "AppBar title of the home screen"
|
||||
},
|
||||
"selectCountryButton": "Select country manually",
|
||||
"@selectCountryButton": {
|
||||
"description": "Label of the button/tooltip used to open the manual country picker"
|
||||
},
|
||||
"retryButton": "Try again",
|
||||
"@retryButton": {
|
||||
"description": "Label of the button that retries country/number detection after an error"
|
||||
},
|
||||
"errorGeneric": "Unknown error while loading the emergency numbers.",
|
||||
"@errorGeneric": {
|
||||
"description": "Fallback error message shown when the provider does not report a specific error"
|
||||
},
|
||||
"countryUnknownMessage": "Country could not be determined.",
|
||||
"@countryUnknownMessage": {
|
||||
"description": "Shown when the country could not be detected automatically (and no location permission info is shown separately)"
|
||||
},
|
||||
"countryNotInDatabaseMessage": "Country not listed in the emergency number database. Only the global emergency number is available.",
|
||||
"@countryNotInDatabaseMessage": {
|
||||
"description": "Shown when the detected country has no entry in the emergency number database"
|
||||
},
|
||||
"pickerTitle": "Select country",
|
||||
"@pickerTitle": {
|
||||
"description": "AppBar title of the manual country picker screen"
|
||||
},
|
||||
"pickerSearchHint": "Search country",
|
||||
"@pickerSearchHint": {
|
||||
"description": "Hint text of the search field in the manual country picker screen"
|
||||
},
|
||||
"pickerNoResults": "No country found.",
|
||||
"@pickerNoResults": {
|
||||
"description": "Empty state shown when the search filter matches no country"
|
||||
},
|
||||
"emergencyButtonSemanticLabel": "{label}, call {number}",
|
||||
"@emergencyButtonSemanticLabel": {
|
||||
"description": "Semantics/tooltip label of an emergency button, combining the number's label and the number itself",
|
||||
"placeholders": {
|
||||
"label": {
|
||||
"type": "String"
|
||||
},
|
||||
"number": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"@@locale": "es",
|
||||
"appTitle": "Emergencia",
|
||||
"selectCountryButton": "Elegir país manualmente",
|
||||
"retryButton": "Reintentar",
|
||||
"errorGeneric": "Error desconocido al cargar los números de emergencia.",
|
||||
"countryUnknownMessage": "No se pudo determinar el país.",
|
||||
"countryNotInDatabaseMessage": "País no disponible en la base de datos de números de emergencia. Solo está disponible el número de emergencia global.",
|
||||
"pickerTitle": "Seleccionar país",
|
||||
"pickerSearchHint": "Buscar país",
|
||||
"pickerNoResults": "No se encontró ningún país.",
|
||||
"emergencyButtonSemanticLabel": "{label}, llamar al {number}"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"@@locale": "fr",
|
||||
"appTitle": "Urgence",
|
||||
"selectCountryButton": "Choisir le pays manuellement",
|
||||
"retryButton": "Réessayer",
|
||||
"errorGeneric": "Erreur inconnue lors du chargement des numéros d'urgence.",
|
||||
"countryUnknownMessage": "Impossible de déterminer le pays.",
|
||||
"countryNotInDatabaseMessage": "Pays non répertorié dans la base de données des numéros d'urgence. Seul le numéro d'urgence global est disponible.",
|
||||
"pickerTitle": "Sélectionner un pays",
|
||||
"pickerSearchHint": "Rechercher un pays",
|
||||
"pickerNoResults": "Aucun pays trouvé.",
|
||||
"emergencyButtonSemanticLabel": "{label}, appeler le {number}"
|
||||
}
|
||||
@@ -5,7 +5,10 @@ import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
|
||||
import 'app_localizations_de.dart';
|
||||
import 'app_localizations_en.dart';
|
||||
import 'app_localizations_es.dart';
|
||||
import 'app_localizations_fr.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
@@ -92,7 +95,72 @@ abstract class AppLocalizations {
|
||||
];
|
||||
|
||||
/// A list of this localizations delegate's supported locales.
|
||||
static const List<Locale> supportedLocales = <Locale>[Locale('en')];
|
||||
static const List<Locale> supportedLocales = <Locale>[
|
||||
Locale('de'),
|
||||
Locale('en'),
|
||||
Locale('es'),
|
||||
Locale('fr'),
|
||||
];
|
||||
|
||||
/// AppBar title of the home screen
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Emergency'**
|
||||
String get appTitle;
|
||||
|
||||
/// Label of the button/tooltip used to open the manual country picker
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Select country manually'**
|
||||
String get selectCountryButton;
|
||||
|
||||
/// Label of the button that retries country/number detection after an error
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Try again'**
|
||||
String get retryButton;
|
||||
|
||||
/// Fallback error message shown when the provider does not report a specific error
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Unknown error while loading the emergency numbers.'**
|
||||
String get errorGeneric;
|
||||
|
||||
/// Shown when the country could not be detected automatically (and no location permission info is shown separately)
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Country could not be determined.'**
|
||||
String get countryUnknownMessage;
|
||||
|
||||
/// Shown when the detected country has no entry in the emergency number database
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Country not listed in the emergency number database. Only the global emergency number is available.'**
|
||||
String get countryNotInDatabaseMessage;
|
||||
|
||||
/// AppBar title of the manual country picker screen
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Select country'**
|
||||
String get pickerTitle;
|
||||
|
||||
/// Hint text of the search field in the manual country picker screen
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Search country'**
|
||||
String get pickerSearchHint;
|
||||
|
||||
/// Empty state shown when the search filter matches no country
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No country found.'**
|
||||
String get pickerNoResults;
|
||||
|
||||
/// Semantics/tooltip label of an emergency button, combining the number's label and the number itself
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{label}, call {number}'**
|
||||
String emergencyButtonSemanticLabel(String label, String number);
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate
|
||||
@@ -106,7 +174,7 @@ class _AppLocalizationsDelegate
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) =>
|
||||
<String>['en'].contains(locale.languageCode);
|
||||
<String>['de', 'en', 'es', 'fr'].contains(locale.languageCode);
|
||||
|
||||
@override
|
||||
bool shouldReload(_AppLocalizationsDelegate old) => false;
|
||||
@@ -115,8 +183,14 @@ class _AppLocalizationsDelegate
|
||||
AppLocalizations lookupAppLocalizations(Locale locale) {
|
||||
// Lookup logic when only language code is specified.
|
||||
switch (locale.languageCode) {
|
||||
case 'de':
|
||||
return AppLocalizationsDe();
|
||||
case 'en':
|
||||
return AppLocalizationsEn();
|
||||
case 'es':
|
||||
return AppLocalizationsEs();
|
||||
case 'fr':
|
||||
return AppLocalizationsFr();
|
||||
}
|
||||
|
||||
throw FlutterError(
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
// ignore: unused_import
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
import 'app_localizations.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
/// The translations for German (`de`).
|
||||
class AppLocalizationsDe extends AppLocalizations {
|
||||
AppLocalizationsDe([String locale = 'de']) : super(locale);
|
||||
|
||||
@override
|
||||
String get appTitle => 'Notruf';
|
||||
|
||||
@override
|
||||
String get selectCountryButton => 'Land manuell wählen';
|
||||
|
||||
@override
|
||||
String get retryButton => 'Erneut versuchen';
|
||||
|
||||
@override
|
||||
String get errorGeneric => 'Unbekannter Fehler beim Laden der Notrufnummern.';
|
||||
|
||||
@override
|
||||
String get countryUnknownMessage => 'Land konnte nicht ermittelt werden.';
|
||||
|
||||
@override
|
||||
String get countryNotInDatabaseMessage =>
|
||||
'Land nicht in der Notrufnummern-Datenbasis hinterlegt. Es steht nur der globale Notruf zur Verfügung.';
|
||||
|
||||
@override
|
||||
String get pickerTitle => 'Land auswählen';
|
||||
|
||||
@override
|
||||
String get pickerSearchHint => 'Land suchen';
|
||||
|
||||
@override
|
||||
String get pickerNoResults => 'Kein Land gefunden.';
|
||||
|
||||
@override
|
||||
String emergencyButtonSemanticLabel(String label, String number) {
|
||||
return '$label, $number anrufen';
|
||||
}
|
||||
}
|
||||
@@ -7,4 +7,38 @@ import 'app_localizations.dart';
|
||||
/// The translations for English (`en`).
|
||||
class AppLocalizationsEn extends AppLocalizations {
|
||||
AppLocalizationsEn([String locale = 'en']) : super(locale);
|
||||
|
||||
@override
|
||||
String get appTitle => 'Emergency';
|
||||
|
||||
@override
|
||||
String get selectCountryButton => 'Select country manually';
|
||||
|
||||
@override
|
||||
String get retryButton => 'Try again';
|
||||
|
||||
@override
|
||||
String get errorGeneric =>
|
||||
'Unknown error while loading the emergency numbers.';
|
||||
|
||||
@override
|
||||
String get countryUnknownMessage => 'Country could not be determined.';
|
||||
|
||||
@override
|
||||
String get countryNotInDatabaseMessage =>
|
||||
'Country not listed in the emergency number database. Only the global emergency number is available.';
|
||||
|
||||
@override
|
||||
String get pickerTitle => 'Select country';
|
||||
|
||||
@override
|
||||
String get pickerSearchHint => 'Search country';
|
||||
|
||||
@override
|
||||
String get pickerNoResults => 'No country found.';
|
||||
|
||||
@override
|
||||
String emergencyButtonSemanticLabel(String label, String number) {
|
||||
return '$label, call $number';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// ignore: unused_import
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
import 'app_localizations.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
/// The translations for Spanish Castilian (`es`).
|
||||
class AppLocalizationsEs extends AppLocalizations {
|
||||
AppLocalizationsEs([String locale = 'es']) : super(locale);
|
||||
|
||||
@override
|
||||
String get appTitle => 'Emergencia';
|
||||
|
||||
@override
|
||||
String get selectCountryButton => 'Elegir país manualmente';
|
||||
|
||||
@override
|
||||
String get retryButton => 'Reintentar';
|
||||
|
||||
@override
|
||||
String get errorGeneric =>
|
||||
'Error desconocido al cargar los números de emergencia.';
|
||||
|
||||
@override
|
||||
String get countryUnknownMessage => 'No se pudo determinar el país.';
|
||||
|
||||
@override
|
||||
String get countryNotInDatabaseMessage =>
|
||||
'País no disponible en la base de datos de números de emergencia. Solo está disponible el número de emergencia global.';
|
||||
|
||||
@override
|
||||
String get pickerTitle => 'Seleccionar país';
|
||||
|
||||
@override
|
||||
String get pickerSearchHint => 'Buscar país';
|
||||
|
||||
@override
|
||||
String get pickerNoResults => 'No se encontró ningún país.';
|
||||
|
||||
@override
|
||||
String emergencyButtonSemanticLabel(String label, String number) {
|
||||
return '$label, llamar al $number';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// ignore: unused_import
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
import 'app_localizations.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
/// The translations for French (`fr`).
|
||||
class AppLocalizationsFr extends AppLocalizations {
|
||||
AppLocalizationsFr([String locale = 'fr']) : super(locale);
|
||||
|
||||
@override
|
||||
String get appTitle => 'Urgence';
|
||||
|
||||
@override
|
||||
String get selectCountryButton => 'Choisir le pays manuellement';
|
||||
|
||||
@override
|
||||
String get retryButton => 'Réessayer';
|
||||
|
||||
@override
|
||||
String get errorGeneric =>
|
||||
'Erreur inconnue lors du chargement des numéros d\'urgence.';
|
||||
|
||||
@override
|
||||
String get countryUnknownMessage => 'Impossible de déterminer le pays.';
|
||||
|
||||
@override
|
||||
String get countryNotInDatabaseMessage =>
|
||||
'Pays non répertorié dans la base de données des numéros d\'urgence. Seul le numéro d\'urgence global est disponible.';
|
||||
|
||||
@override
|
||||
String get pickerTitle => 'Sélectionner un pays';
|
||||
|
||||
@override
|
||||
String get pickerSearchHint => 'Rechercher un pays';
|
||||
|
||||
@override
|
||||
String get pickerNoResults => 'Aucun pays trouvé.';
|
||||
|
||||
@override
|
||||
String emergencyButtonSemanticLabel(String label, String number) {
|
||||
return '$label, appeler le $number';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user