Search code examples
fluttermachine-learninghuawei-mobile-serviceshuawei-ml-kit

Multiple local HMS ML Kit translator models in Flutter?


I've defined a class that wraps the HMS ML Kit in-device translator. This class has two translator instances, with two different settings:

MLLocalTranslator translatorSend = new MLLocalTranslator();
MLLocalTranslator translatorReceive = new MLLocalTranslator();
MLTranslateSetting settingSend = new MLTranslateSetting();
MLTranslateSetting settingReceive = new MLTranslateSetting();

translatorSend translates request from a language (for example it) to English (en). translatorReceive translates the response of the request from en to it.
However, the prepare method only downloads the model for en_it translation and not the it_en model (if exists).

HMSTranslator(String languageCode) {
  settingSend.sourceLangCode = languageCode;
  settingSend.targetLangCode = "en";
  settingReceive.sourceLangCode = "en";
  settingReceive.targetLangCode = languageCode;
}

Future<bool> prepare() async {
  if(settingSend.sourceLangCode != settingSend.targetLangCode) {
    bool isSendPrepared = await translatorSend.prepareModel(setting: settingSend)
    bool isReceivePrepared = await translatorReceive.prepareModel(setting: settingReceive);
    isPrepared = isSendPrepared && isReceivePrepared;
  }
  else {
    isPrepared = false;
  }
  return isPrepared;
}

The problem comes when I translate a string with translatorSend.

Future<String> translateString(String stringToTranslate) async {
  if(settingSend.sourceLangCode != settingSend.targetLangCode) {
    String result;
    if (isPrepared) {
      result = await translatorSend.asyncTranslate(sourceText: stringToTranslate);
    }
    else {
      settingSend.sourceTextOnRemote = stringToTranslate;
      result = await sendRemoteTranslator.asyncTranslate(setting: settingSend);
    }
    return result;
  }
  else {
    return stringToTranslate;
  }
}

This method should translate an it String to an en String. However, it seems to call the en_it model and fails the translation:

I/flutter (28228): TRANSLATOR: it to en
I/flutter (28228): TRANSLATOR: PREPARED
I/MLLocalTranslator(28228): translate sourceLanguage: en targetLanguage: it
WHAT: vestiti usati -> vestiti usati  - WHERE applicazione -> applicazione 

The translation of the response, from en to it works.
I've tested other languages and that happens also with fr.
Further testing showed that the process worked with es:

WHAT: ropa usada -> Used clothing  - WHERE aplicación -> application 

Solution

  • Pls check whether you are using the new version of the Flutter plug-in.

    Language packs can be used in two-way. For example, en-it can be used for en to it or it to en.

    The following are for your reference:

    Modify based on the plugin Demo in the official website

    The same instance is used for bidirectional translation by invoking multiple times.

    //Entry function
    _translationMake() async {
      try {
        await _prepareModel_run("it","en","vestiti usati");
        await _prepareModel_run("en","it","application");
      } on Exception catch (e) {
        print(e.toString());
      }
    }
    
    _prepareModel_run(String srcLang, String dstLang, String content) async {
      setting.sourceLangCode = srcLang;
      setting.targetLangCode = dstLang;
      try {
        final bool res = await translator.prepareModel(setting: setting); 
        if (res) {
          final String s = await _localTranslate_run(content);
          if (s != null) {
            print("_prepareModel_run " + content + " translate to "+s);
          }
        }else {
          print("_prepareModel_run res false");
        }
      } on Exception catch (e) {
        print(e.toString());
      }
    }
    
    
    Future<String> _localTranslate_run(String Content) async {
      try {
        final String s =
        await translator.syncTranslate(sourceText: Content);
        if (s != null) {
          _stopLocalTranslate();
          
          setState(() => _translateResult = s);
          return s;
        } else {
          print("no Translation");
          setState(() => _translateResult = "no translation");
          return "no translation";
        }
      } on Exception catch (e) {
        print(e.toString());
      }
    }
    
    

    And the log print results are as follows:

    _prepareModel_run vestiti usati translate to Used clothes
    _prepareModel_run application translate to applicazione