Flutter 鸿蒙插件适配实战:用 locale_plus 2.0.0 读取语言、地区与格式偏好

适配仓库: https://atomgit.com/oh-flutter/locale_plus

适配分支: feat/ohos_locale_plus_2.0.0

受测提交: 1387b3d8b3eadbb782c77c679a6446e50e9ebca0

一、最终效果与适配目标

国际化页面不只需要 zh_CN。金额输入要知道小数和分组符,日历要知道周首日,时间页需要 12/24 小时制、AM/PM 文本、IANA 时区及 UTC 偏移。locale_plus 2.0.0 已提供 13 个 Dart 查询接口,本次适配目标是保持接口和可空返回值不变,在 OHOS 上从系统国际化能力读取真实数据。

图 1:CHZ-AL00 / HarmonyOS 7.0.0.105 上读取到 zhCNAsia/Shanghai、28800 秒偏移、中文时段符号和公制偏好。

验证点 实测结果 证据
语言与地区 zh / CN,二者独立读取 图 1、图 6
时间信息 Asia/Shanghai、UTC 偏移 28800 秒、周首日 7 图 1、图 6
格式偏好 小数点、分组符、AM/PM、日期模式、12/24 小时制均返回 图 1
自动化与构建 15 Dart + 3 Widget + 15 ArkTS,共 33 项及 HAP 通过 图 4、图 5
验证边界 未修改系统语言、地区、历法或时区;其他 locale 由自动化覆盖 图 6

成果速览

项目 内容
上游基线 TAG v2.0.0,提交 9897037d81007432306825c3fb860c204efb853c,MIT
适配分支 feat/ohos_locale_plus_2.0.0
适配提交 1387b3d8b3eadbb782c77c679a6446e50e9ebca0
新增 OHOS 能力 13 项语言、地区、数字、日期、时区与单位偏好查询
保持不变的接口 LocalePlus 全部公开方法与 locale_plus 通道
真机结论 13 项基础读取通过;系统设置切换与其他设备未覆盖

二、实测环境与选库核对

组件 实测版本
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
插件 locale_plus 2.0.0

环境搭建参考 Flutter OH 环境搭建指南。本文使用已完整回归的稳定版 Flutter OH;3.44.9+ohos-0.0.1-canary1 是预览标签,不冒充本次实测版本。

2026 年 9 月 11 日,我核对 pub.dev 最新版 2.0.0、上游 TAG 与发布包,并对目标组织仓库做同名排查。没有发现可直接使用的 OHOS 实现后,才创建本次仓库。发布包 SHA 与上游来源均记录在适配批次证据中。

三、从上游基线建立 OHOS 分支

shell 复制代码
git clone https://atomgit.com/oh-flutter/locale_plus.git
cd locale_plus
git switch -c feat/ohos_locale_plus_2.0.0 v2.0.0
flutter create --template=plugin --platforms=ohos --no-pub .

我保留原 Dart、Android、iOS 和 Web 代码,只新增 OHOS HAR、示例宿主、双语说明与测试。模板生成后把插件类改为 LocalePlusPlugin,通道继续使用 locale_plus

图 2:AtomGit origin、适配分支、完整 HEAD 与工作区状态。

四、先梳理 13 个接口的语义

公开接口都返回可空值,原生系统数据缺失时不应自行编造:

接口组 API 返回语义
locale getLanguageCode()getRegionCode() 基础语言码和地区码
数字 getDecimalSeparator()getGroupingSeparator() 当前 locale 的数字符号
时区 getTimeZoneIdentifier()getSecondsFromGMT() IANA 标识和当前偏移秒数
时间/日期 is24HourTime()getAmSymbol()getPmSymbol()getFirstDayOfWeek()getDateFormatPattern() 系统格式偏好
其他 usesMetricSystem()isUsingSamsungKeyboard() 单位策略与上游平台特定判断

语言和地区必须分开读。例如系统语言可能是 zh-Hans,基础语言码应解析为 zh;地区则来自独立的系统 region。UTC 偏移必须按"当前时刻"计算,才能包含夏令时,而不能写死时区的标准偏移。

五、用 LocalizationKit 实现格式查询

LocalePlusPlugin.ets 通过 i18n.Systemi18n.getTimeZone()systemDateTime 取得基础数据;数字、时段和日期格式通过 IntlformatToParts() 拆解:

typescript 复制代码
case 'getRegionCode':
  return i18n.System.getSystemRegion();
case 'getLanguageCode':
  return new Intl.Locale(i18n.System.getSystemLanguage()).language;
case 'getTimeZoneIdentifier':
  return systemDateTime.getTimezoneSync();
case 'getSecondsFromGMT':
  return i18n.getTimeZone().getOffset(Date.now()) / 1000;

日期模式不能通过替换格式化后的数字猜测。实现用一个固定 UTC 日期拆出 year、month、day 和 literal,再按照字段宽度生成 yyyy/M/ddd/MM/yyyy 等模式。字面量中如果有字母,需要加引号,防止被 intl.DateFormat 当成模式字符。

getFirstDayOfWeek() 保持系统返回的 ISO 1 到 7,不再把星期日改成 1。公制判断沿用上游 Android 的地区策略:US、LR、MM 返回 false,其他地区返回 true;它是地区规则,不是用户可单独修改的单位设置。Samsung 键盘是其他平台特定能力,OHOS 明确返回 false。

