android6适配繁体
最近测试同学提了个bug,说android6的手机切换不了中文繁体,看了下,,代码是这样的:
val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags("zh-Hant")
AppCompatDelegate.setApplicationLocales(appLocale)
修改方法
把 zh-Hant 换成 zh-TW 就好了,差不多是这样
val appLocale = LocaleListCompat.forLanguageTags(if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) "zh-TW" else "zh-Hant"
)
AppCompatDelegate.setApplicationLocales(appLocale)
原因
Android 系统中,语言和区域的识别依赖于 Locale 对象。在 Android 7.0(API 24)之前,系统只支持通过语言代码(例如 “zh”)和可选的地区代码(例如 “TW”)来标识区域。这种格式通常用下划线或连字符连接,例如 zh_TW 或 zh-TW。
而 BCP 47 语言标签(如 zh-Hant)是一种更现代和更精确的表示方法,它使用脚本代码(如 Hant 表示繁体中文)来区分同一语言的不同书写形式。但是,Android 6.0(API 23)及以下版本的系统并不支持通过脚本代码来设置区域。
具体原因如下:
- 历史背景:
在 Android 7.0 之前,Locale 类只支持语言和地区两个字段,不支持脚本字段。因此,当我们尝试使用 zh-Hant 这样的标签时,系统无法识别 Hant 部分,因为它既不是语言代码也不是地区代码。
资源目录匹配:
Android 系统在查找资源时,会根据设备的区域设置去匹配 res 目录下的相应子目录。在 Android 6.0 上,资源目录的命名规则是:
values-zh-rTW:表示台湾繁体中文
values-zh-rHK:表示香港繁体中文
注意:这里使用 zh 表示中文,TW 或 HK 表示地区,r 是固定前缀(表示区域)。
系统在匹配资源时,只会根据语言(zh)和地区(TW、HK)来匹配,而不会根据脚本(Hant)来匹配。
项目中没有香港繁体资源,所以设置为zh-HK,会识别不到。
所以系统默认是zh-HK的时候,选中的其实是英文。
- Locale 解析:
当我们使用 Locale.forLanguageTag(“zh-Hant”) 在 Android 6.0 上时,由于系统无法识别脚本代码,它会尝试解析这个标签。但是,在 Android 6.0 上,Locale 类会忽略它不认识的部分(即 Hant),结果可能只会保留 zh。这样,系统就会使用简体中文(因为默认的 zh 资源可能是简体)。
繁体中文的表示:
在 Android 6.0 时代,表示繁体中文通常使用地区变体:
zh-TW:台湾(使用繁体中文)
zh-HK:香港(使用繁体中文)
zh-MO:澳门(使用繁体中文)
因此,为了在 Android 6.0 上正确显示繁体中文,我们必须使用这些地区代码,而不是脚本代码。
- AndroidX 的兼容行为:
当我们使用 AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(“zh-Hant”)) 时,在 Android 7.0 以上,兼容库会正确使用 LocaleList API 并设置脚本。但在 Android 6.0 上,兼容库会回退到旧的 API(通过 Configuration.locale 设置),而 zh-Hant 会被解析成一个只有语言(zh)的 Locale 对象,因此无法正确匹配到繁体中文资源。
因此,为了在 Android 6.0 上正确设置繁体中文,我们需要将语言标签替换为系统能够识别的地区变体,如 zh-TW 或 zh-HK。这样,系统就能正确匹配到 values-zh-rTW 或 values-zh-rHK 目录下的资源。
参考
- deepseek
- https://lausai360.blogspot.com/2017/10/android-70.html
- https://issuetracker.google.com/issues/37102249
- https://issuetracker.google.com/issues/37093759
