I want to set Dutch Language in my TTS object. Following is the code,
#Override
public void onInit(int status)
{
if ( status == TextToSpeech.SUCCESS )
{
int result = tts.setLanguage(Locale.getDefault());
System.out.println ( "Result : " + result + " " + Locale.getDefault().getLanguage() );
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED)
{
Toast.makeText( this , "Please Set your Language to English US.", Toast.LENGTH_LONG ).show();
}
else
{
tts.speak( "Hoe gaat het",TextToSpeech.QUEUE_FLUSH, null );
}
}
}
Following line sets the language in TTS
int result = tts.setLanguage(Locale.getDefault());
Available Locale's in Locale.
Now if my Phone's Language's is Dutch then I am able to set TTS's language as Dutch Language, but if My Phone's Language is not dutch ( for e.g. if it is English ) then there is no option to set the TTS's language as Dutch.
Can anybody help me to set the Dutch language in TTS?
This should work
int result = tts.setLanguage(new Locale("nl_NL"));
You are setting default Locale in setLocale. That's the reason of this issue: Now if my Phone's Language's is Dutch then I am able to set TTS's language as Dutch Language, but if My Phone's Language is not dutch ( for e.g. if it is English ) then there is no option to set the TTS's language as Dutch.
You should use Locale you need instead. So replace
int result = tts.setLanguage(Locale.getDefault());
with
int result = tts.setLanguage(Locale.XYZ); //XYZ is Locale you want.
Example:
int result = tts.setLanguage(Locale.GERMAN);
Referdocumentation, which includes available Locales, which you can set. DUTCH is not available there.
Though this article mentions that DUTCH is available Locale. May be it is not for android, but for java, as suggested here
Hope this helps.
for hindi-india
newsReaderTTS.setLanguage(new Locale("hin", "IND", "variant"));
for english usa
newsReaderTTS.setLanguage(new Locale("eng", "USA", "variant"));
where newsreaderTTS is TTS.
I've faced a problem with quantity strings (plurals).
The manual says, I may provide quantity strings that are specific for each localization, and there are several common cases: "zero", "one", "two", "few", "many", and "other". I don't know if all possible cases for all languages in the world were covered; anyway, it is more than enough for Russian that I'm trying to make a localization for.
In Russian, numbers from 2 to 4 should be treated like "few" (the rule is actually more complex but I only need numbers below ten).
However, when I request a quantity string for 2, the system takes the "other" string. It doesn't take neither "two" string nor "few" one (I have provided them in my resources). If I removed the "other" string, I get the exception:
android.content.res.Resources$NotFoundException:
Plural resource ID #0x7f080000 quantity=2 item=other
I tried this both on emulator (Android 2.1) and on a real device (Android 2.3), the behaviour is the same wrong in both cases. Obviously, there is a mistake somewhere—the system does not recognize locale-specific quantities for my language. Could it be that Android has some bug here?
I believe this is currently broken in Android.
http://code.google.com/p/android/issues/detail?id=8287
Specifically, the following code in PluralRules.java shows that most languages only use the one or other strings, but Czech will use the few string:
static final PluralRules ruleForLocale(Locale locale) {
String lang = locale.getLanguage();
if ("cs".equals(lang)) {
if (cs == null) cs = new cs();
return cs;
}
else {
if (en == null) en = new en();
return en;
}
}
private static PluralRules cs;
private static class cs extends PluralRules {
int quantityForNumber(int n) {
if (n == 1) {
return QUANTITY_ONE;
}
else if (n >= 2 && n <= 4) {
return QUANTITY_FEW;
}
else {
return QUANTITY_OTHER;
}
}
}
private static PluralRules en;
private static class en extends PluralRules {
int quantityForNumber(int n) {
if (n == 1) {
return QUANTITY_ONE;
}
else {
return QUANTITY_OTHER;
}
}
}
Thanks to Brigham who has pointed to the issue where the problem is explained; that explanation first rised more questions but now they seem to be solved. Indeed, the quantity strings don't work properly (at least prior to API 11, which is Android 3.x), so you have to use an alternative.
The solution for APIs prior to version 11 is mentioned in the comment 15 that contains a link to the project for alternative handling of quantity strings. That project is a program that simply does what the system was supposed to do. It can be converted to a library easily, so you just add it to your project, import the class and go.
Define your plurals strings in values-ru/strings.xml not in values/strings.xml
set your mobile device language as Russian (from setting->Language&input->Language->select Russian)
If your language is not Russian it will take plurals strings from values/strings.xml
I'm working on a text-to-speech implementation of a flashcard program. Text in different languages should be read out. In order to do this properly the user has to select the language of the text to read (will be stored and used later without question).
Is there a possibility of getting the available TTS languages on an Android system? If not, is there a possibility of getting all availably locales on the system?
I guess, I got it: getAvailableLocales() and tts.isLocaleAvailable(locale)
Someone else has done the hard work, at http://kaviddiss.com/2012/08/12/android-text-to-speech-languages/
To save you time, here's their code extract
TextToSpeech tts = ...
// let's assume tts is already inited at this point:
Locale[] locales = Locale.getAvailableLocales();
List<Locale> localeList = new ArrayList<Locale>();
for (Locale locale : locales) {
int res = tts.isLanguageAvailable(locale);
if (res == TextToSpeech.LANG_COUNTRY_AVAILABLE) {
localeList.add(locale);
}
}
// at this point the localeList object will contain
// all available languages for Text to Speech
The results depend on which TTS engine has been selected. For instance, one of my phones includes both the Pico-TTS and Google-text-to-speech engines.
Q-Smart (Vietnamese Phone with Google TTS as selected engine)
D/SpeakRepeatedly( 3979): Engine Google Text-to-speech Engine:com.google.android.tts
D/SpeakRepeatedly( 3979): Engine Pico TTS:com.svox.pico
D/SpeakRepeatedly( 3979): German (Germany):German:de_DE
D/SpeakRepeatedly( 3979): English (United Kingdom):English:en_GB
D/SpeakRepeatedly( 3979): English (United States):English:en_US
D/SpeakRepeatedly( 3979): English (United States,Computer):English:en_US_POSIX
D/SpeakRepeatedly( 3979): Spanish (Spain):Spanish:es_ES
D/SpeakRepeatedly( 3979): French (France):French:fr_FR
D/SpeakRepeatedly( 3979): Italian (Italy):Italian:it_IT
D/SpeakRepeatedly( 3979): Portuguese (Brazil):Portuguese:pt_BR
D/SpeakRepeatedly( 3979): Portuguese (Portugal):Portuguese:pt_PT
And with Pico selected
D/SpeakRepeatedly( 4837): Engine Google Text-to-speech Engine:com.google.android.tts
D/SpeakRepeatedly( 4837): Engine Pico TTS:com.svox.pico
D/SpeakRepeatedly( 4837): German (Germany):German:de_DE
D/SpeakRepeatedly( 4837): English (United Kingdom):English:en_GB
D/SpeakRepeatedly( 4837): English (United States):English:en_US
D/SpeakRepeatedly( 4837): English (United States,Computer):English:en_US_POSIX
D/SpeakRepeatedly( 4837): Spanish (Spain):Spanish:es_ES
D/SpeakRepeatedly( 4837): French (France):French:fr_FR
D/SpeakRepeatedly( 4837): Italian (Italy):Italian:it_IT
Note:
Portuguese isn’t listed in the TTS Settings UI. When I select Portuguese programmatically in my app it speaks with a Portuguese accent! FWIW here's my code to select Portuguese (it accepts both Brazilian and Portuguese locales).
if (locale.getDisplayName().startsWith("Portuguese")) {
Log.i(SPEAK_REPEATEDLY, "Setting Locale to: " + locale.toString());
tts.setLanguage(locale);
}
}
Since different TTS engines return different results for isLanguageAvailable, I found that the following solution works best on several common TTS engines.
Please also note that starting with Android Lollipop, there is a simple method in TextToSpeech called getAvailableLanguages that does that easily for you (if the device is running API 21 or later).
You need to call the following methods in the onInit method of your OnInitListener assigned to the TextToSpeech object.
ArrayList<Locale> languages;
TextToSpeech initTTS;
private void initSupportedLanguagesLollipop()
{
Set<Locale> availableLocales = initTTS.getAvailableLanguages();
for (Locale locale : availableLocales)
{
languages.add(locale);
}
}
private void initSupportedLanguagesLegacy()
{
Locale[] allLocales = Locale.getAvailableLocales();
for (Locale locale : allLocales)
{
try
{
int res = initTTS.isLanguageAvailable(locale);
boolean hasVariant = (null != locale.getVariant() && locale.getVariant().length() > 0);
boolean hasCountry = (null != locale.getCountry() && locale.getCountry().length() > 0);
boolean isLocaleSupported =
false == hasVariant && false == hasCountry && res == TextToSpeech.LANG_AVAILABLE ||
false == hasVariant && true == hasCountry && res == TextToSpeech.LANG_COUNTRY_AVAILABLE ||
res == TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE;
Log.d(TAG, "TextToSpeech Engine isLanguageAvailable " + locale + " (supported=" + isLocaleSupported + ",res=" + res + ", country=" + locale.getCountry() + ", variant=" + locale.getVariant() + ")");
if (true == isLocaleSupported)
{
languages.add(locale);
}
}
catch (Exception ex)
{
Log.e(TAG, "Error checking if language is available for TTS (locale=" + locale +"): " + ex.getClass().getSimpleName() + "-" + ex.getMessage());
}
}
}
Find all available TTS Locale on the device using following function.
Locale.getAvailableLocales()
Output of: Arrays.toString(Locale.getAvailableLocales())
[ar, ar_EG, bg, bg_BG, ca, ca_ES, cs, cs_CZ, da, da_DK, de, de_AT, de_BE, de_CH, de_DE, de_LI, de_LU, el, el_CY, el_GR, en, en
_AU, en_BE, en_BW, en_BZ, en_CA, en_GB, en_HK, en_IE, en_IN, en_JM, en_MH, en_MT, en_NA, en_NZ, en_PH, en_PK, en_RH, en_SG, en_TT, en_US, en_US_POSIX,
en_VI, en_ZA, en_ZW, es, es_AR, es_BO, es_CL, es_CO, es_CR, es_DO, es_EC, es_ES, es_GT, es_HN, es_MX, es_NI, es_PA, es_PE, es_PR, es_PY, es_SV, es_US
, es_UY, es_VE, et, et_EE, eu, eu_ES, fa, fa_IR, fi, fi_FI, fr, fr_BE, fr_CA, fr_CH, fr_FR, fr_LU, fr_MC, gl, gl_ES, hr, hr_HR, hu, hu_HU, in, in_ID,
is, is_IS, it, it_CH, it_IT, iw, iw_IL, ja, ja_JP, kk, kk_KZ, ko, ko_KR, lt, lt_LT, lv, lv_LV, mk, mk_MK, ms, ms_BN, ms_MY, nl, nl_BE, nl_NL, no, no_N
O, no_NO_NY, pl, pl_PL, pt, pt_BR, pt_PT, ro, ro_RO, ru, ru_RU, ru_UA, sh, sh_BA, sh_CS, sh_YU, sk, sk_SK, sl, sl_SI, sq, sq_AL, sr, sr_BA, sr_ME, sr_
RS, sv, sv_FI, sv_SE, th, th_TH, tr, tr_TR, uk, uk_UA, vi, vi_VN, zh, zh_CN, zh_HK, zh_HANS_SG, zh_HANT_MO, zh_MO, zh_TW]
Starting from Android 5.0 (API level 21), TextToSpeech.getAvailableLanguages has been added to fetch a set of all locales supported by the TTS engine.
TextToSpeech tts; // assume this is initialized
tts.getAvailableLanguages(); // returns a set of available locales
I have also noticed that the set of locales returned by TextToSpeech.getAvailableLanguages might not be a strict subset of Locale.getAvailableLocales, i.e. there might a locale supported by the TTS engine that isn't supported by the system.