Android使用AndroidUtilCode实现多语言

作者:TimeFine 时间:2023-08-28 15:25:50 

一、项目中配置多语言

多语言的实现是通过AndroidUtilCode实现的,表示感谢!

项目里面有4种语言:中文,英文,德文,俄文。文件夹如下:

Android使用AndroidUtilCode实现多语言

配置多语言的思路是:

1、判断是否为国内版本,如果为国内版本则设置为简体中文

2、 如果为国外版本,获取用户之前设置的App语言,如果用户之前有设置App语言,则设置为之前用户设置的语言;如果用户之前没有设置App语言则获取手机系统的语言。

3、判断当前手机系统的语言是否App有做语言适配,如果有适配则设置成跟手机系统一样的语言,如果没有适配则设置为英文。

二、具体实现

1、初始化PropertiesUtil和MMKV,具体代码请参考上篇博客

2、在BaseApplication中设置语言

abstract class BaseApplication : Application() {
   abstract fun init()
   override fun onCreate() {
       super.onCreate()
       init()
       PropertiesUtil.init(this)
       MMKV.initialize(this)
       MMKVUtil.setUserId(1000L)
       //设置App语言
       setAppLanguage()
   }
   /**
    * 判断是否为国内版本,如果为国内版本则设置为简体中文
    * 如果为国外版本,获取用户之前设置的App语言,
    * 如果用户之前有设置App语言,则设置为之前用户设置的语言
    * 如果用户之前没有设置App语言则获取手机系统的语言
    * 判断手机系统的语言是否App有做语言适配,如果有适配则设置成跟手机系统一样的语言
    * 如果App没有对当前系统语言做适配则设置为英文
    */
   private fun setAppLanguage() {
       if (PropertiesUtil.isCN()) {   //国内版本
           LanguageUtils.applyLanguage(Locale.SIMPLIFIED_CHINESE, false)
       } else {
           MMKVUtil.getLanguage().also {
               if (it.isNotEmpty()) {
                   setLanguageAndBackCountry(it)
               } else {
                   //获取系统语言
                   LanguageUtils.getSystemLanguage().country.also { country ->
                       setLanguageAndBackCountry(country).also { value ->
                           //保存设置的语言
                           MMKVUtil.setLanguage(value)
                       }
                   }
               }
           }
       }
   }
   private fun setLanguageAndBackCountry(it: String): String {
       return when (it) {
           LanguageType.CN.name -> {
               LanguageUtils.applyLanguage(Locale.SIMPLIFIED_CHINESE, false)
               it
           }
           LanguageType.US.name -> {
               LanguageUtils.applyLanguage(Locale.ENGLISH, false)
               it
           }
           LanguageType.DE.name -> {
               LanguageUtils.applyLanguage(Locale.GERMANY, false)
               it
           }
           LanguageType.RU.name -> {
               LanguageUtils.applyLanguage(Locale("ru"), false)
               it
           }
           else -> {
               LanguageUtils.applyLanguage(Locale.ENGLISH, false)
               LanguageType.US.name
           }
       }
   }
}

3、切换语言

比如设置为德文,按钮触发:

MMKVUtil.setLanguage(LanguageType.DE.name)
LanguageUtils.applyLanguage(Locale.GERMANY, false)  //true:重启App false:不重启App

4、注意gradle配置resConfigs不要限制为只有中文,比如:resConfigs "zh-rCN", "en"

三、AndroidX和多进程存在的问题

1、多进程读取Configuration时发现其他进程与主进程获取的Configuration值不一致,导致主进程切换语言后其他语言并没有切换成功。

2、AndroidX切换失败的问题,具体可以看下这篇博客【踩坑记录】多语言切换在Androidx失效

解决办法:重写Activity的attachBaseContext方法,修改Context

