How do I get the user's current Locale in Android?
I can get the default one, but this may not be the current one correct?
Basically I want the two letter language code from the current locale. Not the default one. There is no Locale.current()
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.
Update for > API 24 from the comments
Locale current = getResources().getConfiguration().getLocales().get(0) // is now the preferred accessor. Log.d("localeChange", "Default locale lang: " + Locale.getDefault().getLanguage()); Log.d("localeChange", "Config locale lang: " + getResources().getConfiguration().locale.getLanguage());locale This field was deprecated in API level 24. Do not set or read this directly. Use getLocales() and setLocales(LocaleList). If only the primary locale is needed, getLocales().get(0) is now the preferred accessor.Android N (Api level 24) update (no warnings):
Locale getCurrentLocale(Context context){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){ return context.getResources().getConfiguration().getLocales().get(0); } else{ //noinspection deprecation return context.getResources().getConfiguration().locale; } } LocaleList.getDefault().get(0); as this will return the Locales sorted by the preferred language.ConfigurationCompat, as ConfigurationCompat.getLocales(getResources().getConfiguration()).get(0)Locale.getDefault()?If you are using the Android Support Library you can use ConfigurationCompat instead of @Makalele's method to get rid of deprecation warnings:
Locale current = ConfigurationCompat.getLocales(getResources().getConfiguration()).get(0); or in Kotlin:
val currentLocale = ConfigurationCompat.getLocales(resources.configuration)[0] ConfigurationCompat.getLocales(Resources.getSystem().getConfiguration()).get(0);From getDefault's documentation:
Returns the user's preferred locale. This may have been overridden for this process with setDefault(Locale).
Also from the Locale docs:
The default locale is appropriate for tasks that involve presenting data to the user.
Seems like you should just use it.
Locale.setDefault(), it get's called when I change the device language at least back to Android 5.0 (that's as far as I tested)All answers above - do not work. So I will put here a function that works on 4 and 9 android
private String getCurrentLanguage(){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){ return LocaleList.getDefault().get(0).getLanguage(); } else{ return Locale.getDefault().getLanguage(); } } LocaleListCompat.getDefault() if you use AndroidX.As per official documentation ConfigurationCompat is deprecated in support libraries
You can consider using
LocaleListCompat.getDefault()[0].toLanguageTag() 0th position will be user preferred locale
To get Default locale at 0th position would be LocaleListCompat.getAdjustedDefault()
I´ve used this:
String currentLanguage = Locale.getDefault().getDisplayLanguage(); if (currentLanguage.toLowerCase().contains("en")) { //do something } if (locale.getLanguage().equals("he")) // BAD! Instead, do if (locale.getLanguage().equals(new Locale("he").getLanguage()))The current one is indeed the one you get by Locale.getDefault.
I've tested what other people have answered here. Indeed there are 2 solutions that seem to be very similar: LocaleListCompat.getDefault() and Resources.getSystem().configuration.locales. However, there is at least one difference between them:
When you use Locale.setDefault(), the LocaleListCompat.getDefault() will return a new order in the list, yet the Resources.getSystem().configuration.locales will stay the same as the OS.
There might be another difference in case the user has set the locale of the app via the new per-app locale feature:
https://developer.android.com/guide/topics/resources/app-languages
In any way, if you want to get all current locales, you can use this:
/**returns a list of all current locales, or null if not needed as there aren't at least 2 (if it's one, it's the default locale anyway). * @param haveFirstAsCurrentLocale when true, makes sure the first locale is also the default one. If not, it depends on what you've set as locale*/ fun getLocalesList(haveFirstAsCurrentLocale: Boolean = true): ArrayList<Locale>? { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { if(haveFirstAsCurrentLocale) return arrayListOf(Locale.getDefault()) return null } val localeList = Resources.getSystem().configuration.locales if (localeList.size() <= 1) return null val defaultLocale = if (haveFirstAsCurrentLocale) Locale.getDefault() else null val result = ArrayList<Locale>(localeList.size()) if (defaultLocale != null) result.add(defaultLocale) for (i in 0 until localeList.size()) { val locale = localeList[i]!! if (locale == defaultLocale) continue result.add(locale) } return result } Usage:
getLocalesList().forEachIndexed { index, it -> Log.d("AppLog", "$index:$it") } This is available on my small tools repository, here:
default()is a pretty safe bet, just don't use it for processing (like the docs say).default(), but not for stuff that can break code.