Flutter 鸿蒙插件适配实战:用 country_codes_plus 5.2.0 读取语言、地区和国家名称
适配仓库: https://atomgit.com/oh-flutter/country_codes_plus
适配分支:
feat/ohos_country_codes_plus_5.2.0受测提交:
723e6828bf66f92347c4dd828a6524bf23e5fa6e
一、最终效果与适配目标
国家选择器、电话号码输入、地址表单和本地化展示需要语言码、系统地区以及国家名称表。country_codes_plus 5.2.0 还包含 250 个国家/地区键、ISO 3166-2 行政区和查询工具。已有的 country_codes 是另一个包,不能因为名称相近就把它当成同一适配。
本次目标是保留 CountryCodes.init() 和所有 Dart 数据能力,只补原生 getLanguage、getRegion、getLocale。传给 init() 的 locale 只决定国家名称用哪种语言显示,不能偷偷修改设备语言或地区。

图 1:真机宿主显示设备 locale、国家表键数与中英文名称。
| 验证点 | 实测结果 | 证据 |
|---|---|---|
| 设备语言与地区 | 两轮均为 zh / CN,Dart locale 为 zh_CN | 图 1、图 6 |
| 国家/地区表 | getLocale('en-US') 返回 250 个键 | 图 6 |
| 显示语言切换 | 中国在英文与中文显示为 China / 中国 | 图 6 |
| 自动化与构建 | 81 项 Dart/Widget/ArkTS 功能测试及 HAP 构建通过 | 图 4、图 5 |
| 验证边界 | 未修改系统语言/地区,也未覆盖应用独立语言偏好与其他系统版本 | 真机说明 |
成果速览
| 项目 | 内容 |
|---|---|
| 上游基线 | TAG v5.2.0,提交 be52bfa68d98697550bedf6716137a2f26b6bd93,MIT |
| 适配分支 | feat/ohos_country_codes_plus_5.2.0 |
| 适配 TAG | 尚未发布 |
| 真机受测提交 | 723e6828bf66f92347c4dd828a6524bf23e5fa6e |
| 当前远程 HEAD | 723e6828bf66f92347c4dd828a6524bf23e5fa6e |
| 新增 OHOS 能力 | 读取设备 language/region,按显示 locale 生成 250 个国家/地区名称 |
| 真机结论 | 原生通道、公开 API、中英文名称与键集完整性两轮通过 |
二、本次环境
| 项目 | 实测版本 |
|---|---|
| Flutter OH | 3.41.10-ohos-1.0.1 |
| Dart | 3.11.5 |
| DevEco Studio | 26.0.0 Release |
| HarmonyOS SDK | API 26,示例兼容 API 18 |
| 设备 | CHZ-AL00,HarmonyOS 7.0.0.105(SP10C00E105R2P4) |
| 目标库 | country_codes_plus 5.2.0 |
环境安装参考 Flutter OH 环境搭建指南。截至 2026 年 9 月 12 日,版本号最大的 Flutter OH 标签是预览版 3.44.9+ohos-0.0.1-canary1,最新正式稳定标签仍是本文完成构建和真机回归的 3.41.10-ohos-1.0.1。
三、最新版本和仓库排重
2026 年 9 月 9 日通过发布 API 核对最新版本为 5.2.0,Dart 约束兼容 3.11.5。上游标签 v5.2.0 和基线提交都是 be52bfa68d98697550bedf6716137a2f26b6bd93,主要源码与发布包一致,MIT 许可证保留。
适配前完整分页检查 oh-flutter、CPF-Flutter、hxa-flutter 共 634 个公开仓库,并查询清单与包名,未发现本包适配。该结论只代表当时公开搜索范围,不是“全网绝对不存在”的证明。
git clone https://atomgit.com/oh-flutter/country_codes_plus.git
cd country_codes_plus
git switch feat/ohos_country_codes_plus_5.2.0
git branch --show-current
从基线复现适配分支和 OHOS 壳:
git switch -c feat/ohos_country_codes_plus_5.2.0 be52bfa68d98697550bedf6716137a2f26b6bd93
flutter create --template=plugin --platforms=ohos --no-pub .
图 2 汇总了实际 AtomGit origin、适配分支和 HEAD,可核对仓库来源与当前分支状态。

