安卓 国际化

安卓 国际化

准备多语言资源包

image-20240104153728990

:values中的语言资源文件为app默认的语言资源文件。

接入多语言工具类

package com.starnet.nextsmart.util

import android.content.Context
import android.content.res.Configuration
import android.os.Build
import android.os.LocaleList
import androidx.annotation.RequiresApi
import androidx.appcompat.view.ContextThemeWrapper
import com.starnet.nextsmart.R
import com.starnet.nhhttplib.utils.ENGLISH
import com.starnet.nhhttplib.utils.SIMPLIFIED_CHINESE
import com.starnet.nhhttplib.utils.getSystemLanguage
import java.util.Locale

/**
 * 应用多语言切换,重写BaseActivity中的attachBaseContext即可
 *
 * @param context  上下文
 * @param language 语言
 * @return context
 */
fun attachBaseContext(context: Context, language: String): Context {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
        createConfigurationContext(context, language)
    } else {
        updateConfiguration(context, language)
    }
}

/**
 * 获取Local,根据language
 *
 * @param language 语言
 * @return Locale
 */
private fun getLanguageLocale(language: String): Locale {
    return when (language) {
        ENGLISH -> {
            Locale.ENGLISH
        }

        SIMPLIFIED_CHINESE -> {
            Locale.SIMPLIFIED_CHINESE
        }
        //用户选择跟随系统
        else -> {
            if (getSystemLanguage() == ENGLISH) Locale.ENGLISH
            else Locale.SIMPLIFIED_CHINESE
        }
    }
}

/**
 * Android 7.1 以下通过 updateConfiguration
 *
 * @param context  context
 * @param language 语言
 * @return Context
 */
private fun updateConfiguration(context: Context, language: String): Context {
    val resources = context.resources
    val configuration = resources.configuration
    val locale = getLanguageLocale(language)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        // apply locale
        configuration.setLocales(LocaleList(locale))
    } else {
        // updateConfiguration
        configuration.locale = locale
        val dm = resources.displayMetrics
        resources.updateConfiguration(configuration, dm)
    }
    return context
}

/**
 * Android 7.1以上通过createConfigurationContext
 * N增加了通过config.setLocales去修改多语言
 *
 * @param context  上下文
 * @param language 语言
 * @return context
 */
@RequiresApi(api = Build.VERSION_CODES.N_MR1)
private fun createConfigurationContext(context: Context, language: String): Context {
    val resources = context.resources
    val configuration = resources.configuration
    val locale = getLanguageLocale(language)
    val localeList = LocaleList(locale)
    configuration.setLocales(localeList)
    return context.createConfigurationContext(configuration)
}

/**
 * 获取新语言的 Context,修复了androidx.appCompact 1.2.0的问题
 *
 * @param newBase newBase
 * @return Context
 */
fun getNewLocalContext(newBase: Context, language: String): Context {
    try {
        // 多语言适配
        val context = attachBaseContext(newBase, language)
        // 兼容appcompat 1.2.0后切换语言失效问题
        val configuration = context.resources.configuration
        return object : ContextThemeWrapper(context, R.style.AppTheme) {
            override fun applyOverrideConfiguration(overrideConfiguration: Configuration) {
                overrideConfiguration.setTo(configuration)
                super.applyOverrideConfiguration(overrideConfiguration)
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return newBase
}

/**
 * 更新Application的Resource local,应用不重启的情况才调用,因为部分会用到application中的context
 * 切记不能走新api createConfigurationContext,亲测
 * @param context context
 * @param newLanguage newLanguage
 */
fun updateApplicationLocale(context: Context, newLanguage: String) {
    val resources = context.resources
    val configuration = resources.configuration
    val locale = getLanguageLocale(newLanguage)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        // apply locale
        configuration.setLocales(LocaleList(locale))
    } else {
        configuration.setLocale(locale)
    }
    val dm = resources.displayMetrics
    resources.updateConfiguration(configuration, dm)
}

在APP中对语言切换进行处理

APP初始化时进行处理

override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)
        // 系统资源配置发生更改,例如主题模式,需要重新刷新多语言
        updateApplicationLocale(
            this,
            DataStoreUtil.getData(com.starnet.nhcommunitylib.Constants.DS_LANGUAGE_SETTING, "")
        )
        mService?.turnOnPushChannel()
    }

活动基类中进行处理

override fun attachBaseContext(newBase: Context) {
        super.attachBaseContext(
            getNewLocalContext(
                newBase,
                DataStoreUtil.getData(com.starnet.nhcommunitylib.Constants.DS_LANGUAGE_SETTING, "")
            )
        )
        // 切换语言之后时间日期格式也要自动更新,例如十二小时制的上午切换成am
        TimeFormatUtil.setFormat(DataStoreUtil.getData(DS_TIME_FORMAT, FOLLOW_SYSTEM), newBase)
    }

注:attachBaseContext的作用:

​ attachBaseContext是Android中的一个方法,通常用于在创建Activity时将上下文(Context)与Activity关联起来。这个方法通常在Activity的onCreate方法中调用,用于传递一个新的上下文给Activity。这个新的上下文通常是一个包装了原始上下文的上下文对象,可以用于在Activity中执行一些特定的操作,比如修改主题、语言等。这个方法的作用是确保Activity在创建时能够正确地获取到所需的上下文信息,以便正常运行。

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值