/**
* 多语言的切换类, 解决多进程切换语言失败的问题以及AndroidX多语言切换失效的问题
* 解决由于 WebView 初始化会修改 Activity 语种配置,间接导致 Activity 语种会被还原,所以需要你手动重写 WebView 对这个问题进行修复
*/
object MultiLanguageUtil {
   fun getAttachBaseContext(context: Context): Context {
       return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
           configAppcompatLanguage(setAppLanguageApi24(context))
       } else {
           setAppLanguage(context)
           configAppcompatLanguage(context)
       }
   }
   /**
    * 设置应用语言
    */
   @Suppress("DEPRECATION")
   private fun setAppLanguage(context: Context) {
       val resources = context.resources
       val displayMetrics = resources.displayMetrics
       val configuration = resources.configuration
       // 获取当前系统语言,默认设置跟随系统
       val locale = getLocale()
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
           configuration.setLocale(locale)
       } else {
           configuration.locale = locale
       }
       resources.updateConfiguration(configuration, displayMetrics)
   }
   /**
    * 兼容 7.0 及以上
    */
   @TargetApi(Build.VERSION_CODES.N)
   fun setAppLanguageApi24(context: Context): Context {
       val locale = getLocale()
       val resource = context.resources
       val configuration = resource.configuration
       configuration.setLocale(locale)
       configuration.setLocales(LocaleList(locale))
       return context.createConfigurationContext(configuration)
   }
   private fun configAppcompatLanguage(context: Context): Context {
       val configuration = context.resources.configuration
       //兼容appcompat 1.2.0后切换语言失效问题
       return object : ContextThemeWrapper(context, R.style.Base_Theme_AppCompat_Empty) {
           override fun applyOverrideConfiguration(overrideConfiguration: Configuration?) {
               overrideConfiguration?.setTo(configuration)
               super.applyOverrideConfiguration(overrideConfiguration)
           }
       }
   }
   private fun getLocale(): Locale {
       return when (CacheUtil.getInt(GlobalConstants.LANGUAGE_KEY, true)) {
           0 -> {
               Locale.SIMPLIFIED_CHINESE
           }
           1 -> {
               Locale.ENGLISH
           }
           2 -> {
               Locale.GERMANY
           }
           3 -> {
               Locale("ru")
           }
           else -> Locale.ENGLISH
       }
   }
   /**
    * 解决WebView多语言失效的问题
    */
   fun updateLanguage(context: Context) {
       val resources = context.resources
       val config = resources.configuration
       val settingLanguage = getLocale().language
       val systemLanguage = config.locales[0].language
       if (settingLanguage != systemLanguage) {
           setLocale(config, Locale(settingLanguage))
           resources.updateConfiguration(config, resources.displayMetrics)
       }
   }
   private fun setLocale(config: Configuration, locale: Locale?) {
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
           if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
               val localeList = LocaleList(locale)
               config.setLocales(localeList)
           } else {
               config.setLocale(locale)
           }
       } else {
           config.locale = locale
       }
   }
}

获取appContext

lateinit var appContext: Application
//BaseApplication中调用方法获取Application的上下文
fun BaseApplication.getContext(application: BaseApplication) {
   appContext = application
}

四、WebView导致的语言重置的问题

由于 WebView 初始化会修改 Activity 语种配置,间接导致 Activity 语种会被还原,所以需要你手动重写 WebView 对这个问题进行修复,如下:

/**
* 由于 WebView 初始化会修改 Activity 语种配置,间接导致 Activity 语种会被还原回去,所以需要你手动重写 WebView 对这个问题进行修复
*/
class LanguagesWebView(
   context: Context,
   @Nullable attrs: AttributeSet?,
   defStyleAttr: Int
) : WebView(context, attrs, defStyleAttr) {
   constructor(context: Context) : this(context, null) {}
   constructor(context: Context, @Nullable attrs: AttributeSet?) : this(
       context,
       attrs,
       0
   )
   init {
       //修复 WebView 初始化时会修改Activity 语种配置的问题
       MultiLanguageUtil.updateLanguage(context)
   }
}