图 2:AtomGit origin、适配分支与当前 HEAD。
四、Dart 数据与原生 locale 的职责
WidgetsFlutterBinding.ensureInitialized();
await CountryCodes.init(const Locale('zh'));
final deviceLocale = CountryCodes.getDeviceLocale();
final selected = CountryCodes.lookupDetails().details;
final countries = CountryCodes.allCountries;
通道名为 country_codes_plus。getLanguage 返回设备基础语言码,如 zh;getRegion 返回系统地区,如 CN;getLocale 返回 [language, region, localizedCountryNames]。国家与行政区查询仍由原 Dart 数据实现。
CountryCodes.init(appLocale) 会缓存最近一次初始化结果。系统语言改变后需要再次 init 才能刷新,不应宣称它自动监听变化。上游还有 MissingPluginException 降级路径,集成验收必须显式探测三个原生方法,防止通道没有注册却被降级掩盖。
五、OHOS locale 与国家译名实现
在 pubspec.yaml 注册 CountryCodesPlugin。ArkTS 使用 LocalizationKit:
if (call.method === 'getRegion') {
value = i18n.System.getSystemRegion();
} else {
const systemLocale = new intl.Locale(i18n.System.getSystemLocale());
if (call.method === 'getLanguage') {
value = systemLocale.language;
} else {
const region = i18n.System.getSystemRegion();
const displayLocale = requestedLocale.length > 0
? new intl.Locale(requestedLocale).baseName
: systemLocale.baseName;
// 遍历与 Dart 数据一致的 COUNTRY_CODES,读取本地化名称。
}
}
原生 COUNTRY_CODES 不是手写的第二份来源,而是由 dart run ohos/tool/generate_country_codes.dart 从 lib/src/codes.dart 生成。Dart 测试比较两边 250 个键完全一致,避免后续国家数据更新时漏改 ArkTS。
遍历名称时,系统若对单个地区返回错误 890001,实现保留该键并把译名设为空。像 XK 这类系统数据不完整的地区不应从国家表消失;只有所有名称都为空,才把整体查询视为失败。其他系统异常返回 LOCALE_QUERY_FAILED,非字符串显示语言参数返回 INVALID_ARGUMENT。
系统能力从 API 9 提供。getSystemLocale 等兼容接口从 API 20 起标记弃用,本次为兼容示例 API 18 保留使用,后续提高最低版本时可重新评估新接口。

图 3:getLocale/getLanguage/getRegion 路由、参数校验与系统 locale 读取。
六、交付文件
适配分支保留原 Dart、Android、iOS、macOS、Web 运行时代码、国家/行政区数据、MIT LICENSE 和完整历史;新增 OHOS HAR、example/ohos/、双语文档、生成脚本、Dart 契约测试、widget 测试、生产 ArkTS 测试及设备入口。
示例展示默认、英文和中文显示语言下的名称结果,并覆盖窄屏。签名、SDK 路径、依赖缓存、生成注册文件和 HAP 不入库。
七、测试、失败预检和构建
flutter pub get
flutter test --no-pub test
flutter analyze --no-pub
NODE_PATH="${DEVECO_HOME}/tools/ohpm/node_modules" \
node --test ohos/test/country_codes_plus.test.cjs
cd example
flutter test --no-pub test/widget_test.dart
flutter analyze --no-pub
flutter build hap --debug --no-codesign --no-pub
上游 48 项加新增 5 项 Dart 测试、9 项 widget 和 19 项生产 ArkTS 测试通过,共 81 项功能测试;根目录与示例静态分析无问题,无签名 HAP 构建成功。
早期 ArkTS 构建曾因为直接抛出任意对象失败,最终改成保留系统错误码和消息的 result.error 路径,19 项原生测试和 HAP 再次通过。失败预检日志保留,不能只展示最终绿色结果。
最终提交为 723e6828bf66f92347c4dd828a6524bf23e5fa6e。

