mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-12 00:40:28 +00:00
Add localization support for various UI elements and messages
- Integrated localization for alert dialogs, snack bars, and button labels in PacketLogScreen and SettingsScreen. - Updated location tracking service messages to use localized strings. - Enhanced ContactTile and DirectMessageSheet with localized text for user interactions. - Implemented localization in DrawingLayer and DrawingToolbar for map-related actions. - Updated SAR Update Sheet to utilize localized strings for user prompts and actions. - Ensured consistent use of localization across all relevant widgets and screens.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
/// Reusable location display widget with tap-to-show modal
|
||||
/// Shows coordinates in a compact format with ability to view all formats
|
||||
@@ -149,7 +150,7 @@ class LocationDisplay extends StatelessWidget {
|
||||
Clipboard.setData(ClipboardData(text: value));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('$label copied to clipboard'),
|
||||
content: Text(AppLocalizations.of(context)!.copiedToClipboard(label)),
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -11,6 +11,7 @@ import '../../providers/map_provider.dart';
|
||||
import 'direct_message_sheet.dart';
|
||||
import 'room_login_sheet.dart';
|
||||
import '../../utils/toast_logger.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
class ContactTile extends StatelessWidget {
|
||||
final Contact contact;
|
||||
@@ -359,7 +360,7 @@ class ContactTile extends StatelessWidget {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Delete Contact'),
|
||||
title: Text(AppLocalizations.of(context)!.deleteContact),
|
||||
content: Text(
|
||||
'Are you sure you want to delete "${contact.displayName}"?\n\n'
|
||||
'This will remove the contact from both the app and the companion radio device.',
|
||||
@@ -367,7 +368,7 @@ class ContactTile extends StatelessWidget {
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: const Text('Cancel'),
|
||||
child: Text(AppLocalizations.of(context)!.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
@@ -376,7 +377,7 @@ class ContactTile extends StatelessWidget {
|
||||
await _deleteContact(context, contact);
|
||||
},
|
||||
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
||||
child: const Text('Delete'),
|
||||
child: Text(AppLocalizations.of(context)!.delete),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -504,9 +505,9 @@ class ContactTile extends StatelessWidget {
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(text: contact.publicKeyHex));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Public key copied to clipboard'),
|
||||
duration: Duration(seconds: 2),
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.publicKeyCopied),
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -587,7 +588,7 @@ class ContactTile extends StatelessWidget {
|
||||
DefaultTabController.of(context).animateTo(2);
|
||||
},
|
||||
icon: const Icon(Icons.map, size: 18),
|
||||
label: const Text('View on Map'),
|
||||
label: Text(AppLocalizations.of(context)!.viewOnMap),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
),
|
||||
@@ -645,7 +646,7 @@ class ContactTile extends StatelessWidget {
|
||||
ToastLogger.info(context, 'Requesting telemetry from ${contact.displayName}...');
|
||||
},
|
||||
icon: const Icon(Icons.refresh, size: 18),
|
||||
label: const Text('Refresh'),
|
||||
label: Text(AppLocalizations.of(context)!.refresh),
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
),
|
||||
@@ -688,7 +689,7 @@ class ContactTile extends StatelessWidget {
|
||||
_showDirectMessageDialog(context, contact);
|
||||
},
|
||||
icon: const Icon(Icons.message),
|
||||
label: const Text('Send Direct Message'),
|
||||
label: Text(AppLocalizations.of(context)!.sendDirectMessage),
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
backgroundColor: _getTypeColor(contact.type, context),
|
||||
@@ -705,7 +706,7 @@ class ContactTile extends StatelessWidget {
|
||||
ToastLogger.info(context, 'Path reset for ${contact.displayName}. Next message will find a new route.');
|
||||
},
|
||||
icon: const Icon(Icons.route),
|
||||
label: const Text('Reset Path (Re-route)'),
|
||||
label: Text(AppLocalizations.of(context)!.resetPath),
|
||||
style: OutlinedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
side: BorderSide(color: _getTypeColor(contact.type, context)),
|
||||
@@ -742,7 +743,7 @@ class ContactTile extends StatelessWidget {
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: () => _showDeleteConfirmation(context, contact),
|
||||
icon: const Icon(Icons.delete_outline),
|
||||
label: const Text('Delete Contact'),
|
||||
label: Text(AppLocalizations.of(context)!.deleteContact),
|
||||
style: OutlinedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
side: const BorderSide(color: Colors.red),
|
||||
@@ -803,7 +804,7 @@ class ContactTile extends StatelessWidget {
|
||||
Clipboard.setData(ClipboardData(text: value));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('$label copied to clipboard'),
|
||||
content: Text(AppLocalizations.of(context)!.copiedToClipboard(label)),
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -7,6 +7,7 @@ import '../../models/message.dart';
|
||||
import '../../providers/connection_provider.dart';
|
||||
import '../../providers/messages_provider.dart';
|
||||
import '../../utils/toast_logger.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
class DirectMessageSheet extends StatefulWidget {
|
||||
final Contact contact;
|
||||
@@ -51,7 +52,7 @@ class _DirectMessageSheetState extends State<DirectMessageSheet> {
|
||||
|
||||
if (!connectionProvider.deviceInfo.isConnected) {
|
||||
if (!mounted) return;
|
||||
ToastLogger.error(context, 'Not connected to device');
|
||||
ToastLogger.error(context, AppLocalizations.of(context)!.notConnectedToDevice);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -100,10 +101,10 @@ class _DirectMessageSheetState extends State<DirectMessageSheet> {
|
||||
if (!mounted) return;
|
||||
Navigator.pop(context); // Close the dialog
|
||||
|
||||
ToastLogger.success(context, 'Direct message sent to ${widget.contact.displayName}');
|
||||
ToastLogger.success(context, AppLocalizations.of(context)!.directMessageSentTo(widget.contact.displayName));
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
ToastLogger.error(context, 'Failed to send: $e');
|
||||
ToastLogger.error(context, AppLocalizations.of(context)!.failedToSend(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +138,7 @@ class _DirectMessageSheetState extends State<DirectMessageSheet> {
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
'Direct Message',
|
||||
AppLocalizations.of(context)!.directMessage,
|
||||
style: TextStyle(
|
||||
color: colorScheme.onSurface,
|
||||
fontSize: 18,
|
||||
@@ -173,7 +174,7 @@ class _DirectMessageSheetState extends State<DirectMessageSheet> {
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'This message will be sent directly to ${widget.contact.displayName}. It will also appear in the main messages feed.',
|
||||
AppLocalizations.of(context)!.directMessageInfo(widget.contact.displayName),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||
fontSize: 13,
|
||||
@@ -210,7 +211,7 @@ class _DirectMessageSheetState extends State<DirectMessageSheet> {
|
||||
maxLengthEnforcement: MaxLengthEnforcement.enforced,
|
||||
style: TextStyle(color: colorScheme.onSurface),
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Type your message...',
|
||||
hintText: AppLocalizations.of(context)!.typeYourMessage,
|
||||
hintStyle: TextStyle(color: colorScheme.onSurfaceVariant),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
@@ -246,7 +247,7 @@ class _DirectMessageSheetState extends State<DirectMessageSheet> {
|
||||
? null
|
||||
: _sendDirectMessage,
|
||||
icon: const Icon(Icons.send),
|
||||
label: const Text('Send Direct Message'),
|
||||
label: Text(AppLocalizations.of(context)!.sendDirectMessage),
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
backgroundColor: colorScheme.primary,
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../../models/contact.dart';
|
||||
import '../../providers/connection_provider.dart';
|
||||
import '../../providers/contacts_provider.dart';
|
||||
@@ -62,7 +63,7 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: const Text('Please enter a password'),
|
||||
content: Text(AppLocalizations.of(context)!.pleaseEnterPassword),
|
||||
backgroundColor: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
);
|
||||
@@ -73,7 +74,7 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: const Text('Not connected to device'),
|
||||
content: Text(AppLocalizations.of(context)!.deviceNotConnected),
|
||||
backgroundColor: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
);
|
||||
@@ -183,7 +184,7 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Failed to sync contacts: $e'),
|
||||
content: Text(AppLocalizations.of(context)!.failedToSyncContacts(e.toString())),
|
||||
backgroundColor: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
);
|
||||
@@ -215,7 +216,7 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: const Text('Logged in successfully! Waiting for room messages...'),
|
||||
content: Text(AppLocalizations.of(context)!.loggedInSuccessfully),
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
duration: const Duration(seconds: 3),
|
||||
),
|
||||
@@ -233,7 +234,7 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: const Text('Login failed - incorrect password'),
|
||||
content: Text(AppLocalizations.of(context)!.loginFailed),
|
||||
backgroundColor: Theme.of(context).colorScheme.error,
|
||||
duration: const Duration(seconds: 3),
|
||||
),
|
||||
@@ -255,7 +256,7 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Logging in to ${widget.contact.displayName}...'),
|
||||
content: Text(AppLocalizations.of(context)!.loggingIn(widget.contact.displayName)),
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
@@ -268,7 +269,7 @@ class _RoomLoginSheetState extends State<RoomLoginSheet> {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Failed to send login: $e'),
|
||||
content: Text(AppLocalizations.of(context)!.failedToSendLogin(e.toString())),
|
||||
backgroundColor: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import '../../models/map_drawing.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
/// Widget that renders map drawings as polylines
|
||||
class DrawingLayer extends StatelessWidget {
|
||||
@@ -212,14 +213,14 @@ class DrawingMarkersLayer extends StatelessWidget {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Delete Drawing'),
|
||||
title: Text(AppLocalizations.of(context)!.deleteDrawing),
|
||||
content: Text(
|
||||
'Delete this ${drawing.type.name}?',
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: const Text('Cancel'),
|
||||
child: Text(AppLocalizations.of(context)!.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
@@ -229,7 +230,7 @@ class DrawingMarkersLayer extends StatelessWidget {
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: Colors.red,
|
||||
),
|
||||
child: const Text('Delete'),
|
||||
child: Text(AppLocalizations.of(context)!.delete),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -7,6 +7,7 @@ import '../../providers/contacts_provider.dart';
|
||||
import '../../providers/messages_provider.dart';
|
||||
import '../../models/map_drawing.dart';
|
||||
import '../../models/contact.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
/// Toolbar for drawing controls on the map
|
||||
class DrawingToolbar extends StatelessWidget {
|
||||
@@ -53,7 +54,7 @@ class DrawingToolbar extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
_getTitleForMode(drawingProvider.drawingMode),
|
||||
_getTitleForMode(drawingProvider.drawingMode, context),
|
||||
style: Theme.of(context).textTheme.titleSmall?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
@@ -119,7 +120,7 @@ class DrawingToolbar extends StatelessWidget {
|
||||
IconButton(
|
||||
icon: const Icon(Icons.undo),
|
||||
onPressed: () => drawingProvider.cancelCurrentDrawing(),
|
||||
tooltip: 'Cancel',
|
||||
tooltip: AppLocalizations.of(context)!.cancel,
|
||||
iconSize: 20,
|
||||
padding: const EdgeInsets.all(4),
|
||||
constraints: const BoxConstraints(),
|
||||
@@ -184,8 +185,8 @@ class DrawingToolbar extends StatelessWidget {
|
||||
const Divider(),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.show_chart),
|
||||
title: const Text('Draw Line'),
|
||||
subtitle: const Text('Draw a freehand line on the map'),
|
||||
title: Text(AppLocalizations.of(context)!.drawLine),
|
||||
subtitle: Text(AppLocalizations.of(context)!.drawLineDesc),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
drawingProvider.setDrawingMode(DrawingMode.line);
|
||||
@@ -193,8 +194,8 @@ class DrawingToolbar extends StatelessWidget {
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.crop_square),
|
||||
title: const Text('Draw Rectangle'),
|
||||
subtitle: const Text('Draw a rectangular area on the map'),
|
||||
title: Text(AppLocalizations.of(context)!.drawRectangle),
|
||||
subtitle: Text(AppLocalizations.of(context)!.drawRectangleDesc),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
drawingProvider.setDrawingMode(DrawingMode.rectangle);
|
||||
@@ -204,7 +205,7 @@ class DrawingToolbar extends StatelessWidget {
|
||||
const Divider(),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.share, color: Colors.blue),
|
||||
title: const Text('Share Drawings'),
|
||||
title: Text(AppLocalizations.of(context)!.shareDrawings),
|
||||
subtitle: Text(
|
||||
'Broadcast ${drawingProvider.drawings.length} drawings to team',
|
||||
),
|
||||
@@ -220,7 +221,7 @@ class DrawingToolbar extends StatelessWidget {
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.delete_sweep, color: Colors.red),
|
||||
title: const Text('Clear All Drawings'),
|
||||
title: Text(AppLocalizations.of(context)!.clearAllDrawings),
|
||||
subtitle: Text(
|
||||
'Remove all ${drawingProvider.drawings.length} drawings',
|
||||
),
|
||||
@@ -244,14 +245,14 @@ class DrawingToolbar extends StatelessWidget {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Clear All Drawings'),
|
||||
title: Text(AppLocalizations.of(context)!.clearAllDrawings),
|
||||
content: Text(
|
||||
'Delete all ${drawingProvider.drawings.length} drawings from the map?',
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: const Text('Cancel'),
|
||||
child: Text(AppLocalizations.of(context)!.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
@@ -259,7 +260,7 @@ class DrawingToolbar extends StatelessWidget {
|
||||
drawingProvider.clearAllDrawings();
|
||||
},
|
||||
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
||||
child: const Text('Clear All'),
|
||||
child: Text(AppLocalizations.of(context)!.clearAll),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -279,12 +280,12 @@ class DrawingToolbar extends StatelessWidget {
|
||||
}
|
||||
|
||||
/// Get title for drawing mode
|
||||
String _getTitleForMode(DrawingMode mode) {
|
||||
String _getTitleForMode(DrawingMode mode, BuildContext context) {
|
||||
switch (mode) {
|
||||
case DrawingMode.line:
|
||||
return 'Draw Line';
|
||||
return AppLocalizations.of(context)!.drawLine;
|
||||
case DrawingMode.rectangle:
|
||||
return 'Draw Rectangle';
|
||||
return AppLocalizations.of(context)!.drawRectangle;
|
||||
case DrawingMode.none:
|
||||
return 'Drawing';
|
||||
}
|
||||
@@ -321,8 +322,8 @@ class DrawingToolbar extends StatelessWidget {
|
||||
|
||||
if (!connectionProvider.deviceInfo.isConnected) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Not connected to device'),
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.deviceNotConnected),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
@@ -342,8 +343,8 @@ class DrawingToolbar extends StatelessWidget {
|
||||
|
||||
if (localDrawings.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('No local drawings to share'),
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.noLocalDrawings),
|
||||
backgroundColor: Colors.orange,
|
||||
),
|
||||
);
|
||||
@@ -384,8 +385,8 @@ class DrawingToolbar extends StatelessWidget {
|
||||
// Option: Send to Public Channel
|
||||
ListTile(
|
||||
leading: const Icon(Icons.public, color: Colors.blue),
|
||||
title: const Text('Public Channel'),
|
||||
subtitle: const Text('Broadcast to all nearby nodes (ephemeral)'),
|
||||
title: Text(AppLocalizations.of(context)!.publicChannel),
|
||||
subtitle: Text(AppLocalizations.of(context)!.broadcastToAll),
|
||||
onTap: () async {
|
||||
debugPrint('📤 [DrawingToolbar] Public Channel tapped');
|
||||
// Share BEFORE popping the navigator
|
||||
@@ -406,7 +407,7 @@ class DrawingToolbar extends StatelessWidget {
|
||||
(room) => ListTile(
|
||||
leading: const Icon(Icons.meeting_room, color: Colors.green),
|
||||
title: Text(room.advName),
|
||||
subtitle: const Text('Stored permanently in room'),
|
||||
subtitle: Text(AppLocalizations.of(context)!.storedPermanently),
|
||||
onTap: () async {
|
||||
debugPrint('📤 [DrawingToolbar] Room ${room.advName} tapped');
|
||||
// Share BEFORE popping the navigator
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import '../models/contact.dart';
|
||||
import '../models/sar_marker.dart';
|
||||
import '../l10n/app_localizations.dart';
|
||||
|
||||
class MapMarkers {
|
||||
static List<Marker> createTeamMemberMarkers(
|
||||
@@ -238,7 +239,7 @@ class MapMarkers {
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: const Text('Close'),
|
||||
child: Text(AppLocalizations.of(context)!.close),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -272,7 +273,7 @@ class MapMarkers {
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: const Text('Close'),
|
||||
child: Text(AppLocalizations.of(context)!.close),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -6,6 +6,7 @@ import '../../providers/contacts_provider.dart';
|
||||
import '../../models/contact.dart';
|
||||
import '../../models/sar_marker.dart';
|
||||
import '../../services/validation_service.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
/// SAR Update Sheet - Modal bottom sheet for creating and sending SAR markers
|
||||
/// This widget is public so it can be used from both messages_tab.dart and map_tab.dart
|
||||
@@ -167,7 +168,7 @@ class _SarUpdateSheetState extends State<SarUpdateSheet> {
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
'Send SAR Marker',
|
||||
AppLocalizations.of(context)!.sendSarMarker,
|
||||
style: TextStyle(
|
||||
color: colorScheme.onSurface,
|
||||
fontSize: 18,
|
||||
@@ -645,7 +646,7 @@ class _SarUpdateSheetState extends State<SarUpdateSheet> {
|
||||
final shouldContinue = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Low Location Accuracy'),
|
||||
title: Text(AppLocalizations.of(context)!.lowLocationAccuracy),
|
||||
content: Text(
|
||||
'Location accuracy is ±${_currentPosition!.accuracy!.round()}m. '
|
||||
'This may not be accurate enough for SAR operations.\n\n'
|
||||
@@ -654,11 +655,11 @@ class _SarUpdateSheetState extends State<SarUpdateSheet> {
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, false),
|
||||
child: const Text('Cancel'),
|
||||
child: Text(AppLocalizations.of(context)!.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
child: const Text('Continue'),
|
||||
child: Text(AppLocalizations.of(context)!.continue_),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -688,9 +689,9 @@ class _SarUpdateSheetState extends State<SarUpdateSheet> {
|
||||
),
|
||||
),
|
||||
icon: const Icon(Icons.send, size: 20),
|
||||
label: const Text(
|
||||
'Send SAR Marker',
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
|
||||
label: Text(
|
||||
AppLocalizations.of(context)!.sendSarMarker,
|
||||
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user