Change App Language Programmatically in Android

Change app language programmatically in Android

It's possible. You can set the locale. However, I would not recommend that. We've tried it at early stages, it's basically fighting the system.

We have the same requirement for changing the language but decided to settle to the fact that UI should be same as phone UI. It was working via setting locale but was too buggy. And you have to set it every time you enter activity (each activity) from my experience. here is a code if you still need this (again, I don't recommend that)

Resources res = context.getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.setLocale(new Locale(language_code.toLowerCase())); // API 17+ only.
// Use conf.locale = new Locale(...) if targeting lower versions
res.updateConfiguration(conf, dm);

If you have language specific content - you can change that base on the setting.


update on 26th of march 2020

    public static void setLocale(Activity activity, String languageCode) {
Locale locale = new Locale(languageCode);
Locale.setDefault(locale);
Resources resources = activity.getResources();
Configuration config = resources.getConfiguration();
config.setLocale(locale);
resources.updateConfiguration(config, resources.getDisplayMetrics());
}
  • NOTES: Language code cannot got '-' & must be 2 small case letter only

Android - Change application locale programmatically

A blog article, how to change the language on Android at runtime and don’t go mad, addressed the issue (along with others) and the author created a library called Lingver to solve the issues.

EDIT (3 Jun 2022): Lingver library has completely failed to address a few issues and appears to be inactive for some time. After a thorough investigation, I have came up with my own implementation: (You can copy the code below under the terms of either Apache-2.0 or GPL-3.0-or-later license)

LangUtils.java

public final class LangUtils {
public static final String LANG_AUTO = "auto";
public static final String LANG_DEFAULT = "en";

private static ArrayMap<String, Locale> sLocaleMap;

public static void init(@NonNull Application application) {
application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
private final HashMap<ComponentName, Locale> mLastLocales = new HashMap<>();
@Override
public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
mLastLocales.put(activity.getComponentName(), applyLocaleToActivity(activity));
}

@Override
public void onActivityStarted(@NonNull Activity activity) {
if (!Objects.equals(mLastLocales.get(activity.getComponentName()), getFromPreference(activity))) {
Log.d("LangUtils", "Locale changed in activity " + activity.getComponentName());
ActivityCompat.recreate(activity);
}
}

@Override
public void onActivityResumed(@NonNull Activity activity) {
}

@Override
public void onActivityPaused(@NonNull Activity activity) {
}

@Override
public void onActivityStopped(@NonNull Activity activity) {
}

@Override
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
}

@Override
public void onActivityDestroyed(@NonNull Activity activity) {
mLastLocales.remove(activity.getComponentName());
}
});
application.registerComponentCallbacks(new ComponentCallbacks() {
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
applyLocale(application);
}

@Override
public void onLowMemory() {
}
});
applyLocale(application);
}

public static void setAppLanguages(@NonNull Context context) {
if (sLocaleMap == null) sLocaleMap = new ArrayMap<>();
Resources res = context.getResources();
Configuration conf = res.getConfiguration();
// Assume that there is an array called language_key which contains all the supported language tags
String[] locales = context.getResources().getStringArray(R.array.languages_key);
Locale appDefaultLocale = Locale.forLanguageTag(LANG_DEFAULT);

for (String locale : locales) {
conf.setLocale(Locale.forLanguageTag(locale));
Context ctx = context.createConfigurationContext(conf);
String langTag = ctx.getString(R.string._lang_tag);

if (LANG_AUTO.equals(locale)) {
sLocaleMap.put(LANG_AUTO, null);
} else if (LANG_DEFAULT.equals(langTag)) {
sLocaleMap.put(LANG_DEFAULT, appDefaultLocale);
} else sLocaleMap.put(locale, ConfigurationCompat.getLocales(conf).get(0));
}
}

@NonNull
public static ArrayMap<String, Locale> getAppLanguages(@NonNull Context context) {
if (sLocaleMap == null) setAppLanguages(context);
return sLocaleMap;
}

@NonNull
public static Locale getFromPreference(@NonNull Context context) {
String language = // TODO: Fetch current language from the shared preferences
getAppLanguages(context);
Locale locale = sLocaleMap.get(language);
if (locale != null) {
return locale;
}
// Load from system configuration
Configuration conf = Resources.getSystem().getConfiguration();
//noinspection deprecation
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? conf.getLocales().get(0) : conf.locale;
}

public static Locale applyLocaleToActivity(Activity activity) {
Locale locale = applyLocale(activity);
// Update title
try {
ActivityInfo info = activity.getPackageManager().getActivityInfo(activity.getComponentName(), 0);
if (info.labelRes != 0) {
activity.setTitle(info.labelRes);
}
} catch (Exception e) {
e.printStackTrace();
}
// Update menu
activity.invalidateOptionsMenu();
return locale;
}

private static Locale applyLocale(Context context) {
return applyLocale(context, LangUtils.getFromPreference(context));
}

private static Locale applyLocale(@NonNull Context context, @NonNull Locale locale) {
updateResources(context, locale);
Context appContext = context.getApplicationContext();
if (appContext != context) {
updateResources(appContext, locale);
}
return locale;
}

private static void updateResources(@NonNull Context context, @NonNull Locale locale) {
Locale.setDefault(locale);

Resources res = context.getResources();
Configuration conf = res.getConfiguration();
//noinspection deprecation
Locale current = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? conf.getLocales().get(0) : conf.locale;

if (current == locale) {
return;
}

conf = new Configuration(conf);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
setLocaleApi24(conf, locale);
} else {
conf.setLocale(locale);
}
//noinspection deprecation
res.updateConfiguration(conf, res.getDisplayMetrics());
}

@RequiresApi(Build.VERSION_CODES.N)
private static void setLocaleApi24(@NonNull Configuration config, @NonNull Locale locale) {
LocaleList defaultLocales = LocaleList.getDefault();
LinkedHashSet<Locale> locales = new LinkedHashSet<>(defaultLocales.size() + 1);
// Bring the target locale to the front of the list
// There's a hidden API, but it's not currently used here.
locales.add(locale);
for (int i = 0; i < defaultLocales.size(); ++i) {
locales.add(defaultLocales.get(i));
}
config.setLocales(new LocaleList(locales.toArray(new Locale[0])));
}
}

MyApplication.java

public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
LangUtils.init(this);
}
}

In your preference where you are changing the language, you can simply restart the preferences activity like this:

ActivityCompat.recreate(activity);

Activites that use Android WebView
After loading the webview via Activity.findViewById() you can add the following line immediately:

// Fix locale issue due to WebView (https://issuetracker.google.com/issues/37113860)
LangUtils.applyLocaleToActivity(this);

How can I change language of whole application by only single click?

Change Language Programmatically in Android

Here is the appropriate way of changing the locale of the application:

There are some difficulties which you have to overcome to change the language programmatically.

1.)Your application will not remember your language change after it is closed or recreated during the configuration change.

2.)You should update currently visible UI properly according to the selected language.

Solution

LocaleHelper” is the solution all you need. You just have to initialize locale on your application’s main class. After that all your language changes will persist.

After the recent changes in Android API Version 24(Nougat) we need to override attachBaseContext to reflect changes.

Below method used to change language for application :

private static boolean updateResources(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);

Resources resources = context.getResources();

Configuration configuration = resources.getConfiguration();
configuration.locale = locale;

resources.updateConfiguration(configuration, resources.getDisplayMetrics());

return true;
}

find more details in below link :

Changing Android’s Locale Programmatically



Related Topics



Leave a reply



Submit