avoid double translation and strip replyInfo from translated text.

This commit is contained in:
ZIER
2026-05-13 12:08:41 +02:00
parent 75ae903b99
commit f941f0dbfa
+51 -63
View File
@@ -1072,7 +1072,7 @@ class MeshCoreConnector extends ChangeNotifier {
} }
} }
Future<void> _translateIncomingContactMessage( Future<TranslationResult?> _translateIncomingContactMessage(
String contactKeyHex, String contactKeyHex,
Message message, Message message,
) async { ) async {
@@ -1084,7 +1084,7 @@ class MeshCoreConnector extends ChangeNotifier {
isCli: message.isCli, isCli: message.isCli,
isOutgoing: message.isOutgoing, isOutgoing: message.isOutgoing,
)) { )) {
return; return null;
} }
final targetLanguageCode = service.resolvedIncomingLanguageCode( final targetLanguageCode = service.resolvedIncomingLanguageCode(
_appSettingsService?.settings.languageOverride, _appSettingsService?.settings.languageOverride,
@@ -1094,7 +1094,7 @@ class MeshCoreConnector extends ChangeNotifier {
targetLanguageCode: targetLanguageCode, targetLanguageCode: targetLanguageCode,
); );
if (result == null) { if (result == null) {
return; return null;
} }
final translated = result.status == MessageTranslationStatus.completed final translated = result.status == MessageTranslationStatus.completed
? result.translatedText ? result.translatedText
@@ -1109,12 +1109,14 @@ class MeshCoreConnector extends ChangeNotifier {
translationModelId: result.modelId, translationModelId: result.modelId,
), ),
); );
return result;
} catch (error) { } catch (error) {
appLogger.warn('Translation failed for contact message: $error'); appLogger.warn('Translation failed for contact message: $error');
return null;
} }
} }
Future<void> _translateIncomingChannelMessage( Future<TranslationResult?> _translateIncomingChannelMessage(
int channelIndex, int channelIndex,
ChannelMessage message, ChannelMessage message,
) async { ) async {
@@ -1126,7 +1128,7 @@ class MeshCoreConnector extends ChangeNotifier {
isCli: false, isCli: false,
isOutgoing: message.isOutgoing, isOutgoing: message.isOutgoing,
)) { )) {
return; return null;
} }
final targetLanguageCode = service.resolvedIncomingLanguageCode( final targetLanguageCode = service.resolvedIncomingLanguageCode(
_appSettingsService?.settings.languageOverride, _appSettingsService?.settings.languageOverride,
@@ -1136,11 +1138,16 @@ class MeshCoreConnector extends ChangeNotifier {
targetLanguageCode: targetLanguageCode, targetLanguageCode: targetLanguageCode,
); );
if (result == null) { if (result == null) {
return; return null;
} }
final translated = result.status == MessageTranslationStatus.completed var translated = result.status == MessageTranslationStatus.completed
? result.translatedText ? result.translatedText
: null; : null;
// Strip replyInfo prefix from translated text to match stored message.text
if (translated != null) {
final regex = RegExp(r'^@\[[^\]]+\]\s+', dotAll: true);
translated = translated.replaceFirst(regex, '');
}
_updateStoredChannelMessage( _updateStoredChannelMessage(
channelIndex, channelIndex,
message.messageId, message.messageId,
@@ -1151,8 +1158,10 @@ class MeshCoreConnector extends ChangeNotifier {
translationModelId: result.modelId, translationModelId: result.modelId,
), ),
); );
return result;
} catch (error) { } catch (error) {
appLogger.warn('Translation failed for channel message: $error'); appLogger.warn('Translation failed for channel message: $error');
return null;
} }
} }
@@ -4394,9 +4403,11 @@ class MeshCoreConnector extends ChangeNotifier {
} }
} }
_addMessage(message.senderKeyHex, message); _addMessage(message.senderKeyHex, message);
TranslationResult? translationResult;
if (!message.isOutgoing) { if (!message.isOutgoing) {
unawaited( translationResult = await _translateIncomingContactMessage(
_translateIncomingContactMessage(message.senderKeyHex, message), message.senderKeyHex,
message,
); );
} }
_maybeIncrementContactUnread(message); _maybeIncrementContactUnread(message);
@@ -4412,10 +4423,9 @@ class MeshCoreConnector extends ChangeNotifier {
final msg = message; final msg = message;
if (contact?.type == advTypeChat) { if (contact?.type == advTypeChat) {
unawaited(() async { unawaited(() async {
final resolvedText = await _maybeTranslateForNotification( final resolvedText = translationResult != null
msg.text, ? translationResult.translatedText.trim()
isCli: msg.isCli, : msg.text;
);
await _notificationService.showMessageNotification( await _notificationService.showMessageNotification(
contactName: contact?.name ?? 'Unknown', contactName: contact?.name ?? 'Unknown',
message: resolvedText, message: resolvedText,
@@ -4429,10 +4439,9 @@ class MeshCoreConnector extends ChangeNotifier {
? msg.text.substring(4) ? msg.text.substring(4)
: msg.text; : msg.text;
unawaited(() async { unawaited(() async {
final resolvedText = await _maybeTranslateForNotification( final resolvedText = translationResult != null
bodyText, ? translationResult.translatedText.trim()
isCli: msg.isCli, : bodyText;
);
await _notificationService.showMessageNotification( await _notificationService.showMessageNotification(
contactName: contact?.name ?? 'Unknown Room', contactName: contact?.name ?? 'Unknown Room',
message: resolvedText, message: resolvedText,
@@ -4708,6 +4717,7 @@ class MeshCoreConnector extends ChangeNotifier {
void _maybeNotifyChannelMessage( void _maybeNotifyChannelMessage(
ChannelMessage message, { ChannelMessage message, {
String? channelName, String? channelName,
TranslationResult? translationResult,
}) { }) {
if (message.isOutgoing || _appSettingsService == null) return; if (message.isOutgoing || _appSettingsService == null) return;
final channelIndex = message.channelIndex; final channelIndex = message.channelIndex;
@@ -4721,12 +4731,11 @@ class MeshCoreConnector extends ChangeNotifier {
final label = channelName ?? _channelDisplayName(channelIndex); final label = channelName ?? _channelDisplayName(channelIndex);
if (_appSettingsService!.isChannelMuted(label)) return; if (_appSettingsService!.isChannelMuted(label)) return;
// Translate channel notification text if enabled // Reuse translation result from earlier translation, or use original text
final resolvedText = translationResult != null
? translationResult.translatedText.trim()
: message.text;
unawaited(() async { unawaited(() async {
final resolvedText = await _maybeTranslateForNotification(
message.text,
isCli: false,
);
await _notificationService.showChannelMessageNotification( await _notificationService.showChannelMessageNotification(
channelName: label, channelName: label,
senderName: message.senderName, senderName: message.senderName,
@@ -4737,41 +4746,7 @@ class MeshCoreConnector extends ChangeNotifier {
}()); }());
} }
Future<String> _maybeTranslateForNotification( void _handleIncomingChannelMessage(Uint8List frame) async {
String text, {
required bool isCli,
}) async {
final service = _translationService;
if (service == null) return text;
try {
if (!service.shouldTranslateIncoming(
text: text,
isCli: isCli,
isOutgoing: false,
)) {
return text;
}
final targetLanguageCode = service.resolvedIncomingLanguageCode(
_appSettingsService?.settings.languageOverride,
);
if (targetLanguageCode == null || targetLanguageCode.isEmpty) {
return text;
}
final result = await service.translateIncomingText(
text: text,
targetLanguageCode: targetLanguageCode,
);
final translated = result?.translatedText.trim();
if (translated != null && translated.isNotEmpty) {
return translated;
}
} catch (_) {
// Fallback to original text on any error
}
return text;
}
void _handleIncomingChannelMessage(Uint8List frame) {
final parsed = ChannelMessage.fromFrame(frame); final parsed = ChannelMessage.fromFrame(frame);
if (parsed != null && parsed.channelIndex != null) { if (parsed != null && parsed.channelIndex != null) {
if (_shouldDropSelfChannelMessage(parsed.senderName, parsed.pathBytes)) { if (_shouldDropSelfChannelMessage(parsed.senderName, parsed.pathBytes)) {
@@ -4790,15 +4765,20 @@ class MeshCoreConnector extends ChangeNotifier {
pathBytes: message.pathBytes, pathBytes: message.pathBytes,
); );
final isNew = _addChannelMessage(message.channelIndex!, message); final isNew = _addChannelMessage(message.channelIndex!, message);
TranslationResult? translationResult;
if (isNew && !message.isOutgoing) { if (isNew && !message.isOutgoing) {
unawaited( translationResult = await _translateIncomingChannelMessage(
_translateIncomingChannelMessage(message.channelIndex!, message), message.channelIndex!,
message,
); );
} }
_maybeIncrementChannelUnread(message, isNew: isNew); _maybeIncrementChannelUnread(message, isNew: isNew);
notifyListeners(); notifyListeners();
if (isNew) { if (isNew) {
_maybeNotifyChannelMessage(message); _maybeNotifyChannelMessage(
message,
translationResult: translationResult,
);
} }
_handleQueuedMessageReceived(); _handleQueuedMessageReceived();
} else if (_isSyncingQueuedMessages) { } else if (_isSyncingQueuedMessages) {
@@ -4806,7 +4786,7 @@ class MeshCoreConnector extends ChangeNotifier {
} }
} }
void _handleLogRxData(Uint8List frame) { void _handleLogRxData(Uint8List frame) async {
if (frame.length < 4) return; if (frame.length < 4) return;
try { try {
final reader = BufferReader(frame); final reader = BufferReader(frame);
@@ -4874,8 +4854,12 @@ class MeshCoreConnector extends ChangeNotifier {
pathBytes: message.pathBytes, pathBytes: message.pathBytes,
); );
final isNew = _addChannelMessage(channel.index, message); final isNew = _addChannelMessage(channel.index, message);
TranslationResult? translationResult;
if (isNew && !message.isOutgoing) { if (isNew && !message.isOutgoing) {
unawaited(_translateIncomingChannelMessage(channel.index, message)); translationResult = await _translateIncomingChannelMessage(
channel.index,
message,
);
} }
_maybeIncrementChannelUnread(message, isNew: isNew); _maybeIncrementChannelUnread(message, isNew: isNew);
notifyListeners(); notifyListeners();
@@ -4883,7 +4867,11 @@ class MeshCoreConnector extends ChangeNotifier {
final label = channel.name.isEmpty final label = channel.name.isEmpty
? 'Channel ${channel.index}' ? 'Channel ${channel.index}'
: channel.name; : channel.name;
_maybeNotifyChannelMessage(message, channelName: label); _maybeNotifyChannelMessage(
message,
channelName: label,
translationResult: translationResult,
);
} }
return; return;
} catch (e) { } catch (e) {