Use custom locale for plurals - android

I am trying to override the locale to use Czech locale no matter what is set in the phone. However, although when I try to get the current locale, it returns czech, but for plurals, it acts like it still takes the real phone locale.
Here is my code:
<application
android:name=".xxx"
android:allowBackup="true"
android:icon="#drawable/logo"
android:label="#string/app_name"
android:theme="#style/Theme.mystyle"
android:configChanges="locale"
>
In application:
String lang = settings.getString("cs", "");
locale = new Locale(lang);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());

I posted on GitHub simple LocaleAssistant class I just tested with plurals for Slovak and also Czech language, and it worked on the device with default locale set to EN. Just call those two methods from within your custom Application on the member instance of LocaleAssistant.

In the end I found the correct solution. Gray Wolf's solution did not work for me for some reason. Maybe it is all about the API level you develop your app for.
This is the working code. Besides that, it is also necessary to add configChanges:locale to AndroidManifest. This should work on Android 4.0.1 and above.
public class MyApplication extends Application
{
private Locale locale = null;
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
if (locale != null)
{
newConfig.locale = locale;
Locale.setDefault(locale);
getBaseContext().getResources().updateConfiguration(newConfig, getBaseContext().getResources().getDisplayMetrics());
}
}
#Override
public void onCreate()
{
super.onCreate();
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
Configuration config = getBaseContext().getResources().getConfiguration();
String lang = "cs";
if (!"".equals(lang) && !config.locale.getLanguage().equals(lang))
{
locale = new Locale(lang);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
}
}

Related

Android Locale Changed but translated strings not coming in the app

Following is the Application code of my Android app:
public class MyApplication extends Application
{
private Locale locale = null;
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
if (locale != null)
{
newConfig.locale = locale;
Locale.setDefault(locale);
getBaseContext().getResources().updateConfiguration(newConfig, getBaseContext().getResources().getDisplayMetrics());
}
}
#Override
public void onCreate()
{
super.onCreate();
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
Configuration config = getBaseContext().getResources().getConfiguration();
String lang = settings.getString(getString(R.string.pref_language), "");
if (! "".equals(lang) && ! config.locale.getLanguage().equals(lang))
{
locale = new Locale(lang);
Log.i("Locale" , lang);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
}
}
I have got to change the value of settings.getString(getString(R.string.pref_language), ""); from the Settings Activity of my app.
The problem is none of the strings (which have a translation) and are accessed using getString() method, are showing the translated text.
EDIT1 : I am using Android 8.0
In android 8, the behavior of the Locales changed, now every Activity context will take its locale, i.e if you in Activity1 and changed the locale for Activity1, then Activity2 will remain on the default locale.
The solution is to change the locale for every Activity and your issue will be fixed.
When you are using getString(R.string.pref_language) the call will return the string from the language matching Locale.getDefault() as long as a translation is provided.
If a translation is not provided it will return the default language, that is the language your using in the values/strings.xml file.
All translated values are in values-xx folders, where xx is the 2 letter ISO code for the language.

Change language in android application resources

after studying about supporting multiple languages in android application, i have good the basic idea about how i can make resources for different languages within application, for example i want to add Spanish language in my application so in res direction within my application i have added values-en directory and in that direct i have added strings resource and within that resource i have added strings with values of Spanish text, in my application default language is English now i want to know how can i switch it to Spanish, i have the resources ready i just need to change my application language to Spanish
Use below code in your onCreate() after setContentView:
String languageToLoad = "es";
Locale locale = new Locale(languageToLoad);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
You also have to change your value folder to values-es. values-en is for English. Hope this helps.
To change App locale follow below code:
1) Create LocaleUtils class:
public class LocaleUtils {
private static Locale sLocale;
public static void setLocale(Locale locale) {
sLocale = locale;
if(sLocale != null) {
Locale.setDefault(sLocale);
}
}
public static void updateConfig(ContextThemeWrapper wrapper) {
if(sLocale != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
Configuration configuration = new Configuration();
configuration.setLocale(sLocale);
wrapper.applyOverrideConfiguration(configuration);
}
}
public static void updateConfig(Application app, Configuration configuration) {
if (sLocale != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
//Wrapping the configuration to avoid Activity endless loop
Configuration config = new Configuration(configuration);
// We must use the now-deprecated config.locale and res.updateConfiguration here,
// because the replacements aren't available till API level 24 and 17 respectively.
config.locale = sLocale;
Resources res = app.getBaseContext().getResources();
res.updateConfiguration(config, res.getDisplayMetrics());
}
}
}
2) In Application Class:
public class YourAppName extends Application {
public void onCreate(){
super.onCreate();
LocaleUtils.setLocale(new Locale("es"));
LocaleUtils.updateConfig(this, getBaseContext().getResources().getConfiguration());
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
LocaleUtils.updateConfig(this, newConfig);
}
}
3) Remember, Your Application class name and <application android:name=".YourAppName"> should be same. Otherwise it won't work. Kudos to this answer.

How to Refresh App with onConfigChanges without loosing instance

