前言

Android中实现国际化相对来说还是简单的,因为Android有很独特的资源管理方式,我们可以很轻松的创建资源支持不同语言.

资源文件的的使用

android是在res/values目录下通过不同values文件夹的命名来匹配不同的资源

values-语言代码-r国家代码

例如:values-zh-rCN(中文)和values-en(英文)

先看效果,再扯淡

cfb8ca877d94

device-2018-01-10-172927~2.gif

一些帮助工具

API 25 (Android 7.1.1) 以下的方案

Resources resources = getContext().getResources();

DisplayMetrics dm = resources.getDisplayMetrics();

Configuration config = resources.getConfiguration();

config.locale = Locale.getDefault()

resources.updateConfiguration(config, dm);

通过以上代码我们就能通过更改Configuration配置来进行APP语言切换,但是

在API 25以后推荐我们使用,Context.createConfigurationContext(Configuration),Resources.updateConfiguration(config, dm)被弃用

cfb8ca877d94

image.png

新的系统的变更

Android 6.0

cfb8ca877d94

Screenshot_1515571286.png

Android 8.0

cfb8ca877d94

Screenshot_1515571209.png

根据2个截图来看在Android 6.0系统语言为单选,而在在Android 8.0 变成多选对应的Configuration API 也要求我们从configuration.locale = locale; 替换成configuration.configuration.setLocales(locales);

cfb8ca877d94

image.png

getLocales().get(0)为首选语言

开始兼容API 25 (Android 7.1.1)

API 25 (Android 7.1.1)的以后更改语言配置,我们需要重新替换Context,把Context替换成设置了指定语言的Context对象,我们可以采取以下方案。

1.重写一个ContextWrapper类 ContextWrapper构造函数中必须包含一个真正的Context引用,同时ContextWrapper中提供了attachBaseContext()用于给ContextWrapper对象中指定真正的Context对象,调用ContextWrapper的方法都会被转向其所包含的真正的Context对象。

2.每个Activity都替换一次Context,这里我们可以把封装在BaseActivity中。

@Override

protected void attachBaseContext(Context newBase) {

SharedPreferences preferences = newBase.getSharedPreferences("language", Context.MODE_PRIVATE);

String selectedLanguage = preferences.getString("language", "");

super.attachBaseContext(LanguageUtil.attachBaseContext(newBase, selectedLanguage));

}

然后通过recreate重启Activity:

activity.recreate();

finish();

startActivity(new Intent(MainActivity.this,MainActivity.class));

来一个Util

public class LanguageConstants {

// 简体中文

public static final String SIMPLIFIED_CHINESE = "zh";

// 英文

public static final String ENGLISH = "en";

// 繁体中文

public static final String TRADITIONAL_CHINESE = "zh-hant";

// 法语

public static final String FRANCE = "fr";

// 德语

public static final String GERMAN = "de";

// 意大利语

public static final String ITALIAN = "it";

//日语

public static final String JAPAN = "ja";

}

public class SupportLanguageUtil {

private static Map mSupportLanguages = new HashMap(7) {{

put(LanguageConstants.ENGLISH, Locale.ENGLISH);

put(LanguageConstants.SIMPLIFIED_CHINESE, Locale.SIMPLIFIED_CHINESE);

put(LanguageConstants.TRADITIONAL_CHINESE, Locale.TRADITIONAL_CHINESE);

put(LanguageConstants.FRANCE, Locale.FRANCE);

put(LanguageConstants.GERMAN, Locale.GERMANY);

put(LanguageConstants.HINDI, new Locale(LanguageConstants.HINDI, "IN"));

put(LanguageConstants.ITALIAN, Locale.ITALY);

put(LanguageConstants.JAPAN, Locale.JAPAN);

}};

/**

* 是否支持此语言

*

* @param language language

* @return true:支持 false:不支持

*/

public static boolean isSupportLanguage(String language) {

return mSupportLanguages.containsKey(language);

}

/**

* 获取支持语言

*

* @param language language

* @return 支持返回支持语言,不支持返回系统首选语言

*/

@TargetApi(Build.VERSION_CODES.N)

public static Locale getSupportLanguage(String language) {

if (isSupportLanguage(language)) {

return mSupportLanguages.get(language);

}

return getSystemPreferredLanguage();

}

/**

* 获取系统首选语言

*

* @return Locale

*/

@RequiresApi(api = Build.VERSION_CODES.N)

public static Locale getSystemPreferredLanguage() {

Locale locale;

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

locale = LocaleList.getDefault().get(0);

} else {

locale = Locale.getDefault();

}

return locale;

}

}

public class LanguageUtil {

public static void applyLanguage(Context context, String newLanguage) {

Resources resources = context.getResources();

Configuration configuration = resources.getConfiguration();

Locale locale = SupportLanguageUtil.getSupportLanguage(newLanguage);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

// apply locale

configuration.setLocale(locale);

} else {

// updateConfiguration

configuration.locale = locale;

DisplayMetrics dm = resources.getDisplayMetrics();

resources.updateConfiguration(configuration, dm);

}

}

public static Context attachBaseContext(Context context, String language) {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

return createConfigurationResources(context, language);

} else {

applyLanguage(context, language);

return context;

}

}

@TargetApi(Build.VERSION_CODES.N)

private static Context createConfigurationResources(Context context, String language) {

Resources resources = context.getResources();

Configuration configuration = resources.getConfiguration();

Locale locale;

if (TextUtils.isEmpty(language)) {//如果没有指定语言使用系统首选语言

locale = SupportLanguageUtil.getSystemPreferredLanguage();

} else {//指定了语言使用指定语言,没有则使用首选语言

locale = SupportLanguageUtil.getSupportLanguage(language);

}

configuration.setLocale(locale);

return context.createConfigurationContext(configuration);

}

}

最后参考:

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