diff --git a/lib/connector/meshcore_connector.dart b/lib/connector/meshcore_connector.dart index 982f7e75..7eca6e88 100644 --- a/lib/connector/meshcore_connector.dart +++ b/lib/connector/meshcore_connector.dart @@ -1072,18 +1072,30 @@ class MeshCoreConnector extends ChangeNotifier { } } - Future _translateIncomingContactMessage( + Future translateContactMessage( String contactKeyHex, - Message message, - ) async { + Message message, { + bool manualTranslation = false, + }) async { try { + if (message.translatedText?.trim().isNotEmpty == true || + (!manualTranslation && + message.translationStatus != MessageTranslationStatus.none)) { + return null; + } final service = _translationService; if (service == null || - !service.shouldTranslateIncoming( - text: message.text, - isCli: message.isCli, - isOutgoing: message.isOutgoing, - )) { + !(manualTranslation + ? service.canTranslateIncoming( + text: message.text, + isCli: message.isCli, + isOutgoing: message.isOutgoing, + ) + : service.shouldAutoTranslateIncoming( + text: message.text, + isCli: message.isCli, + isOutgoing: message.isOutgoing, + ))) { return null; } final targetLanguageCode = service.resolvedIncomingLanguageCode( @@ -1116,18 +1128,30 @@ class MeshCoreConnector extends ChangeNotifier { } } - Future _translateIncomingChannelMessage( + Future translateChannelMessage( int channelIndex, - ChannelMessage message, - ) async { + ChannelMessage message, { + bool manualTranslation = false, + }) async { try { + if (message.translatedText?.trim().isNotEmpty == true || + (!manualTranslation && + message.translationStatus != MessageTranslationStatus.none)) { + return null; + } final service = _translationService; if (service == null || - !service.shouldTranslateIncoming( - text: message.text, - isCli: false, - isOutgoing: message.isOutgoing, - )) { + !(manualTranslation + ? service.canTranslateIncoming( + text: message.text, + isCli: false, + isOutgoing: message.isOutgoing, + ) + : service.shouldAutoTranslateIncoming( + text: message.text, + isCli: false, + isOutgoing: message.isOutgoing, + ))) { return null; } final targetLanguageCode = service.resolvedIncomingLanguageCode( @@ -4421,7 +4445,7 @@ class MeshCoreConnector extends ChangeNotifier { final msg = message; // capture for closure final c = contact; // capture contact reference unawaited(() async { - final translationResult = await _translateIncomingContactMessage( + final translationResult = await translateContactMessage( msg.senderKeyHex, msg, ); @@ -4784,7 +4808,7 @@ class MeshCoreConnector extends ChangeNotifier { if (isNew && !message.isOutgoing) { final msg = message; // capture for closure unawaited(() async { - final translationResult = await _translateIncomingChannelMessage( + final translationResult = await translateChannelMessage( msg.channelIndex!, msg, ); @@ -4867,7 +4891,7 @@ class MeshCoreConnector extends ChangeNotifier { if (isNew) { // Run translation + notification asynchronously to avoid blocking unawaited(() async { - final translationResult = await _translateIncomingChannelMessage( + final translationResult = await translateChannelMessage( channel.index, message, ); diff --git a/lib/l10n/app_bg.arb b/lib/l10n/app_bg.arb index 45536cf6..c70ca78d 100644 --- a/lib/l10n/app_bg.arb +++ b/lib/l10n/app_bg.arb @@ -2099,6 +2099,9 @@ "translation_composerTitle": "Преведете преди да изпратите", "translation_enableSubtitle": "Превеждайте входящите съобщения и позволявайте предварително превеждане преди изпращане.", "translation_composerSubtitle": "Контролира началния статус на иконата за превод, създадена от композитора.", + "translation_autoIncomingTitle": "Автоматичен превод на съобщения", + "translation_autoIncomingSubtitle": "Превежда автоматично съобщенията за известия, както и за чатове или канали.", + "translation_translateMessage": "Преведи съобщението", "translation_targetLanguage": "Целеви език", "translation_useAppLanguage": "Използвайте езика на приложението", "translation_downloadedModelLabel": "Изтегнат модел", diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 7f491d4f..4a9be70b 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -2127,6 +2127,9 @@ "translation_enableSubtitle": "Nachrichten empfangen und übersetzen sowie die Möglichkeit bieten, Nachrichten vor dem Versenden zu übersetzen.", "translation_enableTitle": "Aktivieren Sie die Übersetzung", "translation_composerSubtitle": "Steuert den Standardzustand des Icons für die Übersetzung des Komponisten.", + "translation_autoIncomingTitle": "Nachrichten automatisch übersetzen", + "translation_autoIncomingSubtitle": "Übersetzt Nachrichten für Benachrichtigungen sowie für Chats oder Kanäle automatisch.", + "translation_translateMessage": "Nachricht übersetzen", "translation_targetLanguage": "Zielsprache", "translation_useAppLanguage": "Verwenden Sie die App-Sprache", "translation_downloadedModelLabel": "Heruntergeladenes Modell", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 456fab56..b3c5774a 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -2288,6 +2288,9 @@ "translation_enableSubtitle": "Translate incoming messages and allow pre-send translation.", "translation_composerTitle": "Translate before sending", "translation_composerSubtitle": "Controls the default state of the composer translation icon.", + "translation_autoIncomingTitle": "Auto-translate incoming messages", + "translation_autoIncomingSubtitle": "Translates Messages for notification and for chat or channel automatically.", + "translation_translateMessage": "Translate message", "translation_targetLanguage": "Target language", "translation_useAppLanguage": "Use app language", "translation_downloadedModelLabel": "Downloaded model", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index d4cf27da..b85e7652 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -2128,6 +2128,9 @@ "translation_enableTitle": "Habilitar la traducción", "translation_composerTitle": "Traducir antes de enviar", "translation_composerSubtitle": "Controla el estado predeterminado del icono de traducción del compositor.", + "translation_autoIncomingTitle": "Traducir mensajes automáticamente", + "translation_autoIncomingSubtitle": "Traduce mensajes para notificaciones y para chats o canales automáticamente.", + "translation_translateMessage": "Traducir mensaje", "translation_targetLanguage": "Idioma de destino", "translation_useAppLanguage": "Utilizar el idioma de la aplicación", "translation_downloadedModelLabel": "Modelo descargado", diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 7817c20d..fd6b53e0 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -2099,6 +2099,9 @@ "translation_title": "Traduction", "translation_enableSubtitle": "Traduire les messages entrants et permettre la traduction avant l'envoi.", "translation_composerSubtitle": "Contrôle l'état par défaut de l'icône de traduction du composant.", + "translation_autoIncomingTitle": "Traduire automatiquement les messages", + "translation_autoIncomingSubtitle": "Traduit automatiquement les messages pour les notifications et pour les discussions ou les canaux.", + "translation_translateMessage": "Traduire le message", "translation_targetLanguage": "Langue cible", "translation_useAppLanguage": "Utiliser la langue de l'application", "translation_downloadedModelLabel": "Modèle téléchargé", diff --git a/lib/l10n/app_hu.arb b/lib/l10n/app_hu.arb index 97426183..d41c62f2 100644 --- a/lib/l10n/app_hu.arb +++ b/lib/l10n/app_hu.arb @@ -2137,6 +2137,9 @@ "translation_enableSubtitle": "Fordítsa az érkező üzeneteket, és lehetővé tegye a küldés előtti fordítást.", "translation_composerTitle": "Fordítsa el, mielőtt elküldi", "translation_composerSubtitle": "Ellenőrzi a zeneszerző fordítási ikon alapértékét.", + "translation_autoIncomingTitle": "Üzenetek automatikus fordítása", + "translation_autoIncomingSubtitle": "Automatikusan lefordítja az üzeneteket az értesítésekhez, valamint a csevegésekhez vagy csatornákhoz.", + "translation_translateMessage": "Üzenet fordítása", "translation_targetLanguage": "Célnyelv", "translation_useAppLanguage": "Használja az alkalmazás nyelvének beállítását.", "translation_downloadedModelLabel": "Letöltött modell", diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb index 664bceef..e60cfc4a 100644 --- a/lib/l10n/app_it.arb +++ b/lib/l10n/app_it.arb @@ -2100,6 +2100,9 @@ "translation_enableTitle": "Abilitare la traduzione", "translation_title": "Traduzione", "translation_composerSubtitle": "Controlla lo stato predefinito dell'icona di traduzione del compositore.", + "translation_autoIncomingTitle": "Traduci automaticamente i messaggi", + "translation_autoIncomingSubtitle": "Traduce automaticamente i messaggi per le notifiche e per le chat o i canali.", + "translation_translateMessage": "Traduci messaggio", "translation_targetLanguage": "Lingua di destinazione", "translation_useAppLanguage": "Utilizza la lingua dell'app", "translation_downloadedModelLabel": "Modello scaricato", diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index 9d2cef21..c68fc98d 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -2137,6 +2137,9 @@ "translation_composerTitle": "送信する前に翻訳する", "translation_enableTitle": "翻訳機能を有効にする", "translation_composerSubtitle": "作曲家翻訳アイコンのデフォルト状態を制御する。", + "translation_autoIncomingTitle": "メッセージを自動翻訳", + "translation_autoIncomingSubtitle": "通知やチャット、チャンネルのメッセージを自動的に翻訳します。", + "translation_translateMessage": "メッセージを翻訳", "translation_targetLanguage": "翻訳対象言語", "translation_useAppLanguage": "アプリの言語設定", "translation_downloadedModelLabel": "ダウンロードしたモデル", diff --git a/lib/l10n/app_ko.arb b/lib/l10n/app_ko.arb index d778429b..7418068c 100644 --- a/lib/l10n/app_ko.arb +++ b/lib/l10n/app_ko.arb @@ -2137,6 +2137,9 @@ "translation_enableTitle": "번역 기능 활성화", "translation_composerTitle": "보내기 전에 번역", "translation_composerSubtitle": "컴포저 번역 아이콘의 기본 상태를 제어합니다.", + "translation_autoIncomingTitle": "메시지 자동 번역", + "translation_autoIncomingSubtitle": "알림과 채팅 또는 채널의 메시지를 자동으로 번역합니다.", + "translation_translateMessage": "메시지 번역", "translation_targetLanguage": "목표 언어", "translation_useAppLanguage": "앱 언어 사용", "translation_downloadedModelLabel": "다운로드한 모델", diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index 159d755c..b8c6558c 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -7114,6 +7114,24 @@ abstract class AppLocalizations { /// **'Controls the default state of the composer translation icon.'** String get translation_composerSubtitle; + /// No description provided for @translation_autoIncomingTitle. + /// + /// In en, this message translates to: + /// **'Auto-translate incoming messages'** + String get translation_autoIncomingTitle; + + /// No description provided for @translation_autoIncomingSubtitle. + /// + /// In en, this message translates to: + /// **'Translates Messages for notification and for chat or channel automatically.'** + String get translation_autoIncomingSubtitle; + + /// No description provided for @translation_translateMessage. + /// + /// In en, this message translates to: + /// **'Translate message'** + String get translation_translateMessage; + /// No description provided for @translation_targetLanguage. /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_bg.dart b/lib/l10n/app_localizations_bg.dart index 409803b2..19883f16 100644 --- a/lib/l10n/app_localizations_bg.dart +++ b/lib/l10n/app_localizations_bg.dart @@ -4161,6 +4161,16 @@ class AppLocalizationsBg extends AppLocalizations { String get translation_composerSubtitle => 'Контролира началния статус на иконата за превод, създадена от композитора.'; + @override + String get translation_autoIncomingTitle => 'Автоматичен превод на съобщения'; + + @override + String get translation_autoIncomingSubtitle => + 'Превежда автоматично съобщенията за известия, както и за чатове или канали.'; + + @override + String get translation_translateMessage => 'Преведи съобщението'; + @override String get translation_targetLanguage => 'Целеви език'; diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index 9f06906d..20d64c39 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -4176,6 +4176,17 @@ class AppLocalizationsDe extends AppLocalizations { String get translation_composerSubtitle => 'Steuert den Standardzustand des Icons für die Übersetzung des Komponisten.'; + @override + String get translation_autoIncomingTitle => + 'Nachrichten automatisch übersetzen'; + + @override + String get translation_autoIncomingSubtitle => + 'Übersetzt Nachrichten für Benachrichtigungen sowie für Chats oder Kanäle automatisch.'; + + @override + String get translation_translateMessage => 'Nachricht übersetzen'; + @override String get translation_targetLanguage => 'Zielsprache'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 6def06b7..5da877e1 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -4085,6 +4085,17 @@ class AppLocalizationsEn extends AppLocalizations { String get translation_composerSubtitle => 'Controls the default state of the composer translation icon.'; + @override + String get translation_autoIncomingTitle => + 'Auto-translate incoming messages'; + + @override + String get translation_autoIncomingSubtitle => + 'Translates Messages for notification and for chat or channel automatically.'; + + @override + String get translation_translateMessage => 'Translate message'; + @override String get translation_targetLanguage => 'Target language'; diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index bb4f40e8..f55bb1c7 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -4163,6 +4163,17 @@ class AppLocalizationsEs extends AppLocalizations { String get translation_composerSubtitle => 'Controla el estado predeterminado del icono de traducción del compositor.'; + @override + String get translation_autoIncomingTitle => + 'Traducir mensajes automáticamente'; + + @override + String get translation_autoIncomingSubtitle => + 'Traduce mensajes para notificaciones y para chats o canales automáticamente.'; + + @override + String get translation_translateMessage => 'Traducir mensaje'; + @override String get translation_targetLanguage => 'Idioma de destino'; diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index 44e40657..a1770dc3 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -4193,6 +4193,17 @@ class AppLocalizationsFr extends AppLocalizations { String get translation_composerSubtitle => 'Contrôle l\'état par défaut de l\'icône de traduction du composant.'; + @override + String get translation_autoIncomingTitle => + 'Traduire automatiquement les messages'; + + @override + String get translation_autoIncomingSubtitle => + 'Traduit automatiquement les messages pour les notifications et pour les discussions ou les canaux.'; + + @override + String get translation_translateMessage => 'Traduire le message'; + @override String get translation_targetLanguage => 'Langue cible'; diff --git a/lib/l10n/app_localizations_hu.dart b/lib/l10n/app_localizations_hu.dart index 298a6fd6..ee41febf 100644 --- a/lib/l10n/app_localizations_hu.dart +++ b/lib/l10n/app_localizations_hu.dart @@ -4181,6 +4181,16 @@ class AppLocalizationsHu extends AppLocalizations { String get translation_composerSubtitle => 'Ellenőrzi a zeneszerző fordítási ikon alapértékét.'; + @override + String get translation_autoIncomingTitle => 'Üzenetek automatikus fordítása'; + + @override + String get translation_autoIncomingSubtitle => + 'Automatikusan lefordítja az üzeneteket az értesítésekhez, valamint a csevegésekhez vagy csatornákhoz.'; + + @override + String get translation_translateMessage => 'Üzenet fordítása'; + @override String get translation_targetLanguage => 'Célnyelv'; diff --git a/lib/l10n/app_localizations_it.dart b/lib/l10n/app_localizations_it.dart index e3f7ee58..55804809 100644 --- a/lib/l10n/app_localizations_it.dart +++ b/lib/l10n/app_localizations_it.dart @@ -4169,6 +4169,17 @@ class AppLocalizationsIt extends AppLocalizations { String get translation_composerSubtitle => 'Controlla lo stato predefinito dell\'icona di traduzione del compositore.'; + @override + String get translation_autoIncomingTitle => + 'Traduci automaticamente i messaggi'; + + @override + String get translation_autoIncomingSubtitle => + 'Traduce automaticamente i messaggi per le notifiche e per le chat o i canali.'; + + @override + String get translation_translateMessage => 'Traduci messaggio'; + @override String get translation_targetLanguage => 'Lingua di destinazione'; diff --git a/lib/l10n/app_localizations_ja.dart b/lib/l10n/app_localizations_ja.dart index 263a906e..844f3b66 100644 --- a/lib/l10n/app_localizations_ja.dart +++ b/lib/l10n/app_localizations_ja.dart @@ -3941,6 +3941,16 @@ class AppLocalizationsJa extends AppLocalizations { @override String get translation_composerSubtitle => '作曲家翻訳アイコンのデフォルト状態を制御する。'; + @override + String get translation_autoIncomingTitle => 'メッセージを自動翻訳'; + + @override + String get translation_autoIncomingSubtitle => + '通知やチャット、チャンネルのメッセージを自動的に翻訳します。'; + + @override + String get translation_translateMessage => 'メッセージを翻訳'; + @override String get translation_targetLanguage => '翻訳対象言語'; diff --git a/lib/l10n/app_localizations_ko.dart b/lib/l10n/app_localizations_ko.dart index f9c0d760..1bc02940 100644 --- a/lib/l10n/app_localizations_ko.dart +++ b/lib/l10n/app_localizations_ko.dart @@ -3942,6 +3942,16 @@ class AppLocalizationsKo extends AppLocalizations { @override String get translation_composerSubtitle => '컴포저 번역 아이콘의 기본 상태를 제어합니다.'; + @override + String get translation_autoIncomingTitle => '메시지 자동 번역'; + + @override + String get translation_autoIncomingSubtitle => + '알림과 채팅 또는 채널의 메시지를 자동으로 번역합니다.'; + + @override + String get translation_translateMessage => '메시지 번역'; + @override String get translation_targetLanguage => '목표 언어'; diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index ad140bf3..cf78b5e7 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -4146,6 +4146,16 @@ class AppLocalizationsNl extends AppLocalizations { String get translation_composerSubtitle => 'Stelt de standaardstatus van het pictogram voor de vertaling van de componist in.'; + @override + String get translation_autoIncomingTitle => 'Berichten automatisch vertalen'; + + @override + String get translation_autoIncomingSubtitle => + 'Vertaalt berichten automatisch voor meldingen en voor chats of kanalen.'; + + @override + String get translation_translateMessage => 'Bericht vertalen'; + @override String get translation_targetLanguage => 'Doeltaal'; diff --git a/lib/l10n/app_localizations_pl.dart b/lib/l10n/app_localizations_pl.dart index 6c7c3696..e4b33f9f 100644 --- a/lib/l10n/app_localizations_pl.dart +++ b/lib/l10n/app_localizations_pl.dart @@ -4184,6 +4184,17 @@ class AppLocalizationsPl extends AppLocalizations { String get translation_composerSubtitle => 'Kontroluje domyślny stan ikony tłumaczenia w edytorze.'; + @override + String get translation_autoIncomingTitle => + 'Automatycznie tłumacz wiadomości'; + + @override + String get translation_autoIncomingSubtitle => + 'Automatycznie tłumaczy wiadomości do powiadomień oraz do czatów lub kanałów.'; + + @override + String get translation_translateMessage => 'Przetłumacz wiadomość'; + @override String get translation_targetLanguage => 'Język docelowy'; diff --git a/lib/l10n/app_localizations_pt.dart b/lib/l10n/app_localizations_pt.dart index e6fd49e3..f0ad632b 100644 --- a/lib/l10n/app_localizations_pt.dart +++ b/lib/l10n/app_localizations_pt.dart @@ -4159,6 +4159,17 @@ class AppLocalizationsPt extends AppLocalizations { String get translation_composerSubtitle => 'Controla o estado padrão do ícone de tradução do compositor.'; + @override + String get translation_autoIncomingTitle => + 'Traduzir mensagens automaticamente'; + + @override + String get translation_autoIncomingSubtitle => + 'Traduz automaticamente mensagens para notificações e para chats ou canais.'; + + @override + String get translation_translateMessage => 'Traduzir mensagem'; + @override String get translation_targetLanguage => 'Língua-alvo'; diff --git a/lib/l10n/app_localizations_ru.dart b/lib/l10n/app_localizations_ru.dart index 25452003..46ef46b6 100644 --- a/lib/l10n/app_localizations_ru.dart +++ b/lib/l10n/app_localizations_ru.dart @@ -4177,6 +4177,17 @@ class AppLocalizationsRu extends AppLocalizations { String get translation_composerSubtitle => 'Управляет исходным состоянием значка перевода, предоставляемого редактором.'; + @override + String get translation_autoIncomingTitle => + 'Автоматически переводить сообщения'; + + @override + String get translation_autoIncomingSubtitle => + 'Автоматически переводит сообщения для уведомлений, а также для чатов и каналов.'; + + @override + String get translation_translateMessage => 'Перевести сообщение'; + @override String get translation_targetLanguage => 'Целевой язык'; diff --git a/lib/l10n/app_localizations_sk.dart b/lib/l10n/app_localizations_sk.dart index 91461385..29a0b8a9 100644 --- a/lib/l10n/app_localizations_sk.dart +++ b/lib/l10n/app_localizations_sk.dart @@ -4141,6 +4141,16 @@ class AppLocalizationsSk extends AppLocalizations { String get translation_composerSubtitle => 'Riadi výchoce stav ikony pre preklad, ktorú používa program.'; + @override + String get translation_autoIncomingTitle => 'Automaticky prekladať správy'; + + @override + String get translation_autoIncomingSubtitle => + 'Automaticky prekladá správy pre upozornenia aj pre čet alebo kanál.'; + + @override + String get translation_translateMessage => 'Preložiť správu'; + @override String get translation_targetLanguage => 'Cieľový jazyk'; diff --git a/lib/l10n/app_localizations_sl.dart b/lib/l10n/app_localizations_sl.dart index 48103647..125aa604 100644 --- a/lib/l10n/app_localizations_sl.dart +++ b/lib/l10n/app_localizations_sl.dart @@ -4139,6 +4139,16 @@ class AppLocalizationsSl extends AppLocalizations { String get translation_composerSubtitle => 'Ureja privzeto stanje ikone za prevod, ki jo uporablja avtor.'; + @override + String get translation_autoIncomingTitle => 'Samodejno prevajaj sporočila'; + + @override + String get translation_autoIncomingSubtitle => + 'Samodejno prevaja sporočila za obvestila ter za klepete ali kanale.'; + + @override + String get translation_translateMessage => 'Prevedi sporočilo'; + @override String get translation_targetLanguage => 'Ciljna jezika'; diff --git a/lib/l10n/app_localizations_sv.dart b/lib/l10n/app_localizations_sv.dart index 7453c18f..4bf43719 100644 --- a/lib/l10n/app_localizations_sv.dart +++ b/lib/l10n/app_localizations_sv.dart @@ -4113,6 +4113,17 @@ class AppLocalizationsSv extends AppLocalizations { String get translation_composerSubtitle => 'Styr standardtillståndet för kompositorns översättningsikon.'; + @override + String get translation_autoIncomingTitle => + 'Översätt meddelanden automatiskt'; + + @override + String get translation_autoIncomingSubtitle => + 'Översätter meddelanden automatiskt för aviseringar och för chattar eller kanaler.'; + + @override + String get translation_translateMessage => 'Översätt meddelande'; + @override String get translation_targetLanguage => 'Målmedvetet språk'; diff --git a/lib/l10n/app_localizations_uk.dart b/lib/l10n/app_localizations_uk.dart index 9c30fd8e..58f381cf 100644 --- a/lib/l10n/app_localizations_uk.dart +++ b/lib/l10n/app_localizations_uk.dart @@ -4176,6 +4176,17 @@ class AppLocalizationsUk extends AppLocalizations { String get translation_composerSubtitle => 'Контролює стан ікон перекладу, який використовується за замовчуванням.'; + @override + String get translation_autoIncomingTitle => + 'Автоматично перекладати повідомлення'; + + @override + String get translation_autoIncomingSubtitle => + 'Автоматично перекладає повідомлення для сповіщень, а також для чатів і каналів.'; + + @override + String get translation_translateMessage => 'Перекласти повідомлення'; + @override String get translation_targetLanguage => 'Цільова мова'; diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index d2304a66..ec03b8e8 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -3816,6 +3816,15 @@ class AppLocalizationsZh extends AppLocalizations { @override String get translation_composerSubtitle => '控制作曲家翻译图标的默认状态。'; + @override + String get translation_autoIncomingTitle => '自动翻译消息'; + + @override + String get translation_autoIncomingSubtitle => '自动为通知以及聊天或频道翻译消息。'; + + @override + String get translation_translateMessage => '翻译消息'; + @override String get translation_targetLanguage => '目标语言'; diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb index 7e83215b..68d53148 100644 --- a/lib/l10n/app_nl.arb +++ b/lib/l10n/app_nl.arb @@ -2101,6 +2101,9 @@ "translation_composerTitle": "Vertaal voor verzending", "translation_composerSubtitle": "Stelt de standaardstatus van het pictogram voor de vertaling van de componist in.", "translation_useAppLanguage": "Gebruik de taal van de app", + "translation_autoIncomingTitle": "Berichten automatisch vertalen", + "translation_autoIncomingSubtitle": "Vertaalt berichten automatisch voor meldingen en voor chats of kanalen.", + "translation_translateMessage": "Bericht vertalen", "translation_targetLanguage": "Doeltaal", "translation_downloadedModelLabel": "Gedownloade model", "translation_presetModelLabel": "Voorgeprogrammeerd Hugging Face-model", diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index 4366e273..f79a589a 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -2137,6 +2137,9 @@ "translation_enableTitle": "Włącz tłumaczenie", "translation_enableSubtitle": "Tłumaczenie otrzymywanych wiadomości oraz umożliwienie tłumaczenia przed wysłaniem.", "translation_composerSubtitle": "Kontroluje domyślny stan ikony tłumaczenia w edytorze.", + "translation_autoIncomingTitle": "Automatycznie tłumacz wiadomości", + "translation_autoIncomingSubtitle": "Automatycznie tłumaczy wiadomości do powiadomień oraz do czatów lub kanałów.", + "translation_translateMessage": "Przetłumacz wiadomość", "translation_targetLanguage": "Język docelowy", "translation_useAppLanguage": "Użyj języka aplikacji", "translation_downloadedModelLabel": "Pobudowany model", diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index 6b8abbbc..994ff8a2 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -2100,6 +2100,9 @@ "translation_enableTitle": "Ativar a tradução", "translation_title": "Tradução", "translation_composerSubtitle": "Controla o estado padrão do ícone de tradução do compositor.", + "translation_autoIncomingTitle": "Traduzir mensagens automaticamente", + "translation_autoIncomingSubtitle": "Traduz automaticamente mensagens para notificações e para chats ou canais.", + "translation_translateMessage": "Traduzir mensagem", "translation_targetLanguage": "Língua-alvo", "translation_useAppLanguage": "Utilize o idioma da aplicação", "translation_downloadedModelLabel": "Modelo baixado", diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index 5d5bcfc3..2b0978a6 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -1268,6 +1268,9 @@ "translation_title": "Перевод", "translation_enableTitle": "Включить перевод", "translation_composerSubtitle": "Управляет исходным состоянием значка перевода, предоставляемого редактором.", + "translation_autoIncomingTitle": "Автоматически переводить сообщения", + "translation_autoIncomingSubtitle": "Автоматически переводит сообщения для уведомлений, а также для чатов и каналов.", + "translation_translateMessage": "Перевести сообщение", "translation_targetLanguage": "Целевой язык", "translation_useAppLanguage": "Используйте язык приложения", "translation_downloadedModelLabel": "Загруженная модель", diff --git a/lib/l10n/app_sk.arb b/lib/l10n/app_sk.arb index 713c3976..1a65b35f 100644 --- a/lib/l10n/app_sk.arb +++ b/lib/l10n/app_sk.arb @@ -2100,6 +2100,9 @@ "translation_composerTitle": "Preložte pred odeslaním", "translation_title": "Preklad", "translation_composerSubtitle": "Riadi výchoce stav ikony pre preklad, ktorú používa program.", + "translation_autoIncomingTitle": "Automaticky prekladať správy", + "translation_autoIncomingSubtitle": "Automaticky prekladá správy pre upozornenia aj pre čet alebo kanál.", + "translation_translateMessage": "Preložiť správu", "translation_targetLanguage": "Cieľový jazyk", "translation_useAppLanguage": "Použite jazyk aplikácie", "translation_downloadedModelLabel": "Stiahnutý model", diff --git a/lib/l10n/app_sl.arb b/lib/l10n/app_sl.arb index 00930c85..eff2db17 100644 --- a/lib/l10n/app_sl.arb +++ b/lib/l10n/app_sl.arb @@ -2099,6 +2099,9 @@ "translation_enableSubtitle": "Prevedite vstopne sporočila in omogočite predhodno prevajanje.", "translation_enableTitle": "Omogočite prevod", "translation_composerSubtitle": "Ureja privzeto stanje ikone za prevod, ki jo uporablja avtor.", + "translation_autoIncomingTitle": "Samodejno prevajaj sporočila", + "translation_autoIncomingSubtitle": "Samodejno prevaja sporočila za obvestila ter za klepete ali kanale.", + "translation_translateMessage": "Prevedi sporočilo", "translation_targetLanguage": "Ciljna jezika", "translation_useAppLanguage": "Uporabite jezik aplikacije", "translation_downloadedModelLabel": "Naložen model", diff --git a/lib/l10n/app_sv.arb b/lib/l10n/app_sv.arb index 00fd3b08..044abbc7 100644 --- a/lib/l10n/app_sv.arb +++ b/lib/l10n/app_sv.arb @@ -2100,6 +2100,9 @@ "translation_title": "Översättning", "translation_composerTitle": "Översätt innan du skickar", "translation_composerSubtitle": "Styr standardtillståndet för kompositorns översättningsikon.", + "translation_autoIncomingTitle": "Översätt meddelanden automatiskt", + "translation_autoIncomingSubtitle": "Översätter meddelanden automatiskt för aviseringar och för chattar eller kanaler.", + "translation_translateMessage": "Översätt meddelande", "translation_targetLanguage": "Målmedvetet språk", "translation_useAppLanguage": "Använd appens språk", "translation_downloadedModelLabel": "Nedladdad modell", diff --git a/lib/l10n/app_uk.arb b/lib/l10n/app_uk.arb index 8330d364..37300095 100644 --- a/lib/l10n/app_uk.arb +++ b/lib/l10n/app_uk.arb @@ -2109,6 +2109,9 @@ "translation_enableTitle": "Увімкнути переклад", "translation_enableSubtitle": "Перекладати отримані повідомлення та дозволяти попередній переклад перед відправкою.", "translation_composerSubtitle": "Контролює стан ікон перекладу, який використовується за замовчуванням.", + "translation_autoIncomingTitle": "Автоматично перекладати повідомлення", + "translation_autoIncomingSubtitle": "Автоматично перекладає повідомлення для сповіщень, а також для чатів і каналів.", + "translation_translateMessage": "Перекласти повідомлення", "translation_targetLanguage": "Цільова мова", "translation_useAppLanguage": "Використовувати мову застосунку", "translation_downloadedModelLabel": "Завантажений шаблон", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 1e289315..5603034f 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -2105,6 +2105,9 @@ "translation_composerTitle": "在发送之前进行翻译", "translation_enableTitle": "启用翻译功能", "translation_composerSubtitle": "控制作曲家翻译图标的默认状态。", + "translation_autoIncomingTitle": "自动翻译消息", + "translation_autoIncomingSubtitle": "自动为通知以及聊天或频道翻译消息。", + "translation_translateMessage": "翻译消息", "translation_targetLanguage": "目标语言", "translation_useAppLanguage": "使用应用程序语言", "translation_downloadedModelLabel": "下载的模型", diff --git a/lib/models/app_settings.dart b/lib/models/app_settings.dart index 4e95311f..6995b6ed 100644 --- a/lib/models/app_settings.dart +++ b/lib/models/app_settings.dart @@ -113,6 +113,7 @@ class AppSettings { final int tcpServerPort; final bool jumpToOldestUnread; final bool translationEnabled; + final bool autoTranslateIncomingMessages; final String? translationTargetLanguageCode; final bool composerTranslationEnabled; final String? translationModelSourceUrl; @@ -166,6 +167,7 @@ class AppSettings { this.tcpServerPort = 0, this.jumpToOldestUnread = false, this.translationEnabled = false, + this.autoTranslateIncomingMessages = true, this.translationTargetLanguageCode, this.composerTranslationEnabled = false, this.translationModelSourceUrl, @@ -226,6 +228,7 @@ class AppSettings { 'tcp_server_port': tcpServerPort, 'jump_to_oldest_unread': jumpToOldestUnread, 'translation_enabled': translationEnabled, + 'auto_translate_incoming_messages': autoTranslateIncomingMessages, 'translation_target_language_code': translationTargetLanguageCode, 'composer_translation_enabled': composerTranslationEnabled, 'translation_model_source_url': translationModelSourceUrl, @@ -307,6 +310,8 @@ class AppSettings { tcpServerPort: json['tcp_server_port'] as int? ?? 0, jumpToOldestUnread: json['jump_to_oldest_unread'] as bool? ?? false, translationEnabled: json['translation_enabled'] as bool? ?? false, + autoTranslateIncomingMessages: + json['auto_translate_incoming_messages'] as bool? ?? true, translationTargetLanguageCode: json['translation_target_language_code'] as String?, composerTranslationEnabled: @@ -396,6 +401,7 @@ class AppSettings { int? tcpServerPort, bool? jumpToOldestUnread, bool? translationEnabled, + bool? autoTranslateIncomingMessages, Object? translationTargetLanguageCode = _unset, bool? composerTranslationEnabled, Object? translationModelSourceUrl = _unset, @@ -453,6 +459,8 @@ class AppSettings { tcpServerPort: tcpServerPort ?? this.tcpServerPort, jumpToOldestUnread: jumpToOldestUnread ?? this.jumpToOldestUnread, translationEnabled: translationEnabled ?? this.translationEnabled, + autoTranslateIncomingMessages: + autoTranslateIncomingMessages ?? this.autoTranslateIncomingMessages, translationTargetLanguageCode: translationTargetLanguageCode == _unset ? this.translationTargetLanguageCode : translationTargetLanguageCode as String?, diff --git a/lib/screens/app_settings_screen.dart b/lib/screens/app_settings_screen.dart index 94b3efe8..4d791381 100644 --- a/lib/screens/app_settings_screen.dart +++ b/lib/screens/app_settings_screen.dart @@ -559,6 +559,7 @@ class AppSettingsScreen extends StatelessWidget { TranslationService translationService, ) { final settings = settingsService.settings; + final translationEnabled = settings.translationEnabled; return Card( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -579,11 +580,41 @@ class AppSettingsScreen extends StatelessWidget { ), const Divider(height: 1), SwitchListTile( - secondary: const Icon(Icons.outgoing_mail), - title: Text(context.l10n.translation_composerTitle), - subtitle: Text(context.l10n.translation_composerSubtitle), + secondary: Icon( + Icons.auto_awesome_outlined, + color: translationEnabled ? null : Colors.grey, + ), + title: Text( + context.l10n.translation_autoIncomingTitle, + style: TextStyle(color: translationEnabled ? null : Colors.grey), + ), + subtitle: Text( + context.l10n.translation_autoIncomingSubtitle, + style: TextStyle(color: translationEnabled ? null : Colors.grey), + ), + value: settings.autoTranslateIncomingMessages, + onChanged: translationEnabled + ? settingsService.setAutoTranslateIncomingMessages + : null, + ), + const Divider(height: 1), + SwitchListTile( + secondary: Icon( + Icons.outgoing_mail, + color: translationEnabled ? null : Colors.grey, + ), + title: Text( + context.l10n.translation_composerTitle, + style: TextStyle(color: translationEnabled ? null : Colors.grey), + ), + subtitle: Text( + context.l10n.translation_composerSubtitle, + style: TextStyle(color: translationEnabled ? null : Colors.grey), + ), value: settings.composerTranslationEnabled, - onChanged: settingsService.setComposerTranslationEnabled, + onChanged: translationEnabled + ? settingsService.setComposerTranslationEnabled + : null, ), const Divider(height: 1), ListTile( diff --git a/lib/screens/channel_chat_screen.dart b/lib/screens/channel_chat_screen.dart index fcd50861..b57bd235 100644 --- a/lib/screens/channel_chat_screen.dart +++ b/lib/screens/channel_chat_screen.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:convert'; import 'dart:math' as math; @@ -1320,6 +1321,18 @@ class _ChannelChatScreenState extends State { } void _showMessageActions(ChannelMessage message) { + final settings = context.read().settings; + final translationService = context.read(); + final canTranslateMessage = + settings.translationEnabled && + !settings.autoTranslateIncomingMessages && + translationService.canTranslateIncoming( + text: message.text, + isCli: false, + isOutgoing: message.isOutgoing, + ) && + (message.translatedText?.trim().isEmpty ?? true); + showModalBottomSheet( context: context, builder: (sheetContext) => SafeArea( @@ -1361,6 +1374,21 @@ class _ChannelChatScreenState extends State { _copyMessageText(message.text); }, ), + if (canTranslateMessage) + ListTile( + leading: const Icon(Icons.translate), + title: Text(context.l10n.translation_translateMessage), + onTap: () { + Navigator.pop(sheetContext); + unawaited( + context.read().translateChannelMessage( + widget.channel.index, + message, + manualTranslation: true, + ), + ); + }, + ), if (!message.isOutgoing) ListTile( leading: const Icon(Icons.mark_chat_unread_outlined), diff --git a/lib/screens/chat_screen.dart b/lib/screens/chat_screen.dart index 8d3bc66c..07884b96 100644 --- a/lib/screens/chat_screen.dart +++ b/lib/screens/chat_screen.dart @@ -1577,6 +1577,18 @@ class _ChatScreenState extends State { } void _showMessageActions(Message message, Contact contact) { + final settings = context.read().settings; + final translationService = context.read(); + final canTranslateMessage = + settings.translationEnabled && + !settings.autoTranslateIncomingMessages && + translationService.canTranslateIncoming( + text: message.text, + isCli: message.isCli, + isOutgoing: message.isOutgoing, + ) && + (message.translatedText?.trim().isEmpty ?? true); + showModalBottomSheet( context: context, builder: (sheetContext) => SafeArea( @@ -1610,6 +1622,21 @@ class _ChatScreenState extends State { _copyMessageText(message.text); }, ), + if (canTranslateMessage) + ListTile( + leading: const Icon(Icons.translate), + title: Text(context.l10n.translation_translateMessage), + onTap: () { + Navigator.pop(sheetContext); + unawaited( + context.read().translateContactMessage( + widget.contact.publicKeyHex, + message, + manualTranslation: true, + ), + ); + }, + ), if (!message.isOutgoing) ListTile( leading: const Icon(Icons.mark_chat_unread_outlined), diff --git a/lib/services/app_settings_service.dart b/lib/services/app_settings_service.dart index 7b3d5848..88ff0f47 100644 --- a/lib/services/app_settings_service.dart +++ b/lib/services/app_settings_service.dart @@ -235,6 +235,12 @@ class AppSettingsService extends ChangeNotifier { await updateSettings(_settings.copyWith(translationEnabled: value)); } + Future setAutoTranslateIncomingMessages(bool value) async { + await updateSettings( + _settings.copyWith(autoTranslateIncomingMessages: value), + ); + } + Future setTranslationTargetLanguageCode(String? value) async { await updateSettings( _settings.copyWith(translationTargetLanguageCode: value), diff --git a/lib/services/translation_service.dart b/lib/services/translation_service.dart index 148650ca..4437d1f1 100644 --- a/lib/services/translation_service.dart +++ b/lib/services/translation_service.dart @@ -89,7 +89,22 @@ class TranslationService extends ChangeNotifier { 'en'; } - bool shouldTranslateIncoming({ + bool shouldAutoTranslateIncoming({ + required String text, + required bool isCli, + required bool isOutgoing, + }) { + if (!_settings.autoTranslateIncomingMessages) { + return false; + } + return canTranslateIncoming( + text: text, + isCli: isCli, + isOutgoing: isOutgoing, + ); + } + + bool canTranslateIncoming({ required String text, required bool isCli, required bool isOutgoing,