protected void onResume() {
super.onResume();
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
Configuration config = getBaseContext().getResources().getConfiguration();
String lang = settings.getString("lang_list", "");
// Log.d("Lang",lang);
if (!"".equals(lang) && !config.locale.getLanguage().equals(lang)) {
recreate();
Locale locale = new Locale(lang);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
if (AppController.getInstance().isPreferenceChanged()) {
setupViewPager(viewPager);
adapter.notifyDataSetChanged();
}
}
I want to change the app language without recreate the app. I mean I want to do it when user select any language from the setting then it Should change the Setting Activity language without using recreate();, because when I use recreate(); it blinks the App once.
So I am not using recreate();. Instead I wrote below code in Setting Activity in AndroidManifest.xml
<activity
android:name=".activity.SettingsActivity"
android:label="#string/title_activity_settings"
android:configChanges="orientation|keyboardHidden|screenSize|locale|layoutDirection"/>
As in below screenshot you can see that I have selected "Hindi" for the language but it is not updating the Activity to Hindi. I mean "Select Country", "Select Your Language" and "Select Categories" should be display in Hindi instead of English. I have wrote String in both languages.
Can Anybody know How to change it when Change the language ?
OR
Why onConfigChanges is not working for locale as it is working for Orientation.
Thank you !
In your MainActivity call sharedPrefrences on onStart callback insted of calling in onCreate
Example:-
protected void onStart() {
SharedPreferences sharedPreferences = this.getSharedPreferences("selectedLanguage", Context.MODE_PRIVATE);
String pine = sharedPreferences.getString("language", DEFAULT);
String languageToLoad = pine;
Locale locale = new Locale(languageToLoad);//Set Selected Locale
Locale.setDefault(locale);//set new locale as default
Configuration config = new Configuration();//get Configuration
config.locale = locale;//set config locale as selected locale
this.getResources().updateConfiguration(config, this.getResources().getDisplayMetrics());
invalidateOptionsMenu(); //This changes language in OptionsMenu too
setTitle(R.string.app_name); //calling app name according to language selected by user
super.onStart();
}
You can use a singleton class that will handle the language change without restarting the activity,
public class MyApplication extends Application
{
private Locale locale = null;
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
if (locale != null)
{
newConfig.locale = locale;
Locale.setDefault(locale);
getBaseContext().getResources().updateConfiguration(newConfig, getBaseContext().getResources().getDisplayMetrics());
}
}
#Override
public void onCreate()
{
super.onCreate();
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
Configuration config = getBaseContext().getResources().getConfiguration();
String lang = settings.getString(getString(R.string.pref_locale), "");
if (! "".equals(lang) && ! config.locale.getLanguage().equals(lang))
{
locale = new Locale(lang);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
}
}

Is there a android attribute to disable locale change in my app

When user changes the system locale from US to China. I don't want to change the language from English to Chinese in my app, I expect that my app's language still in English.
May I do this by setting a android attribute in AndroidManifest.xml?
Thanks
I think it would be better to do this once and put your code in your application class
public class MyApplication extends Application {
#Override
protected void attachBaseContext(Context base) {
Resources res = base.getResources();
Locale locale = new Locale("en");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
res.updateConfiguration(config, res.getDisplayMetrics());
super.attachBaseContext(base);
}
}
If you just want the Chinese xml to stay in the app but not plan in using it, you can simply comment all its content, and the App will consider only the English strings
You can use below code to maintain locale as per your requirement,
Locale locale = new Locale("en");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());

Android - App locale changes and displayed orientation

I'm having a headache with the locale thing in my app. So basically my app supports two languages, English and Vietnamese, and user can choose to change the language to be displayed. So I have a SettingActivity like this:
public class SettingsActivity extends SherlockPreferenceActivity implements OnPreferenceChangeListener{
private ListPreference langPref;
private SharedPreferences languagepref;
private String language;
private Locale locale;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
languagepref = PreferenceManager.getDefaultSharedPreferences(this);
Configuration config = getBaseContext().getResources().getConfiguration();
language = languagepref.getString("languageToLoad","en");
locale = new Locale(language);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
addPreferencesFromResource(R.xml.preferences_login);
langPref = (ListPreference) findPreference("lang_pref");
if (language.equalsIgnoreCase("vi")){
langPref.setValueIndex(1);
}
else{
langPref.setValueIndex(0);
}
langPref.setOnPreferenceChangeListener(this);
}
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String key = preference.getKey();
if (key.equals("lang_pref")){
String languageToLoad = (String) newValue;
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
SharedPreferences.Editor editor = languagepref.edit();
editor.putString("languageToLoad",languageToLoad );
editor.commit();
recreate();
}
return false;
}
}
In every other activity, I add this in their onCreate method:
SharedPreferences languagepref = PreferenceManager.getDefaultSharedPreferences(this);
Configuration config = getBaseContext().getResources().getConfiguration();
String language = languagepref.getString("languageToLoad","en");
Locale locale = new Locale(language);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
And now my app is acting weird: in the SettingActivity, the language is displayed properly whenever I rotate my device, even without the need of adding android:configChanges="locale" in the activity's manifest. However, in every other activity, the language is changed back to English when I rotate the device. I've try adding android:configChanges="locale" in their manifest but it doesn't work. Also, I've tried every solution found on Stackoverflow but none of them works for me, so I'm basically clueless now. Could anyone of you help me point out the mistake I made here? Please do and thanks in advance.
Try adding
android:configChanges="orientation|keyboard|keyboardHidden"
in the manifest for each activity.
Then you should override onConfigurationChanged in your activities, and in this method reload layout (depending orientation). If you still have problems with locale, reload the appropriate locale in onConfigurationChanged.

Categories

Resources