374

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()

CQM
  • 42,592
  • 75
  • 224
  • 366
  • 1
    `default()` is a pretty safe bet, just don't use it for processing (like the docs say). – A--C Jan 17 '13 at 22:43
  • 1
    @A--C use it for processing? – CQM Jan 17 '13 at 22:45
  • Yeah, see what the [docs](http://developer.android.com/reference/java/util/Locale.html) say: *some locales will use ',' as the decimal point and '.' for digit grouping.* so stuff like parseInt() may fail. Note that they still recommend using `default()`, but not for stuff that can break code. – A--C Jan 17 '13 at 22:48
  • Does this answer your question? [How to identify device language from the App language in Android 13?](https://stackoverflow.com/questions/73399280/how-to-identify-device-language-from-the-app-language-in-android-13) – k4dima Mar 31 '23 at 18:37

10 Answers10

570

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.
Blundell
  • 75,855
  • 30
  • 208
  • 233
devunwired
  • 62,780
  • 12
  • 127
  • 139
  • Suppose I wish to save&restore it using sharedPreferences, how should I do that? Would what I retrieve be comparable to what I have? – android developer Apr 30 '14 at 22:56
  • 1
    Did anyone check that the default Locale isn't changed in app when you change it in system? I think it's one of those "configuration changes" which make activities destroyed and recreated – Michał Klimczak Jan 05 '15 at 14:38
  • 12
    I tested it, outputting both while I kept on changing locale; result is, the output is the same. So Locale.getDefault() can be used safely as it gets immediately updated. `Log.d("localeChange", "Default locale lang: " + Locale.getDefault().getLanguage()); Log.d("localeChange", "Config locale lang: " + getResources().getConfiguration().locale.getLanguage());` – Alessio Mar 30 '16 at 05:27
  • 74
    This has been deprecated in the Configuration class, see the latest docs for this advice: `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.` – MrBigglesworth Jul 01 '16 at 18:23
  • 9
    why don't they just add a getFirstLocale() method to avoid that weird getLocales().get(0)? – user3290180 Jul 08 '16 at 12:47
  • 2
    What if you want to support older and newer versions of api? – Ivan Apr 24 '17 at 11:42
  • It also returns the wrong value for some languages for example nn_NO always returns as the next one in the list.. – Oliver Dixon Dec 05 '17 at 13:20
  • Is this still relevant? Checked Locale.getDefault (), the language changes on the fly, and not just at startup. – Zakhar Rodionov May 14 '20 at 14:38
  • @user3290180 Because it's a simple list/array. No need to add a function for getting the first item. – android developer Feb 14 '21 at 10:38
225

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;
        }
    }
ericn
  • 12,476
  • 16
  • 84
  • 127
Makalele
  • 7,431
  • 5
  • 54
  • 81
  • 6
    Is there something in the support library to avoid the if-else? – Federico Ponzi Oct 27 '16 at 13:43
  • 8
    @TargetApi(Build.VERSION_CODES.N) is not needed in your code if you include the if and fallback code – Patrick Dec 11 '16 at 08:39
  • @FedericoPonzi no ResourceCompat does not seem to have a method for locale as of 25.0.1 – Patrick Dec 11 '16 at 08:40
  • 4
    This may not work if the user has multiple languages installed. You should use `LocaleList.getDefault().get(0);` as this will return the Locales sorted by the preferred language. – SoftWyer Sep 08 '17 at 08:58
  • 34
    @FedericoPonzi @for3st I found this in `ConfigurationCompat`, as `ConfigurationCompat.getLocales(getResources().getConfiguration()).get(0)` – yuval Sep 22 '17 at 00:19
  • I pass in basecontext incase using a contextWrapper. good code. – j2emanue Aug 09 '18 at 12:47
  • @yuval ConfigurationCompat.getLocales crashes on Emulator with Android 5 API 21 – David Feb 17 '20 at 12:06
  • 3
    Why not just use `Locale.getDefault()`? – android developer Feb 14 '21 at 10:40
  • 1
    @androiddeveloper because Locale.getDefault() returns the default locale. If you change it in run time (for instance, if you implement a possibility to change language within the app), you will probably need the current Locale instead – Leo DroidCoder May 28 '21 at 22:51
  • @LeoDroidcoder You can change the locale of the app? Where do you do this? I never saw any UI to do this... Maybe you mean something in code? – android developer May 29 '21 at 06:38
