Android get current Locale, not default
The default Locale
is constructed statically at runtime for your application process from the system property settings, so it will represent the Locale
selected on that device when the application was launched. Typically, this is fine, but it does mean that if the user changes their Locale
in settings after your application process is running, the value of getDefaultLocale()
probably will not be immediately updated.
If you need to trap events like this for some reason in your application, you might instead try obtaining the Locale
available from the resource Configuration
object, i.e.
Locale current = getResources().getConfiguration().locale;
You may find that this value is updated more quickly after a settings change if that is necessary for your application.
How to get language (locale) currently Android app displays?
My own solution is to add to strings.xml
key-value pair locale=<locale code>
, thus context.getResources().getString(R.string.locale)
will return locale code specific for used locale.
Get the current language in device
If you want to get the selected language of your device, this might help you:
Locale.getDefault().getDisplayLanguage();
You can use Locale.getDefault().getLanguage();
to get the usual language code (e.g. "de", "en")
Android get device locale
There's a much simpler and cleaner way to do this than using reflection or parsing some system property.
As you noticed once you set the default Locale in your app you don't have access to the system default Locale any more. The default Locale you set in your app is valid only during the life cycle of your app. Whatever you set in your Locale.setDefault(Locale) is gone once the process is terminated . When the app is restarted you will again be able to read the system default Locale.
So all you need to do is retrieve the system default Locale when the app starts, remember it as long as the app runs and update it should the user decide to change the language in the Android settings. Because we need that piece of information only as long as the app runs, we can simply store it in a static variable, which is accessible from anywhere in your app.
And here's how we do it:
public class MyApplication extends Application {
public static String sDefSystemLanguage;
@Override
public void onCreate() {
super.onCreate();
sDefSystemLanguage = Locale.getDefault().getLanguage();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
sDefSystemLanguage = newConfig.locale.getLanguage();
}
}
Using an Application (don't forget to define it in your manifest) we get the default locale when the app starts (onCreate()) and we update it when the user changes the language in the Android settings (onConfigurationChanged(Configuration)). That's all there is.
Whenever you need to know what the system default language was before you used your setDefault call, sDefSystemLanguage will give you the answer.
There's one issue I spotted in your code. When you set the new Locale you do:
Configuration config = new Configuration();
config.locale = locale;
pContext.getResources().updateConfiguration(config, null);
When you do that, you overwrite all Configuration information that you might want to keep. E.g. Configuration.fontScale reflects the Accessibility settings Large Text. By settings the language and losing all other Configuration your app would not reflect the Large Text settings any more, meaning text is smaller than it should be (if the user has enabled the large text setting).
The correct way to do it is:
Resources res = pContext.getResources();
Configuration config = res.getConfiguration();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLocale(locale);
}
else {
configuration.locale = locale;
}
res.updateConfiguration(config, null);
So instead of creating a new Configuration object we just update the current one.
In Per-app language, how to get App locale in API 33 if System locale is different?
Can you use AppCompatDelegate.getApplicationLocales()
?
I'm working through the same challenges as you right now, and this seems to work for me.
AppCompatDelegate -> [es_US] // after setting with AppCompatDelegate
Locale -> en_US // never changed, my system default
// Worked on emulators for both API 27 and 33
Related Topics
How to Determine If One of My Activities Is in the Foreground
Android Volley - How to Isolate Requests in Another Class
Failed to Find Build Tools Revision 23.0.1
Neither User 10102 Nor Current Process Has Android.Permission.Read_Phone_State
How to Make an Android Slidingdrawer Slide Out from the Left
Multi Selection Spinner in Android Without Alertdialog
Setting Drawable Folder to Use for Different Resolutions
Creating Tabs Using Fragments Now That Tabactivity Is Deprecated
Googlesignatureverifier Signature Not Valid Message (Google Play Services 9.0.0)
How to Block a Mobile Number Call and Message Receiving in Android Application Development
Activenetworkinfo.Type Is Deprecated in API Level 28
Android Runtimeexception: Unable to Instantiate the Service
How to Tell If the Sdcard Is Mounted in Android
Pass Arraylist from One Activity to Other
Location Needs to Be Enabled for Bluetooth Low Energy Scanning on Android 6.0
Android - Setonclicklistener VS Onclicklistener VS View.Onclicklistener