I'm need to show date in dd/MM/yyyy format (full month name) in Hebrew.
In Samsung s1 - it shows me English locale and in Motorola Atrix 4G it works fine
(shows the month name in Hebrew).
I'm using:
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT, getLocale());
// I TRIED ALL THESE 3 LOCALES
private Locale getLocale() {
return new Locale("he");
//return new Locale("iw_IL");
//return new Locale("iw");
}
Note: I need to show Hebrew even if the phone defalt locale is different.
How can I implement for all devices (that has hebrew)?
Per Google, en_US ... is the only locale Java guarantees is always available.
If you know you're going to need Hebrew month names regardless of what's provided by the underlying platform, you should include that data in your app.
Related
In my application I'm using SpeechRecognizer, in order to detect what the user said.
My device's language is set to English and it works perfect when I say something in English, but when I say something in other languages, for example - Hebrew, it doesn't work all the time as it works for English, until I set the device's language to Hebrew and then it works OK.
I'm trying to avoid from setting the device's language and want it to automatically detect the user language.
I've noticed that "OK Google" works and detect the correct words in Hebrew even when the device's language is set to English.
For the meantime, what I tried to do is when the user enter for the first time
to my application, I'm asking him to enter his country.
Then when I have his country -> I'm getting the country code and then I create a Locale using the country code.
This locale is then sent as the language to the speech recognizer.
But it didn't help..
// example of how to get the locale using the country code
Locale myLocale = null;
String toSearch = "IL";
toSearch = toSearch.trim().toLowerCase();
for (Locale locale : Locale.getAvailableLocales())
{
if(locale.getCountry().trim().toLowerCase().contains(toSearch))
{
myLocale = locale;
break;
}
}
// example of how I'm sending the locale
Intent recIntent= new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
recIntent.putExtra(RecognizerIntent.ExtraLanguage,myLocale);
original question
I have a standard texttospeech, android.speech.tts.TextToSpeech
I initialize it and set a language by using tts.setLanguage(Locale.getDefault())
That default Locale is de_DE (for germany, correct).
Right after setting it, i ask the tts to give me its language tts.getLanguage()
now it tells me that its set to "deu_DEU"
There is no Locale with that setting. So i cant even check if its set to the right language because i cant find the Locale object that has the matching values.
Issue might be related to Android 4.3, but i didnt find any info.
Background is, that i need to show values with the same decimal symbol, but tts needs the correct symbol or it says "dot" in german which makes NO sense at all.
Conclusion:
A Locale is a container that contains a string that is composed of a language, a country and an optional string. Every text-to-speech engine can return a custom Locale like "eng_USA_texas".
Furthermore the Locale that is returned by the tts engine can only be a "close match" to the wanted Locale. So "en_US" instead of "en_UK".
However, Locale has a method called getLanguage() and it returns the first part of above mentioned string. "en" or "eng". Those Language codes are regulated by ISO and one can hope that everyone sticks to it. (see link in the accepted answer)
So checking for tts.getLanguage().getLanguage().startsWith("en") should always be true if its some form of english language setting and the ISO standards are fulfilled.
It is important to mention that Locales should not be compared by locale_a == locale_b as both can be different objects yet have the same content, they are containers of sort.
Always compare with locale_a.equals(locale_b)
I hope this helps people sort out some problems with tts and language
You're right, it's frustrating how the locale codes the TTS object uses are different to those of the device locale. I don't understand why this decision was made.
To add further complication, the TTS Engine can supply all kinds of different locales, such as eng_US_sarah or en-US-female etc. It's down to the TTS Engine how these are stored and displayed.
I've had to write additional code to iterate through the returned locales and attempt to match them to the locale the system can use, or vica-versa.
To start with, take a look at how the engines you have installed are returning their locale information. You can then start to collate in your code a list to associate 'deu_DEU' to 'de_De'.
This is often simplistic by using split("_") & startsWith(String), but unfortunately not for all locales.
Here's some base code I've used to analyse the installed TTS Engines' locale structure.
private void getEngines() {
final Intent ttsIntent = new Intent();
ttsIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
final PackageManager pm = getActivity().getPackageManager();
final List<ResolveInfo> list = pm.queryIntentActivities(ttsIntent, PackageManager.GET_META_DATA);
final ArrayList<Intent> intentArray = new ArrayList<Intent>(list.size());
for (int i = 0; i < list.size(); i++) {
final Intent getIntent = new Intent();
getIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
getIntent.setPackage(list.get(i).activityInfo.applicationInfo.packageName);
getIntent.getStringArrayListExtra(TextToSpeech.Engine.EXTRA_AVAILABLE_VOICES);
intentArray.add(getIntent);
}
for (int i = 0; i < intentArray.size(); i++) {
startActivityForResult(intentArray.get(i), i);
}
}
#Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
try {
if (data != null) {
System.out.print(data.getStringArrayListExtra("availableVoices").toString());
}
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
From the above ISO-3 codes and the device locale format, you should be able to come up with something for the locales you are concerned with.
I've been intending to submit an enhancement request to AOSP for a while, as all TTS Engines need to use constant values and extras such as gender etc need to be added to use the TTS Engines to their full capabilities.
EDIT: Further to your edit, note the wording regarding setLanguage(). The individual TTS Engine will try and match as close as possible to the requested locale, but that applied locale may be completely wrong, depending on how lenient the Engine provider is in their code and their response.
After creating an object of TextToSpeech class, you should configure it (or check it's available state/values) into TextToSpeech.OnInitListener's onInit() callback. You will get reliable information there about your TextToSpeech object.
Check my answer here:
https://stackoverflow.com/a/65620221/7835969
I have several language files in Android application: value/strings.xml, value-en/strings.xml, ...etc
It is possible to load the content of this files in some arrays or something. For example, I would like to load default text strings and english strings in 2 different arrays at run time.
Thanks
Alin
Create a method like this:
Resources getResourcesByLocale( Context context, String localeName ) {
Resource res = context.getResources();
Configuration conf = new Configuration(res.getConfiguration());
conf.locale = new Locale(localeName);
return new Resources(res.getAssets(), res.getDisplayMetrics(), conf);
}
Than you can get resources for any locale you've defined, for example:
Resources res_en = getResourcesByLocale(context, "en");
Resources res_de = getResourcesByLocale(context, "de");
Resources res_fr = getResourcesByLocale(context, "fr");
String some_name_en = res_en.getString(R.string.some_name);
String some_name_fr = res_fr.getString(R.string.some_name);
// etc...
Moreover, you do not need to take care about exceptions if you did not define string for some locale, because anyway default (from res/values/*) will be loaded instead.
Actually the situation is like that. Imagine I have this scenario: some chinese open the application. He has the mobile phone set with ch locale. The application default is xx as language, meaning I have 2 language files values/strings.xml (spanish for eg as default) and another language values-en/strings.xml for english. The default will make no sense for him, so english will be the most appropiate for his understanding, even if he does not understand it very good. So at the app start I open language settings (android language settings), where any selection will set the app in spanish unless he select english. I am forcing him to change the phone locale in english basically, just to use my app. Overall the concept of android is wrong, because i need to be able to see an application in any language I want without changing device language.
What I have done: - I created in values folder one more string_xx.xml file. Now, for a translation string name = "txtTranslation" I have in string_xx file "en_txtTranslation" key. R.java loads them all and in my app, based on a global var selectedLanguage = xx, I attach the write string using this code:
public String translate(String text)
{
String appLanguage = UtilsCentral.getUserLanguage(getApplicationContext());
if (appLanguage != "")
{
return getString(getResources().getIdentifier(appLanguage + "_" + text, "string", this.getPackageName()));
}
else
{
return getString(getResources().getIdentifier(text, "string", this.getPackageName()));
}
}
Indeed, at activity on create i need to set all views with .text = tarnslate("txtTranslation")
Note: UtilsCentral.getUserLanguage(getApplicationContext()) returns app language (user selection)
Conclusion, there is more unuseful work, but lets me do what i need, and what i believe is normal.
I'm using following code in my app:
Calendar tmpCalendar = Calendar.getInstance(Locale.getDefault());
String itemTime = String.format(
Locale.getDefault(),
"%1$tA, %1$te. %1$tB %1$tY",
tmpCalendar);
German is the default language on my device, so I'd expect to get something like:
Dienstag, 7. Juni 2011
Instead I'm getting:
3, 7. 6 2011
If I use Locale.US instead of Locale.getDefault() everything works fine. Am I doing something wrong?
Oddly, it works in an emulator running Android 2.2 in German, but not on a HTC Desire, also running 2.2. Why?
It seems to be a bug of some vendors and is issue #9453 in the Android issue tracker.
SimpleDateFormat sdf = new SimpleDateFormat("EE/MM/yyyy");
Date date = new Date();
String sDate= sdf.format(date);
Read more on it here
It does exactly what you ask it to do. If you want to have fine-grain control over the process, you can always use SimpleDateFormat. However, I would rather recommend this method:
Calendar tmpCalendar = Calendar.getInstance(Locale.getDefault());
DateFormat formatter = DateFormat.getDateInstance(DateFormat.LONG, Locale.getDefault());
formatter.setTimeZone(TimeZone.getDefault());
String itemTime = formatter.format(tmpCalendar.getTime());
Also, I would recommend using DateFormat.DEFAULT but you expect long date format, so...
I've found using the android.text.format.DateUtils relative APIs that return values like "yesterday" or "2 hours ago" very nice - but my app does not support every language Android does. So, I default to English, but for every language I don't support, the relative string shows in the device's setting.
For example, like:
Last attempt: hace 11 minutos.
I'd like to make the API call default to English for any languages I don't support. However, I don't see anywhere to set the Locale for the API call - I'm hoping I'm just missing it somewhere.
Is there a way to set the Locale just for the API call, ignoring the device setting?
This is working for me up to Android 7
void forceLocale(Locale locale) {
Configuration conf = getBaseContext().getResources().getConfiguration();
updateConfiguration(conf, locale);
getBaseContext().getResources().updateConfiguration(conf, getResources().getDisplayMetrics());
Configuration systemConf = Resources.getSystem().getConfiguration();
updateConfiguration(systemConf, locale);
Resources.getSystem().updateConfiguration(conf, getResources().getDisplayMetrics());
Locale.setDefault(locale);
}
void updateConfiguration(Configuration conf, Locale locale) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
conf.setLocale(locale);
}else {
//noinspection deprecation
conf.locale = locale;
}
}
According to the source code of the DateUtils class it uses both Resource.getSystem() and Locale.getDefault() method for formatting date and time. You can change the default Locale using Locale.setDefault() method but I don't think it's possible to change the return value of the Resource.getSystem() method. You can try to change the default locale to Locale.US but it seems to me that results will be even worse in this case.