图 3:13 个方法的路由,以及语言、地区、时区和格式数据来源。

该插件只读取公开系统 locale 数据,无需新增权限,也不会修改系统设置。Engine 解绑后清除 handler;系统异常返回 locale_query_failed,未知方法返回 notImplemented

六、测试和 HAP 构建

shell 复制代码
flutter pub get
flutter analyze
flutter test
node --test ohos/test/locale_plus.test.cjs
cd example
flutter analyze
flutter test
flutter build hap --debug --no-codesign

15 项 Dart、3 项 Widget 和 15 项 ArkTS,共 33 项通过。原生测试覆盖英语、德语、法语、阿拉伯语、印地语数字符号,正负及半小时时区偏移,中英文 AM/PM,四种日期顺序,地区公制规则、错误恢复和 Engine 重绑。

图 4:静态分析、33 项功能测试和示例回归结果。

图 5:无签名 HAP 元数据及远程 Git 依赖锁定口径。

七、固定提交接入与真机验证

yaml 复制代码
dependencies:
  locale_plus:
    git:
      url: https://atomgit.com/oh-flutter/locale_plus.git
      ref: 1387b3d8b3eadbb782c77c679a6446e50e9ebca0

隔离宿主的 pubspec.lock 解析到同一 SHA,签名 HAP 构建和覆盖安装通过。真机逐项读取 13 个接口,并用 Dart 本地时区偏移对照 28800 秒,全部通过。页面结果包括 zhCNAsia/Shanghai、小数点、分组符、中文上午/下午、12 小时制、周首日 7、yyyy/M/d 和公制。

图 6:13 项真机读取结论及未修改系统设置的验证边界。

本轮没有切换语言、地区、历法和时区,因此不能声称所有组合都已真机验收。自动化覆盖不同 locale 的算法分支,但它和真实设备切换是两类证据。

应用内真实截图:刷新后的格式信息

图 7:页面上半段展示语言、地区、时区、UTC 偏移及数字分隔符。

图 8:刷新后第 2 次读取,日期模式、周首日、24 小时制和公制偏好仍保持一致。

八、FAQ

Q1:为什么语言码和地区码不能从同一个字符串截取

  • 现象: 脚本假定 locale 总是 language_REGION,遇到脚本码或缺少地区时解析错误。
  • 原因: 系统语言和地区是独立设置,语言标签也可能包含 script。
  • 解决方法: 分别读取 system language 与 system region,语言再交给 Intl.Locale 解析。
  • 验证结果: 自动化用 zh-HansGB 的组合确认返回 zh / GB

Q2:UTC 偏移为什么不能写成时区常量

  • 现象: 夏令时地区在不同日期返回值会变化。
  • 原因: IANA 时区标识不等于固定偏移,偏移与当前时间有关。
  • 解决方法: 调用 getOffset(Date.now()) 并从毫秒换算为秒。
  • 验证结果: 测试覆盖负偏移、零偏移和半小时偏移,真机与 Dart 当前偏移一致。

Q3:usesMetricSystem 是否读取用户偏好

  • 现象: 调用方以为它代表系统设置页中的自定义单位。
  • 原因: 上游 API 按地区规则推断,OHOS 适配保持同一语义。
  • 解决方法: 将它用于默认值;用户明确选择的单位仍应保存在业务配置中。
  • 验证结果: US/LR/MM 与 CN/GB 的规则由 ArkTS 测试覆盖。

九、总结

locale_plus 2.0.0 已在 OHOS 上补齐全部 13 项系统 locale 查询,并保留可空返回值和原通道契约。33 项自动化、HAP 构建和 API 26 真机基础读取通过,且没有申请权限或修改系统设置。

正式项目应锁定受测 SHA,把这些结果当作格式默认值,并为系统数据缺失保留降级显示。语言与地区切换、其他历法和更多设备仍需按业务覆盖。

十、参考链接

欢迎加入CPF-Flutter 鸿蒙社区:https://atomgit.com/CPF-Flutter

相关推荐
贾伟康10 小时前
【HarmonyOS 7新能力|008】互动卡片入门实战:从能力边界到最小可运行链路
harmonyos·arkts·arkui·harmonyos 7·互动卡片
●VON11 小时前
Flutter 鸿蒙插件适配实战:用 clipboard_watcher 0.3.0 监听剪贴板变化
flutter·华为·harmonyos
昇腾知识体系12 小时前
CANN 安装升级避坑:version.cfg 查版本、银河麒麟找不到驱动、nnrt --version 无输出排查
人工智能·华为·知识图谱
贾伟康13 小时前
【HarmonyOS 7新能力|005】沉浸光感入门实战:从能力边界到最小可运行链路
harmonyos·arkts·arkui·harmonyos 7·交互动效
天空之城--14 小时前
Flutter Drift 完全指南:从原理到实战
jvm·flutter·oracle
yume_sibai17 小时前
02-Flutter进阶开发
前端·flutter
心态还需努力呀18 小时前
把 Flameshot 编译进鸿蒙 PC:一次 Qt C++ 截图工具的源码级移植实战
c++·qt·harmonyos