translateMessage method

Future<void> translateMessage(
  1. ChatMessage message, {
  2. MessageTranslationSource source = MessageTranslationSource.manual,
})

Implementation

Future<void> translateMessage(
  ChatMessage message, {
  MessageTranslationSource source = MessageTranslationSource.manual,
}) async {
  if (!IMKitClient.enableMessageTranslation) {
    return;
  }
  final nimMessage = message.nimMessage;
  final text = nimMessage.text?.trim();
  if (nimMessage.messageType != NIMMessageType.text ||
      text?.isNotEmpty != true) {
    return;
  }
  final translationContent =
      MessageTranslationHelper.buildTextTranslationContent(
    nimMessage.text!,
    serverExtension: nimMessage.serverExtension,
  );
  final translatableParts = translationContent.translatableParts;
  if (translatableParts.isEmpty) {
    return;
  }
  final messageId = MessageTranslationHelper.messageIdentity(nimMessage);
  if (messageId.isEmpty || _translatingMessageIds.contains(messageId)) {
    return;
  }
  final targetLanguage = await ConfigRepo.getMessageTranslateTargetLanguage();
  final existing = MessageTranslationHelper.parseMessageTranslation(
    nimMessage,
  );
  final existingMemoryState = _messageTranslationStates[messageId];
  if (existing != null &&
      existing.text.isNotEmpty &&
      existing.targetLanguage == targetLanguage) {
    if (existing.hidden) {
      await _saveMessageTranslation(
        nimMessage,
        existing.copyWith(hidden: false),
        messageId,
        existing.source,
      );
      if (!_isDisposed) {
        notifyListeners();
      }
    }
    return;
  }
  if (existingMemoryState?.translation?.text.isNotEmpty == true &&
      existingMemoryState?.translation?.targetLanguage == targetLanguage) {
    final memoryTranslation = existingMemoryState!.translation!;
    if (memoryTranslation.hidden) {
      await _saveMessageTranslation(
        nimMessage,
        memoryTranslation.copyWith(hidden: false),
        messageId,
        memoryTranslation.source,
      );
      if (!_isDisposed) {
        notifyListeners();
      }
    }
    return;
  }
  final isManual = source == MessageTranslationSource.manual;
  var manualSerial = _manualTranslationSerial;
  if (isManual) {
    final previousMessageId = _activeManualTranslationMessageId;
    if (previousMessageId?.isNotEmpty == true &&
        previousMessageId != messageId) {
      _translatingMessageIds.remove(previousMessageId);
      _messageTranslationStates.remove(previousMessageId);
    }
    _activeManualTranslationMessageId = messageId;
    manualSerial = ++_manualTranslationSerial;
  }
  if (isManual && manualSerial != _manualTranslationSerial) {
    return;
  }
  if (!await haveConnectivity()) {
    if (isManual && manualSerial == _manualTranslationSerial) {
      _activeManualTranslationMessageId = null;
    }
    return;
  }
  if (isManual && manualSerial != _manualTranslationSerial) {
    return;
  }
  _translatingMessageIds.add(messageId);
  _messageTranslationStates.remove(messageId);
  notifyListeners();
  try {
    final translatedParts = <String>[];
    String? sourceLanguage;
    var resolvedTargetLanguage = targetLanguage;
    for (final part in translatableParts) {
      final result = await NimCore.instance.messageService.translateText(
        params: NIMTextTranslateParams(
          text: part.textToTranslate,
          targetLanguage: targetLanguage,
        ),
        config: NIMTranslatorConfig(strictMode: false),
      );
      if (_isDisposed ||
          (isManual && manualSerial != _manualTranslationSerial)) {
        return;
      }
      final translatedPart = result.data?.translatedText?.trim();
      if (!result.isSuccess || translatedPart?.isNotEmpty != true) {
        _setMessageTranslationFailed(messageId, source);
        return;
      }
      translatedParts.add(translatedPart!);
      sourceLanguage ??= result.data?.sourceLanguage;
      if (result.data?.targetLanguage?.isNotEmpty == true) {
        resolvedTargetLanguage = result.data!.targetLanguage!;
      }
    }
    final translatedText = translationContent.combine(translatedParts).trim();
    if (translatedText.isEmpty) {
      _setMessageTranslationFailed(messageId, source);
      return;
    }
    final info = MessageTranslationInfo(
      targetLanguage: resolvedTargetLanguage,
      sourceLanguage: sourceLanguage,
      text: translatedText,
      translatedAt: DateTime.now().millisecondsSinceEpoch,
      source: source,
    );
    await _saveMessageTranslation(nimMessage, info, messageId, source);
  } catch (e) {
    Alog.e(
      tag: logTag,
      moduleName: 'message translation',
      content: 'translate message failed: $e',
    );
    if (!_isDisposed &&
        (!isManual || manualSerial == _manualTranslationSerial)) {
      _setMessageTranslationFailed(messageId, source);
    }
  } finally {
    if (!_isDisposed) {
      _translatingMessageIds.remove(messageId);
      if (isManual && manualSerial == _manualTranslationSerial) {
        _activeManualTranslationMessageId = null;
      }
      notifyListeners();
    }
  }
}