diff --git a/lib/l10n/app_bg.arb b/lib/l10n/app_bg.arb index 86ad421..01afb0c 100644 --- a/lib/l10n/app_bg.arb +++ b/lib/l10n/app_bg.arb @@ -1569,6 +1569,13 @@ "contacts_zeroHopContactAdvertFailed": "Неуспешно изпращане на контакт.", "contacts_zeroHopContactAdvertSent": "Изпратен контакт по обява.", "contacts_contactAdvertCopyFailed": "Копирането на обявата в клипборда не успя.", + "notification_activityTitle": "Активност на MeshCore", + "notification_messagesCount": "{count} {count, plural, =1{съобщение} other{съобщения}}", + "notification_channelMessagesCount": "{count} {count, plural, =1{съобщение в канал} other{съобщения в канали}}", + "notification_newNodesCount": "{count} {count, plural, =1{нов възел} other{нови възли}}", + "notification_newTypeDiscovered": "Открит нов {contactType}", + "notification_receivedNewMessage": "Получено ново съобщение", + "contacts_contactAdvertCopyFailed": "Копирането на обявата в клипборда не успя.", "settings_gpxExportContactsSubtitle": "Експортира спътници с местоположение в GPX файл.", "settings_gpxExportRepeatersSubtitle": "Изпраща повторители / roomserver с местоположение в GPX файл.", "settings_gpxExportAll": "Експортирай всички контакти в GPX", @@ -1585,4 +1592,5 @@ "settings_gpxExportShareText": "Картинни данни изнесени от meshcore-open", "settings_gpxExportShareSubject": "meshcore-open износ на данни за карта в формат GPX", "pathTrace_someHopsNoLocation": "Един или повече от хмелите липсва местоположение!" + } diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index ccbdb2e..3dcd0ca 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -1569,6 +1569,34 @@ "contacts_zeroHopContactAdvertSent": "Kontakt über Anzeige gesendet", "contacts_contactAdvertCopied": "Anzeige in die Zwischenablage kopiert.", "contacts_contactAdvertCopyFailed": "Kopieren des Werbeinhalts in die Zwischenablage fehlgeschlagen.", + + "notification_activityTitle": "MeshCore Aktivität", + "notification_messagesCount": "{count} {count, plural, =1{Nachricht} other{Nachrichten}}", + "@notification_messagesCount": { + "placeholders": { + "count": {"type": "int"} + } + }, + "notification_channelMessagesCount": "{count} {count, plural, =1{Kanalnachricht} other{Kanalnachrichten}}", + "@notification_channelMessagesCount": { + "placeholders": { + "count": {"type": "int"} + } + }, + "notification_newNodesCount": "{count} {count, plural, =1{neuer Knoten} other{neue Knoten}}", + "@notification_newNodesCount": { + "placeholders": { + "count": {"type": "int"} + } + }, + "notification_newTypeDiscovered": "Neuer {contactType} entdeckt", + "@notification_newTypeDiscovered": { + "placeholders": { + "contactType": {"type": "String"} + } + }, + "notification_receivedNewMessage": "Neue Nachricht empfangen", + "contacts_contactAdvertCopyFailed": "Kopieren des Werbeinhalts in die Zwischenablage fehlgeschlagen.", "settings_gpxExportAll": "Alle Kontakte nach GPX exportieren", "settings_gpxExportAllSubtitle": "Exportiert alle Kontakte mit einem Standort in eine GPX-Datei.", "settings_gpxExportRepeaters": "Repeater und Raumserver nach GPX exportieren", @@ -1585,4 +1613,5 @@ "settings_gpxExportShareSubject": "meshcore-open GPX-Kartendaten exportieren", "settings_gpxExportShareText": "Kartendaten aus meshcore-open exportiert", "pathTrace_someHopsNoLocation": "Eine oder mehrere der Hopfen fehlen einen Standort!" + } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index d939bea..0c54be3 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -1346,12 +1346,39 @@ "contacts_contactAdvertCopied": "Advert copied to Clipboard.", "contacts_contactAdvertCopyFailed": "Copying advert to Clipboard failed.", + "notification_activityTitle": "MeshCore Activity", + "notification_messagesCount": "{count} {count, plural, =1{message} other{messages}}", + "@notification_messagesCount": { + "placeholders": { + "count": {"type": "int"} + } + }, + "notification_channelMessagesCount": "{count} {count, plural, =1{channel message} other{channel messages}}", + "@notification_channelMessagesCount": { + "placeholders": { + "count": {"type": "int"} + } + }, + "notification_newNodesCount": "{count} {count, plural, =1{new node} other{new nodes}}", + "@notification_newNodesCount": { + "placeholders": { + "count": {"type": "int"} + } + }, + "notification_newTypeDiscovered": "New {contactType} discovered", + "@notification_newTypeDiscovered": { + "placeholders": { + "contactType": {"type": "String"} + } + }, + "notification_receivedNewMessage": "Received new message", + "settings_gpxExportRepeaters": "Export repeaters / room server to GPX", "settings_gpxExportRepeatersSubtitle": "Exports repeaters / roomserver with a location to GPX file.", "settings_gpxExportContacts": "Export companions to GPX", "settings_gpxExportContactsSubtitle": "Exports companions with a location to GPX file.", "settings_gpxExportAll": "Export all contacts to GPX", - "settings_gpxExportAllSubtitle": "Exports all contacts with a location to GPX file.", + "settings_gpxExportAllSubtitle": "Exports all contacts with a location to GPX file.", "settings_gpxExportSuccess": "Successfully exported GPX file.", "settings_gpxExportNoContacts": "No contacts to export.", "settings_gpxExportNotAvailable": "Not supported on your device/OS", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 049d6a9..3d5ab63 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -1569,6 +1569,34 @@ "contacts_zeroHopContactAdvertSent": "Envió contacto por anuncio.", "contacts_contactAdvertCopied": "Anuncio copiado al Portapapeles.", "contacts_contactAdvertCopyFailed": "Copiar anuncio al Portapapeles ha fallado.", + + "notification_activityTitle": "Actividad de MeshCore", + "notification_messagesCount": "{count} {count, plural, =1{mensaje} other{mensajes}}", + "@notification_messagesCount": { + "placeholders": { + "count": {"type": "int"} + } + }, + "notification_channelMessagesCount": "{count} {count, plural, =1{mensaje de canal} other{mensajes de canal}}", + "@notification_channelMessagesCount": { + "placeholders": { + "count": {"type": "int"} + } + }, + "notification_newNodesCount": "{count} {count, plural, =1{nuevo nodo} other{nuevos nodos}}", + "@notification_newNodesCount": { + "placeholders": { + "count": {"type": "int"} + } + }, + "notification_newTypeDiscovered": "Nuevo {contactType} descubierto", + "@notification_newTypeDiscovered": { + "placeholders": { + "contactType": {"type": "String"} + } + }, + "notification_receivedNewMessage": "Nuevo mensaje recibido", + "contacts_contactAdvertCopyFailed": "Copiar anuncio al Portapapeles ha fallado.", "settings_gpxExportContactsSubtitle": "Exporta compañeros con una ubicación a archivo GPX.", "settings_gpxExportRepeaters": "Exportar repetidores / servidor de sala a GPX", "settings_gpxExportSuccess": "Archivo GPX exportado con éxito.", @@ -1585,4 +1613,5 @@ "settings_gpxExportShareText": "Datos del mapa exportados desde meshcore-open", "settings_gpxExportShareSubject": "meshcore-open exportación de datos de mapa GPX", "pathTrace_someHopsNoLocation": "Uno o más de los lúpulos carecen de una ubicación" + } diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 293a30e..044b806 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -1569,6 +1569,13 @@ "contacts_contactAdvertCopyFailed": "La copie de l'annonce vers le presse-papiers a échoué.", "contacts_zeroHopContactAdvertSent": "Envoyer un contact par annonce.", "contacts_zeroHopContactAdvertFailed": "Échec de l'envoi du contact.", + "notification_activityTitle": "Activité MeshCore", + "notification_messagesCount": "{count} {count, plural, =1{message} other{messages}}", + "notification_channelMessagesCount": "{count} {count, plural, =1{message de canal} other{messages de canal}}", + "notification_newNodesCount": "{count} {count, plural, =1{nouveau nœud} other{nouveaux nœuds}}", + "notification_newTypeDiscovered": "Nouveau {contactType} découvert", + "notification_receivedNewMessage": "Nouveau message reçu", + "contacts_zeroHopContactAdvertFailed": "Échec de l'envoi du contact.", "settings_gpxExportRepeaters": "Exporter les répéteurs / serveur de salle au format GPX", "settings_gpxExportRepeatersSubtitle": "Exporte les répéteurs / roomserver avec une localisation vers un fichier GPX.", "settings_gpxExportNoContacts": "Aucun contact à exporter.", @@ -1585,4 +1592,5 @@ "settings_gpxExportShareText": "Données de carte exportées à partir de meshcore-open", "settings_gpxExportShareSubject": "meshcore-open exporter les données de carte GPX", "pathTrace_someHopsNoLocation": "Une ou plusieurs des houblons manquent d'une localisation !" + } diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb index 74c9205..dd9c373 100644 --- a/lib/l10n/app_it.arb +++ b/lib/l10n/app_it.arb @@ -1569,6 +1569,13 @@ "contacts_ShareContactZeroHop": "Condividi contatto tramite annuncio", "contacts_zeroHopContactAdvertFailed": "Invio del contatto non riuscito.", "contacts_contactAdvertCopied": "Annuncio copiato negli Appunti.", + "notification_activityTitle": "Attività MeshCore", + "notification_messagesCount": "{count} {count, plural, =1{messaggio} other{messaggi}}", + "notification_channelMessagesCount": "{count} {count, plural, =1{messaggio del canale} other{messaggi del canale}}", + "notification_newNodesCount": "{count} {count, plural, =1{nuovo nodo} other{nuovi nodi}}", + "notification_newTypeDiscovered": "Nuovo {contactType} scoperto", + "notification_receivedNewMessage": "Nuovo messaggio ricevuto", + "contacts_contactAdvertCopied": "Annuncio copiato negli Appunti.", "settings_gpxExportRepeaters": "Esporta ripetitori / server di stanza in GPX", "settings_gpxExportContacts": "Esporta compagni in GPX", "settings_gpxExportSuccess": "Esportazione del file GPX completata con successo.", @@ -1585,4 +1592,5 @@ "settings_gpxExportShareText": "Dati mappa esportati da meshcore-open", "settings_gpxExportShareSubject": "meshcore-open esportazione dati mappa GPX", "pathTrace_someHopsNoLocation": "Uno o più dei luppoli mancano di una posizione!" + } diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index b86882b..8f4d693 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -4862,6 +4862,42 @@ abstract class AppLocalizations { /// **'Copying advert to Clipboard failed.'** String get contacts_contactAdvertCopyFailed; + /// No description provided for @notification_activityTitle. + /// + /// In en, this message translates to: + /// **'MeshCore Activity'** + String get notification_activityTitle; + + /// No description provided for @notification_messagesCount. + /// + /// In en, this message translates to: + /// **'{count} {count, plural, =1{message} other{messages}}'** + String notification_messagesCount(int count); + + /// No description provided for @notification_channelMessagesCount. + /// + /// In en, this message translates to: + /// **'{count} {count, plural, =1{channel message} other{channel messages}}'** + String notification_channelMessagesCount(int count); + + /// No description provided for @notification_newNodesCount. + /// + /// In en, this message translates to: + /// **'{count} {count, plural, =1{new node} other{new nodes}}'** + String notification_newNodesCount(int count); + + /// No description provided for @notification_newTypeDiscovered. + /// + /// In en, this message translates to: + /// **'New {contactType} discovered'** + String notification_newTypeDiscovered(String contactType); + + /// No description provided for @notification_receivedNewMessage. + /// + /// In en, this message translates to: + /// **'Received new message'** + String get notification_receivedNewMessage; + /// No description provided for @settings_gpxExportRepeaters. /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_bg.dart b/lib/l10n/app_localizations_bg.dart index 0527949..68e821e 100644 --- a/lib/l10n/app_localizations_bg.dart +++ b/lib/l10n/app_localizations_bg.dart @@ -2771,6 +2771,50 @@ class AppLocalizationsBg extends AppLocalizations { String get contacts_contactAdvertCopyFailed => 'Копирането на обявата в клипборда не успя.'; + @override + String get notification_activityTitle => 'Активност на MeshCore'; + + @override + String notification_messagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'съобщения', + one: 'съобщение', + ); + return '$count $_temp0'; + } + + @override + String notification_channelMessagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'съобщения в канали', + one: 'съобщение в канал', + ); + return '$count $_temp0'; + } + + @override + String notification_newNodesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'нови възли', + one: 'нов възел', + ); + return '$count $_temp0'; + } + + @override + String notification_newTypeDiscovered(String contactType) { + return 'Открит нов $contactType'; + } + + @override + String get notification_receivedNewMessage => 'Получено ново съобщение'; + @override String get settings_gpxExportRepeaters => 'Експортиране на повтарящи се устройства / сървър на стаята до GPX'; diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index f66a37e..8ad7f1e 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -2778,6 +2778,50 @@ class AppLocalizationsDe extends AppLocalizations { String get contacts_contactAdvertCopyFailed => 'Kopieren des Werbeinhalts in die Zwischenablage fehlgeschlagen.'; + @override + String get notification_activityTitle => 'MeshCore Aktivität'; + + @override + String notification_messagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'Nachrichten', + one: 'Nachricht', + ); + return '$count $_temp0'; + } + + @override + String notification_channelMessagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'Kanalnachrichten', + one: 'Kanalnachricht', + ); + return '$count $_temp0'; + } + + @override + String notification_newNodesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'neue Knoten', + one: 'neuer Knoten', + ); + return '$count $_temp0'; + } + + @override + String notification_newTypeDiscovered(String contactType) { + return 'Neuer $contactType entdeckt'; + } + + @override + String get notification_receivedNewMessage => 'Neue Nachricht empfangen'; + @override String get settings_gpxExportRepeaters => 'Repeater und Raumserver nach GPX exportieren'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index b0315a8..8eb76e8 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -2728,6 +2728,50 @@ class AppLocalizationsEn extends AppLocalizations { String get contacts_contactAdvertCopyFailed => 'Copying advert to Clipboard failed.'; + @override + String get notification_activityTitle => 'MeshCore Activity'; + + @override + String notification_messagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'messages', + one: 'message', + ); + return '$count $_temp0'; + } + + @override + String notification_channelMessagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'channel messages', + one: 'channel message', + ); + return '$count $_temp0'; + } + + @override + String notification_newNodesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'new nodes', + one: 'new node', + ); + return '$count $_temp0'; + } + + @override + String notification_newTypeDiscovered(String contactType) { + return 'New $contactType discovered'; + } + + @override + String get notification_receivedNewMessage => 'Received new message'; + @override String get settings_gpxExportRepeaters => 'Export repeaters / room server to GPX'; diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index c08c67a..cc9bff7 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -2771,6 +2771,50 @@ class AppLocalizationsEs extends AppLocalizations { String get contacts_contactAdvertCopyFailed => 'Copiar anuncio al Portapapeles ha fallado.'; + @override + String get notification_activityTitle => 'Actividad de MeshCore'; + + @override + String notification_messagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'mensajes', + one: 'mensaje', + ); + return '$count $_temp0'; + } + + @override + String notification_channelMessagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'mensajes de canal', + one: 'mensaje de canal', + ); + return '$count $_temp0'; + } + + @override + String notification_newNodesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'nuevos nodos', + one: 'nuevo nodo', + ); + return '$count $_temp0'; + } + + @override + String notification_newTypeDiscovered(String contactType) { + return 'Nuevo $contactType descubierto'; + } + + @override + String get notification_receivedNewMessage => 'Nuevo mensaje recibido'; + @override String get settings_gpxExportRepeaters => 'Exportar repetidores / servidor de sala a GPX'; diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index 0241b3b..474d528 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -2792,6 +2792,50 @@ class AppLocalizationsFr extends AppLocalizations { String get contacts_contactAdvertCopyFailed => 'La copie de l\'annonce vers le presse-papiers a échoué.'; + @override + String get notification_activityTitle => 'Activité MeshCore'; + + @override + String notification_messagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'messages', + one: 'message', + ); + return '$count $_temp0'; + } + + @override + String notification_channelMessagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'messages de canal', + one: 'message de canal', + ); + return '$count $_temp0'; + } + + @override + String notification_newNodesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'nouveaux nœuds', + one: 'nouveau nœud', + ); + return '$count $_temp0'; + } + + @override + String notification_newTypeDiscovered(String contactType) { + return 'Nouveau $contactType découvert'; + } + + @override + String get notification_receivedNewMessage => 'Nouveau message reçu'; + @override String get settings_gpxExportRepeaters => 'Exporter les répéteurs / serveur de salle au format GPX'; diff --git a/lib/l10n/app_localizations_it.dart b/lib/l10n/app_localizations_it.dart index e758ea4..68465dd 100644 --- a/lib/l10n/app_localizations_it.dart +++ b/lib/l10n/app_localizations_it.dart @@ -2774,6 +2774,50 @@ class AppLocalizationsIt extends AppLocalizations { String get contacts_contactAdvertCopyFailed => 'Copia dell\'annuncio nella Clipboard non riuscita.'; + @override + String get notification_activityTitle => 'Attività MeshCore'; + + @override + String notification_messagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'messaggi', + one: 'messaggio', + ); + return '$count $_temp0'; + } + + @override + String notification_channelMessagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'messaggi del canale', + one: 'messaggio del canale', + ); + return '$count $_temp0'; + } + + @override + String notification_newNodesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'nuovi nodi', + one: 'nuovo nodo', + ); + return '$count $_temp0'; + } + + @override + String notification_newTypeDiscovered(String contactType) { + return 'Nuovo $contactType scoperto'; + } + + @override + String get notification_receivedNewMessage => 'Nuovo messaggio ricevuto'; + @override String get settings_gpxExportRepeaters => 'Esporta ripetitori / server di stanza in GPX'; diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index f081a20..a093a35 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -2763,6 +2763,50 @@ class AppLocalizationsNl extends AppLocalizations { String get contacts_contactAdvertCopyFailed => 'Kopiëren van advertentie naar Clipboard is mislukt.'; + @override + String get notification_activityTitle => 'MeshCore Activiteit'; + + @override + String notification_messagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'berichten', + one: 'bericht', + ); + return '$count $_temp0'; + } + + @override + String notification_channelMessagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'kanaalberichten', + one: 'kanaalbericht', + ); + return '$count $_temp0'; + } + + @override + String notification_newNodesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'nieuwe knooppunten', + one: 'nieuw knooppunt', + ); + return '$count $_temp0'; + } + + @override + String notification_newTypeDiscovered(String contactType) { + return 'Nieuw $contactType ontdekt'; + } + + @override + String get notification_receivedNewMessage => 'Nieuw bericht ontvangen'; + @override String get settings_gpxExportRepeaters => 'Exporteer repeaters / roomserver naar GPX'; diff --git a/lib/l10n/app_localizations_pl.dart b/lib/l10n/app_localizations_pl.dart index 04b959c..895e3c7 100644 --- a/lib/l10n/app_localizations_pl.dart +++ b/lib/l10n/app_localizations_pl.dart @@ -2771,6 +2771,56 @@ class AppLocalizationsPl extends AppLocalizations { String get contacts_contactAdvertCopyFailed => 'Kopiowanie ogłoszenia do schowka nie powiodło się.'; + @override + String get notification_activityTitle => 'Aktywność MeshCore'; + + @override + String notification_messagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'wiadomości', + many: 'wiadomości', + few: 'wiadomości', + one: 'wiadomość', + ); + return '$count $_temp0'; + } + + @override + String notification_channelMessagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'wiadomości kanału', + many: 'wiadomości kanału', + few: 'wiadomości kanału', + one: 'wiadomość kanału', + ); + return '$count $_temp0'; + } + + @override + String notification_newNodesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'nowych węzłów', + many: 'nowych węzłów', + few: 'nowe węzły', + one: 'nowy węzeł', + ); + return '$count $_temp0'; + } + + @override + String notification_newTypeDiscovered(String contactType) { + return 'Nowy $contactType wykryty'; + } + + @override + String get notification_receivedNewMessage => 'Otrzymano nową wiadomość'; + @override String get settings_gpxExportRepeaters => 'Eksportuj powtórki / serwer pokojowy do GPX'; diff --git a/lib/l10n/app_localizations_pt.dart b/lib/l10n/app_localizations_pt.dart index de4adf5..ce8d07c 100644 --- a/lib/l10n/app_localizations_pt.dart +++ b/lib/l10n/app_localizations_pt.dart @@ -2773,6 +2773,50 @@ class AppLocalizationsPt extends AppLocalizations { String get contacts_contactAdvertCopyFailed => 'Cópia do anúncio para a Área de Transferência falhou.'; + @override + String get notification_activityTitle => 'Atividade MeshCore'; + + @override + String notification_messagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'mensagens', + one: 'mensagem', + ); + return '$count $_temp0'; + } + + @override + String notification_channelMessagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'mensagens de canal', + one: 'mensagem de canal', + ); + return '$count $_temp0'; + } + + @override + String notification_newNodesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'novos nós', + one: 'novo nó', + ); + return '$count $_temp0'; + } + + @override + String notification_newTypeDiscovered(String contactType) { + return 'Novo $contactType descoberto'; + } + + @override + String get notification_receivedNewMessage => 'Nova mensagem recebida'; + @override String get settings_gpxExportRepeaters => 'Exportar repetidores / servidor de sala para GPX'; diff --git a/lib/l10n/app_localizations_ru.dart b/lib/l10n/app_localizations_ru.dart index e3050af..9e4cd95 100644 --- a/lib/l10n/app_localizations_ru.dart +++ b/lib/l10n/app_localizations_ru.dart @@ -2778,6 +2778,56 @@ class AppLocalizationsRu extends AppLocalizations { String get contacts_contactAdvertCopyFailed => 'Копирование рекламы в буфер обмена не удалось.'; + @override + String get notification_activityTitle => 'Активность MeshCore'; + + @override + String notification_messagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'сообщений', + many: 'сообщений', + few: 'сообщения', + one: 'сообщение', + ); + return '$count $_temp0'; + } + + @override + String notification_channelMessagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'сообщений канала', + many: 'сообщений канала', + few: 'сообщения канала', + one: 'сообщение канала', + ); + return '$count $_temp0'; + } + + @override + String notification_newNodesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'новых узлов', + many: 'новых узлов', + few: 'новых узла', + one: 'новый узел', + ); + return '$count $_temp0'; + } + + @override + String notification_newTypeDiscovered(String contactType) { + return 'Обнаружен новый $contactType'; + } + + @override + String get notification_receivedNewMessage => 'Получено новое сообщение'; + @override String get settings_gpxExportRepeaters => 'Экспортировать рипитеры / сервер комнаты в GPX'; diff --git a/lib/l10n/app_localizations_sk.dart b/lib/l10n/app_localizations_sk.dart index 745b3fd..ed66f97 100644 --- a/lib/l10n/app_localizations_sk.dart +++ b/lib/l10n/app_localizations_sk.dart @@ -2757,6 +2757,53 @@ class AppLocalizationsSk extends AppLocalizations { String get contacts_contactAdvertCopyFailed => 'Kopírovanie inzerátu do schránky zlyhalo.'; + @override + String get notification_activityTitle => 'Aktivita MeshCore'; + + @override + String notification_messagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'správ', + few: 'správy', + one: 'správa', + ); + return '$count $_temp0'; + } + + @override + String notification_channelMessagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'správ kanálu', + few: 'správy kanálu', + one: 'správa kanálu', + ); + return '$count $_temp0'; + } + + @override + String notification_newNodesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'nových uzlov', + few: 'nové uzly', + one: 'nový uzol', + ); + return '$count $_temp0'; + } + + @override + String notification_newTypeDiscovered(String contactType) { + return 'Nový $contactType objavený'; + } + + @override + String get notification_receivedNewMessage => 'Prijatá nová správa'; + @override String get settings_gpxExportRepeaters => 'Exportovať repeater / server miestnosti do GPX'; diff --git a/lib/l10n/app_localizations_sl.dart b/lib/l10n/app_localizations_sl.dart index 70b2839..3307547 100644 --- a/lib/l10n/app_localizations_sl.dart +++ b/lib/l10n/app_localizations_sl.dart @@ -2759,6 +2759,56 @@ class AppLocalizationsSl extends AppLocalizations { String get contacts_contactAdvertCopyFailed => 'Kopiranje oglasa v odložišče je spodletelo.'; + @override + String get notification_activityTitle => 'Aktivnost MeshCore'; + + @override + String notification_messagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'sporočil', + few: 'sporočila', + two: 'sporočili', + one: 'sporočilo', + ); + return '$count $_temp0'; + } + + @override + String notification_channelMessagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'sporočil kanala', + few: 'sporočila kanala', + two: 'sporočili kanala', + one: 'sporočilo kanala', + ); + return '$count $_temp0'; + } + + @override + String notification_newNodesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'novih vozlišč', + few: 'nova vozlišča', + two: 'novi vozlišči', + one: 'novo vozlišče', + ); + return '$count $_temp0'; + } + + @override + String notification_newTypeDiscovered(String contactType) { + return 'Odkrito novo $contactType'; + } + + @override + String get notification_receivedNewMessage => 'Prejeto novo sporočilo'; + @override String get settings_gpxExportRepeaters => 'Izvoz ponoviteljev / strežnika sobe v GPX'; diff --git a/lib/l10n/app_localizations_sv.dart b/lib/l10n/app_localizations_sv.dart index f930dcb..5239b06 100644 --- a/lib/l10n/app_localizations_sv.dart +++ b/lib/l10n/app_localizations_sv.dart @@ -2744,6 +2744,50 @@ class AppLocalizationsSv extends AppLocalizations { String get contacts_contactAdvertCopyFailed => 'Kopiering av annons till Urklipp misslyckades.'; + @override + String get notification_activityTitle => 'MeshCore Aktivitet'; + + @override + String notification_messagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'meddelanden', + one: 'meddelande', + ); + return '$count $_temp0'; + } + + @override + String notification_channelMessagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'kanalmeddelanden', + one: 'kanalmeddelande', + ); + return '$count $_temp0'; + } + + @override + String notification_newNodesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'nya noder', + one: 'ny nod', + ); + return '$count $_temp0'; + } + + @override + String notification_newTypeDiscovered(String contactType) { + return 'Ny $contactType upptäckt'; + } + + @override + String get notification_receivedNewMessage => 'Nytt meddelande mottaget'; + @override String get settings_gpxExportRepeaters => 'Exportera repeater / rumsservrar till GPX'; diff --git a/lib/l10n/app_localizations_uk.dart b/lib/l10n/app_localizations_uk.dart index e48563d..b6ff8ce 100644 --- a/lib/l10n/app_localizations_uk.dart +++ b/lib/l10n/app_localizations_uk.dart @@ -2784,6 +2784,56 @@ class AppLocalizationsUk extends AppLocalizations { String get contacts_contactAdvertCopyFailed => 'Копіювання оголошення в буфер обміну завершилося невдало'; + @override + String get notification_activityTitle => 'Активність MeshCore'; + + @override + String notification_messagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'повідомлень', + many: 'повідомлень', + few: 'повідомлення', + one: 'повідомлення', + ); + return '$count $_temp0'; + } + + @override + String notification_channelMessagesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'повідомлень каналу', + many: 'повідомлень каналу', + few: 'повідомлення каналу', + one: 'повідомлення каналу', + ); + return '$count $_temp0'; + } + + @override + String notification_newNodesCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'нових вузлів', + many: 'нових вузлів', + few: 'нових вузли', + one: 'новий вузол', + ); + return '$count $_temp0'; + } + + @override + String notification_newTypeDiscovered(String contactType) { + return 'Виявлено новий $contactType'; + } + + @override + String get notification_receivedNewMessage => 'Отримано нове повідомлення'; + @override String get settings_gpxExportRepeaters => 'Експортувати ретранслятори / сервер кімнати до GPX'; diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index 51d3463..a529a1b 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -2625,6 +2625,32 @@ class AppLocalizationsZh extends AppLocalizations { @override String get contacts_contactAdvertCopyFailed => '将广告复制到剪贴板操作失败。'; + @override + String get notification_activityTitle => 'MeshCore 活动'; + + @override + String notification_messagesCount(int count) { + return '$count 条消息'; + } + + @override + String notification_channelMessagesCount(int count) { + return '$count 条频道消息'; + } + + @override + String notification_newNodesCount(int count) { + return '$count 个新节点'; + } + + @override + String notification_newTypeDiscovered(String contactType) { + return '发现新 $contactType'; + } + + @override + String get notification_receivedNewMessage => '收到新消息'; + @override String get settings_gpxExportRepeaters => '导出重复器/房间服务器到GPX'; diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb index fece968..91163ac 100644 --- a/lib/l10n/app_nl.arb +++ b/lib/l10n/app_nl.arb @@ -1569,6 +1569,13 @@ "contacts_ShareContact": "Kontakt naar Klembord kopiëren", "contacts_ShareContactZeroHop": "Contact delen via advertentie", "contacts_zeroHopContactAdvertFailed": "Mislukt om contact te verzenden", + "notification_activityTitle": "MeshCore Activiteit", + "notification_messagesCount": "{count} {count, plural, =1{bericht} other{berichten}}", + "notification_channelMessagesCount": "{count} {count, plural, =1{kanaalbericht} other{kanaalberichten}}", + "notification_newNodesCount": "{count} {count, plural, =1{nieuw knooppunt} other{nieuwe knooppunten}}", + "notification_newTypeDiscovered": "Nieuw {contactType} ontdekt", + "notification_receivedNewMessage": "Nieuw bericht ontvangen", + "contacts_zeroHopContactAdvertFailed": "Mislukt om contact te verzenden", "settings_gpxExportRepeatersSubtitle": "Exporteert repeaters / roomserver met een locatie naar GPX-bestand.", "settings_gpxExportRepeaters": "Exporteer repeaters / roomserver naar GPX", "settings_gpxExportSuccess": "Succesvol GPX-bestand geëxporteerd.", @@ -1585,4 +1592,5 @@ "settings_gpxExportShareText": "Kaartgegevens geëxporteerd uit meshcore-open", "settings_gpxExportShareSubject": "meshcore-open GPX kaartgegevens exporteren", "pathTrace_someHopsNoLocation": "Een of meer van de hops ontbreken een locatie!" + } diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index a5b4925..3c2a96f 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -1569,6 +1569,13 @@ "contacts_ShareContactZeroHop": "Udostępnij kontakt przez ogłoszenie", "contacts_ShareContact": "Kopiuj kontakt do schowka", "contacts_zeroHopContactAdvertFailed": "Nie udało się wysłać kontaktu.", + "notification_activityTitle": "Aktywność MeshCore", + "notification_messagesCount": "{count} {count, plural, =1{wiadomość} few{wiadomości} many{wiadomości} other{wiadomości}}", + "notification_channelMessagesCount": "{count} {count, plural, =1{wiadomość kanału} few{wiadomości kanału} many{wiadomości kanału} other{wiadomości kanału}}", + "notification_newNodesCount": "{count} {count, plural, =1{nowy węzeł} few{nowe węzły} many{nowych węzłów} other{nowych węzłów}}", + "notification_newTypeDiscovered": "Nowy {contactType} wykryty", + "notification_receivedNewMessage": "Otrzymano nową wiadomość", + "contacts_zeroHopContactAdvertFailed": "Nie udało się wysłać kontaktu.", "settings_gpxExportContacts": "Eksportuj towarzyszy do GPX", "settings_gpxExportRepeaters": "Eksportuj powtórki / serwer pokojowy do GPX", "settings_gpxExportRepeatersSubtitle": "Eksportuje powtarzacze / roomserver z lokalizacją do pliku GPX.", @@ -1585,4 +1592,5 @@ "settings_gpxExportShareText": "Dane mapy wyeksportowane z meshcore-open", "settings_gpxExportShareSubject": "Eksport danych mapy GPX meshcore-open", "pathTrace_someHopsNoLocation": "Jeden lub więcej z chmieli nie ma określonej lokalizacji!" + } diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index 6c260b9..dc38c11 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -1569,6 +1569,13 @@ "contacts_contactAdvertCopyFailed": "Cópia do anúncio para a Área de Transferência falhou.", "contacts_ShareContactZeroHop": "Compartilhar contato por anúncio", "contacts_zeroHopContactAdvertFailed": "Falha ao enviar contato.", + "notification_activityTitle": "Atividade MeshCore", + "notification_messagesCount": "{count} {count, plural, =1{mensagem} other{mensagens}}", + "notification_channelMessagesCount": "{count} {count, plural, =1{mensagem de canal} other{mensagens de canal}}", + "notification_newNodesCount": "{count} {count, plural, =1{novo nó} other{novos nós}}", + "notification_newTypeDiscovered": "Novo {contactType} descoberto", + "notification_receivedNewMessage": "Nova mensagem recebida", + "contacts_zeroHopContactAdvertFailed": "Falha ao enviar contato.", "settings_gpxExportRepeaters": "Exportar repetidores / servidor de sala para GPX", "settings_gpxExportRepeatersSubtitle": "Exporta repetidores / roomserver com localização para arquivo GPX.", "settings_gpxExportSuccess": "Arquivo GPX exportado com sucesso.", @@ -1585,4 +1592,5 @@ "settings_gpxExportShareText": "Dados do mapa exportados do meshcore-open", "settings_gpxExportShareSubject": "meshcore-open exportação de dados de mapa GPX", "pathTrace_someHopsNoLocation": "Um ou mais dos lúpulos estão sem localização!" + } diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index 8ab90e7..ddbbe79 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -809,6 +809,13 @@ "contacts_addContactFromClipboard": "Добавить контакт из буфера обмена", "contacts_ShareContactZeroHop": "Поделиться контактом по объявлению", "contacts_zeroHopContactAdvertSent": "Отправлено сообщение по объявлению.", + "notification_activityTitle": "Активность MeshCore", + "notification_messagesCount": "{count} {count, plural, =1{сообщение} few{сообщения} many{сообщений} other{сообщений}}", + "notification_channelMessagesCount": "{count} {count, plural, =1{сообщение канала} few{сообщения канала} many{сообщений канала} other{сообщений канала}}", + "notification_newNodesCount": "{count} {count, plural, =1{новый узел} few{новых узла} many{новых узлов} other{новых узлов}}", + "notification_newTypeDiscovered": "Обнаружен новый {contactType}", + "notification_receivedNewMessage": "Получено новое сообщение", + "contacts_zeroHopContactAdvertSent": "Отправлено сообщение по объявлению.", "settings_gpxExportRepeaters": "Экспортировать рипитеры / сервер комнаты в GPX", "settings_gpxExportRepeatersSubtitle": "Экспортирует ретрансляторы / сервер комнат с местоположением в файл GPX.", "settings_gpxExportContacts": "Экспортировать спутников в GPX", @@ -825,4 +832,5 @@ "settings_gpxExportShareText": "Данные карты экспортированы из meshcore-open", "settings_gpxExportShareSubject": "meshcore-open экспорт данных карты GPX", "pathTrace_someHopsNoLocation": "Одному или нескольким хмелям не указано местоположение!" + } diff --git a/lib/l10n/app_sk.arb b/lib/l10n/app_sk.arb index 9988138..c09502a 100644 --- a/lib/l10n/app_sk.arb +++ b/lib/l10n/app_sk.arb @@ -1569,6 +1569,13 @@ "contacts_zeroHopContactAdvertFailed": "Zlyhalo odoslanie kontaktu.", "contacts_ShareContactZeroHop": "Zdieľať kontakt cez inzerát", "contacts_ShareContact": "Kopírovať kontakt do schránky", + "notification_activityTitle": "Aktivita MeshCore", + "notification_messagesCount": "{count} {count, plural, =1{správa} few{správy} other{správ}}", + "notification_channelMessagesCount": "{count} {count, plural, =1{správa kanálu} few{správy kanálu} other{správ kanálu}}", + "notification_newNodesCount": "{count} {count, plural, =1{nový uzol} few{nové uzly} other{nových uzlov}}", + "notification_newTypeDiscovered": "Nový {contactType} objavený", + "notification_receivedNewMessage": "Prijatá nová správa", + "contacts_ShareContact": "Kopírovať kontakt do schránky", "settings_gpxExportRepeatersSubtitle": "Exportuje repeater / roomserver s lokalitou do súboru GPX.", "settings_gpxExportContacts": "Export sprievodcov do GPX", "settings_gpxExportSuccess": "Úspešne exportovaný súbor GPX.", @@ -1585,4 +1592,5 @@ "settings_gpxExportShareText": "Mapové údaje exportované z meshcore-open", "settings_gpxExportShareSubject": "meshcore-open export dát GPX mapových údajov", "pathTrace_someHopsNoLocation": "Jedna alebo viac chmeľov chýba lokalita!" + } diff --git a/lib/l10n/app_sl.arb b/lib/l10n/app_sl.arb index 6392dff..97a396a 100644 --- a/lib/l10n/app_sl.arb +++ b/lib/l10n/app_sl.arb @@ -1569,6 +1569,13 @@ "contacts_contactAdvertCopyFailed": "Kopiranje oglasa v odložišče je spodletelo.", "contacts_ShareContactZeroHop": "Deliti kontakt prek oglasa", "contacts_ShareContact": "Kopiraj stik v Odložišče", + "notification_activityTitle": "Aktivnost MeshCore", + "notification_messagesCount": "{count} {count, plural, =1{sporočilo} =2{sporočili} few{sporočila} other{sporočil}}", + "notification_channelMessagesCount": "{count} {count, plural, =1{sporočilo kanala} =2{sporočili kanala} few{sporočila kanala} other{sporočil kanala}}", + "notification_newNodesCount": "{count} {count, plural, =1{novo vozlišče} =2{novi vozlišči} few{nova vozlišča} other{novih vozlišč}}", + "notification_newTypeDiscovered": "Odkrito novo {contactType}", + "notification_receivedNewMessage": "Prejeto novo sporočilo", + "contacts_ShareContact": "Kopiraj stik v Odložišče", "settings_gpxExportAll": "Izvozi vse kontakte v GPX", "settings_gpxExportContacts": "Izvoz spremljevalcev v GPX", "settings_gpxExportRepeatersSubtitle": "Izvozi ponovljene oddajnike / strežnik sobe z lokacijo v datoteko GPX.", @@ -1585,4 +1592,5 @@ "settings_gpxExportNotAvailable": "Ni podprto na vašem napravi/operacijskem sistemu", "settings_gpxExportShareSubject": "meshcore-open izvoz podatkov GPX karte", "pathTrace_someHopsNoLocation": "Ena ali več hmelju manjka lokacija!" + } diff --git a/lib/l10n/app_sv.arb b/lib/l10n/app_sv.arb index 08ed323..6df28bd 100644 --- a/lib/l10n/app_sv.arb +++ b/lib/l10n/app_sv.arb @@ -1569,6 +1569,13 @@ "contacts_ShareContact": "Kopiera kontakt till Urklipp", "contacts_zeroHopContactAdvertFailed": "Misslyckades med att skicka kontakt.", "contacts_ShareContactZeroHop": "Dela kontakt via annons", + "notification_activityTitle": "MeshCore Aktivitet", + "notification_messagesCount": "{count} {count, plural, =1{meddelande} other{meddelanden}}", + "notification_channelMessagesCount": "{count} {count, plural, =1{kanalmeddelande} other{kanalmeddelanden}}", + "notification_newNodesCount": "{count} {count, plural, =1{ny nod} other{nya noder}}", + "notification_newTypeDiscovered": "Ny {contactType} upptäckt", + "notification_receivedNewMessage": "Nytt meddelande mottaget", + "contacts_ShareContactZeroHop": "Dela kontakt via annons", "settings_gpxExportAll": "Exportera alla kontakter till GPX", "settings_gpxExportRepeatersSubtitle": "Exporterar repeater / roomserver med plats till GPX-fil.", "settings_gpxExportSuccess": "Har exporterat GPX-fil med framgång", @@ -1585,4 +1592,5 @@ "settings_gpxExportShareSubject": "meshcore-open export av GPX-kartdata", "settings_gpxExportShareText": "Kartdata exporterad från meshcore-open", "pathTrace_someHopsNoLocation": "En eller flera av humlen saknar en plats!" + } diff --git a/lib/l10n/app_uk.arb b/lib/l10n/app_uk.arb index 2cea864..9f5e64d 100644 --- a/lib/l10n/app_uk.arb +++ b/lib/l10n/app_uk.arb @@ -1569,6 +1569,13 @@ "contacts_zeroHopContactAdvertSent": "Відправлено контакт за оголошенням", "contacts_addContactFromClipboard": "Додати контакт з буфера обміну", "contacts_ShareContactZeroHop": "Поділитися контактом за оголошенням", + "notification_activityTitle": "Активність MeshCore", + "notification_messagesCount": "{count} {count, plural, =1{повідомлення} few{повідомлення} many{повідомлень} other{повідомлень}}", + "notification_channelMessagesCount": "{count} {count, plural, =1{повідомлення каналу} few{повідомлення каналу} many{повідомлень каналу} other{повідомлень каналу}}", + "notification_newNodesCount": "{count} {count, plural, =1{новий вузол} few{нових вузли} many{нових вузлів} other{нових вузлів}}", + "notification_newTypeDiscovered": "Виявлено новий {contactType}", + "notification_receivedNewMessage": "Отримано нове повідомлення", + "contacts_ShareContactZeroHop": "Поділитися контактом за оголошенням", "settings_gpxExportRepeaters": "Експортувати ретранслятори / сервер кімнати до GPX", "settings_gpxExportRepeatersSubtitle": "Експортує ретранслятори / сервер кімнати з місцезнаходженням у файл GPX.", "settings_gpxExportSuccess": "Успішно експортовано файл GPX.", @@ -1585,4 +1592,5 @@ "settings_gpxExportAllContacts": "Усі місця контактів", "settings_gpxExportShareSubject": "експорт даних карти meshcore-open у форматі GPX", "pathTrace_someHopsNoLocation": "Одне або більше хмелів відсутнє місце розташування!" + } diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index c6b27f5..8c65510 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -1569,6 +1569,13 @@ "contacts_zeroHopContactAdvertFailed": "发送联系方式失败。", "contacts_contactAdvertCopied": "广告内容已复制到剪贴板。", "contacts_contactAdvertCopyFailed": "将广告复制到剪贴板操作失败。", + "notification_activityTitle": "MeshCore 活动", + "notification_messagesCount": "{count} 条消息", + "notification_channelMessagesCount": "{count} 条频道消息", + "notification_newNodesCount": "{count} 个新节点", + "notification_newTypeDiscovered": "发现新 {contactType}", + "notification_receivedNewMessage": "收到新消息", + "contacts_contactAdvertCopyFailed": "将广告复制到剪贴板操作失败。", "settings_gpxExportRepeaters": "导出重复器/房间服务器到GPX", "settings_gpxExportRepeatersSubtitle": "导出带有位置的重复器/房间服务器到GPX文件。", "settings_gpxExportContactsSubtitle": "导出带有位置的伙伴到GPX文件。", @@ -1585,4 +1592,5 @@ "settings_gpxExportShareText": "来自meshcore-open的导出地图数据", "settings_gpxExportShareSubject": "meshcore-open GPX 地图数据导出", "pathTrace_someHopsNoLocation": "其中一个或多个啤酒花缺少位置!" + } diff --git a/lib/main.dart b/lib/main.dart index 96a853d..8ee0ca4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -150,6 +150,12 @@ class MeshCoreApp extends StatelessWidget { themeMode: _themeModeFromSetting( settingsService.settings.themeMode, ), + builder: (context, child) { + // Update notification service with resolved locale + final locale = Localizations.localeOf(context); + NotificationService().setLocale(locale); + return child ?? const SizedBox.shrink(); + }, home: const ScannerScreen(), ); }, diff --git a/lib/services/notification_service.dart b/lib/services/notification_service.dart index d835d07..57331aa 100644 --- a/lib/services/notification_service.dart +++ b/lib/services/notification_service.dart @@ -1,6 +1,10 @@ +import 'dart:ui'; + import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter/foundation.dart'; +import '../l10n/app_localizations.dart'; + class NotificationService { static final NotificationService _instance = NotificationService._internal(); factory NotificationService() => _instance; @@ -10,6 +14,34 @@ class NotificationService { FlutterLocalNotificationsPlugin(); bool _isInitialized = false; + // Locale for localized notification strings + Locale _locale = const Locale('en'); + + /// Set the locale for notification strings (call when app locale changes) + void setLocale(Locale locale) { + _locale = locale; + } + + AppLocalizations get _l10n => lookupAppLocalizations(_locale); + + // Rate limiting to prevent notification storms + // (Added after getting notification-flooded while evaluating RF flood management. The irony.) + static const _minNotificationInterval = Duration(seconds: 3); + static const _batchWindow = Duration(seconds: 5); + + DateTime? _lastNotificationTime; + final List<_PendingNotification> _pendingNotifications = []; + bool _isBatchingActive = false; + bool _suppressNotifications = false; + + /// Temporarily suppress all notifications (e.g., during sync) + void suppressNotifications(bool suppress) { + _suppressNotifications = suppress; + if (suppress) { + _pendingNotifications.clear(); + } + } + Future initialize() async { if (_isInitialized) return; @@ -76,7 +108,7 @@ class NotificationService { return true; } - Future showMessageNotification({ + Future _showMessageNotificationImpl({ required String contactName, required String message, String? contactId, @@ -125,7 +157,7 @@ class NotificationService { ); } - Future showAdvertNotification({ + Future _showAdvertNotificationImpl({ required String contactName, required String contactType, String? contactId, @@ -163,14 +195,14 @@ class NotificationService { await _notifications.show( contactId?.hashCode ?? DateTime.now().millisecondsSinceEpoch, - 'New $contactType discovered', + _l10n.notification_newTypeDiscovered(contactType), contactName, notificationDetails, payload: 'advert:$contactId', ); } - Future showChannelMessageNotification({ + Future _showChannelMessageNotificationImpl({ required String channelName, required String message, int? channelIndex, @@ -211,7 +243,9 @@ class NotificationService { ); final preview = message.trim(); - final body = preview.isEmpty ? 'Received new message' : preview; + final body = preview.isEmpty + ? _l10n.notification_receivedNewMessage + : preview; await _notifications.show( channelIndex?.hashCode ?? DateTime.now().millisecondsSinceEpoch, @@ -222,6 +256,21 @@ class NotificationService { ); } + /// Returns a privacy-safe identifier for debug logging. + /// - advert: shows device name (body contains contactName) + /// - message: shows "from: sender" (avoids logging message content) + /// - channelMessage: shows "in: channel" (avoids logging message content) + String _getNotificationIdentifier(_PendingNotification n) { + switch (n.type) { + case _NotificationType.advert: + return n.body; + case _NotificationType.message: + return 'from: ${n.title}'; + case _NotificationType.channelMessage: + return 'in: ${n.title}'; + } + } + void _onNotificationTapped(NotificationResponse response) { final payload = response.payload; if (payload != null) { @@ -238,4 +287,212 @@ class NotificationService { Future cancel(int id) async { await _notifications.cancel(id); } + + // ───────────────────────────────────────────────────────────────── + // Public notification methods (rate limiting is enforced automatically) + // ───────────────────────────────────────────────────────────────── + + Future showMessageNotification({ + required String contactName, + required String message, + String? contactId, + int? badgeCount, + }) async { + if (_suppressNotifications) return; + + _queueNotification( + _PendingNotification( + type: _NotificationType.message, + title: contactName, + body: message, + id: contactId, + badgeCount: badgeCount, + ), + ); + } + + Future showAdvertNotification({ + required String contactName, + required String contactType, + String? contactId, + }) async { + if (_suppressNotifications) return; + + _queueNotification( + _PendingNotification( + type: _NotificationType.advert, + title: contactType, + body: contactName, + id: contactId, + ), + ); + } + + Future showChannelMessageNotification({ + required String channelName, + required String message, + int? channelIndex, + int? badgeCount, + }) async { + if (_suppressNotifications) return; + + _queueNotification( + _PendingNotification( + type: _NotificationType.channelMessage, + title: channelName, + body: message, + id: channelIndex?.toString(), + badgeCount: badgeCount, + ), + ); + } + + void _queueNotification(_PendingNotification notification) { + final now = DateTime.now(); + + // If we recently showed a notification, start batching + if (_lastNotificationTime != null && + now.difference(_lastNotificationTime!) < _minNotificationInterval) { + _pendingNotifications.add(notification); + debugPrint( + '[Notification] queued: ${notification.type.name} (${_getNotificationIdentifier(notification)})', + ); + + // Start batch timer if not already running + if (!_isBatchingActive) { + _isBatchingActive = true; + Future.delayed(_batchWindow, _processBatch); + } + return; + } + + // Show immediately if enough time has passed + debugPrint( + '[Notification] sent immediately: ${notification.type.name} (${_getNotificationIdentifier(notification)})', + ); + _showNotificationImmediately(notification); + _lastNotificationTime = now; + } + + Future _processBatch() async { + _isBatchingActive = false; + + if (_pendingNotifications.isEmpty) return; + + final batch = List<_PendingNotification>.from(_pendingNotifications); + _pendingNotifications.clear(); + + if (batch.length == 1) { + // Single notification, show normally + _showNotificationImmediately(batch.first); + } else { + // Multiple notifications, show summary + await _showBatchSummary(batch); + } + + _lastNotificationTime = DateTime.now(); + } + + Future _showNotificationImmediately( + _PendingNotification notification, + ) async { + switch (notification.type) { + case _NotificationType.message: + await _showMessageNotificationImpl( + contactName: notification.title, + message: notification.body, + contactId: notification.id, + badgeCount: notification.badgeCount, + ); + break; + case _NotificationType.advert: + await _showAdvertNotificationImpl( + contactName: notification.body, + contactType: notification.title, + contactId: notification.id, + ); + break; + case _NotificationType.channelMessage: + await _showChannelMessageNotificationImpl( + channelName: notification.title, + message: notification.body, + channelIndex: int.tryParse(notification.id ?? ''), + badgeCount: notification.badgeCount, + ); + break; + } + } + + Future _showBatchSummary(List<_PendingNotification> batch) async { + if (!_isInitialized) await initialize(); + + // Group by type + final messages = batch + .where((n) => n.type == _NotificationType.message) + .toList(); + final adverts = batch + .where((n) => n.type == _NotificationType.advert) + .toList(); + final channelMsgs = batch + .where((n) => n.type == _NotificationType.channelMessage) + .toList(); + + // Build summary text using localized plurals + final parts = []; + if (messages.isNotEmpty) { + parts.add(_l10n.notification_messagesCount(messages.length)); + } + if (channelMsgs.isNotEmpty) { + parts.add(_l10n.notification_channelMessagesCount(channelMsgs.length)); + } + if (adverts.isNotEmpty) { + parts.add(_l10n.notification_newNodesCount(adverts.length)); + } + + if (parts.isEmpty) return; + + // Show first few device names in batch summary for debugging (only if adverts exist) + final deviceInfo = adverts.isNotEmpty + ? ' (${adverts.take(5).map((n) => n.body).join(', ')}${adverts.length > 5 ? ', ...' : ''})' + : ''; + debugPrint('[Notification] batch summary: ${parts.join(", ")}$deviceInfo'); + + const androidDetails = AndroidNotificationDetails( + 'batch_summary', + 'Activity Summary', + channelDescription: 'Batched notification summaries', + importance: Importance.defaultImportance, + priority: Priority.defaultPriority, + icon: '@mipmap/ic_launcher', + ); + + const notificationDetails = NotificationDetails(android: androidDetails); + + await _notifications.show( + 'batch_summary'.hashCode, + _l10n.notification_activityTitle, + parts.join(', '), + notificationDetails, + payload: 'batch', + ); + } +} + +// Helper class for pending notifications +enum _NotificationType { message, advert, channelMessage } + +class _PendingNotification { + final _NotificationType type; + final String title; + final String body; + final String? id; + final int? badgeCount; + + _PendingNotification({ + required this.type, + required this.title, + required this.body, + this.id, + this.badgeCount, + }); } diff --git a/untranslated.json b/untranslated.json index 9e26dfe..e0ad904 100644 --- a/untranslated.json +++ b/untranslated.json @@ -1 +1,127 @@ -{} \ No newline at end of file +{ + "bg": [ + "notification_activityTitle", + "notification_messagesCount", + "notification_channelMessagesCount", + "notification_newNodesCount", + "notification_newTypeDiscovered", + "notification_receivedNewMessage" + ], + + "de": [ + "notification_activityTitle", + "notification_messagesCount", + "notification_channelMessagesCount", + "notification_newNodesCount", + "notification_newTypeDiscovered", + "notification_receivedNewMessage" + ], + + "es": [ + "notification_activityTitle", + "notification_messagesCount", + "notification_channelMessagesCount", + "notification_newNodesCount", + "notification_newTypeDiscovered", + "notification_receivedNewMessage" + ], + + "fr": [ + "notification_activityTitle", + "notification_messagesCount", + "notification_channelMessagesCount", + "notification_newNodesCount", + "notification_newTypeDiscovered", + "notification_receivedNewMessage" + ], + + "it": [ + "notification_activityTitle", + "notification_messagesCount", + "notification_channelMessagesCount", + "notification_newNodesCount", + "notification_newTypeDiscovered", + "notification_receivedNewMessage" + ], + + "nl": [ + "notification_activityTitle", + "notification_messagesCount", + "notification_channelMessagesCount", + "notification_newNodesCount", + "notification_newTypeDiscovered", + "notification_receivedNewMessage" + ], + + "pl": [ + "notification_activityTitle", + "notification_messagesCount", + "notification_channelMessagesCount", + "notification_newNodesCount", + "notification_newTypeDiscovered", + "notification_receivedNewMessage" + ], + + "pt": [ + "notification_activityTitle", + "notification_messagesCount", + "notification_channelMessagesCount", + "notification_newNodesCount", + "notification_newTypeDiscovered", + "notification_receivedNewMessage" + ], + + "ru": [ + "notification_activityTitle", + "notification_messagesCount", + "notification_channelMessagesCount", + "notification_newNodesCount", + "notification_newTypeDiscovered", + "notification_receivedNewMessage" + ], + + "sk": [ + "notification_activityTitle", + "notification_messagesCount", + "notification_channelMessagesCount", + "notification_newNodesCount", + "notification_newTypeDiscovered", + "notification_receivedNewMessage" + ], + + "sl": [ + "notification_activityTitle", + "notification_messagesCount", + "notification_channelMessagesCount", + "notification_newNodesCount", + "notification_newTypeDiscovered", + "notification_receivedNewMessage" + ], + + "sv": [ + "notification_activityTitle", + "notification_messagesCount", + "notification_channelMessagesCount", + "notification_newNodesCount", + "notification_newTypeDiscovered", + "notification_receivedNewMessage" + ], + + "uk": [ + "notification_activityTitle", + "notification_messagesCount", + "notification_channelMessagesCount", + "notification_newNodesCount", + "notification_newTypeDiscovered", + "notification_receivedNewMessage" + ], + + "zh": [ + "notification_activityTitle", + "notification_messagesCount", + "notification_channelMessagesCount", + "notification_newNodesCount", + "notification_newTypeDiscovered", + "notification_receivedNewMessage" + ] +}