Android has a curious way of handling locale.
With the introduction of per-app language preferences, things have gotten even more complicated.
This post won’t go deep into explaining the nooks and crannies of localization. Better blog posts (and the actual android documentation) exist for that.
Theory is boring enough, let’s look at a real world example.
Limit language resources.
The resource folders should look something like this.
Default resource configuration is used. (es-ES is not supported)
Locale.getDefault() returns the system language.
Add an additional system language: en-AU.
Since en-AU is supported, Locale.getDefault() will coincide with the current resource configuration.
Setting locale with per-app language preferences
First, use the compat method:
Let’s stop and consider what should be expected:
it resource configuration is supported in the build.gradle file.
It should be used since it is a fallback for it-IT.
Remember, we are on Android 11 (per-app languages are supported via system settings Android 13 onwards, not before).
What about Android 13+?
Same setup as above.
Set it-IT via AppCompatDelete.setApplicationLocales.
Locale.getDefault does follow the application locale now, unlike API <13.
Consider carefully what would work best for you when using Accept-Language headers. (or anything of that sort where uniform localization might be desired)
In-app language pickers can be implemented with the AndroidX support library for backward compatibility with all android versions. A welcome addition, but adds overhead on an already convoluted problem.
Behaviour can differ depending on API version, system locale and per-app language preferences.
One could piggyback on android’s resource resolution mechanism instead.
Language/region can be declared arbitrarily as strings in the respective strings.xml files for each configuration.
This might introduce other complications though. The app locale is now “tied” to resources.
What region would one set in the en folder anyway? How many resource configurations should the app support now? Is a region even needed?
Depending on how complex your usecase is, this simple thing could be enough.
Gotchas with AndroidX support library
AppCompatDelegate.getApplicationLocales() will return nothing (empty list) if no app locale has been set manually.
Since this method is reaching for an activity behind the scenes to resolve locale, it should only be called after Activity#onCreate. For instance, calling this at Application#onCreate will always return nothing.
Hope you found this somewhat useful.