适配仓库: 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 数据能力,只补原生 getLanguagegetRegiongetLocale。传给 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
当前远程 HEAD723e6828bf66f92347c4dd828a6524bf23e5fa6e
新增 OHOS 能力读取设备 language/region,按显示 locale 生成 250 个国家/地区名称
真机结论原生通道、公开 API、中英文名称与键集完整性两轮通过

二、本次环境

项目实测版本
Flutter OH3.41.10-ohos-1.0.1
Dart3.11.5
DevEco Studio26.0.0 Release
HarmonyOS SDKAPI 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-flutterCPF-Flutterhxa-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_plusgetLanguage 返回设备基础语言码,如 zhgetRegion 返回系统地区,如 CNgetLocale 返回 [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.dartlib/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.lockresolved-ref。当前没有 OHOS 适配 TAG,因此示例使用完整受测 SHA,避免分支后续更新改变依赖内容。

远程 Git 依赖在隔离宿主中锁定到 723e6828bf66f92347c4dd828a6524bf23e5fa6e,宿主分析、签名 HAP 构建和覆盖安装完成。2026 年 9 月 11 日在 SP10 真机连续跑两轮,系统语言与地区每次均为 zh / CN,Dart 设备 locale 为 zh_CN,与宿主独立原生通道一致。

直连 MethodChannel 的 getLocale('en-US') 返回 3 段结构,国家名称表包含 250 个键,CN=ChinaUS=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

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