Browse Source

Simplify the espeak locale name mapping for maintainability.

master
Reece H. Dunn 9 years ago
parent
commit
5be36dddf9
1 changed files with 54 additions and 56 deletions
  1. 54
    56
      android/src/com/reecedunn/espeak/SpeechSynthesis.java

+ 54
- 56
android/src/com/reecedunn/espeak/SpeechSynthesis.java View File

@@ -107,6 +107,23 @@ public class SpeechSynthesis {
return (BUFFER_SIZE_IN_MILLIS * mSampleRate) / 1000;
}

private Locale getLocaleFromLanguageName(String name) {
if (mLocaleFixes.containsKey(name)) {
return mLocaleFixes.get(name);
}
String[] parts = name.split("-");
switch (parts.length) {
case 1: // language
return new Locale(parts[0]);
case 2: // language-country
return new Locale(parts[0], parts[1]);
case 3: // language-country-variant
return new Locale(parts[0], parts[1], parts[2]);
default:
return null;
}
}

public List<Voice> getAvailableVoices() {
final List<Voice> voices = new LinkedList<Voice>();
final String[] results = nativeGetAvailableVoices();
@@ -117,72 +134,38 @@ public class SpeechSynthesis {
final String identifier = results[i + 1];
final int gender = Integer.parseInt(results[i + 2]);
final int age = Integer.parseInt(results[i + 3]);

final Locale locale;
if (name.equals("fa-pin")) {
// Android locales do not support scripts, so fa-Latn is not possible for Farsi Pinglish:
locale = null;
} else if (identifier.equals("asia/fa-en-us")) {
locale = null;
} else if (name.equals("om")) {
// This is an experimental voice that is not currently well tested to be used.
if (identifier.equals("asia/fa-en-us")) {
locale = null;
} else if (name.equals("en-sc")) {
// 'SC' is not a country code.
locale = new Locale("en", "GB", "scotland");
} else if (name.equals("en-wi")) {
// 'WI' is not a country code. Also, territory code 029 (Caribbean)
// is not supported by Android.
locale = new Locale("en", "JM");
} else if (name.equals("es-la")) {
// 'LA' is the country code for Laos, not Latin America. Also, territory code 419
// (Latin America) is not supported by Android.
locale = new Locale("es", "MX");
} else if (name.equals("hy-west")) {
// 'west' is not a country code.
locale = null;
} else if (name.equals("vi-hue")) {
// 'hue' is for the Hue Province accent/dialect (Central Vietnamese).
locale = new Locale("vi", "VN", "hue");
} else if (name.equals("vi-sgn")) {
// 'sgn' is for the Saigon accent/dialect (South Vietnamese).
locale = new Locale("vi", "VN", "saigon");
} else if (name.equals("zh-yue")) {
// Android/Java does not support macrolanguages.
locale = new Locale("zh", "HK");
} else {
String[] parts = name.split("-");
switch (parts.length) {
case 1: // language
locale = new Locale(parts[0]);
break;
case 2: // language-country
if (parts[1].equals("uk")) {
// 'uk' is the language code for Ukranian, not Great Britain.
parts[1] = "GB";
}
locale = new Locale(parts[0], parts[1]);
break;
case 3: // language-country-variant
if (parts[1].equals("uk")) {
// 'uk' is the language code for Ukranian, not Great Britain.
parts[1] = "GB";
}
locale = new Locale(parts[0], parts[1], parts[2]);
break;
default:
locale = null;
}
locale = getLocaleFromLanguageName(name);
}
if (locale == null) {
Log.d(TAG, "getAvailableResources: skipping " + name + " => locale not supported");
continue;
}

try {
if (locale != null && !locale.getISO3Language().equals("")) {
final Voice voice = new Voice(name, identifier, gender, age, locale);
voices.add(voice);
String language = locale.getISO3Language();
if (language.equals("")) {
throw new IllegalArgumentException("Language '" + locale.getLanguage() + "' not supported.");
}

String country = locale.getISO3Country();
if (country.equals("") && !locale.getCountry().equals("")) {
throw new IllegalArgumentException("Country '" + locale.getCountry() + "' not supported.");
}

final Voice voice = new Voice(name, identifier, gender, age, locale);
voices.add(voice);
} catch (MissingResourceException e) {
// Android 4.3 throws this exception if the 3-letter language
// (e.g. nci) or country (e.g. 021) code is missing for a locale.
// Earlier versions of Android return an empty string.
// Earlier versions return an empty string (handled above).
Log.d(TAG, "getAvailableResources: skipping " + name + " => " + e.getMessage());
} catch (IllegalArgumentException e) {
Log.d(TAG, "getAvailableResources: skipping " + name + " => " + e.getMessage());
}
}

@@ -374,6 +357,7 @@ public class SpeechSynthesis {

private static final Map<String, String> mJavaToIanaLanguageCode = new HashMap<String, String>();
private static final Map<String, String> mJavaToIanaCountryCode = new HashMap<String, String>();
private static final HashMap<String, Locale> mLocaleFixes = new HashMap<String, Locale>();
static {
mJavaToIanaLanguageCode.put("afr", "af");
mJavaToIanaLanguageCode.put("amh", "am");
@@ -453,5 +437,19 @@ public class SpeechSynthesis {
mJavaToIanaCountryCode.put("PRT", "PT");
mJavaToIanaCountryCode.put("USA", "US");
mJavaToIanaCountryCode.put("VNM", "VN");

// Map eSpeak locales to their correct BCP47 locales supported by Android:
mLocaleFixes.put("en-sc", new Locale("en", "GB", "scotland"));
mLocaleFixes.put("en-uk-north", new Locale("en", "GB", "north"));
mLocaleFixes.put("en-uk-rp", new Locale("en", "GB", "rp"));
mLocaleFixes.put("en-uk-wmids", new Locale("en", "GB", "wmids"));
mLocaleFixes.put("en-wi", new Locale("en", "JM"));
mLocaleFixes.put("es-la", new Locale("es", "MX"));
mLocaleFixes.put("fa-pin", null); // Script tags not supported.
mLocaleFixes.put("hy-west", null); // language-variant locales not supported.
mLocaleFixes.put("om", null); // This is an experimental voice that is not currently well tested to be used.
mLocaleFixes.put("vi-hue", new Locale("vi", "VN", "hue"));
mLocaleFixes.put("vi-sgn", new Locale("vi", "VN", "saigon"));
mLocaleFixes.put("zh-yue", new Locale("zh", "HK"));
}
}

Loading…
Cancel
Save