In above examples you understand how to localize resources of application. Following example explain how to change the application locale within application, not from device. In order to change Application locale only, you can use below locale util.
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.preference.PreferenceManager;
import android.view.ContextThemeWrapper;
import java.util.Locale;
/**
* Created by Umesh on 10/10/16.
*/
public class LocaleUtils {
private static Locale mLocale;
public static void setLocale(Locale locale){
mLocale = locale;
if(mLocale != null){
Locale.setDefault(mLocale);
}
}
public static void updateConfiguration(ContextThemeWrapper wrapper){
if(mLocale != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
Configuration configuration = new Configuration();
configuration.setLocale(mLocale);
wrapper.applyOverrideConfiguration(configuration);
}
}
public static void updateConfiguration(Application application, Configuration configuration){
if(mLocale != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1){
Configuration config = new Configuration(configuration);
config.locale = mLocale;
Resources res = application.getBaseContext().getResources();
res.updateConfiguration(configuration, res.getDisplayMetrics());
}
}
public static void updateConfiguration(Context context, String language, String country){
Locale locale = new Locale(language,country);
setLocale(locale);
if(mLocale != null){
Resources res = context.getResources();
Configuration configuration = res.getConfiguration();
configuration.locale = mLocale;
res.updateConfiguration(configuration,res.getDisplayMetrics());
}
}
public static String getPrefLangCode(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context).getString("lang_code","en");
}
public static void setPrefLangCode(Context context, String mPrefLangCode) {
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
editor.putString("lang_code",mPrefLangCode);
editor.commit();
}
public static String getPrefCountryCode(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context).getString("country_code","US");
}
public static void setPrefCountryCode(Context context,String mPrefCountryCode) {
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
editor.putString("country_code",mPrefCountryCode);
editor.commit();
}
}
Initialize locale that user preferred, from Application class.
public class LocaleApp extends Application{
@Override
public void onCreate() {
super.onCreate();
LocaleUtils.setLocale(new Locale(LocaleUtils.getPrefLangCode(this), LocaleUtils.getPrefCountryCode(this)));
LocaleUtils.updateConfiguration(this, getResources().getConfiguration());
}
}
You also need to create a base activity and extend this activity to all other activity so that you can change locale of application only one place as follows :
public abstract class LocalizationActivity extends AppCompatActivity {
public LocalizationActivity() {
LocaleUtils.updateConfiguration(this);
}
// We only override onCreate
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
Note : Always initialize locale in constructor.
Now you can use LocalizationActivity as follow.
public class MainActivity extends LocalizationActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Note: When you change locale of application programmatically, need to restart your activity to take the effect of locale change In order to work properly for this solution you and use locale from shared preferences on app startup you
android:name=".LocaleApp"
in you Manifest.xml.
Sometimes Lint checker prompt to create the release build. To solve such issue follow below options.
First:
If you want to disable translation for some strings only then add following attribute to default string.xml
<string name="developer" translatable="false">Developer Name</string>
Second:
Ignore all missing translation from resource file add following attribute It's the ignore attribute of the tools namespace in your strings file, as follows:
<?xml version="1.0" encoding="utf-8"?>
<resources
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="MissingTranslation" >
http://stackoverflow.com/documentation/android/3345/localization-with-resources-in-android#
<!-- your strings here; no need now for the translatable attribute -->
</resources>
Third:
Another way to disable non-translatable string
http://tools.android.com/recent/non-translatablestrings
If you have a lot of resources that should not be translated, you can place them in a file named donottranslate.xml and lint will consider all of them non-translatable resources.
Fourth:
You can also add locale in resource file
<resources
xmlns:tools="http://schemas.android.com/tools"
tools:locale="en" tools:ignore="MissingTranslation">
You can also disable missing translation check for lint from app/build.gradle
lintOptions {
disable 'MissingTranslation'
}