在应用层开始时,经常会需要用到国际化的处理,常见的包括中文和英文的切换等,实际的开发中包括对于应用适配的国际化,应用该应用和修改系统的国际三种方式。
- 应用适配方式(被动)
- 应用修改该应用语言环境(主动)
- 应用修改系统语言环境(主动)
其中第一种中是根据系统设置中修改的系统语言环境,应用被动适配实现国际化的效果;后两种是应用主动修改语言环境,主动实现国际化的效果。应用修改该应用的国际化方式,实现效果是只改变当前应用,无法修改系统属性,而后一种是通过修改系统的语言环境实现所有应用适配国际化的效果。
无论是主动还是被动的实现国际化效果,在该应用中都需要适配好对应的字符串或图片,详细讲解见第一部分,实现效果如下。
1.应用适配方式(被动)
对于该功能的实现比较简单,只需要在res目录下创建相应的资源文件即可,如果手动创建比较麻烦,可以下载AndroidStudio的插件AndroidLocalizationer或直接在plugins中搜索添加。
安装完成后,重启AndroidStudio,在values的选择strings.xml,右键选择“Convert to other languages ”,如下图所示。
进入语言选择界面,选择需要转化的国际化语言,例如English,如下图所示。
但是目前该插件,有些不稳定,有时AndroidStudio版本不支持。
在实际开发中,经常会用到将string.xml导出至excel中,翻译完成后需要将excel中的文件导入至string.xml中,该操作可参考AndroidStudio 开发中字符串国际化string.xml与Excel表格的互相导入
除了对字符串国际化操作外,我们还可以基于图片的国际化,如下图所示
2.应用修改该应用语言环境(主动)
以上是基于应用层常见的国际化的实现,在设置中修改当前系统语言后,应用就会更换为对应的语言环境,实现国际化的效果。除此之外,还可通过主动方式修改当前应用的国际化,不需要在设置中修改系统的语言环境。
实现方式很简单,只需要去动态的修改当前应用的resources配置即可实现,代码如下所示
private void switchLanguage(Locale locale) {
//设置应用语言类型
Resources resources = getResources();
Configuration config = resources.getConfiguration();
DisplayMetrics dm = resources.getDisplayMetrics();
config.setLocale(locale);
resources.updateConfiguration(config, dm);
//更新语言后,destroy当前页面,重新绘制
/* finish();
Intent it = new Intent(MainActivity.this, MainActivity.class);
//清空任务栈确保当前打开activit为前台任务栈栈顶
it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(it);*/
}
在应用初始化时,根据业务需要修改为指定的语言环境,需要注意的是传入的字符串不是随意传入的,需要根据各国的语言简写,可参考Locale中针对语言的简写,如下图所示
如果需要的国家在该类中无法查找到,就需要在网上查找,这里推荐一个网友整理的材料《每个国家对应的语言Locale和国家代码对照表》,例如,想使用俄罗斯语言,但是在Locale中未查找到,此时就需要我们在网上查找到俄罗斯的语言简称“ru”,例如调用以上可以通过以下方式。
//在Locale中已存在的语言属性
switchLanguage(Locale.SIMPLIFIED_CHINESE);
//自定义方式
switchLanguage(new Locale("ru"));
注意:语言属性的修改,最好在应用初始化时修改,因为已经加载的界面再次修改resources配置,不会立即生效,需要先将该界面销毁,重新加载才能生效,详见实例代码中注释部分。
3.应用修改系统语言环境(主动)
第三种是修改系统的语言环境,我们知道如果想修改系统的应用配置,需要具有系统权限才可以,因此在AndroidManifest.xml中需要加上“android.uid.system”,在应用签名时需要使用系统签名,具体系统签名如何使用,详见《Android 系统签名实现的三种方式》。
修改系统的配置项,主要是通过反射的方式实现,修改系统的Configuration类中的config配置项,实现对系统语言环境的修改。代码实现如下所示
public static void changeLangue(Locale locale) {
Class amnClass = null;
try {
amnClass = Class.forName("android.app.ActivityManagerNative");
Object amn = null;
Configuration config = null;
// amn = ActivityManagerNative.getDefault();
Method methodGetDefault = amnClass.getMethod("getDefault");
methodGetDefault.setAccessible(true);
amn = methodGetDefault.invoke(amnClass);
// config = amn.getConfiguration();
Method methodGetConfiguration = amnClass.getMethod("getConfiguration");
methodGetConfiguration.setAccessible(true);
config = (Configuration) methodGetConfiguration.invoke(amn);
// config.userSetLocale = true;
Class configClass = config.getClass();
Field f = configClass.getField("userSetLocale");
f.setBoolean(config, true);
// set the locale to the new value
config.locale = locale;
// amn.updateConfiguration(config);
Method methodUpdateConfiguration = amnClass.getMethod("updateConfiguration", Configuration.class);
methodUpdateConfiguration.setAccessible(true);
methodUpdateConfiguration.invoke(amn, config);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
详细Demo下载地址,欢迎star和fork。