安卓 国际化
准备多语言资源包
注: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在创建时能够正确地获取到所需的上下文信息,以便正常运行。