feat(#172): channel 'Block sender' (resolve->pubkey / global name)

Long-press a channel post -> Block sender: resolve the claimed name to known
pubkey(s) and block each (full block across DM+adverts+all channels, multi-device
covered); if unresolved, block the name globally across ALL channels (promotes to
pubkey later, #174). Adds block_* l10n strings. A5 channel surface;
contacts/chat/discovery + unblock still to come.

Epic A #165 / A5 #172. Design: docs/architecture/block-contract-as-built.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pull/209/head
Strycher 2 weeks ago
parent 18e49ba4b5
commit 41113cddde

@ -2566,5 +2566,32 @@
"contact_typeRepeater": "Repeater",
"contact_typeRoom": "Room",
"contact_typeSensor": "Sensor",
"contact_typeUnknown": "Unknown"
"contact_typeUnknown": "Unknown",
"block_block": "Block",
"block_unblock": "Unblock",
"block_sender": "Block sender",
"block_blocked": "Blocked {name}",
"@block_blocked": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"block_unblocked": "Unblocked {name}",
"@block_unblocked": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"block_blockedNameOnly": "Blocked \"{name}\" across all channels — name only until we learn their key",
"@block_blockedNameOnly": {
"placeholders": {
"name": {
"type": "String"
}
}
}
}

@ -7797,6 +7797,42 @@ abstract class AppLocalizations {
/// In en, this message translates to:
/// **'Unknown'**
String get contact_typeUnknown;
/// No description provided for @block_block.
///
/// In en, this message translates to:
/// **'Block'**
String get block_block;
/// No description provided for @block_unblock.
///
/// In en, this message translates to:
/// **'Unblock'**
String get block_unblock;
/// No description provided for @block_sender.
///
/// In en, this message translates to:
/// **'Block sender'**
String get block_sender;
/// No description provided for @block_blocked.
///
/// In en, this message translates to:
/// **'Blocked {name}'**
String block_blocked(String name);
/// No description provided for @block_unblocked.
///
/// In en, this message translates to:
/// **'Unblocked {name}'**
String block_unblocked(String name);
/// No description provided for @block_blockedNameOnly.
///
/// In en, this message translates to:
/// **'Blocked \"{name}\" across all channels — name only until we learn their key'**
String block_blockedNameOnly(String name);
}
class _AppLocalizationsDelegate

@ -4564,4 +4564,28 @@ class AppLocalizationsBg extends AppLocalizations {
@override
String get contact_typeUnknown => 'Unknown';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4582,4 +4582,28 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get contact_typeUnknown => 'Unknown';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4486,4 +4486,28 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get contact_typeUnknown => 'Unknown';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4569,4 +4569,28 @@ class AppLocalizationsEs extends AppLocalizations {
@override
String get contact_typeUnknown => 'Unknown';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4598,4 +4598,28 @@ class AppLocalizationsFr extends AppLocalizations {
@override
String get contact_typeUnknown => 'Unknown';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4585,4 +4585,28 @@ class AppLocalizationsHu extends AppLocalizations {
@override
String get contact_typeUnknown => 'Unknown';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4574,4 +4574,28 @@ class AppLocalizationsIt extends AppLocalizations {
@override
String get contact_typeUnknown => 'Unknown';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4339,4 +4339,28 @@ class AppLocalizationsJa extends AppLocalizations {
@override
String get contact_typeUnknown => 'Unknown';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4340,4 +4340,28 @@ class AppLocalizationsKo extends AppLocalizations {
@override
String get contact_typeUnknown => 'Unknown';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4549,4 +4549,28 @@ class AppLocalizationsNl extends AppLocalizations {
@override
String get contact_typeUnknown => 'Unknown';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4586,4 +4586,28 @@ class AppLocalizationsPl extends AppLocalizations {
@override
String get contact_typeUnknown => 'Unknown';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4562,4 +4562,28 @@ class AppLocalizationsPt extends AppLocalizations {
@override
String get contact_typeUnknown => 'Unknown';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4580,4 +4580,28 @@ class AppLocalizationsRu extends AppLocalizations {
@override
String get contact_typeUnknown => 'Неизвестно';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4545,4 +4545,28 @@ class AppLocalizationsSk extends AppLocalizations {
@override
String get contact_typeUnknown => 'Unknown';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4543,4 +4543,28 @@ class AppLocalizationsSl extends AppLocalizations {
@override
String get contact_typeUnknown => 'Unknown';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4518,4 +4518,28 @@ class AppLocalizationsSv extends AppLocalizations {
@override
String get contact_typeUnknown => 'Unknown';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4581,4 +4581,28 @@ class AppLocalizationsUk extends AppLocalizations {
@override
String get contact_typeUnknown => 'Невідомо';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -4213,4 +4213,28 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get contact_typeUnknown => 'Unknown';
@override
String get block_block => 'Block';
@override
String get block_unblock => 'Unblock';
@override
String get block_sender => 'Block sender';
@override
String block_blocked(String name) {
return 'Blocked $name';
}
@override
String block_unblocked(String name) {
return 'Unblocked $name';
}
@override
String block_blockedNameOnly(String name) {
return 'Blocked \"$name\" across all channels — name only until we learn their key';
}
}

@ -504,6 +504,30 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
connector.setChannelUnreadCount(widget.channel.index, count);
}
/// Block the sender of a channel post. Resolves the claimed name to known
/// pubkey(s) and blocks each (full block: DM + adverts + all channels); if it
/// resolves to nothing, blocks the name globally across all channels (promotes
/// to a pubkey block later, once the identity is learned #174).
Future<void> _blockChannelSender(ChannelMessage message) async {
final connector = context.read<MeshCoreConnector>();
final blockService = context.read<BlockService>();
final messenger = ScaffoldMessenger.of(context);
final l10n = context.l10n;
final name = message.senderName;
final keys = connector.resolveContactKeysByName(name);
if (keys.isNotEmpty) {
for (final key in keys) {
await blockService.block(key);
}
messenger.showSnackBar(SnackBar(content: Text(l10n.block_blocked(name))));
} else {
await blockService.blockName(name);
messenger.showSnackBar(
SnackBar(content: Text(l10n.block_blockedNameOnly(name))),
);
}
}
/// A channel post is hidden only when its claimed name resolves to at least
/// one identity and *every* matching pubkey is blocked (an ambiguous namesake
/// with any unblocked match is still shown), or the name is in blockedNames.
@ -1518,6 +1542,15 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
await _deleteMessage(message);
},
),
if (!message.isOutgoing)
ListTile(
leading: Icon(Icons.block, color: Colors.red.shade700),
title: Text(context.l10n.block_sender),
onTap: () {
Navigator.pop(sheetContext);
_blockChannelSender(message);
},
),
ListTile(
leading: const Icon(Icons.close),
title: Text(context.l10n.common_cancel),

@ -20,21 +20,13 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
],
"de": [
@ -58,21 +50,13 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
],
"es": [
@ -96,21 +80,13 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
],
"fr": [
@ -134,21 +110,13 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
],
"hu": [
@ -172,21 +140,13 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
],
"it": [
@ -210,21 +170,13 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
],
"ja": [
@ -248,21 +200,13 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
],
"ko": [
@ -286,21 +230,13 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
],
"nl": [
@ -324,21 +260,13 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
],
"pl": [
@ -362,21 +290,13 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
],
"pt": [
@ -400,21 +320,13 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
],
"ru": [
@ -438,21 +350,13 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
],
"sk": [
@ -476,21 +380,13 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
],
"sl": [
@ -514,21 +410,13 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
],
"sv": [
@ -552,21 +440,13 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
],
"uk": [
@ -590,21 +470,13 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
],
"zh": [
@ -628,20 +500,12 @@
"appSettings_clock24h",
"chat_replyWithRoute",
"channel_heardTooltip",
"path_suggestedRoute",
"path_searchRepeaters",
"channels_shareQr",
"channels_shareQrTitle",
"channels_shareQrInstructions",
"channels_scanQr",
"channels_scanQrDesc",
"channels_scanQrInstructions",
"channels_invalidQr",
"channels_noFreeSlot",
"channels_qrAddConfirm",
"channels_qrAdded",
"channels_qrExists",
"contacts_repeaterPathTraceVia",
"snrIndicator_noNeighbors"
"snrIndicator_noNeighbors",
"block_block",
"block_unblock",
"block_sender",
"block_blocked",
"block_unblocked",
"block_blockedNameOnly"
]
}

Loading…
Cancel
Save

Powered by TurnKey Linux.