Force locale for Android flavor with resConfig
Well, after many hours, here's the solution to my problem for those ending up with the same problem.
Turns out that resConfig is not for what I though. The proper and only way I found to force the locale for a specific flavor is like this:
First, make sure all your activities extends a common activity which will be responsible to force the locale. (I had to create 2 since I have some activities extending FragmentActivity and some extending Activity. I also don't really like doing so in the Activities constructor but since I have to call applyOverrideConfiguration before any call is done on getResources, I need to call it before the activity's onStart).
public class LocaleMainActivity extends Activity {
public LocaleMainActivity() {
ActivityUtils.forceLocale(this);
}
}
public class LocaleMainFragmentActivity extends FragmentActivity {
public LocaleMainFragmentActivity() {
ActivityUtils.forceLocale(this);
}
}
//Method from ActivityUtils
public static void forceLocale(ContextThemeWrapper contextThemeWrapper) {
Configuration configuration = new Configuration();
Locale defaultLocale = new Locale(BuildConfig.LOCALE);
configuration.locale = defaultLocale;
contextThemeWrapper.applyOverrideConfiguration(configuration);
}
Next, you need to define the locale in your build.gradle flavors
productFlavors {
myFrenchFlavor {
buildConfigField "String", "LOCALE", "\"fr\""
}
myEnglishFlavor {
buildConfigField "String", "LOCALE", "\"en\""
}
}
I tested the solution on API 19+. Works when you change language while in the app too.
Alternate solution (won't work on Android M+ see android bug report)
This solution is wide spreaded on stackOverflow but I faced a wall while implementing this on Android M so keep this in mind.
In the onCreate() of your AndroidApplication you can call updateConfiguration with the locale set.
Locale myLocale = new Locale(BuildConfig.LOCALE);
Resources res = getResources();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, res.getDisplayMetrics());
You will also need to reset it if you defined onConfigurationChanged()
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Configuration config = new Configuration(newConfig);
config.locale = new Locale(BuildConfig.LOCALE);
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
EDIT: Be aware that this applyOverrideConfiguration currently has a side effect which is explained here Chromium webview does not seems to work with Android applyOverrideConfiguration. The Chromium team are currently working on it!
Thanks.
resConfig
does not override the specified resConfigs
of the defaultConfig
, but just combines them instead. Thus you'll end up with all flavors containing en
and fr
resources.
So, to avoid that, you shouldn't specify any resConfigs
in the defaultConfig
and just set it in the specific flavor.
Further, the app will always include the default values
, which means if you have English strings there, the fr
flavor will still show up with English content on a device set to any non-French locale.