i18n: Add 247 missing translation keys across all 13 languages

Replace hardcoded English strings in 32 Dart source files with l10n
references. Covers settings labels, UI actions, map/SAR features,
device config, notifications, profiles, spectrum scan, and status
messages for sl, de, hr, pl, es, fr, it, el, ru, tr, uk, zh, pt.
This commit is contained in:
Janez T
2026-03-17 10:36:58 +01:00
parent bbd5d108cb
commit fa2b586ab7
70 changed files with 16366 additions and 742 deletions

View File

@@ -200,7 +200,7 @@ class _CustomMapSarUpdateSheetState extends State<CustomMapSarUpdateSheet> {
),
);
}),
const SizedBox(height: 24),
SizedBox(height: 24),
Text(
AppLocalizations.of(context)!.sendTo,
style: TextStyle(
@@ -231,7 +231,7 @@ class _CustomMapSarUpdateSheetState extends State<CustomMapSarUpdateSheet> {
color: Colors.red.withValues(alpha: 0.3),
),
),
child: const Text('No destinations available'),
child: Text(AppLocalizations.of(context)!.noDestinationsAvailableLabel),
);
}
@@ -426,7 +426,7 @@ class _CustomMapSarUpdateSheetState extends State<CustomMapSarUpdateSheet> {
(!_sendToAllContacts && _selectedContact == null)) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Select marker type and destination'),
content: Text(AppLocalizations.of(context)!.selectMarkerTypeAndDestination),
),
);
return;
@@ -449,8 +449,8 @@ class _CustomMapSarUpdateSheetState extends State<CustomMapSarUpdateSheet> {
Navigator.pop(context);
}
},
icon: const Icon(Icons.send),
label: const Text('Send'),
icon: Icon(Icons.send),
label: Text(AppLocalizations.of(context)!.send),
),
),
),

View File

