
1. 项目概述为什么你需要一份Android语言/国家代码清单在Android开发或者产品本地化的过程中你有没有遇到过这样的场景产品经理拿着一份Excel表格里面列着“简体中文中国”、“繁体中文台湾”、“英语美国”、“英语英国”……然后要求你在App里为这些地区配置不同的资源、价格或者功能。你打开Android Studio准备在res目录下新建values-zh-rCN这样的文件夹时突然卡壳了——台湾地区的代码是zh-rTW还是zh-TW香港呢沙特阿拉伯的阿拉伯语和埃及的阿拉伯语代码又有什么区别这份看似简单的“Android语言/国家代码清单”恰恰是解决这些混乱的基石。它不是什么高深的算法但却是构建全球化应用的“螺丝刀”和“扳手”。没有它你的本地化工作就像在黑暗中摸索很容易因为代码格式错误导致资源加载失败或者更糟糕出现文化或区域上的不当展示。我见过不少团队在临近上线时才发现某个地区的语言包根本没生效排查半天原因竟是一个字母的大小写错误或者分隔符用错了。这份清单就是帮你避免这些低级但致命错误的“避坑指南”。简单来说这份清单定义了Android系统如何识别和匹配设备语言与区域的标准。它基于ISO标准但在Android环境下有自己特定的格式和规则。无论是为strings.xml创建本地化文件还是在代码中动态判断用户区域以提供定制化服务都离不开对这些代码的正确理解和使用。接下来我们就把它彻底拆解清楚。2. 核心概念解析Locale、语言代码与国家/地区代码在深入清单之前我们必须先理清两个核心概念语言代码Language Code和国家/地区代码Region Code以及它们如何组成Android所使用的Locale对象。2.1 语言代码ISO 639语言代码用于标识人类语言。Android主要采用ISO 639-1的两字母代码对于一些没有两字母代码的语言则使用ISO 639-2的三字母代码。常见两字母代码zh(中文)en(英语)es(西班牙语)fr(法语)ja(日语)ko(韩语)。三字母代码示例fil(菲律宾语)zho(中文 – 通常作为备用的三字母代码但Android中更常用zh)。注意代码是小写敏感的。虽然标准规定是小写但在实际使用中务必保持一致性。2.2 国家/地区代码ISO 3166-1国家/地区代码用于标识地理区域。Android采用ISO 3166-1 alpha-2的两字母代码。常见代码CN(中国)US(美国)GB(英国)TW(台湾地区)HK(香港地区)MO(澳门地区)JP(日本)KR(韩国)。重要提示在Android的语境下国家/地区代码用于区分同一语言在不同地区的变体如简体中文zh-CN和繁体中文zh-TW或者同一国家内的不同语言偏好。使用时需严格遵守相关的开发规范。2.3 Android Locale的构成格式在Android中语言代码和地区代码组合成一个Locale对象其字符串表示遵循特定的格式基本格式语言代码或语言代码-地区代码例如zh,en,zh-CN,en-US,en-GB。传统格式Legacy语言代码_r地区代码这是早期Android资源目录命名使用的格式例如values-zh-rCNvalues-en-rUS。其中的r是固定字面量。在代码中创建Locale对象或进行区域设置时请使用短横线-分隔符。资源目录命名则两种格式系统都能识别但短横线格式是现在更推荐的方式。包含脚本代码罕见语言代码-脚本代码-地区代码脚本代码遵循ISO 15924用于区分书写系统。例如塞尔维亚语可以用西里尔字母(sr-Cyrl-RS)或拉丁字母(sr-Latn-RS)书写。在大多数常见开发场景中较少用到。理解这些格式差异至关重要尤其是在处理资源目录和API调用时。混淆格式是导致本地化失败的常见原因之一。3. Android资源系统中的代码应用实战理论清楚了我们来看最实际的应用如何利用这些代码来组织你的应用资源实现多语言适配。3.1 资源目录命名规范Android的资源系统通过为res下的子目录如values,drawable添加后缀来自动匹配设备Locale。规则如下默认资源res/values/strings.xml(无后缀)指定语言的资源res/values-zh/strings.xml(仅语言代码)指定语言和地区的资源res/values-zh-CN/strings.xml或res/values-zh-rCN/strings.xml(语言-地区代码)指定语言、脚本和地区的资源res/values-zh-Hans-CN/strings.xml(简体中文中国)当用户设备设置为“中文中国”时系统会按以下优先级查找strings.xmlvalues-zh-CN(精确匹配)values-zh(语言匹配)values(默认回退)如果用户设备是“中文台湾”而你没有values-zh-TW系统会回退到values-zh最后是values。实操心得务必设置一个完整、通用的默认values/strings.xml。这是最后的保障可以避免因为缺少某个特定区域资源而导致应用崩溃出现空白文本。我通常会把英文en或最通用的语言版本作为默认资源。3.2 创建与管理多语言资源在Android Studio中操作非常简便在项目视图中右键点击res目录。选择New-Android Resource File。在弹出窗口中Resource type选择ValuesFile name输入strings。在Available qualifiers列表中选择Locale点击添加到Chosen qualifiers。此时会出现语言和地区下拉列表选择你需要的语言如 Chinese (zh)和地区如 China (CN)。Android Studio会自动生成目录名例如values-zh-rCN。点击OK就会创建对应的strings.xml文件。你可以用同样的方法为arrays.xml、colors.xml甚至布局文件创建本地化版本。对于图片资源如果需要本地化例如包含文字的图片可以创建drawable-zh-CN这样的目录。常见问题有时候你创建了values-zh-CN但AS显示的目录名却是values-zh-rCN这是IDE的显示偏好两者是等价的系统都能识别。不必纠结以你在创建时选择的为准。4. 在Java/Kotlin代码中动态使用Locale资源系统是静态匹配有时我们需要在代码中动态地获取或设置区域信息以实现更灵活的逻辑。4.1 获取设备当前Locale// Kotlin val currentLocale if (Build.VERSION.SDK_INT Build.VERSION_CODES.N) { // API 24及以上支持多语言列表 resources.configuration.locales[0] } else { // 旧API Suppress(DEPRECATION) resources.configuration.locale } val language currentLocale.language // 例如 zh val country currentLocale.country // 例如 CN Log.d(LocaleInfo, 当前语言: $language, 国家/地区: $country)// Java Locale currentLocale; if (Build.VERSION.SDK_INT Build.VERSION_CODES.N) { currentLocale getResources().getConfiguration().getLocales().get(0); } else { currentLocale getResources().getConfiguration().locale; } String language currentLocale.getLanguage(); String country currentLocale.getCountry(); Log.d(LocaleInfo, 当前语言: language , 国家/地区: country);4.2 根据Locale执行特定逻辑你可以根据获取到的代码来决定应用行为when (currentLocale.language) { zh - { // 中文用户逻辑 if (currentLocale.country CN) { // 中国大陆特定逻辑例如接入微信支付 setupWeChatPay() } else if (currentLocale.country TW) { // 台湾地区特定逻辑 setupTraditionalChineseUI() } } en - { // 英文用户逻辑 showEnglishContent() } else - { // 其他语言回退到默认逻辑 fallbackToDefault() } }4.3 以编程方式创建和比较Locale// 创建特定的Locale对象 val localeChina Locale(zh, CN) val localeTaiwan Locale(zh, TW) val localeUS Locale(en, US) // 比较Locale val isChinese localeChina.language zh val isSimplifiedChinese localeChina Locale.SIMPLIFIED_CHINESE // 使用常量更可靠 val isTraditionalChinese localeTaiwan Locale.TRADITIONAL_CHINESE // 格式化信息如日期、货币 val dateFormat DateFormat.getDateInstance(DateFormat.MEDIUM, localeChina) val formattedDate dateFormat.format(Date())Android提供了一些常用的Locale常量如Locale.CHINA(zh_CN)、Locale.US(en_US)、Locale.TAIWAN(zh_TW)。在代码中使用这些常量比手动拼接字符串更安全、更可读。注意事项在代码中拼接语言和地区字符串时务必使用Locale构造函数或Locale.forLanguageTag(“zh-CN”)方法而不是自己用“zh-CN”这样的字符串去比较或创建。因为Locale对象的内部表示可能包含更多信息直接进行字符串比较可能不可靠。5. 高级主题与最佳实践掌握了基础应用后我们来看一些更深层次的内容和实践中总结出的“干货”。5.1 处理区域设置变更当用户在系统设置中切换语言时默认情况下Android会重启当前前台的Activity。为了提供更流畅的体验你可以选择在应用内提供语言切换选项并动态更新资源。方法一更新Configuration并重建ActivityAPI 17推荐fun switchAppLocale(locale: Locale) { val resources context.resources val configuration resources.configuration configuration.setLocale(locale) // API 17 使用 setLocale // 对于API 25可以配合 applyOverrideConfiguration但更简单的方式是创建新的Context val newContext context.createConfigurationContext(configuration) // 使用newContext的resources来获取更新后的字符串 // 通常需要重启Activity来全局生效 activity.recreate() // 重启当前Activity }方法二使用AppCompatDelegateAndroidX这是更现代、更易于管理的方式尤其配合ViewModel保存语言状态。// 在Application或BaseActivity中保存语言选择例如到SharedPreferences // 在Activity的onCreate中调用super.onCreate之前设置 val savedLocale getSavedLocaleFromPrefs() val config resources.configuration config.setLocale(savedLocale) // 对于使用AppCompat的应用 AppCompatDelegate.setApplicationLocales( LocaleListCompat.forLanguageTags(savedLocale.toLanguageTag()) )实操心得应用内切换语言是个复杂功能涉及到所有Activity的重建和状态恢复。一个常见的“坑”是WebView或第三方SDK它们可能没有正确响应语言变更。建议在应用设计初期就决定是否支持应用内切换并做好全面的测试。对于大多数应用引导用户去系统设置切换可能是更稳定和省心的选择。5.2 语言与国家/地区代码的常见“陷阱”清单以下是我在多年开发中踩过或见过的坑请你务必绕行大小写问题语言代码始终小写国家代码始终大写。zh-cn是错误的应该是zh-CN。虽然有些API容错性强但坚持规范能避免意想不到的问题。分隔符混淆在资源目录名中zh-CN和zh_rCN历史共存但在代码Locale对象和toLanguageTag()方法中统一使用短横线-。建议在新项目中统一使用短横线格式。“国家”不等于“地区”Locale中的country字段实际代表的是地区。对于像en英语这种在许多地区使用的语言必须结合地区代码才能准确匹配资源en-US美式英语en-GB英式英语。繁体中文的复杂性zh-TW中文台湾。使用繁体字一些词汇和用语与大陆不同。zh-HK中文香港。使用繁体字部分用语受粤语影响。zh-MO中文澳门。类似香港。不要假设zh-TW能完美覆盖所有繁体中文用户。如果资源允许为香港和澳门单独配置是更专业的做法。“方言”或“变体”的处理有些语言有重要变体但ISO代码可能相同。例如西班牙语es-ES卡斯蒂利亚西班牙语和es-US美国西班牙语在用词上有差异。葡萄牙语pt-PT欧洲葡萄牙语和pt-BR巴西葡萄牙语差异显著。法语fr-FR法国法语和fr-CA加拿大法语也有不同。最佳实践针对这些有显著差异的地区创建独立的资源文件即使语言代码相同。回退链的误解系统回退是zh-CN-zh-默认。但没有zh-CN-zh-TW这样的回退。不要指望系统会自动在繁体中文和简体中文之间切换。如果你希望简体中文用户也能看到繁体中文内容作为一种备选需要在你的应用逻辑中手动实现。API Level的差异旧API如configuration.locale在API 24Android 7.0后被标记为废弃改用configuration.locales以支持多语言列表。处理时务必做好版本判断。5.3 获取完整的支持列表与校验你可能会问我怎么知道Android具体支持哪些代码虽然Android遵循ISO标准但并非所有代码都在资源选择器中有图形化选项。通过代码获取系统支持的语言val locales Locale.getAvailableLocales() locales.forEach { locale - Log.d(SupportedLocale, ${locale.language}-${locale.country} - ${locale.displayName}) }这会打印出JVMAndroid Runtime所识别的所有Locale。列表非常长包含很多历史或罕见的组合。实践建议你不需要支持列表中的所有项。通常你只需要关注你的目标市场。根据产品需求从上述列表或ISO官方网站筛选出你需要支持的10-20个语言地区组合即可。创建一个枚举类或常量文件来管理这些支持的Locale是一个好习惯。object SupportedLocales { val SIMPLIFIED_CHINESE Locale(“zh”, “CN”) val TRADITIONAL_CHINESE_TW Locale(“zh”, “TW”) val TRADITIONAL_CHINESE_HK Locale(“zh”, “HK”) val ENGLISH_US Locale(“en”, “US”) val ENGLISH_UK Locale(“en”, “GB”) val JAPANESE Locale(“ja”, “JP”) // ... 其他 val ALL listOf(SIMPLIFIED_CHINESE, TRADITIONAL_CHINESE_TW, ENGLISH_US, JAPANESE) fun isValid(target: Locale): Boolean { return ALL.any { it.language target.language it.country target.country } } }6. 清单速查与实战案例最后为了方便大家“抄作业”我整理了一份最常见语言/地区代码的速查表并附上一个实战案例。6.1 常用Android语言/国家代码速查表显示名称 (Display Name)语言代码 (Language)国家/地区代码 (Region)Android Locale Tag (推荐)传统资源目录示例简体中文 (中国)zhCNzh-CNvalues-zh-rCN繁体中文 (台湾)zhTWzh-TWvalues-zh-rTW繁体中文 (香港)zhHKzh-HKvalues-zh-rHK繁体中文 (澳门)zhMOzh-MOvalues-zh-rMO英语 (美国)enUSen-USvalues-en-rUS英语 (英国)enGBen-GBvalues-en-rGB英语 (澳大利亚)enAUen-AUvalues-en-rAU日语 (日本)jaJPja-JPvalues-ja-rJP韩语 (韩国)koKRko-KRvalues-ko-rKR法语 (法国)frFRfr-FRvalues-fr-rFR法语 (加拿大)frCAfr-CAvalues-fr-rCA德语 (德国)deDEde-DEvalues-de-rDE西班牙语 (西班牙)esESes-ESvalues-es-rES西班牙语 (美国)esUSes-USvalues-es-rUS葡萄牙语 (巴西)ptBRpt-BRvalues-pt-rBR葡萄牙语 (葡萄牙)ptPTpt-PTvalues-pt-rPT俄语 (俄罗斯)ruRUru-RUvalues-ru-rRU阿拉伯语 (沙特阿拉伯)arSAar-SAvalues-ar-rSA印地语 (印度)hiINhi-INvalues-hi-rIN说明“Android Locale Tag”列是你在代码中创建Locale对象或使用toLanguageTag()时应使用的格式。“传统资源目录示例”列是Android资源系统可以识别的目录名格式。现在新建目录时更推荐直接使用zh-CN这样的短横线格式如values-zh-CNAndroid Studio和构建系统都能正确处理。6.2 实战案例为电商App配置多区域价格和文案假设你开发一个电商App需要针对美国、英国、中国大陆、台湾地区展示不同的价格货币符号和格式和促销文案。步骤1创建本地化字符串资源res/values/strings.xml(默认例如用美式英语)string nameproduct_pricePrice: $%.2f/string string namepromo_textSummer Sale! Up to 50%% off!/stringres/values-en-GB/strings.xmlstring nameproduct_pricePrice: £%.2f/string string namepromo_textSummer Sale! Up to 50%% off!/stringres/values-zh-CN/strings.xmlstring nameproduct_price价格¥%.2f/string string namepromo_text夏季大促低至5折/stringres/values-zh-TW/strings.xmlstring nameproduct_price價格NT$%.2f/string string namepromo_text夏季特賣最高50%% off/string步骤2在代码中动态格式化和显示fun displayProductInfo(price: Double) { // 获取当前Locale val currentLocale getCurrentLocale() // 获取本地化字符串 val priceFormat resources.getString(R.string.product_price) val promoText resources.getString(R.string.promo_text) // 创建区域特定的数字格式用于小数位、千分位分隔符 val numberFormat NumberFormat.getCurrencyInstance(currentLocale) val localizedPriceString numberFormat.format(price) // 更专业的方式 // 或者使用字符串格式如果字符串里已包含符号 val formattedPrice String.format(currentLocale, priceFormat, price) // 更新UI priceTextView.text localizedPriceString // 或 formattedPrice promoTextView.text promoText // 更进一步根据地区决定是否显示促销例如某些地区无此活动 if (currentLocale.country CN isSummerSaleInChina()) { promoTextView.visibility View.VISIBLE } else { promoTextView.visibility View.GONE } }步骤3处理货币转换逻辑价格本身通常来自后端APIAPI应返回基础价格如美元和货币代码如USD。客户端需要根据用户区域和实时汇率可能依赖本地逻辑或再次查询服务端进行换算和显示。NumberFormat.getCurrencyInstance(locale)能根据Locale自动匹配正确的货币符号和格式但它不负责汇率计算。这个案例展示了如何将简单的代码清单融入到真实的业务逻辑中实现真正的国际化用户体验。记住本地化不仅仅是翻译文字还包括数字、日期、货币格式乃至图片、布局和功能逻辑的适配。而这一切的起点就是正确理解和使用那份“Android语言/国家代码清单”。希望这份超详细的拆解能让你在应对全球化开发的挑战时手里多一份扎实的地图。