图 4:构建失败预检回归、81 项完整用例统计与 Flutter 复跑。

图 5:HAP 元数据、SHA-256 与远程依赖提交。
八、Demo 与真机验收
dependencies:
country_codes_plus:
git:
url: https://atomgit.com/oh-flutter/country_codes_plus.git
ref: 723e6828bf66f92347c4dd828a6524bf23e5fa6e
执行 flutter pub get 后应核对 pubspec.lock 的 resolved-ref。当前没有 OHOS 适配 TAG,因此示例使用完整受测 SHA,避免分支后续更新改变依赖内容。
远程 Git 依赖在隔离宿主中锁定到 723e6828bf66f92347c4dd828a6524bf23e5fa6e,宿主分析、签名 HAP 构建和覆盖安装完成。2026 年 9 月 11 日在 SP10 真机连续跑两轮,系统语言与地区每次均为 zh / CN,Dart 设备 locale 为 zh_CN,与宿主独立原生通道一致。
直连 MethodChannel 的 getLocale('en-US') 返回 3 段结构,国家名称表包含 250 个键,CN=China、US=United States;公共 API 用 en-US 初始化时,中国显示为 China、区号 +86,用 zh-CN 初始化时显示为“中国”。切换显示 locale 前后,设备 locale 始终是 zh_CN;未知方法返回 notImplemented。这次没有修改系统语言或地区,因此不需要伪造“设置恢复”截图;应用独立语言偏好和不同系统版本的译名数据仍需单独覆盖。

图 6:两轮系统 locale、中英文显示名称、250 个国家键与原生通道对照。
应用内多状态补拍

图 7:跟随设备时读取 zh/CN,中国本地化名称为“中国”,区号为 +86。

图 8:切换应用显示语言为英文后,设备 locale 不变,本地化名称变为 China。

图 9:完整页面展示 250 条国家数据、34 条中国行政区数据及前三条示例。
九、推送与远端状态
git status --short
git add pubspec.yaml ohos example test README.OpenHarmony.md README.OpenHarmony_CN.md
git commit -m "feat(ohos): add country_codes_plus OpenHarmony support"
git push -u origin feat/ohos_country_codes_plus_5.2.0
仓库公开,适配分支是默认分支。2026 年 9 月 12 日匿名核对 HEAD 为 723e6828bf66f92347c4dd828a6524bf23e5fa6e,与真机受测提交一致。
十、FAQ
Q1:传 Locale(‘zh’) 会修改系统语言吗
- 现象: 调用
CountryCodes.init(const Locale('zh'))。 - 原因: 该参数只决定国家名称的显示语言。
- 解决方法: 设备 language 和 region 始终从系统读取,不调用设置接口。
- 验证结果: 生产源码、参数测试和两轮真机结果都确认,显示语言切换后设备仍为
zh_CN。
Q2:为什么部分地区译名为空
- 现象: 名称 Map 中个别键没有本地化文本。
- 原因: 设备系统 locale 数据可能缺少
XK等地区。 - 解决方法: 保留键和原 Dart 英文数据,不因单项缺失删除国家。
- 验证结果: ArkTS 测试覆盖
890001单地区缺失。
Q3:为什么显式探测原生方法
- 现象: 公共 API 即使插件未注册也可能返回部分结果。
- 原因: 上游有 MissingPluginException 降级逻辑。
- 解决方法: 验收先直连通道检查 language、region、locale,再测公共 API。
- 验证结果: 真机先直连原生通道再调公共 API,两轮均通过,未知方法也返回
notImplemented。
十一、总结
country_codes_plus 已在 OHOS 端补齐语言、地区和 250 个国家/地区本地化名称,并保持原 Dart 数据与查询 API。81 项功能测试、错误路径修复、静态分析和 HAP 构建已完成;两轮真机又覆盖了原生通道、公共 API、中英文国家名称、国家键数和未知方法。本次没有修改系统设置,文章也不会把显示 locale 参数误写成系统语言切换。
十二、参考链接
欢迎加入CPF-Flutter 鸿蒙社区:https://atomgit.com/CPF-Flutter
更多推荐




所有评论(0)