1、项目简介

最近项目中要加入多语言需求,涉及到的有中文简体,中文繁体,英语,西班牙语,泰语,印尼语,葡萄牙语。参考了Android应用内设置多语言,可随系统语言改变而改变,在此基础上做了修改,选择为跟随系统时不再粗暴调用 此方法。android.os.Process.killProcess(android.os.Process.myPid());
直接杀死会有一个类似于崩溃的效果,产品上难以接受。所以跟随系统时查看系统语言单独调用,如果本地string中不存在系统语言对应的语言,那么默认为英语。下面看一下效果图:
因为目前只有一个MainActivity页面,选择语言后切换跳转有闪动,大家可以切换语言后回到首页,就像微信切换语言一样。

 2、实现原理

首先在res下创建对应的string对应语言文件

在Application中调用attachBaseContext方法中的初始化,如果本地有sp保存的语言,显示此语言,如果没有就显示系统语言。

protected void attachBaseContext(Context base) {//系统语言等设置发生改变时会调用此方法,需要要重置app语言super.attachBaseContext(MultiLanguageUtil.attachBaseContext(base));}
@TargetApi(Build.VERSION_CODES.N)private static Context createConfigurationResources(Context context) {Resources resources = context.getResources();Configuration configuration = resources.getConfiguration();Locale appLocale = getAppLocale(context);Log.i("language0", appLocale.getLanguage() + "--------" + appLocale.getCountry() + "--------" + appLocale.toLanguageTag());Constants.SYSTEM_LANGUAGE = appLocale.getLanguage();Constants.SYSTEM_COUNTRY = appLocale.getCountry();Constants.SYSTEM_TOLANGUAGETAG = appLocale.toLanguageTag();//如果本地有语言信息,以本地为主,如果本地没有使用默认LocaleLocale locale = null;String spLanguage = SPUtils.getLanguageString(context, Constants.LOCALE_LANGUAGE);String spCountry = SPUtils.getLanguageString(context, Constants.LOCALE_COUNTRY);if (!TextUtils.isEmpty(spLanguage) && !TextUtils.isEmpty(spCountry)) {if (isSameLocal(appLocale, spLanguage, spCountry)) {locale = appLocale;} else {locale = new Locale(spLanguage, spCountry);}} else {if (Constants.SYSTEM_TOLANGUAGETAG.contains("zh-Hant")) {locale = new Locale(Constants.SYSTEM_LANGUAGE, "TW");} else if (Constants.SYSTEM_TOLANGUAGETAG.contains("zh-Hans") || Constants.SYSTEM_TOLANGUAGETAG.equals("zh-CN")) {locale = new Locale(Constants.SYSTEM_LANGUAGE, "CN");} else {locale = appLocale;}}configuration.setLocale(locale);configuration.setLocales(new LocaleList(locale));return context.createConfigurationContext(configuration);}

在MainActivity主页面initData()方法中显示sp存储过对应的语言,如果为空,那么就选中系统语言

if (!TextUtils.isEmpty(spLanguage) && !TextUtils.isEmpty(spCountry)) {if(spLanguage.equals("zh") && spCountry.equals("CN")){rbgroup.check(rb1.getId());} else if(spLanguage.equals("zh") && spCountry.equals("TW")){rbgroup.check(rb2.getId());}else if(spLanguage.equals("en") && spCountry.equals("US")){rbgroup.check(rb3.getId());}else if(spLanguage.equals("es") && spCountry.equals("ES")){rbgroup.check(rb4.getId());}else if(spLanguage.equals("th") && spCountry.equals("TH")){rbgroup.check(rb5.getId());}else if(spLanguage.equals("in") && spCountry.equals("ID")){rbgroup.check(rb6.getId());}else if(spLanguage.equals("pt") && spCountry.equals("PT")){rbgroup.check(rb7.getId());}} else {rbgroup.check(rb0.getId());}

然后选中语言和取消选中采用的是RadioGroup和RadioButton,选中一种语言设置与之对应的语言和地区

rbgroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup radioGroup, int checkId) {if (checkId == rb0.getId()) {String language = Constants.SYSTEM_LANGUAGE;if (language.equals("zh") && (Constants.SYSTEM_TOLANGUAGETAG.contains("zh-Hans") || Constants.SYSTEM_TOLANGUAGETAG.equals("zh-CN"))) {changeLanguage("zh", "CN",false); //中文简体} else if (language.equals("zh") && Constants.SYSTEM_TOLANGUAGETAG.contains("zh-Hant")) {changeLanguage("zh", "TW",false);//中文繁体} else if (language.equals("en")) {changeLanguage("en", "US",false);  //英语---默认系统语言} else if (language.equals("es")) {changeLanguage("es", "ES",false); //西班牙} else if (language.equals("th")) {changeLanguage("th", "TH",false);// 泰语} else if (language.equals("in")) {changeLanguage("in", "ID",false);// 印度尼西亚语} else if (language.equals("pt")) {changeLanguage("pt", "PT",false);// 葡萄牙} else {changeLanguage("en", "US",false);  //英语---默认系统语言}} else if (checkId == rb1.getId()) {changeLanguage("zh", "CN",true); //中文简体} else if (checkId == rb2.getId()) {changeLanguage("zh", "TW",true);//中文繁体} else if (checkId == rb3.getId()) {changeLanguage("en", "US",true);  //英语---默认系统语言} else if (checkId == rb4.getId()) {changeLanguage("es", "ES",true); //西班牙} else if (checkId == rb5.getId()) {changeLanguage("th", "TH",true);// 泰语} else if (checkId == rb6.getId()) {changeLanguage("in", "ID",true);// 印度尼西亚语} else if (checkId == rb7.getId()) {changeLanguage("pt", "PT",true);// 葡萄牙}}});

在此处我做的改进是当选中的是系统语言时,判断此时的系统语言是哪种,然后设置与之对应的方法,英语为默认语言。

//修改应用内语言设置private void changeLanguage(String language, String area,boolean noSystemLanguage) {if(!noSystemLanguage){SPUtils.saveLanguageString(MainActivity.this,Constants.LOCALE_LANGUAGE, "");SPUtils.saveLanguageString(MainActivity.this,Constants.LOCALE_COUNTRY, "");}//不为空,那么修改app语言,并true是把语言信息保存到sp中,false是不保存到sp中Locale newLocale = new Locale(language, area);MultiLanguageUtil.changeAppLanguage(MainActivity.this, newLocale, noSystemLanguage);//重启app,这一步一定要加上,如果不重启app,可能打开新的页面显示的语言会不正确Intent intent = new Intent(MainActivity.this, MainActivity.class);intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);startActivity(intent);finish();}

如果为系统语言,sp不再存储数据,反之存储对应的语言数据,如果选择为英语,默认设置为Locale.ENGLISH

public static void changeAppLanguage(Context context, Locale locale, boolean persistence) {Resources resources = context.getResources();DisplayMetrics metrics = resources.getDisplayMetrics();Configuration configuration = resources.getConfiguration();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {if (locale.getLanguage().equals("en")) {configuration.setLocale(Locale.getDefault());configuration.setLocale(Locale.ENGLISH);} else {configuration.setLocale(locale);configuration.setLocales(new LocaleList(locale));}context.createConfigurationContext(configuration);} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {configuration.setLocale(locale);} else {configuration.locale = locale;}resources.updateConfiguration(configuration, metrics);if (persistence) {SPUtils.saveLanguageString(context, Constants.LOCALE_LANGUAGE, locale.getLanguage());SPUtils.saveLanguageString(context, Constants.LOCALE_COUNTRY, locale.getCountry());}}

到此处多语言中主要方法已经介绍完了,希望给予有需要的同学一些帮助,如果有什么疑问欢迎评论留言。最后附上多语言demo  点击下载

最全的android各国语言对照表
在线翻译--多语言

多语言适配遇到问题以及解决
1、切换本地语言后杀死 app 重新进入,查看帖子详情以及发帖等页面某些数据无法正确对应本地设置的语言。原因在于项目升级到 AndroidX 版本,Appcompat
1.2+版本导致多语言切换失败,Androidx(appcompat:1.2.0) 中包装了一层
ContextThemeWrapper,但就是因为给包的这一层逻辑有问题,导致了多语言切
换时效。
该包装方法实现了两套逻辑:
1、传入的 context 是经过 ContextThemeWrapper 封装的,则直接使用该
context 配置(包含语言)进行覆盖
2、传入的 context 未经过 ContextThemeWrapper 封装,则从
PackageManger 中获取配置(包含语言),然后和传入的 context 配置(包含语言)
进行对比,并新创建了一个 configration 对象,如果两者有对比不同的配置则
赋值给这个 configration,如果相同则跳过,最后将这个新建的 configration
作为最终配置结果进行覆盖。
而多语言问题就出现在 [2] 这套逻辑上,如果 PackageManager 与 传入的
context 某个配置项一致时就不会给新建的 configration 赋值该配置项。这就
会导致当这一次切换成功后,杀死进程下次启动时,由于 packageManager 配置
的语言 与 context 配置的语言一致,而直接跳过,并没有给新建的
configration 进行赋值,最终表现就是多语言失效。
所以需要在 BaseActivity 手动再给包一层 ContextThemeWrapper:
 
protected void attachBaseContext(Context newBase) {//切换多语言,然后将新生成的 context 覆盖给 attachBaseContext()Context context = MultiLanguageUtils.changeContextLocale(newBase);//兼容 appcompat 1.2.0 后切换语言失效问题final Configuration configuration = context.getResources().getConfiguration();final ContextThemeWrapper wrappedContext = new ContextThemeWrapper(context,R.style.Base_Theme_AppCompat_Empty) {public void applyOverrideConfiguration(Configuration overrideConfiguration) {if (overrideConfiguration != null) {overrideConfiguration.setTo(configuration);}super.applyOverrideConfiguration(overrideConfiguration);}};super.attachBaseContext(wrappedContext);}
这样就很好的解决了整个应用切换语言后重新进入某些数据多语言失效的问题。​​​​​​​

Android应用内设置多语言相关推荐

  1. Android应用内设置多语言,可随系统语言改变而改变,也可设置app为固定语言不受系统语言影响

    转载请标明出处: https://blog.csdn.net/m0_38074457/article/details/84993366,本文出自:[陈少华的博客] 一.效果图 https://gith ...

  2. Android开发应用内多国语言切换

    看到微信可以切换语言,切换语言也就是app国际化问题.我们也都会想到通过改变系统的语言,让app是自己跟随系统走,但是每一台手机系统设置中支持选择的语言,就比较少,比如小米2a:就只有 简体中文,繁体 ...

  3. android改变系统语言,Android 9.0设置系统语言

    1.系统权限 android:sharedUserId="android.uid.system" 2.签名 通过手动签名的方式,用系统的签名文件为程序签名解决签名的问题,将程序加入 ...

  4. Android 9.0设置系统语言

    1.系统权限 android:sharedUserId="android.uid.system" 2.签名 通过手动签名的方式,用系统的签名文件为程序签名解决签名的问题,将程序加入 ...

  5. 特殊纪念日Android APP内设置黑灰色背景

    今天在学习鸿洋大神的博客的时候看到了相关文章,于是动手实现了一下: 当在特殊的某一个日子,我们会表达我们的悼念之情,APP会在某一日设置成黑灰色: 实现: //设置整个APP的所有活动页面变为黑白色: ...

  6. android locale app内设置,Android app应用多语言切换功能实现

    本文实例为大家分享了Android app应用实现多语言切换功能,供大家参考,具体内容如下 1.添加多语言文件在不同的 value 文件夹下(例如 value .value-en.values-zh- ...

  7. Android实现应用内语言切换,android 应用内切换 多国语言

    微信中可以动态设置,apk的语言版本,最近尝试实现了这个功能. 我们知道,android本身就支持多国语言版本的. 不过这个语言的切换 依赖于系统的的语言设置,见图 也依赖apk本身values多国语 ...

  8. Android切换泰语,Android应用内切换语言

    首先扯点别的:这是第一次在简书上写东西,我突然明白为啥这么多人在简书上写东西了,因为没有广告啊,哈哈. 最近接触到Android 应用内切换语言的问题,研究了两天,做个记录先.实现了中文,英文,泰语的 ...

  9. android表情面板_Android Q:应用内设置面板

    android表情面板 In this tutorial, we'll be discussing how to show the Settings Panel in our android appl ...

最新文章

  1. countif函数比较两列不同_COUNT函数家族的使用(下篇)
  2. 如何使用Mockito模拟void方法
  3. 神经网络与机器学习 笔记—支持向量机(SVM)(上)
  4. angularjs组件间通讯_详解Angular2组件之间如何通信
  5. Kafka文件存储机制那些事
  6. linux kvm参数,Linux KVM总结
  7. .net找List1和List2的差集
  8. [转]JavaSE学习 Swing(二)
  9. 数据结构47:查找算法
  10. Bilateral Filters(双边滤波算法)原理及实现
  11. Unity读取TXT文本文件
  12. 西南科技大学OJ题 顺序表上数据的划分问题的实现1102
  13. JSESSIONID是什么
  14. Next主题 - 图片设置
  15. pc端和移动端有什么区别?
  16. cad卸载不干净_BarTender卸载卸不干净的解决技巧
  17. cse7761电能计量芯片驱动程序
  18. 怎样下载苹果 Apple Store 官方 APP 里的限时免费应用福利?
  19. Windows下使用windeployqt打包QML项目(双击运行无反应)
  20. 实习期间总结遇到的Javascript常用函数

热门文章

  1. 英文学习20180319
  2. 浅谈XMl解析的几种方式
  3. C++:梅花桩算法题
  4. Android之获取网络位置的经纬度
  5. React Native 的 ListView 性能问题已解决
  6. 简单的光线追踪教程(三)
  7. 教妹学Java:Java 程序在编译期发生了什么?
  8. 考上清华真的那么重要吗?一男子为考清华复读14年
  9. 【python】(1)pyqt、qt-designer、uic、rcc安装
  10. 数学、哲学与形而上学