react-native-tts icon indicating copy to clipboard operation
react-native-tts copied to clipboard

[Bug] Android language returns weird.

Open guhyeon opened this issue 6 years ago • 2 comments

In Some Devices, voice.language returns wrong language for example 'en-x-Ivariant-001'.

device: galaxy note4 android version: 6.0.1 (Marshmallow)

guhyeon avatar Mar 17 '19 20:03 guhyeon

to get iso2 format locale. (ex. en-US, en-GB, ko-KR...) 2 digit language- 2 digit countryCode

show this source.

TextToSpeechModule.java should be added bellow

`

  public TextToSpeechModule(ReactApplicationContext reactContext) {
       super(reactContext);

       //initialize ISO3, ISO2 languague country code mapping.
      //++++++++++++++++++++++++++
       initCountryLanguageCodeMapping();
       ...
   }

   //++++++++++++++++++++++++++ start
   private Map<String, Locale> localeCountryMap;
   private Map<String, Locale> localeLanguageMap;
   private void initCountryLanguageCodeMapping() {
       String[] countries = Locale.getISOCountries();
       localeCountryMap = new HashMap<String, Locale>(countries.length);
       for (String country : countries) {
           Locale locale = new Locale("", country);
           localeCountryMap.put(locale.getISO3Country().toUpperCase(), locale);
       }
       String[] languages = Locale.getISOLanguages();
       localeLanguageMap = new HashMap<String, Locale>(languages.length);
       for (String language : languages) {
           Locale locale = new Locale(language);
           localeLanguageMap.put(locale.getISO3Language(), locale);
       }
   }

   private String iso3CountryCodeToIso2CountryCode(String iso3CountryCode) {
       return localeCountryMap.get(iso3CountryCode).getCountry();
   }

   private String iso3LanguageCodeToIso2LanguageCode(String iso3LanguageCode) {
       return localeLanguageMap.get(iso3LanguageCode).getLanguage();
   }
   //++++++++++++++++++++++++++ end

   @ReactMethod
   public void voices(Promise promise) {
       if(notReady(promise)) return;

       WritableArray voiceArray = Arguments.createArray();

       if (Build.VERSION.SDK_INT >= 21) {
           try {
               for(Voice voice: tts.getVoices()) {
                   WritableMap voiceMap = Arguments.createMap();
                   voiceMap.putString("id", voice.getName());
                   voiceMap.putString("name", voice.getName());
              
                   //++++++++++++++++++++++++++ 
                   String language = voice.getLocale().getISO3Language();
                   String country = voice.getLocale().getISO3Country();
                   String language_Country = iso3LanguageCodeToIso2LanguageCode(language);
                   if(country!="")
                   {
                       language_Country+="-"+iso3CountryCodeToIso2CountryCode(country);
                   }
                   //++++++++++++++++++++++++++ 
                   //voiceMap.putString("language", voice.getLocale().toLanguageTag());
                   voiceMap.putString("language", language_Country);
                   voiceMap.putInt("quality", voice.getQuality());
                   voiceMap.putInt("latency", voice.getLatency());
                   voiceMap.putBoolean("networkConnectionRequired", voice.isNetworkConnectionRequired());
                   voiceMap.putBoolean("notInstalled", voice.getFeatures().contains(TextToSpeech.Engine.KEY_FEATURE_NOT_INSTALLED));
                   voiceArray.pushMap(voiceMap);
               }
           } catch (Exception e) {
             // Purposefully ignore exceptions here due to some buggy TTS engines.
             // See http://stackoverflow.com/questions/26730082/illegalargumentexception-invalid-int-os-with-samsung-tts
           }
       }

       promise.resolve(voiceArray);
   }

guhyeon avatar Mar 17 '19 20:03 guhyeon

@guhyeon Please submit pull request with your solution.

its4net avatar Mar 20 '19 15:03 its4net