94

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]
ElegyD
  • 4,393
  • 3
  • 21
  • 37
  • 18
    If you don't have any context you can also do `ConfigurationCompat.getLocales(Resources.getSystem().getConfiguration()).get(0);` – Quentin G. Dec 11 '18 at 14:06
  • @QuentinG. Yes, but better to use the [Application](https://developer.android.com/reference/kotlin/android/app/Application.html) context in this case. – McMath Dec 08 '19 at 23:17
  • So to be clear, this won't return the default locale but the user preferred locale? – Csaba Toth Apr 25 '20 at 08:37
14

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.

kabuko
  • 36,028
  • 10
  • 80
  • 93
  • 8
    this answer is wrong, got a default locale but if user changed it on fly it show wrong. next answer is correct – user170317 Jun 11 '13 at 14:41
  • agreed, wrong answer. In my case, I was looking for a way to not have to use getResources(), which means I need a context. My problem was a helper class that didn't have a context, but guess I'll have to pass it on in. If you have an app that lets people change their locale and have the views' strings, number formats etc change, then you need to use Devunwired's response – 1mike12 Nov 18 '15 at 16:09
  • Work for me. If I set a breakpoint at `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) – cambunctious Oct 18 '19 at 01:01
11

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();
   }
}
  • 1
    One of the few answers that returns the user's preferred language direction at the device level. You can also use `LocaleListCompat.getDefault()` if you use AndroidX. – Sam Feb 09 '20 at 05:21
  • Best Answer so far – SVG Aug 17 '23 at 06:01
8

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()

Community
  • 1
  • 1
Rax
  • 1,347
  • 3
  • 20
  • 27
  • Yes but hasn't it been replaced with the androidx ConfigurationCompat version, see https://developer.android.com/reference/androidx/core/os/ConfigurationCompat – DragonLord Jan 27 '20 at 16:09
  • Correct, maybe it's only mentioned because of androidx migration – Rax Jan 28 '20 at 15:30
4

As for now, we can use ConfigurationCompat class to avoid warnings and unnecessary boilerplates.

Locale current = ConfigurationCompat.getLocales(getResources().getConfiguration()).get(0);
Alif Hasnain
  • 1,176
  • 1
  • 11
  • 24
2

I´ve used this:

String currentLanguage = Locale.getDefault().getDisplayLanguage();
if (currentLanguage.toLowerCase().contains("en")) {
   //do something
}
fvaldivia
  • 446
  • 5
  • 13
  • 1
    Note: ISO 639 is not a stable standard— some languages' codes have changed. Locale's constructor recognizes both the new and the old codes for the languages whose codes have changed, but this function always returns the old code. If you want to check for a specific language whose code has changed, don't do `if (locale.getLanguage().equals("he")) // BAD!` Instead, do `if (locale.getLanguage().equals(new Locale("he").getLanguage()))` – Ari Jan 07 '21 at 19:16
  • Please see this link for more information about what @Ari described: https://developer.android.com/reference/java/util/Locale#getLanguage() – James Oct 26 '21 at 22:09
1

I used this simple code:

if(getResources().getConfiguration().locale.getLanguage().equalsIgnoreCase("en"))
{
   //do something
}
farhad.kargaran
  • 2,233
  • 1
  • 24
  • 30
0

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
 * @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) {
        return arrayListOf(Locale.getDefault())
    }
    val defaultLocale =
            if (haveFirstAsCurrentLocale) Locale.getDefault()
            else null
    val localeList = Resources.getSystem().configuration.locales
    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")
}
android developer
  • 114,585
  • 152
  • 739
  • 1,270