網站首頁 編程語言 正文
一、項目中配置多語言
多語言的實現是通過AndroidUtilCode實現的,表示感謝!
項目里面有4種語言:中文,英文,德文,俄文。文件夾如下:
配置多語言的思路是:
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
相關推薦
- 2022-04-19 Python的閉包和裝飾器你真的了解嗎_python
- 2022-06-11 C#把EXCEL數據轉換成DataTable_C#教程
- 2023-12-18 MyBatisSystemException異常產生原因及解決方案
- 2022-12-14 Qt設置窗體(QWidget)透明度的方法總結_C 語言
- 2023-04-11 一文詳解C++11中的lambda函數_C 語言
- 2024-02-17 自定義Matplotlib中的顏色映射(cmap)
- 2023-07-09 【elementplus】解決el-table開啟show-overflow-tooltip后,to
- 2022-04-05 Android判斷是否Root方法介紹_Android
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支