项目中用这个WebView即可。这个问题在华为手机鸿蒙系统上会出现。

五、枚举类的多语言实现

枚举类型是线程安全的,并且只会装载一次,这就导致下面的写法导致枚举的err值在切换语言后不会发生变化。

enum class Error( var code: Int,  var err: String) {
   /**
    * 未知错误
    */
   UNKNOWN(1000,appContext.getString(R.string.error_1000)),
   /**
    * 解析错误
    */
   PARSE_ERROR(1001, appContext.getString(R.string.error_1001)),
   /**
    * 网络错误
    */
   NETWORK_ERROR(1002, appContext.getString(R.string.error_1002)),
   /**
    * 证书出错
    */
   SSL_ERROR(1004, appContext.getString(R.string.error_1004)),
   /**
    * 连接超时
    */
   TIMEOUT_ERROR(1006, appContext.getString(R.string.error_1002));
   fun getValue(): String {
       return err
   }
   fun getKey(): Int {
       return code
   }
}

那么如果做枚举类的多语言适配呢? 代码如下:

enum class Error(private val code: Int, private val err: Int) {
   /**
    * 未知错误
    */
   UNKNOWN(1000, R.string.error_1000),
   /**
    * 解析错误
    */
   PARSE_ERROR(1001, R.string.error_1001),
   /**
    * 网络错误
    */
   NETWORK_ERROR(1002, R.string.error_1002),
   /**
    * 证书出错
    */
   SSL_ERROR(1004, R.string.error_1004),
   /**
    * 连接超时
    */
   TIMEOUT_ERROR(1006, R.string.error_1002);
   fun getValue(): String {
       return appContext.getString(err)
   }
   fun getKey(): Int {
       return code
   }
}

因为字符串的id是固定的不会发生变化,所以即使枚举类只会装载一次也不会有影响,通过getValue就能取到正确语言的字符串。

参考

【踩坑记录】多语言切换在Androidx失效

MulituLanguage

MultiLanguages

来源:https://juejin.cn/post/7173211469029474335

标签:Android,AndroidUtilCode,多语言
0
投稿

猜你喜欢

  • java算法题解牛客BM99顺时针旋转矩阵示例

    2021-07-08 18:55:18
  • Java利用Phantomjs实现生成图片的功能

    2022-01-17 08:21:25
  • NancyFx框架检测任务管理器详解

    2023-02-18 13:10:53
  • Java利用Swagger2自动生成对外接口的文档

    2023-03-31 03:22:38
  • Hadoop组件简介

    2023-08-20 14:07:00
  • Spring整合CXF webservice restful实例详解

    2023-03-20 09:58:21
  • 详解SpringBoot获得Maven-pom中版本号和编译时间戳

    2022-11-27 19:45:27
  • Java使用poi操作excel实例解析

    2022-01-26 00:15:41
  • Android中应用界面主题Theme使用方法和页面定时跳转应用

    2023-08-30 17:05:59
  • 基于swing实现窗体拖拽和拉伸

    2023-11-12 22:32:40
  • Intellij IDEA导入JAVA项目并启动(图文教程)

    2021-11-05 12:30:18
  • java swing实现的扫雷游戏及改进版完整示例

    2022-02-27 02:01:18
  • 浅谈一下Spring中的createBean

    2023-06-08 22:01:26
  • C#操作目录与文件的方法步骤

    2023-11-23 20:45:52
  • 详解path和classpath的区别

    2023-05-02 13:28:32
  • Android实现加载圈

    2023-03-27 16:44:34
  • Android编程实现获取当前连接wifi名字的方法

    2023-11-24 15:41:50
  • Android入门之ViewFlipper翻转视图的使用详解

    2022-09-18 18:09:43
  • C语言实现简单弹跳小球

    2022-07-03 12:54:34
  • Mybatis实现SQL存储流程详解

    2022-09-11 05:17:05
  • asp之家 软件编程 m.aspxhome.com