My app supports 3 (soon 4) languages. Since several locales are quite similar I'd like to give the user the option to change locale in my application, for instance an Italian person might prefer Spanish over English.
Is there a way for the user to select among the locales that are available for the application and then change what locale is used? I don't see it as a problem to set locale for each Activity since it is a simple task to perform in a base class.
As no answer is complete for the current way to solve this problem, I try to give instructions for a complete solution. Please comment if something is missing or could be done better.
General information
First, there exist some libraries that want to solve the problem but they all seem outdated or are missing some features:
Further I think writing a library might not be a good/easy way to solve this problem because there is not very much to do, and what has to be done is rather changing existing code than using something completely decoupled. Therefore I composed the following instructions that should be complete.
My solution is mainly based on https://github.com/gunhansancar/ChangeLanguageExample (as already linked to by localhost). It is the best code I found to orientate at. Some remarks:
updateViews()
in each Activity to manually update all strings after changing locale (using the usualgetString(id)
) which is not necessary in the approach shown belowI changed it a bit, decoupling the part which persists the chosen locale (as one might want to do that separately, as suggested below).
Solution
The solution consists of the following two steps:
Step 1: Change the locale
Use the class
LocaleHelper
, based on gunhansancar's LocaleHelper:ListPreference
in aPreferenceFragment
with the available languages (has to be maintained when languages should be added later)Create a
SettingsFragment
like the following:Create a resource
locales.xml
listing all locales with available translations in the following way (list of locale codes):In your
PreferenceScreen
you can use the following section to let the user select the available languages:which uses the following strings from
strings.xml
:Step 2: Make the app use the custom locale
Now setup each Activity to use the custom locale set. The easiest way to accomplish this is to have a common base class for all activities with the following code (where the important code is in
attachBaseContext(Context base)
andonResume()
):What it does is
attachBaseContext(Context base)
to use the locale previously persisted withLocaleHelper
Notes on this solution
Recreating an Activity does not update the title of the ActionBar (as already observed here: https://github.com/gunhansancar/ChangeLanguageExample/issues/1).
setTitle(R.string.mytitle)
in theonCreate()
method of each activity.It lets the user chose the system default locale, as well as the default locale of the app (which can be named, in this case "English").
Only language codes, no region (country) and variant codes (like
fr-rCA
) are supported so far. To support full locale specifications, a parser similar to that in the Android-Languages library can be used (which supports region but no variant codes).Add a helper class with the following method:
And call it in your startup activity, like
MainActivity.java
:Hope this help(in onResume):
simple and easy
where "en" is language code and "US" is country code.
For people still looking for this answer, since
configuration.locale
is deprecated you can now use from API 24:Take in consideration that the minSkdVersion for this method is API 17.
Full example code:
Don't forget that, if you change the locale with a running Activity, you will need to restart it for the changes to take effect.
EDIT 11th MAY 2018
As from @CookieMonster's post, you might have problems keeping the locale change in higher API versions. If so, add the following code to your Base Activity so that you update the context locale on every Activity creation:
If you use this, don't forget to save the language to SharedPreferences when you set the locale with
setLocate(locale)