@@ -288,7 +288,7 @@ class _MessageBubbleState extends State<MessageBubble> {
children: [
if (!isOwnMessage && widget.onReply != null)
ListTile(
leading: const Icon(Icons.reply),
leading: Icon(Icons.reply),
title: Text(AppLocalizations.of(context)!.reply),
onTap: () {
Navigator.pop(context);
@@ -297,7 +297,7 @@ class _MessageBubbleState extends State<MessageBubble> {
),
// Copy text option
ListTile(
leading: const Icon(Icons.copy),
leading: Icon(Icons.copy),
title: Text(AppLocalizations.of(context)!.copyText),
onTap: () {
Clipboard.setData(ClipboardData(text: widget.message.text));
@@ -329,7 +329,7 @@ class _MessageBubbleState extends State<MessageBubble> {
}
return ListTile(
leading: const Icon(Icons.bookmark_add),
leading: Icon(Icons.bookmark_add),
title: Text(AppLocalizations.of(context)!.saveAsTemplate),
onTap: () {
Navigator.pop(context);
@@ -342,7 +342,7 @@ class _MessageBubbleState extends State<MessageBubble> {
if (widget.message.isSarMarker &&
widget.message.sarGpsCoordinates != null)
ListTile(
leading: const Icon(Icons.share_location),
leading: Icon(Icons.share_location),
title: Text(AppLocalizations.of(context)!.shareLocation),
onTap: () {
Navigator.pop(context);
@@ -352,7 +352,7 @@ class _MessageBubbleState extends State<MessageBubble> {
// Navigate to drawing option (only for drawing messages)
if (widget.message.isDrawing && widget.message.drawingId != null)
ListTile(
leading: const Icon(Icons.map),
leading: Icon(Icons.map),
title: Text(AppLocalizations.of(context)!.navigateToDrawing),
onTap: () {
Navigator.pop(context);
@@ -362,7 +362,7 @@ class _MessageBubbleState extends State<MessageBubble> {
// Copy coordinates option (only for drawing messages)
if (widget.message.isDrawing && widget.message.drawingId != null)
ListTile(
leading: const Icon(Icons.copy),
leading: Icon(Icons.copy),
title: Text(AppLocalizations.of(context)!.copyCoordinates),
onTap: () {
Navigator.pop(context);
@@ -372,7 +372,7 @@ class _MessageBubbleState extends State<MessageBubble> {
// Hide from map option (only for drawing messages)
if (widget.message.isDrawing && widget.message.drawingId != null)
ListTile(
leading: const Icon(Icons.visibility_off),
leading: Icon(Icons.visibility_off),
title: Text(AppLocalizations.of(context)!.hideFromMap),
onTap: () {
Navigator.pop(context);
@@ -381,7 +381,7 @@ class _MessageBubbleState extends State<MessageBubble> {
),
// Technical details option
ListTile(
leading: const Icon(Icons.data_object),
leading: Icon(Icons.data_object),
title: Text(AppLocalizations.of(context)!.technicalDetails),
onTap: () {
Navigator.pop(context);
@@ -392,8 +392,8 @@ class _MessageBubbleState extends State<MessageBubble> {
widget.message.pathLen > 0 &&
widget.message.pathLen < 255)
ListTile(
leading: const Icon(Icons.route),
title: const Text('Trace'),
leading: Icon(Icons.route),
title: Text(AppLocalizations.of(context)!.trace),
onTap: () {
Navigator.pop(context);
_showTraceSheet(context);
@@ -401,7 +401,7 @@ class _MessageBubbleState extends State<MessageBubble> {
),
// Delete message option
ListTile(
leading: const Icon(Icons.delete, color: Colors.red),
leading: Icon(Icons.delete, color: Colors.red),
title: Text(
AppLocalizations.of(context)!.delete,
style: const TextStyle(color: Colors.red),
@@ -686,7 +686,7 @@ class _MessageBubbleState extends State<MessageBubble> {
void copyField(String value) {
Clipboard.setData(ClipboardData(text: value));
ToastLogger.success(context, l10n.textCopiedToClipboard);
ToastLogger.success(context, AppLocalizations.of(context)!.textCopiedToClipboard);
}
showModalBottomSheet(
@@ -708,14 +708,14 @@ class _MessageBubbleState extends State<MessageBubble> {
children: [
Expanded(
child: Text(
l10n.messageTechnicalDetails,
AppLocalizations.of(context)!.messageTechnicalDetails,
style: Theme.of(sheetContext).textTheme.titleLarge,
),
),
IconButton(
onPressed: () => Navigator.pop(sheetContext),
icon: const Icon(Icons.close),
tooltip: l10n.close,
icon: Icon(Icons.close),
tooltip: AppLocalizations.of(context)!.close,
),
],
),
@@ -758,17 +758,17 @@ class _MessageBubbleState extends State<MessageBubble> {
if (widget.message.lastEchoRssiDbm != null ||
snrDb != null ||
rssiDbm != null) ...[
const SizedBox(height: 12),
SizedBox(height: 12),
_techSection(
sheetContext,
icon: Icons.network_check,
title: l10n.linkQuality,
title: AppLocalizations.of(context)!.linkQuality,
child: Column(
children: [
if (rssiDbm != null)
_signalRow(
sheetContext,
label: 'RSSI',
label: AppLocalizations.of(context)!.rssi,
valueLabel: '$rssiDbm dBm',
normalized:
((rssiDbm.toDouble() + 120.0) / 70.0)
@@ -780,10 +780,10 @@ class _MessageBubbleState extends State<MessageBubble> {
: Colors.redAccent,
),
if (snrDb != null) ...[
const SizedBox(height: 8),
SizedBox(height: 8),
_signalRow(
sheetContext,
label: 'SNR',
label: AppLocalizations.of(context)!.snr,
valueLabel: '${snrDb.toStringAsFixed(1)} dB',
normalized: ((snrDb + 20.0) / 40.0).clamp(
0.0,
@@ -800,21 +800,21 @@ class _MessageBubbleState extends State<MessageBubble> {
),
),
],
const SizedBox(height: 12),
SizedBox(height: 12),
_techSection(
sheetContext,
icon: Icons.tune,
title: l10n.delivery,
title: AppLocalizations.of(context)!.delivery,
child: Column(
children: [
_detailRow(
sheetContext,
label: l10n.status,
label: AppLocalizations.of(context)!.status,
value: widget.message.deliveryStatus.name,
),
_detailRow(
sheetContext,
label: 'Received (RFC3339)',
label: AppLocalizations.of(context)!.receivedRfc3339,
value: _formatRfc3339(widget.message.receivedAt),
onCopy: () => copyField(
_formatRfc3339(widget.message.receivedAt),
@@ -823,14 +823,14 @@ class _MessageBubbleState extends State<MessageBubble> {
if (widget.message.expectedAckTag != null)
_detailRow(
sheetContext,
label: l10n.expectedAckTag,
label: AppLocalizations.of(context)!.expectedAckTag,
value: widget.message.expectedAckTag!
.toString(),
),
if (receptionDetails?.senderToReceiptMs != null)
_detailRow(
sheetContext,
label: 'Sender to receipt',
label: AppLocalizations.of(context)!.senderToReceipt,
value: _formatDurationMs(
receptionDetails!.senderToReceiptMs!,
),
@@ -838,7 +838,7 @@ class _MessageBubbleState extends State<MessageBubble> {
if (receptionDetails?.estimatedTransmitMs != null)
_detailRow(
sheetContext,
label: 'Estimated tx',
label: AppLocalizations.of(context)!.estimatedTx,
value: _formatDurationMs(
receptionDetails!.estimatedTransmitMs!,
),
@@ -846,7 +846,7 @@ class _MessageBubbleState extends State<MessageBubble> {
if (receptionDetails?.postTransmitDelayMs != null)
_detailRow(
sheetContext,
label: 'Post-tx delay',
label: AppLocalizations.of(context)!.posttxDelay,
value: _formatDurationMs(
receptionDetails!.postTransmitDelayMs!,
),
@@ -854,44 +854,44 @@ class _MessageBubbleState extends State<MessageBubble> {
if (widget.receivedCopies > 1)
_detailRow(
sheetContext,
label: 'Received copies',
label: AppLocalizations.of(context)!.receivedCopies,
value: '${widget.receivedCopies}',
),
if (widget.message.suggestedTimeoutMs != null)
_detailRow(
sheetContext,
label: 'ACK timeout',
label: AppLocalizations.of(context)!.ackTimeout,
value:
'${widget.message.suggestedTimeoutMs} ms',
),
if (retryCause != null)
_detailRow(
sheetContext,
label: 'Retry cause',
label: AppLocalizations.of(context)!.retryCause,
value: retryCause,
),
if (retryMode != null)
_detailRow(
sheetContext,
label: 'Retry mode',
label: AppLocalizations.of(context)!.retryMode,
value: retryMode,
),
if (widget.message.roundTripTimeMs != null)
_detailRow(
sheetContext,
label: l10n.roundTrip,
label: AppLocalizations.of(context)!.roundTrip,
value: '${widget.message.roundTripTimeMs} ms',
),
if (widget.message.retryAttempt > 0)
_detailRow(
sheetContext,
label: l10n.retryAttempt,
label: AppLocalizations.of(context)!.retryAttempt,
value: '${widget.message.retryAttempt}/4',
),
if (widget.message.lastRetryAt != null)
_detailRow(
sheetContext,
label: 'Last retry',
label: AppLocalizations.of(context)!.lastRetry,
value: _formatRfc3339(
widget.message.lastRetryAt!,
),
@@ -902,49 +902,49 @@ class _MessageBubbleState extends State<MessageBubble> {
if (widget.message.usedFloodFallback)
_detailRow(
sheetContext,
label: l10n.floodFallback,
value: l10n.yes,
label: AppLocalizations.of(context)!.floodFallback,
value: AppLocalizations.of(context)!.yes,
),
if (routeMetadata?.canonicalPath
case final routePath?)
_detailRow(
sheetContext,
label: 'Selected path',
label: AppLocalizations.of(context)!.selectedPath,
value: routePath,
onCopy: () => copyField(routePath),
),
if (retryResult != null)
_detailRow(
sheetContext,
label: 'Retry result',
label: AppLocalizations.of(context)!.retryResult,
value: retryResult,
),
if (packetPathHex != null)
_detailRow(
sheetContext,
label: 'Path bytes',
label: AppLocalizations.of(context)!.pathBytes,
value: packetPathHex,
onCopy: () => copyField(packetPathHex),
),
],
),
),
const SizedBox(height: 12),
SizedBox(height: 12),
_techSection(
sheetContext,
icon: Icons.badge,
title: l10n.identity,
title: AppLocalizations.of(context)!.identity,
child: Column(
children: [
_detailRow(
sheetContext,
label: l10n.messageId,
label: AppLocalizations.of(context)!.messageId,
value: widget.message.id,
onCopy: () => copyField(widget.message.id),
),
_detailRow(
sheetContext,
label: l10n.sender,
label: AppLocalizations.of(context)!.sender,
value:
senderName ??
widget.message.senderName ??
@@ -953,20 +953,20 @@ class _MessageBubbleState extends State<MessageBubble> {
if (senderPrefixHex != null)
_detailRow(
sheetContext,
label: l10n.senderKey,
label: AppLocalizations.of(context)!.senderKey,
value: senderPrefixHex,
onCopy: () => copyField(senderPrefixHex),
),
if (recipientName != null)
_detailRow(
sheetContext,
label: l10n.recipient,
label: AppLocalizations.of(context)!.recipient,
value: recipientName,
),
if (recipientPrefixHex != null)
_detailRow(
sheetContext,
label: l10n.recipientKey,
label: AppLocalizations.of(context)!.recipientKey,
value: recipientPrefixHex,
onCopy: () => copyField(recipientPrefixHex),
),
@@ -974,51 +974,51 @@ class _MessageBubbleState extends State<MessageBubble> {
),
),
if (widget.message.isVoice) ...[
const SizedBox(height: 12),
SizedBox(height: 12),
_techSection(
sheetContext,
icon: Icons.graphic_eq,
title: l10n.voice,
title: AppLocalizations.of(context)!.voice,
child: Column(
children: [
_detailRow(
sheetContext,
label: l10n.voiceId,
label: AppLocalizations.of(context)!.voiceId,
value: widget.message.voiceId ?? '-',
),
_detailRow(
sheetContext,
label: l10n.envelope,
label: AppLocalizations.of(context)!.envelope,
value: envelope != null
? 'VE3 compact'
: l10n.unknown,
: AppLocalizations.of(context)!.unknown,
),
if (voiceSession != null)
_detailRow(
sheetContext,
label: l10n.sessionProgress,
label: AppLocalizations.of(context)!.sessionProgress,
value:
'${voiceSession.receivedCount}/${voiceSession.total} segments',
),
if (voiceSession != null)
_detailRow(
sheetContext,
label: l10n.complete,
label: AppLocalizations.of(context)!.complete,
value: voiceSession.isComplete
? l10n.yes
: l10n.no,
? AppLocalizations.of(context)!.yes
: AppLocalizations.of(context)!.no,
),
if (transferDetails != null)
_detailRow(
sheetContext,
label: 'Transfers',
label: AppLocalizations.of(context)!.transfers,
value: '${transferDetails.totalTransfers}',
),
if (transferDetails != null &&
transferDetails.downloaders.isNotEmpty)
_detailRow(
sheetContext,
label: 'Downloaded by',
label: AppLocalizations.of(context)!.downloadedBy,
value: _formatDownloaderSummary(
transferDetails,
),
@@ -1026,7 +1026,7 @@ class _MessageBubbleState extends State<MessageBubble> {
if (voiceTxEstimate > Duration.zero)
_detailRow(
sheetContext,
label: 'Estimated tx',
label: AppLocalizations.of(context)!.estimatedTx,
value: voiceTxEstimate.inSeconds < 60
? '~${voiceTxEstimate.inSeconds}s'
: '~${voiceTxEstimate.inMinutes}m ${voiceTxEstimate.inSeconds % 60}s',
@@ -1036,32 +1036,32 @@ class _MessageBubbleState extends State<MessageBubble> {
),
],
if (imageEnvelope != null) ...[
const SizedBox(height: 12),
SizedBox(height: 12),
_techSection(
sheetContext,
icon: Icons.image_outlined,
title: 'Image',
title: AppLocalizations.of(context)!.image,
child: Column(
children: [
_detailRow(
sheetContext,
label: l10n.envelope,
label: AppLocalizations.of(context)!.envelope,
value: 'IE1',
),
_detailRow(
sheetContext,
label: 'Format',
label: AppLocalizations.of(context)!.format,
value: imageEnvelope.format.label,
),
_detailRow(
sheetContext,
label: 'Dimensions',
label: AppLocalizations.of(context)!.dimensions,
value:
'${imageEnvelope.width}×${imageEnvelope.height}',
),
_detailRow(
sheetContext,
label: 'Segments',
label: AppLocalizations.of(context)!.segments,
value: imageSession != null
? '${imageSession.receivedCount}/${imageSession.total}'
: '${imageEnvelope.total}',
@@ -1069,22 +1069,22 @@ class _MessageBubbleState extends State<MessageBubble> {
if (imageSession != null)
_detailRow(
sheetContext,
label: l10n.complete,
label: AppLocalizations.of(context)!.complete,
value: imageSession.isComplete
? l10n.yes
: l10n.no,
? AppLocalizations.of(context)!.yes
: AppLocalizations.of(context)!.no,
),
if (transferDetails != null)
_detailRow(
sheetContext,
label: 'Transfers',
label: AppLocalizations.of(context)!.transfers,
value: '${transferDetails.totalTransfers}',
),
if (transferDetails != null &&
transferDetails.downloaders.isNotEmpty)
_detailRow(
sheetContext,
label: 'Downloaded by',
label: AppLocalizations.of(context)!.downloadedBy,
value: _formatDownloaderSummary(
transferDetails,
),
@@ -1092,7 +1092,7 @@ class _MessageBubbleState extends State<MessageBubble> {
if (imageTxEstimate > Duration.zero)
_detailRow(
sheetContext,
label: 'Estimated tx',
label: AppLocalizations.of(context)!.estimatedTx,
value: imageTxEstimate.inSeconds < 60
? '~${imageTxEstimate.inSeconds}s'
: '~${imageTxEstimate.inMinutes}m ${imageTxEstimate.inSeconds % 60}s',
@@ -1107,7 +1107,7 @@ class _MessageBubbleState extends State<MessageBubble> {
dense: true,
visualDensity: VisualDensity.compact,
title: Text(
l10n.rawDump,
AppLocalizations.of(context)!.rawDump,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
@@ -1432,7 +1432,7 @@ class _MessageBubbleState extends State<MessageBubble> {
final lon = coords.longitude.toStringAsFixed(6);
// Build share text
final shareText = l10n.shareLocationText(
final shareText = AppLocalizations.of(context)!.shareLocationText(
markerInfo,
lat,
lon,
@@ -1441,7 +1441,7 @@ class _MessageBubbleState extends State<MessageBubble> {
// Share the location
SharePlus.instance.share(
ShareParams(text: shareText, subject: l10n.sarLocationShare),
ShareParams(text: shareText, subject: AppLocalizations.of(context)!.sarLocationShare),
);
}
@@ -1852,14 +1852,14 @@ class _MessageBubbleState extends State<MessageBubble> {
}
} else if (message.isChannelMessage) {
if (message.channelIdx == 0) {
channelDisplayName = l10n.publicChannel;
channelDisplayName = AppLocalizations.of(context)!.publicChannel;
} else {
final channelContact = contactsProvider.channels.where((c) {
return c.publicKey.length > 1 && c.publicKey[1] == message.channelIdx;
}).firstOrNull;
channelDisplayName =
channelContact?.getLocalizedDisplayName(context) ??
'${l10n.channel} ${message.channelIdx}';
'${AppLocalizations.of(context)!.channel} ${message.channelIdx}';
}
if (isOwnMessage) {
@@ -1869,14 +1869,14 @@ class _MessageBubbleState extends State<MessageBubble> {
final recipientSubtitle =
isOwnMessage && message.isChannelMessage && recipientDisplayName != null
? '${l10n.channel}: $recipientDisplayName'
? '${AppLocalizations.of(context)!.channel}: $recipientDisplayName'
: recipientDisplayName;
final directCounterpartLabel = !message.isChannelMessage
? (isOwnMessage ? recipientSubtitle : l10n.you)
? (isOwnMessage ? recipientSubtitle : AppLocalizations.of(context)!.you)
: null;
final receivedChannelSubtitle =
!isOwnMessage && message.isChannelMessage && channelDisplayName != null
? '${l10n.channel}: $channelDisplayName'
? '${AppLocalizations.of(context)!.channel}: $channelDisplayName'
: null;
final shouldFloatBubble = widget.isCompact;
@@ -1992,7 +1992,7 @@ class _MessageBubbleState extends State<MessageBubble> {
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.draw, size: 16, color: Colors.white),
const SizedBox(width: 4),
SizedBox(width: 4),
Text(
AppLocalizations.of(context)!.mapDrawing,
style: Theme.of(context).textTheme.labelSmall
@@ -2029,7 +2029,7 @@ class _MessageBubbleState extends State<MessageBubble> {
size: 16,
color: Colors.white,
),
const SizedBox(width: 4),
SizedBox(width: 4),
Text(
AppLocalizations.of(context)!.sarAlert,
style: Theme.of(context).textTheme.labelSmall
@@ -2522,7 +2522,7 @@ class _MessageBubbleState extends State<MessageBubble> {
? Colors.red
: Colors.orange,
),
const SizedBox(width: 3),
SizedBox(width: 3),
Text(
message.deliveredRecipientsCount ==
message.recipients!.length

View File

@@ -55,12 +55,12 @@ class MessagesContent extends StatelessWidget {
size: 64,
color: Theme.of(context).disabledColor,
),
const SizedBox(height: 16),
SizedBox(height: 16),
Text(
AppLocalizations.of(context)!.noMessagesYet,
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 8),
SizedBox(height: 8),
Text(
AppLocalizations.of(context)!.pullDownToSync,
style: Theme.of(context).textTheme.bodyMedium,

View File

@@ -111,7 +111,7 @@ class _RecipientSelectorSheetState extends State<RecipientSelectorSheet> {
// Search field
Padding(
padding: const EdgeInsets.all(16),
padding: EdgeInsets.all(16),
child: TextField(
controller: _searchController,
decoration: InputDecoration(
@@ -154,7 +154,7 @@ class _RecipientSelectorSheetState extends State<RecipientSelectorSheet> {
context: context,
icon: Icons.all_inbox,
title: l10n.showAll,
subtitle: 'All messages',
subtitle: l10n.allMessages,
unreadCount: widget.unreadCount,
isSelected: _isSelected('all', null),
onTap: () {
@@ -181,7 +181,7 @@ class _RecipientSelectorSheetState extends State<RecipientSelectorSheet> {
),
if (filteredChannels.isEmpty)
Padding(
padding: const EdgeInsets.all(16),
padding: EdgeInsets.all(16),
child: Text(
l10n.noChannelsFound,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
@@ -234,7 +234,7 @@ class _RecipientSelectorSheetState extends State<RecipientSelectorSheet> {
),
if (filteredContacts.isEmpty)
Padding(
padding: const EdgeInsets.all(16),
padding: EdgeInsets.all(16),
child: Text(
l10n.noContactsFound,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
@@ -283,7 +283,7 @@ class _RecipientSelectorSheetState extends State<RecipientSelectorSheet> {
),
if (filteredRooms.isEmpty)
Padding(
padding: const EdgeInsets.all(16),
padding: EdgeInsets.all(16),
child: Text(
l10n.noRoomsFound,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
@@ -323,7 +323,7 @@ class _RecipientSelectorSheetState extends State<RecipientSelectorSheet> {
size: 64,
color: Theme.of(context).disabledColor,
),
const SizedBox(height: 16),
SizedBox(height: 16),
Text(
l10n.noRecipientsAvailable,
style: Theme.of(context).textTheme.bodyLarge

View File

@@ -381,7 +381,7 @@ class _SarUpdateSheetState extends State<SarUpdateSheet> {
),
);
}),
const SizedBox(height: 16),
SizedBox(height: 16),
// Destination selection (compact dropdown with rooms, channels, and all contacts)
Text(
@@ -505,7 +505,7 @@ class _SarUpdateSheetState extends State<SarUpdateSheet> {
size: 18,
color: colorScheme.onSurface,
),
const SizedBox(width: 12),
SizedBox(width: 12),
Expanded(
child: Text(
AppLocalizations.of(context)!.allTeamContacts,
@@ -593,7 +593,7 @@ class _SarUpdateSheetState extends State<SarUpdateSheet> {
color: Colors.green,
size: 20,
),
const SizedBox(width: 8),
SizedBox(width: 8),
Expanded(
child: Text(
AppLocalizations.of(context)!.directMessagesInfo(chatContactsCount),
@@ -718,7 +718,7 @@ class _SarUpdateSheetState extends State<SarUpdateSheet> {
),
),
),
const SizedBox(width: 16),
SizedBox(width: 16),
Text(
AppLocalizations.of(context)!.gettingLocation,
style: TextStyle(color: colorScheme.onSurface),
@@ -979,7 +979,7 @@ class _SarUpdateSheetState extends State<SarUpdateSheet> {
size: 16,
color: Colors.blue,
),
const SizedBox(width: 8),
SizedBox(width: 8),
Expanded(
child: Text(
AppLocalizations.of(context)!.exampleCoordinates,
@@ -994,7 +994,7 @@ class _SarUpdateSheetState extends State<SarUpdateSheet> {
),
],
const SizedBox(height: 24),
SizedBox(height: 24),
// Optional notes
Text(
@@ -1193,7 +1193,7 @@ class _SarUpdateSheetState extends State<SarUpdateSheet> {
borderRadius: BorderRadius.circular(8),
),
),
icon: const Icon(Icons.send, size: 20),
icon: Icon(Icons.send, size: 20),
label: Text(
AppLocalizations.of(context)!.sendSarMarker,
style: const TextStyle(

View File

@@ -9,6 +9,7 @@ import '../../providers/contacts_provider.dart';
import '../../providers/messages_provider.dart';
import '../../utils/tictactoe_message_parser.dart';
import '../../utils/toast_logger.dart';
import '../../l10n/app_localizations.dart';
class TicTacToeMessageBubble extends StatelessWidget {
final Message message;
@@ -33,7 +34,7 @@ class TicTacToeMessageBubble extends StatelessWidget {
final messages = context.watch<MessagesProvider>().messages;
final selfKey = conn.deviceInfo.publicKey;
if (selfKey == null || selfKey.length < 6) {
return const Text('Tic-Tac-Toe unavailable');
return Text(AppLocalizations.of(context)!.tictactoeUnavailable);
}
final selfKey6 = _key6Hex(selfKey);
@@ -43,7 +44,7 @@ class TicTacToeMessageBubble extends StatelessWidget {
isSentByMe: isSentByMe,
);
if (opponent == null) {
return const Text('Tic-Tac-Toe: opponent unknown');
return Text(AppLocalizations.of(context)!.tictactoeOpponentUnknown);
}
final opponentKey6 = _key6Hex(opponent.publicKey);
@@ -69,7 +70,7 @@ class TicTacToeMessageBubble extends StatelessWidget {
start ??= event.type == TicTacToeEventType.start ? event : null;
if (start == null) {
return const Text('Tic-Tac-Toe: waiting for start');
return Text(AppLocalizations.of(context)!.tictactoeWaitingForStart);
}
final xPlayer = start.playerKey6;