I don't know if there are any other options or not, one way is to do it programmatically. According to Ricardo's great solution, I've created the following class to change the default Local:
public class LocaleHelper {
public static Context onAttach(Context context) {
String lang = Locale.getDefault().getLanguage();
if(lang.equals("it") || lang.equals("de"))
return context;
String locale = "de";
return setLocale(context, locale);
}
private static Context setLocale(Context context, String localeSpec) {
Locale locale;
if (localeSpec.equals("system")) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
locale = Resources.getSystem().getConfiguration().getLocales().get(0);
} else {
locale = Resources.getSystem().getConfiguration().locale;
}
} else {
locale = new Locale(localeSpec);
}
Locale.setDefault(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, locale);
} else {
return updateResourcesLegacy(context, locale);
}
}
@TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, Locale locale) {
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);
return context.createConfigurationContext(configuration);
}
@SuppressWarnings("deprecation")
private static Context updateResourcesLegacy(Context context, Locale locale) {
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLayoutDirection(locale);
}
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}
}
You should use that on your Activity class:
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base));
}
If you are using uk.co.chrisjenx.calligraphy
to change fonts, you should do as follows:
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(CalligraphyContextWrapper.wrap(LocaleHelper.onAttach(base)));
}
Update
Using this outstanding post I managed to find the provided languages automatically. So you no further have to hard code it
, de
or other provided translations whenever you add a new one to the resources.
public class LocaleHelper {
public static Context onAttach(Activity context) {
Set<String> providedLangs = getProvidedLanguages(context);
String lang = Locale.getDefault().getLanguage();
if(providedLangs.contains(lang))
return context;
String locale = "de";
return setLocale(context, locale);
}
private static Set<String> getProvidedLanguages(Activity activity){
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
Resources r = activity.getResources();
Configuration c = r.getConfiguration();
String[] loc = r.getAssets().getLocales();
Set<String> providedLangs = new HashSet<String>();
for (int i = 0; i < loc.length; i++) {
Timber.e("LOCALE: " + i + ": " + loc[i]);
c.locale = new Locale(loc[i]);
Resources res = new Resources(activity.getAssets(), metrics, c);
String s1 = res.getString(R.string.app_name);
c.locale = new Locale("");
Resources res2 = new Resources(activity.getAssets(), metrics, c);
String s2 = res2.getString(R.string.app_name);
if(!s1.equals(s2)){
if(!providedLangs.contains(loc[i]))
providedLangs.add(loc[i]);
}
}
return providedLangs;
}
private static Context setLocale(Context context, String localeSpec) {
Locale locale;
if (localeSpec.equals("system")) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
locale = Resources.getSystem().getConfiguration().getLocales().get(0);
} else {
locale = Resources.getSystem().getConfiguration().locale;
}
} else {
locale = new Locale(localeSpec);
}
Locale.setDefault(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, locale);
} else {
return updateResourcesLegacy(context, locale);
}
}
@TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, Locale locale) {
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);
return context.createConfigurationContext(configuration);
}
@SuppressWarnings("deprecation")
private static Context updateResourcesLegacy(Context context, Locale locale) {
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLayoutDirection(locale);
}
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}
}