Jane books backup
preface
Recently I took over an Android project and needed to support The Uyghur language. Although doing so long android development, only do too much language support, but do in-app multi-language support is the first time, and it is uyghur language support. So, again, search engine oriented programming.
Search-oriented programming
If we search for “Android multilingual switching”, I’m sure most of the answers will be the same, even if the article looks the same:
Locale locale = new Locale("zh");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
Copy the code
The above code should not be a big problem, after all, it does work and can fulfill the requirements. However, as an OCD, I can’t stand the fact that there are 2 lines, which means that there are 2 deprecated parts of the code above (yes, API 25 is deprecated) :
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
Copy the code
I saw two of them abandoned. I have to go in there.
/**
* Current user preference for the locale, corresponding to
* <a href="{@docRoot}guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a>
* resource qualifier.
*
* @deprecated Do not set or read this directly. Use {@link #getLocales()} and
* {@link #setLocales(LocaleList)}. If only the primary locale is needed,
* <code>getLocales().get(0)</code> is now the preferred accessor.
*/
@Deprecated public Locale locale;
Copy the code
Obviously we found an alternative:
config.setLocales(LocaleList);
config.setLocale(locale);
Copy the code
Good, no problem. Keep checking out the next one:
/**
* Store the newly updated configuration.
*
* @deprecated See {@link android.content.Context#createConfigurationContext(Configuration)}.
*/
@Deprecated
public void updateConfiguration(Configuration config, DisplayMetrics metrics) {
updateConfiguration(config, metrics, null);
}
Copy the code
It’s very simple. We found an alternative. And so he went on:
Locale locale = new Locale("ug");
final Resources res = getResources();
final Configuration config = res.getConfiguration();
config.setLocale(locale); // getLocale() should return a Locale
createConfigurationContext(config);
Copy the code
It’s not working! It just doesn’t work. A look again carefully, the document says createConfigurationContext (config) will return a new Context, but the new Context did not mention how to deal with. Again, programming for search, finally hitting the right pose:
@Override
protected void attachBaseContext(Context newBase) {
Locale locale = new Locale("ug");
final Resources res = newBase.getResources();
final Configuration config = res.getConfiguration();
config.setLocale(locale); // getLocale() should return a Locale
final Context newContext = newBase.createConfigurationContext(config);
super.attachBaseContext(newContext);
}
Copy the code
Our Activity should override this method. Then when the Activity is created, the new Context will be applied. Note that if you want the current Activity to work, you need to call Math ().
Of course, we can also write a utility class:
public class ConfigurationWrapper {
private ConfigurationWrapper() {
}
public static Context wrapConfiguration(@NonNull final Context context, @NonNull final Configuration config) {
return context.createConfigurationContext(config);
}
public static Context wrapLocale(@NonNull final Context context,@NonNull final Locale locale) {
final Resources res = context.getResources();
final Configuration config = res.getConfiguration();
config.setLocale(locale);
returnwrapConfiguration(context, config); }}Copy the code
And then you can use it like this. If you want to change the configuration, you can use wrapConfiguration.
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(ConfigurationWrapper.wrapLocale(newContext, getLocale()));
}
Copy the code
About the Locale
We’re using locales to switch languages. Locale contains a lot of common countries and regions and languages, and if we do common languages, we can call the system directly, such as locale.Chinese. But this time do uyghur adaptation, slightly I pit. First, the English name of Uyghur is Uyghur. It’s not in the Locale, or MAYBE I’m looking wrong. Secondly, Uyghur is of Arabic lineage. Well, yes, there’s a word called RTL, and magical things happen. Finally, there is the Uyghur option in values in AndroidStudio. And there are alternatives, including Chinese, which I guess is uyghur. So one was created, full name: values-ug-rcn. The problem is, I started with this:
Locale locale = new Locale("ug-rCN");
Copy the code
Well, I was too naive to use it. I was smart enough to look at how locales are constructed. Then I guess a conclusion
Ug stands for language and rCN for country and region. For example, the same Chinese zh, but divided into many countries and regions, such as China, Taiwan, Hong Kong, Singapore and so onCopy the code
So this is the correct posture:
Locale locale = new Locale("ug", Locale.CHINA.getCountry());
Copy the code