diff --git a/lib/localizations/de.json b/lib/localizations/de.json index 44b572b..16d8e54 100644 --- a/lib/localizations/de.json +++ b/lib/localizations/de.json @@ -176,5 +176,40 @@ "mapTiles": { "title": "Karten-Kacheln", "manageProviders": "Anbieter Verwalten" + }, + "profileEditor": { + "viewProfile": "Profil Anzeigen", + "newProfile": "Neues Profil", + "editProfile": "Profil Bearbeiten", + "profileName": "Profil-Name", + "profileNameHint": "z.B. Benutzerdefinierte ALPR-Kamera", + "profileNameRequired": "Profil-Name ist erforderlich", + "requiresDirection": "Benötigt Richtung", + "requiresDirectionSubtitle": "Ob Kameras dieses Typs ein Richtungs-Tag benötigen", + "submittable": "Übertragbar", + "submittableSubtitle": "Ob dieses Profil für Kamera-Übertragungen verwendet werden kann", + "osmTags": "OSM-Tags", + "addTag": "Tag Hinzufügen", + "saveProfile": "Profil Speichern", + "keyHint": "Schlüssel", + "valueHint": "Wert", + "atLeastOneTagRequired": "Mindestens ein Tag ist erforderlich", + "profileSaved": "Profil \"{}\" gespeichert" + }, + "operatorProfileEditor": { + "newOperatorProfile": "Neues Betreiber-Profil", + "editOperatorProfile": "Betreiber-Profil Bearbeiten", + "operatorName": "Betreiber-Name", + "operatorNameHint": "z.B. Polizei Austin", + "operatorNameRequired": "Betreiber-Name ist erforderlich", + "operatorProfileSaved": "Betreiber-Profil \"{}\" gespeichert" + }, + "operatorProfiles": { + "title": "Betreiber-Profile", + "noProfilesMessage": "Keine Betreiber-Profile definiert. Erstellen Sie eines, um Betreiber-Tags auf Knoten-Übertragungen anzuwenden.", + "tagsCount": "{} Tags", + "deleteOperatorProfile": "Betreiber-Profil Löschen", + "deleteOperatorProfileConfirm": "Sind Sie sicher, dass Sie \"{}\" löschen möchten?", + "operatorProfileDeleted": "Betreiber-Profil gelöscht" } } \ No newline at end of file diff --git a/lib/localizations/en.json b/lib/localizations/en.json index c462848..0ef7594 100644 --- a/lib/localizations/en.json +++ b/lib/localizations/en.json @@ -176,5 +176,40 @@ "mapTiles": { "title": "Map Tiles", "manageProviders": "Manage Providers" + }, + "profileEditor": { + "viewProfile": "View Profile", + "newProfile": "New Profile", + "editProfile": "Edit Profile", + "profileName": "Profile name", + "profileNameHint": "e.g., Custom ALPR Camera", + "profileNameRequired": "Profile name is required", + "requiresDirection": "Requires Direction", + "requiresDirectionSubtitle": "Whether cameras of this type need a direction tag", + "submittable": "Submittable", + "submittableSubtitle": "Whether this profile can be used for camera submissions", + "osmTags": "OSM Tags", + "addTag": "Add tag", + "saveProfile": "Save Profile", + "keyHint": "key", + "valueHint": "value", + "atLeastOneTagRequired": "At least one tag is required", + "profileSaved": "Profile \"{}\" saved" + }, + "operatorProfileEditor": { + "newOperatorProfile": "New Operator Profile", + "editOperatorProfile": "Edit Operator Profile", + "operatorName": "Operator name", + "operatorNameHint": "e.g., Austin Police Department", + "operatorNameRequired": "Operator name is required", + "operatorProfileSaved": "Operator profile \"{}\" saved" + }, + "operatorProfiles": { + "title": "Operator Profiles", + "noProfilesMessage": "No operator profiles defined. Create one to apply operator tags to node submissions.", + "tagsCount": "{} tags", + "deleteOperatorProfile": "Delete Operator Profile", + "deleteOperatorProfileConfirm": "Are you sure you want to delete \"{}\"?", + "operatorProfileDeleted": "Operator profile deleted" } } \ No newline at end of file diff --git a/lib/localizations/es.json b/lib/localizations/es.json index 486ed25..eb981f1 100644 --- a/lib/localizations/es.json +++ b/lib/localizations/es.json @@ -176,5 +176,40 @@ "mapTiles": { "title": "Tiles de Mapa", "manageProviders": "Gestionar Proveedores" + }, + "profileEditor": { + "viewProfile": "Ver Perfil", + "newProfile": "Nuevo Perfil", + "editProfile": "Editar Perfil", + "profileName": "Nombre del perfil", + "profileNameHint": "ej., Cámara ALPR Personalizada", + "profileNameRequired": "El nombre del perfil es requerido", + "requiresDirection": "Requiere Dirección", + "requiresDirectionSubtitle": "Si las cámaras de este tipo necesitan una etiqueta de dirección", + "submittable": "Envíable", + "submittableSubtitle": "Si este perfil puede usarse para envíos de cámaras", + "osmTags": "Etiquetas OSM", + "addTag": "Agregar Etiqueta", + "saveProfile": "Guardar Perfil", + "keyHint": "clave", + "valueHint": "valor", + "atLeastOneTagRequired": "Se requiere al menos una etiqueta", + "profileSaved": "Perfil \"{}\" guardado" + }, + "operatorProfileEditor": { + "newOperatorProfile": "Nuevo Perfil de Operador", + "editOperatorProfile": "Editar Perfil de Operador", + "operatorName": "Nombre del operador", + "operatorNameHint": "ej., Departamento de Policía de Austin", + "operatorNameRequired": "El nombre del operador es requerido", + "operatorProfileSaved": "Perfil de operador \"{}\" guardado" + }, + "operatorProfiles": { + "title": "Perfiles de Operador", + "noProfilesMessage": "No hay perfiles de operador definidos. Cree uno para aplicar etiquetas de operador a los envíos de nodos.", + "tagsCount": "{} etiquetas", + "deleteOperatorProfile": "Eliminar Perfil de Operador", + "deleteOperatorProfileConfirm": "¿Está seguro de que desea eliminar \"{}\"?", + "operatorProfileDeleted": "Perfil de operador eliminado" } } \ No newline at end of file diff --git a/lib/localizations/fr.json b/lib/localizations/fr.json index cd512e9..08c2843 100644 --- a/lib/localizations/fr.json +++ b/lib/localizations/fr.json @@ -176,5 +176,40 @@ "mapTiles": { "title": "Tuiles de Carte", "manageProviders": "Gérer Fournisseurs" + }, + "profileEditor": { + "viewProfile": "Voir Profil", + "newProfile": "Nouveau Profil", + "editProfile": "Modifier Profil", + "profileName": "Nom du profil", + "profileNameHint": "ex., Caméra ALPR Personnalisée", + "profileNameRequired": "Le nom du profil est requis", + "requiresDirection": "Nécessite Direction", + "requiresDirectionSubtitle": "Si les caméras de ce type ont besoin d'une balise de direction", + "submittable": "Soumissible", + "submittableSubtitle": "Si ce profil peut être utilisé pour les soumissions de caméras", + "osmTags": "Balises OSM", + "addTag": "Ajouter Balise", + "saveProfile": "Sauvegarder Profil", + "keyHint": "clé", + "valueHint": "valeur", + "atLeastOneTagRequired": "Au moins une balise est requise", + "profileSaved": "Profil \"{}\" sauvegardé" + }, + "operatorProfileEditor": { + "newOperatorProfile": "Nouveau Profil d'Opérateur", + "editOperatorProfile": "Modifier Profil d'Opérateur", + "operatorName": "Nom de l'opérateur", + "operatorNameHint": "ex., Département de Police d'Austin", + "operatorNameRequired": "Le nom de l'opérateur est requis", + "operatorProfileSaved": "Profil d'opérateur \"{}\" sauvegardé" + }, + "operatorProfiles": { + "title": "Profils d'Opérateur", + "noProfilesMessage": "Aucun profil d'opérateur défini. Créez-en un pour appliquer des balises d'opérateur aux soumissions de nœuds.", + "tagsCount": "{} balises", + "deleteOperatorProfile": "Supprimer Profil d'Opérateur", + "deleteOperatorProfileConfirm": "Êtes-vous sûr de vouloir supprimer \"{}\"?", + "operatorProfileDeleted": "Profil d'opérateur supprimé" } } \ No newline at end of file diff --git a/lib/screens/operator_profile_editor.dart b/lib/screens/operator_profile_editor.dart index 1b62be5..45e1fab 100644 --- a/lib/screens/operator_profile_editor.dart +++ b/lib/screens/operator_profile_editor.dart @@ -4,6 +4,7 @@ import 'package:uuid/uuid.dart'; import '../models/operator_profile.dart'; import '../app_state.dart'; +import '../services/localization_service.dart'; class OperatorProfileEditor extends StatefulWidget { const OperatorProfileEditor({super.key, required this.profile}); @@ -45,46 +46,55 @@ class _OperatorProfileEditorState extends State { @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.profile.name.isEmpty ? 'New Operator Profile' : 'Edit Operator Profile'), - ), - body: ListView( - padding: const EdgeInsets.all(16), - children: [ - TextField( - controller: _nameCtrl, - decoration: const InputDecoration( - labelText: 'Operator name', - hintText: 'e.g., Austin Police Department', - ), + return AnimatedBuilder( + animation: LocalizationService.instance, + builder: (context, child) { + final locService = LocalizationService.instance; + + return Scaffold( + appBar: AppBar( + title: Text(widget.profile.name.isEmpty ? locService.t('operatorProfileEditor.newOperatorProfile') : locService.t('operatorProfileEditor.editOperatorProfile')), ), - const SizedBox(height: 24), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + body: ListView( + padding: const EdgeInsets.all(16), children: [ - const Text('OSM Tags', - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16)), - TextButton.icon( - onPressed: () => setState(() => _tags.add(const MapEntry('', ''))), - icon: const Icon(Icons.add), - label: const Text('Add tag'), + TextField( + controller: _nameCtrl, + decoration: InputDecoration( + labelText: locService.t('operatorProfileEditor.operatorName'), + hintText: locService.t('operatorProfileEditor.operatorNameHint'), + ), + ), + const SizedBox(height: 24), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(locService.t('profileEditor.osmTags'), + style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16)), + TextButton.icon( + onPressed: () => setState(() => _tags.add(const MapEntry('', ''))), + icon: const Icon(Icons.add), + label: Text(locService.t('profileEditor.addTag')), + ), + ], + ), + const SizedBox(height: 8), + ..._buildTagRows(), + const SizedBox(height: 24), + ElevatedButton( + onPressed: _save, + child: Text(locService.t('profileEditor.saveProfile')), ), ], ), - const SizedBox(height: 8), - ..._buildTagRows(), - const SizedBox(height: 24), - ElevatedButton( - onPressed: _save, - child: const Text('Save Profile'), - ), - ], - ), + ); + }, ); } List _buildTagRows() { + final locService = LocalizationService.instance; + return List.generate(_tags.length, (i) { final keyController = TextEditingController(text: _tags[i].key); final valueController = TextEditingController(text: _tags[i].value); @@ -96,9 +106,9 @@ class _OperatorProfileEditorState extends State { Expanded( flex: 2, child: TextField( - decoration: const InputDecoration( - hintText: 'key', - border: OutlineInputBorder(), + decoration: InputDecoration( + hintText: locService.t('profileEditor.keyHint'), + border: const OutlineInputBorder(), isDense: true, ), controller: keyController, @@ -109,9 +119,9 @@ class _OperatorProfileEditorState extends State { Expanded( flex: 3, child: TextField( - decoration: const InputDecoration( - hintText: 'value', - border: OutlineInputBorder(), + decoration: InputDecoration( + hintText: locService.t('profileEditor.valueHint'), + border: const OutlineInputBorder(), isDense: true, ), controller: valueController, @@ -129,10 +139,12 @@ class _OperatorProfileEditorState extends State { } void _save() { + final locService = LocalizationService.instance; final name = _nameCtrl.text.trim(); + if (name.isEmpty) { ScaffoldMessenger.of(context) - .showSnackBar(const SnackBar(content: Text('Operator name is required'))); + .showSnackBar(SnackBar(content: Text(locService.t('operatorProfileEditor.operatorNameRequired')))); return; } @@ -152,7 +164,7 @@ class _OperatorProfileEditorState extends State { Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Operator profile "${newProfile.name}" saved')), + SnackBar(content: Text(locService.t('operatorProfileEditor.operatorProfileSaved', params: [newProfile.name]))), ); } } \ No newline at end of file diff --git a/lib/screens/profile_editor.dart b/lib/screens/profile_editor.dart index 74f0609..ffdb4b6 100644 --- a/lib/screens/profile_editor.dart +++ b/lib/screens/profile_editor.dart @@ -4,6 +4,7 @@ import 'package:uuid/uuid.dart'; import '../models/node_profile.dart'; import '../app_state.dart'; +import '../services/localization_service.dart'; class ProfileEditor extends StatefulWidget { const ProfileEditor({super.key, required this.profile}); @@ -54,68 +55,77 @@ class _ProfileEditorState extends State { @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(!widget.profile.editable - ? 'View Profile' - : (widget.profile.name.isEmpty ? 'New Profile' : 'Edit Profile')), - ), - body: ListView( - padding: const EdgeInsets.all(16), - children: [ - TextField( - controller: _nameCtrl, - readOnly: !widget.profile.editable, - decoration: const InputDecoration( - labelText: 'Profile name', - hintText: 'e.g., Custom ALPR Camera', - ), + return AnimatedBuilder( + animation: LocalizationService.instance, + builder: (context, child) { + final locService = LocalizationService.instance; + + return Scaffold( + appBar: AppBar( + title: Text(!widget.profile.editable + ? locService.t('profileEditor.viewProfile') + : (widget.profile.name.isEmpty ? locService.t('profileEditor.newProfile') : locService.t('profileEditor.editProfile'))), ), - const SizedBox(height: 16), - if (widget.profile.editable) ...[ - CheckboxListTile( - title: const Text('Requires Direction'), - subtitle: const Text('Whether cameras of this type need a direction tag'), - value: _requiresDirection, - onChanged: (value) => setState(() => _requiresDirection = value ?? true), - controlAffinity: ListTileControlAffinity.leading, - ), - CheckboxListTile( - title: const Text('Submittable'), - subtitle: const Text('Whether this profile can be used for camera submissions'), - value: _submittable, - onChanged: (value) => setState(() => _submittable = value ?? true), - controlAffinity: ListTileControlAffinity.leading, - ), - ], - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text('OSM Tags', - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16)), - if (widget.profile.editable) - TextButton.icon( - onPressed: () => setState(() => _tags.add(const MapEntry('', ''))), - icon: const Icon(Icons.add), - label: const Text('Add tag'), - ), + body: ListView( + padding: const EdgeInsets.all(16), + children: [ + TextField( + controller: _nameCtrl, + readOnly: !widget.profile.editable, + decoration: InputDecoration( + labelText: locService.t('profileEditor.profileName'), + hintText: locService.t('profileEditor.profileNameHint'), + ), + ), + const SizedBox(height: 16), + if (widget.profile.editable) ...[ + CheckboxListTile( + title: Text(locService.t('profileEditor.requiresDirection')), + subtitle: Text(locService.t('profileEditor.requiresDirectionSubtitle')), + value: _requiresDirection, + onChanged: (value) => setState(() => _requiresDirection = value ?? true), + controlAffinity: ListTileControlAffinity.leading, + ), + CheckboxListTile( + title: Text(locService.t('profileEditor.submittable')), + subtitle: Text(locService.t('profileEditor.submittableSubtitle')), + value: _submittable, + onChanged: (value) => setState(() => _submittable = value ?? true), + controlAffinity: ListTileControlAffinity.leading, + ), ], - ), - const SizedBox(height: 8), - ..._buildTagRows(), - const SizedBox(height: 24), - if (widget.profile.editable) - ElevatedButton( - onPressed: _save, - child: const Text('Save Profile'), - ), - ], - ), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(locService.t('profileEditor.osmTags'), + style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16)), + if (widget.profile.editable) + TextButton.icon( + onPressed: () => setState(() => _tags.add(const MapEntry('', ''))), + icon: const Icon(Icons.add), + label: Text(locService.t('profileEditor.addTag')), + ), + ], + ), + const SizedBox(height: 8), + ..._buildTagRows(), + const SizedBox(height: 24), + if (widget.profile.editable) + ElevatedButton( + onPressed: _save, + child: Text(locService.t('profileEditor.saveProfile')), + ), + ], + ), + ); + }, ); } List _buildTagRows() { + final locService = LocalizationService.instance; + return List.generate(_tags.length, (i) { final keyController = TextEditingController(text: _tags[i].key); final valueController = TextEditingController(text: _tags[i].value); @@ -127,9 +137,9 @@ class _ProfileEditorState extends State { Expanded( flex: 2, child: TextField( - decoration: const InputDecoration( - hintText: 'key', - border: OutlineInputBorder(), + decoration: InputDecoration( + hintText: locService.t('profileEditor.keyHint'), + border: const OutlineInputBorder(), isDense: true, ), controller: keyController, @@ -143,9 +153,9 @@ class _ProfileEditorState extends State { Expanded( flex: 3, child: TextField( - decoration: const InputDecoration( - hintText: 'value', - border: OutlineInputBorder(), + decoration: InputDecoration( + hintText: locService.t('profileEditor.valueHint'), + border: const OutlineInputBorder(), isDense: true, ), controller: valueController, @@ -167,10 +177,12 @@ class _ProfileEditorState extends State { } void _save() { + final locService = LocalizationService.instance; final name = _nameCtrl.text.trim(); + if (name.isEmpty) { ScaffoldMessenger.of(context) - .showSnackBar(const SnackBar(content: Text('Profile name is required'))); + .showSnackBar(SnackBar(content: Text(locService.t('profileEditor.profileNameRequired')))); return; } @@ -182,7 +194,7 @@ class _ProfileEditorState extends State { if (tagMap.isEmpty) { ScaffoldMessenger.of(context) - .showSnackBar(const SnackBar(content: Text('At least one tag is required'))); + .showSnackBar(SnackBar(content: Text(locService.t('profileEditor.atLeastOneTagRequired')))); return; } @@ -200,7 +212,7 @@ class _ProfileEditorState extends State { Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Profile "${newProfile.name}" saved')), + SnackBar(content: Text(locService.t('profileEditor.profileSaved', params: [newProfile.name]))), ); } } diff --git a/lib/screens/settings_screen_sections/operator_profile_list_section.dart b/lib/screens/settings_screen_sections/operator_profile_list_section.dart index b1b500e..927d8e3 100644 --- a/lib/screens/settings_screen_sections/operator_profile_list_section.dart +++ b/lib/screens/settings_screen_sections/operator_profile_list_section.dart @@ -3,6 +3,7 @@ import 'package:uuid/uuid.dart'; import 'package:provider/provider.dart'; import '../../app_state.dart'; import '../../models/operator_profile.dart'; +import '../../services/localization_service.dart'; import '../operator_profile_editor.dart'; class OperatorProfileListSection extends StatelessWidget { @@ -10,110 +11,117 @@ class OperatorProfileListSection extends StatelessWidget { @override Widget build(BuildContext context) { - final appState = context.watch(); + return AnimatedBuilder( + animation: LocalizationService.instance, + builder: (context, child) { + final locService = LocalizationService.instance; + final appState = context.watch(); - return Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + return Column( children: [ - const Text('Operator Profiles', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), - TextButton.icon( - onPressed: () => Navigator.push( - context, - MaterialPageRoute( - builder: (_) => OperatorProfileEditor( - profile: OperatorProfile( - id: const Uuid().v4(), - name: '', - tags: const {}, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(locService.t('operatorProfiles.title'), style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), + TextButton.icon( + onPressed: () => Navigator.push( + context, + MaterialPageRoute( + builder: (_) => OperatorProfileEditor( + profile: OperatorProfile( + id: const Uuid().v4(), + name: '', + tags: const {}, + ), + ), ), ), + icon: const Icon(Icons.add), + label: Text(locService.t('profiles.newProfile')), + ), + ], + ), + if (appState.operatorProfiles.isEmpty) + Padding( + padding: const EdgeInsets.all(16.0), + child: Text( + locService.t('operatorProfiles.noProfilesMessage'), + style: const TextStyle(color: Colors.grey), + textAlign: TextAlign.center, + ), + ) + else + ...appState.operatorProfiles.map( + (p) => ListTile( + title: Text(p.name), + subtitle: Text(locService.t('operatorProfiles.tagsCount', params: [p.tags.length.toString()])), + trailing: PopupMenuButton( + itemBuilder: (context) => [ + PopupMenuItem( + value: 'edit', + child: Row( + children: [ + const Icon(Icons.edit), + const SizedBox(width: 8), + Text(locService.t('actions.edit')), + ], + ), + ), + PopupMenuItem( + value: 'delete', + child: Row( + children: [ + const Icon(Icons.delete, color: Colors.red), + const SizedBox(width: 8), + Text(locService.t('operatorProfiles.deleteOperatorProfile'), style: const TextStyle(color: Colors.red)), + ], + ), + ), + ], + onSelected: (value) { + if (value == 'edit') { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => OperatorProfileEditor(profile: p), + ), + ); + } else if (value == 'delete') { + _showDeleteProfileDialog(context, p); + } + }, + ), ), ), - icon: const Icon(Icons.add), - label: const Text('New Profile'), - ), ], - ), - if (appState.operatorProfiles.isEmpty) - const Padding( - padding: EdgeInsets.all(16.0), - child: Text( - 'No operator profiles defined. Create one to apply operator tags to node submissions.', - style: TextStyle(color: Colors.grey), - textAlign: TextAlign.center, - ), - ) - else - ...appState.operatorProfiles.map( - (p) => ListTile( - title: Text(p.name), - subtitle: Text('${p.tags.length} tags'), - trailing: PopupMenuButton( - itemBuilder: (context) => [ - PopupMenuItem( - value: 'edit', - child: const Row( - children: [ - Icon(Icons.edit), - SizedBox(width: 8), - Text('Edit'), - ], - ), - ), - PopupMenuItem( - value: 'delete', - child: const Row( - children: [ - Icon(Icons.delete, color: Colors.red), - SizedBox(width: 8), - Text('Delete', style: TextStyle(color: Colors.red)), - ], - ), - ), - ], - onSelected: (value) { - if (value == 'edit') { - Navigator.push( - context, - MaterialPageRoute( - builder: (_) => OperatorProfileEditor(profile: p), - ), - ); - } else if (value == 'delete') { - _showDeleteProfileDialog(context, p); - } - }, - ), - ), - ), - ], + ); + }, ); } void _showDeleteProfileDialog(BuildContext context, OperatorProfile profile) { + final locService = LocalizationService.instance; final appState = context.read(); showDialog( context: context, builder: (context) => AlertDialog( - title: const Text('Delete Operator Profile'), - content: Text('Are you sure you want to delete "${profile.name}"?'), + title: Text(locService.t('operatorProfiles.deleteOperatorProfile')), + content: Text(locService.t('operatorProfiles.deleteOperatorProfileConfirm', params: [profile.name])), actions: [ TextButton( onPressed: () => Navigator.pop(context), - child: const Text('Cancel'), + child: Text(locService.t('actions.cancel')), ), TextButton( onPressed: () { appState.deleteOperatorProfile(profile); Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('Operator profile deleted')), + SnackBar(content: Text(locService.t('operatorProfiles.operatorProfileDeleted'))), ); }, style: TextButton.styleFrom(foregroundColor: Colors.red), - child: const Text('Delete'), + child: Text(locService.t('operatorProfiles.deleteOperatorProfile')), ), ], ),