什么是 App 本地化(i18n)?**

应用面向全球用户时,界面文案需要按用户语言动态呈现:首次启动跟随手机语言、设置页随时切换、阿拉伯语等 RTL(从右向左)语言自动镜像排版。传统 Flutter i18n 方案(intl + arb + 代码生成)链路繁琐,而 app_local 只需要几份 JSON 翻译文件 + 一行初始化,就能拿到全部能力。

适配鸿蒙的关键只有一点:"手机语言"这个系统能力必须由原生提供。Android 走 Locale.getDefault()、iOS 走 Locale.preferredLanguages,鸿蒙则对应 i18n.System.getSystemLanguage()——语义对齐、同样零权限,接上通道后上层 API 一行不改。

开发工具:华为云码道(DevEco Studio)

配套仓库:原库 abom-me/app_local(pub 包名 app_local,版本 1.1.3),鸿蒙适配版 https://atomgit.com/CPF-Flutter/fluttertpc_app_local(TAG:1.1.3-ohos-1.0.0-beta.1,分支 br_v1.1.3_ohos)


一、最终运行效果

示例 App 支持英语 / 中文 / 阿拉伯语三种语言,启动后以默认语言(英语)展示:

页面包含:

  • 欢迎横幅:LocaleText('welcome') 大标题 + 带占位符参数的问候语 LocaleText('greeting', params: [...])——“Hello EN, welcome to app_local!”,其中 EN 与 app_local 是运行时注入的两个参数;
  • Runtime state 卡片:设备语言(Locales.deviceLocale,真机上正确识别为 zh)、当前语言(en)、文字方向(LTR)、支持的语言列表;
  • API features 卡片:四项能力自检(LocaleText 组件、BuildContext 扩展、占位符参数、免重启切换),全部绿勾;
  • Available keys 卡片:当前语言 JSON 里已加载的 26 个键,以 Chip 列表展示;
  • 快捷切换按钮:English / Chinese / Arabic 三个按钮。

点击 Chinese 按钮,整个页面瞬间切换为中文,无需重启、无需 setState 逐层传递:

点击 Arabic 按钮,页面自动镜像为从右向左排版,阿拉伯语文案正确渲染——RTL 判断由 intl.Bidi.isRtlLanguage 在 Dart 层完成,各平台行为一致:

示例首页(英文) 已加载的本地化键列表 语言设置页 示例首页(英文) 示例首页(英文) 示例首页(英文) 示例首页(英文) 示例首页(英文) 示例首页(英文) 示例首页(英文) 示例首页(英文) 示例首页(英文)

验证点结果一览:

验证点结果
插件注册(Adding plugin: AppLangPlugin)✅ 通过
通道注册 app_lang✅ 通过
getPhoneLanguage 通道调用(初始化时两次)✅ 通过
设备语言识别(zh-CN 真机 → zh)✅ 通过
运行时切换 EN → 中文(免重启、整页即时生效)✅ 通过
阿拉伯语 RTL 镜像排版✅ 通过
占位符参数注入(## / ###)✅ 通过
全程无需申请任何敏感权限✅ 通过

鸿蒙技术点:FlutterPage 与 XComponent 渲染管线

与所有 Flutter 鸿蒙化工程一致:Index.ets 的 @Entry 组件在 build() 中使用 FlutterPage(内部封装 XComponent 渲染画布,经 NAPI 桥接 C++ 引擎层);EntryAbility 继承 FlutterAbility,在 configureFlutterEngine 中 GeneratedPluginRegistrant.registerWith(flutterEngine) 完成插件注册——AppLangPlugin 由此挂进引擎。


二、app_local 是什么

原库(pub 包 app_local,作者 abom)是一个轻量级 App 本地化框架:翻译内容放在 assets/lang/xx.json,初始化一次后即可用 LocaleText 组件、Locales.string() 或 BuildContext/String 扩展按键取文案,支持运行时切换、占位符参数、RTL 检测与语言偏好持久化。

鸿蒙适配版新增 ohos 平台:Dart 层公开 API 零改动,OpenHarmony 侧提供 ArkTS 插件 AppLangPlugin,实现 app_lang 方法通道上的 getPhoneLanguage 一个方法。

使用者友好特点(分条):

  • JSON 即翻译:每个语言一个 xx.json,键值对维护,无需代码生成;
  • 一行初始化:Locales.init() 搞定语言探测、偏好读取、代理注册;
  • 免重启切换:基于 InheritedWidget 通知整棵组件树重建,切语言即时生效;
  • 三族取文本 API:LocaleText 组件 / Locales.string() 静态方法 / context.localeString() 与 key.localize() 扩展,按场景任选;
  • 占位符参数:"greeting": "Hello ##, welcome to ###!" + params: [a, b],参数本身还可以是本地化键;
  • RTL 自动处理:isDirectionRTL() 与 LocaleText 均基于 intl.Bidi,阿拉伯语开箱即得;
  • 鸿蒙零权限:getPhoneLanguage 走 i18n.System.getSystemLanguage(),系统语言查询接口,无需申请任何权限。

接口说明

Locales 静态接口:

接口说明
Locales.init(localeNames, localPath, phoneLocale)初始化:注册支持语言、读取翻译目录、phoneLocale: true 时首启跟随手机语言
Locales.string(context, key, params, localeParams)按键取本地化文本
Locales.change(context, lang) / context.changeLocale(lang)运行时切换语言
Locales.currentLocale(context) / Locales.lang当前 Locale / 当前语言码
Locales.deviceLocale设备语言码(来自原生通道)
Locales.isDirectionRTL(context) / Locales.selectedLocaleRtl是否从右向左
Locales.delegates / Locales.delegate交给 MaterialApp 的本地化代理(已合并 Material/Cupertino/Widgets 全家桶)
Locales.of(context)取 Locales 实例(含 availableKeys、hasKey、reload)

组件:

组件说明
LocaleBuilder包住 MaterialApp,语言变化时用新 Locale 重建子树
LocaleTextText 的本地化子类,k 为翻译键,支持 params、upperCase、style 等

AppLang(平台通道):

方法返回说明
AppLang().getPhoneLanguage()Future<String?>设备语言的 BCP-47 标签(如 zh-Hans、en-US);Web/异常时兜底 en-OM

各平台设备语言路径表

平台实现方式返回示例
AndroidLocale.getDefault().toLanguageTag()zh-CN
iOS / macOSLocale.preferredLanguages.firstzh-Hans-CN
OpenHarmony(本文)i18n.System.getSystemLanguage()zh-Hans
Web / 其它Dart 层兜底en-OM

说明:Dart 层只取标签第一段(split("-").first),因此 zh-Hans 与 zh-CN 对上层完全等价。


三、环境准备

本文实测环境:

环境项版本
Flutter(ohos 版)3.47.7-ohos-1.0.0(channel oh-3.47-dev,Dart 3.13.3)
DevEco Studio26.0.0(本机 SDK API 26)
编译 SDK6.1.1(24)(compatibleSdkVersion / targetSdkVersion)
真机华为 TLR-AL00,HarmonyOS 6.1.0.145(C00E120R3P5),API 24(系统语言 zh-CN)

鸿蒙技术点:compatibleSdkVersion 与 API Level 对应关系

example/ohos/build-profile.json5 关键字段为 "compatibleSdkVersion": "6.1.1(24)"、"targetSdkVersion": "6.1.1(24)"(保留括号旧格式)。系统校验应用声明的兼容版本不得高于设备 API,否则安装时报"此应用暂不支持在当前设备安装"。本机 DevEco SDK 为 API 26,向下兼容 API 24 的目标设备。

两点提醒:

  1. 需要 ohos 版 Flutter SDK(本文使用 3.47.7-ohos-1.0.0);
  2. 真机安装报错大多与 compatibleSdkVersion 过高有关,与插件无关,见 FAQ Q5。

四、引入依赖

在工程 pubspec.yaml 中添加 git 依赖:

...

dependencies:
  app_local:
    git:
      url: https://atomgit.com/CPF-Flutter/fluttertpc_app_local
      # ref: 1.1.3-ohos-1.0.0-beta.1
      ref: TAG  # 请根据下方TAG版本对应表选择TAG
...

执行命令:

flutter pub get

TAG 版本对应表

Flutter 框架版本TAG分支
3.471.1.3-ohos-1.0.0-beta.1br_v1.1.3_ohos

TAG 命名规则:原库版本-ohos-版本号。原库 1.1.3 对应 1.1.3-ohos-1.0.0-beta.1(分支 br_v1.1.3_ohos)。

依赖链方面:shared_preferences(Flutter 官方插件)与 intl(纯 Dart)在鸿蒙上均可解析,flutter_localizations 来自 SDK,无额外原生依赖。


五、代码接入

5.1 准备翻译 JSON

在 assets/lang/ 下按语言码各放一份 JSON(示例工程放在 assets/a/):

// assets/lang/zh.json
{
  "localization": "本地化",
  "welcome": "欢迎",
  "greeting": "你好 ##,欢迎来到 ###!",
  "device_language": "设备语言",
  "chinese": "中文",
  "english": "英语",
  "arabic": "阿拉伯语"
}

并在 pubspec.yaml 中声明 assets:

flutter:
  assets:
    - assets/lang/

键名建议全小写下划线风格——库会自动归一化(空格转下划线、转小写),大小写混写也不怕。

5.2 导入并初始化

import 'package:app_local/app_local.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Locales.init(
    localeNames: ['en', 'ar', 'zh'],  // 支持的语言
    localPath: "assets/lang/",        // 翻译文件目录
    phoneLocale: true,                // 首次启动跟随手机语言
  ); // 内部会读取上次保存的语言偏好
  runApp(const MyApp());
}

代码逐段分析:init 都做了什么

  1. 校验 localeNames 非空,规范化翻译目录路径(补末尾 /);
  2. 调 AppLang().getPhoneLanguage() 取设备语言——鸿蒙上这一步走 ArkTS 通道 i18n.System.getSystemLanguage(),真机上返回 zh-Hans,Dart 取第一段得 zh;
  3. phoneLocale: true 时用设备语言初始化(不支持则回退到列表第一个),否则读取持久化偏好;
  4. 全程 try/catch,出错不会让 App 起不来。

5.3 LocaleBuilder 接入 MaterialApp

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return LocaleBuilder(
      builder: (locale) => MaterialApp(
        title: 'Flutter Locales',
        localizationsDelegates: Locales.delegates, // 四个代理一次配齐
        supportedLocales: Locales.supportedLocales,
        locale: locale, // 语言变化时 LocaleBuilder 重建并下发新 locale
        home: HomeScreen(),
      ),
    );
  }
}

Locales.delegates 已合并 Locales.delegate 与 Material / Cupertino / Widgets 三个全局代理,M3 组件的内置文案(日期选择器、对话框按钮等)也会跟着切换。

5.4 三种方式取文本

// ① LocaleText 组件(推荐,最省事)
LocaleText('welcome', style: TextStyle(fontSize: 28))
LocaleText('greeting', params: [Locales.lang.toUpperCase(), 'app_local'])

// ② Locales.string 静态方法(任意位置可用)
Text(Locales.string(context, 'switch_language'))

// ③ BuildContext / String 扩展
Text(context.localeString('about'))
Text('about'.localize(context))

请添加图片描述

代码逐段分析:占位符的规则

"greeting": "你好 ##,欢迎来到 ###!" 中 ## 是第 1 个参数、### 是第 2 个参数(井号个数 = 参数序号)。替换时若 localeParams 传入的值能在翻译表中命中键名,则会先做本地化再注入——比如把 "chinese" 作为参数传入,中文环境下注入的是"中文"而不是"chinese"。剩余未匹配的 # 最后统一清除。

5.5 运行时切换语言

// 任意位置一行调用,整棵组件树即时重建
context.changeLocale('zh');

// 回到"跟随手机语言"
context.changeLocale('auto');

请添加图片描述

切换逻辑在 PreferenceUtils.setLocale:更新 Locales.selectedLocale → 写入偏好 → LocaleBuilder setState 触发 MaterialApp 用新 Locale 重建 → LocalesDelegate.load() 加载对应 JSON。无需重启、无需手动 setState。

注意:切换目标必须是 Locales.init(localeNames: [...]) 里注册过的语言(或 'auto'),否则会打日志忽略这次切换——防止手滑传错语言码导致白屏。

5.6 RTL 与语言元信息

final bool isRtl = Locales.isDirectionRTL(context);
Text(Locales.selectedLocaleRtl ? 'RTL' : 'LTR');

RTL 判断用 intl.Bidi.isRtlLanguage(纯 Dart),阿拉伯语环境下布局自动镜像,无需逐个写 TextDirection.rtl。

请添加图片描述

5.7 实战:语言设置页

把切换、当前态、跟随手机语言整合成一个设置页:

class SettingScreen extends StatelessWidget {
  const SettingScreen({super.key});

  
  Widget build(BuildContext context) {
    final String? current = Locales.currentLocale(context)?.languageCode;
    final Map<String, String> options = {
      'en': Locales.string(context, 'english'),
      'ar': Locales.string(context, 'arabic'),
      'zh': Locales.string(context, 'chinese'),
      'auto': Locales.string(context, 'auto'), // 跟随手机语言
    };

    return Scaffold(
      appBar: AppBar(title: LocaleText('setting')),
      body: ListView(
        children: options.entries.map((entry) => ListTile(
          title: Text(entry.value),
          trailing: current == entry.key
              ? const Icon(Icons.check_circle)
              : null,
          onTap: () => context.changeLocale(entry.key), // 一行切换
        )).toList(),
      ),
    );
  }
}

三点心得:动态色……不对,是三条配置原则——phoneLocale: true 让首启体验国际化、设置页提供 auto 选项让用户随时改主意、选项列表直接从翻译表取文案,新加一门语言只需要新增一个 JSON 和一个语言码。

请添加图片描述


六、运行与验证

Demo Bundle Name:com.abom.app_local_example;设备:华为 TLR-AL00,HarmonyOS 6.1.0.145(API 24),系统语言 zh-CN。打包产物 entry-default-signed.hap(约 118 MB)。

6.1 验证一:安装与启动

hdc install -r entry-default-signed.hap
# [Info]App install path:...entry-default-signed.hap msg:install bundle successfully.

hdc shell aa start -a EntryAbility -b com.abom.app_local_example
# start ability successfully.

启动后即见第一节截图的英语首页。

请添加图片描述

6.2 验证二:插件注册与通道调用日志

hdc shell hilog | grep AppLangPlugin
10-20 23:27:57.005 W A000FF/...Flutter: FlutterEngineCxnRegistry --> Adding plugin: AppLangPlugin
10-20 23:27:57.005 I A00000/...AppLangPlugin: attached to engine, channel [app_lang] registered
10-20 23:27:57.258 D A00000/...AppLangPlugin: onMethodCall: getPhoneLanguage
10-20 23:27:57.277 D A00000/...AppLangPlugin: onMethodCall: getPhoneLanguage

getPhoneLanguage 被调用了两次——一次来自 Locales.init、一次来自 PreferenceUtils.init,都命中鸿蒙原生通道(而非 en-OM 兜底),说明 Platform.isOhos 分支生效。

请添加图片描述

6.3 验证三:设备语言识别

"Runtime state"卡片显示 Device language: zh——真机系统语言为 zh-CN,原生侧返回 zh-Hans 标签、Dart 层取第一段 zh,识别正确。

6.4 验证四:免重启切换与 RTL

真机上依次点击底部 Chinese 与 Arabic 按钮:

  • 点击 Chinese:整页瞬间切为中文(标题"本地化"、问候语"你好 ZH,欢迎来到 app_local!"),过程无重启、无闪屏;
  • 点击 Arabic:页面整体镜像为从右向左排版,AppBar 标题"اللغة"靠右,按钮组反向排列——RTL 生效。

6.5 验证五:语言偏好持久化(重要发现)

aa force-stop 后重新启动,App 回到了默认的英语——即当前示例工程下语言选择没有跨重启记忆。

原因:语言偏好经 shared_preferences 持久化,而示例工程的依赖树里只有 shared_preferences_android/foundation/linux/web/windows 等实现,没有鸿蒙侧的 shared_preferences_ohos 平台实现,SharedPreferences.getInstance() 在鸿蒙上拿不到存储。库对此早有兜底设计(PreferenceUtils 里 try/catch + _runtimeLocale 运行时记忆),所以切换功能本身完全不受影响,只是重启后不记得上次的选择。

解决方案见 FAQ Q3:引入鸿蒙社区的 shared_preferences_ohos 实现后即可恢复持久化。

实测结论表

#验证点结果
1HAP 真机安装成功(compatibleSdkVersion 6.1.1(24))通过
2插件注册与 app_lang 通道挂载通过
3getPhoneLanguage 走鸿蒙原生通道(两次调用)通过
4设备语言识别 zh-CN → zh通过
5运行时切换 EN → ZH 免重启即时生效通过
6阿拉伯语 RTL 镜像排版通过
7占位符参数注入通过
8语言偏好跨重启持久化(当前示例)❌ 未通过(缺 shared_preferences_ohos,见 FAQ Q3)
9全程无需申请任何敏感权限通过

七、工作原理

调用链路

main()
  └─ Locales.init(localeNames, localPath, phoneLocale)
        ├─ AppLang().getPhoneLanguage()
        │     └─ MethodChannel('app_lang') ──▶ ArkTS AppLangPlugin
        │           └─ i18n.System.getSystemLanguage()  // 鸿蒙
        │              (Android: Locale.getDefault() / iOS: preferredLanguages)
        ├─ PreferenceUtils.init()(读偏好 + 设备语言)
        └─ selectedLocale = 偏好 ?? 手机语言 ?? 列表第一项

runApp()
  └─ LocaleBuilder(StatefulWidget,持有当前 Locale)
        └─ LocaleNotifier(InheritedWidget)
              └─ MaterialApp(locale: ...)
                    └─ LocalesDelegate.load() → rootBundle 读 JSON → Locales 实例

context.changeLocale('zh')
  └─ LocaleNotifier.of(context).change('zh')
        └─ _LocaleBuilderState.setState()
              └─ MaterialApp 重建 → 全部文案即时切换

代码逐段分析:Platform.isOhos 分支——适配中最关键的坑

Dart 侧方法通道实现(app_lang_method_channel.dart)原本只在 Android/iOS/macOS 上发起通道调用:

if (Platform.isAndroid || Platform.isIOS || Platform.isMacOS) {
  final version = await methodChannel.invokeMethod<String>('getPhoneLanguage');
  return version;
}
return "en-OM";

如果只写 ArkTS 插件而不改这段 Dart,鸿蒙上原生通道永远不会被调用,设备语言恒为兜底值 en-OM。适配版补上了 Platform.isOhos 分支(Flutter-OHOS 引擎提供的平台判断):

if (Platform.isAndroid || Platform.isIOS || Platform.isMacOS || Platform.isOhos) {
  final version = await methodChannel.invokeMethod<String>('getPhoneLanguage');
  return version;
}

这是所有 Flutter 鸿蒙化插件适配中都要警惕的一类问题——平台判断白名单里没有 ohos,原生写得再好也是空转。

OHOS 插件实现

ArkTS 侧插件(ohos/src/main/ets/components/plugin/AppLangPlugin.ets)核心逻辑:

const CHANNEL_NAME: string = 'app_lang';
const METHOD_GET_PHONE_LANGUAGE: string = 'getPhoneLanguage';

export default class AppLangPlugin implements FlutterPlugin, MethodCallHandler {
  private channel: MethodChannel | null = null;

  onAttachedToEngine(binding: FlutterPluginBinding): void {
    this.channel = new MethodChannel(binding.getBinaryMessenger(), CHANNEL_NAME);
    this.channel.setMethodCallHandler(this);
    hilog.info(DOMAIN, TAG,
      'attached to engine, channel [%{public}s] registered', CHANNEL_NAME);
  }

  onDetachedFromEngine(binding: FlutterPluginBinding): void {
    // 置空 handler,避免引擎销毁后插件实例仍被通道持有而无法释放
    this.channel?.setMethodCallHandler(null);
    this.channel = null;
  }

  private getPhoneLanguage(): string {
    const language: string = i18n.System.getSystemLanguage();
    if (language != null && language.length > 0) {
      return language; // 如 'zh-Hans'、'en-Latn-US'
    }
    return 'en'; // 兜底,与 Dart 层默认语义一致
  }
}

鸿蒙技术点:i18n.System.getSystemLanguage 的选型

OpenHarmony 没有与 Android Locale.getDefault() 完全对等的 API,最贴近"手机语言"语义的是 i18n.System.getSystemLanguage()(返回系统语言标签如 zh-Hans);备选的 i18n.System.getSystemLocale() 返回带地区的完整区域(zh-Hans-CN),语义偏"区域"而非"语言"。由于 Dart 层只取第一段,两者对上层等价,故选语义更贴切的前者。该接口无需申请任何权限。

插件的注册同样由工具链完成:pubspec.yaml 中的

flutter:
  plugin:
    platforms:
      ohos:
        pluginClass: AppLangPlugin

声明会让 ohos 版 Flutter 工具链生成 GeneratedPluginRegistrant,在 EntryAbility.configureFlutterEngine 中自动注册。

代码逐段分析:LocaleNotifier 与 InheritedWidget

LocaleBuilder 持有当前 Locale 并包一层 LocaleNotifier(InheritedWidget)。切换语言时 changeLocale() 走 setState 更新 Locale → 依赖该 InheritedWidget 的子树(整个 MaterialApp)重建 → LocalizationsDelegate.load() 重新加载对应语言的 JSON。updateShouldNotify 恒返回 true,保证任何语言变化都通知到位。这套机制纯 Dart 实现,鸿蒙与其它平台行为完全一致。


八、常见问题

Q1:app_local 和 intl/arb 官方方案怎么选?

官方 intl + .arb 方案功能全(复数、日期、货币格式化)但链路重(代码生成、重建);app_local 胜在极简——JSON 即翻译、运行时切换零成本,适合文案为主的中小型应用。两者可共存:文案用 app_local,日期数字格式化仍用 intl。

Q2:切换语言后为什么有些文案没变?

LocaleText / Locales.string 都会即时响应;但在 Locales.init 之前缓存了文案、或把翻译结果存进了状态变量的地方需要自查。另外新加的语言必须写进 Locales.init(localeNames: [...]),热重载不会重跑 main(),要整包重启才能注册新语言。

Q3:鸿蒙上重启后语言回到了默认值?

当前示例的依赖树里没有 shared_preferences_ohos(只有 Android/iOS/桌面/Web 实现),偏好写入在鸿蒙上不生效。引入鸿蒙社区 flutter_packages 仓库中的 shared_preferences_ohos 平台实现(并在 dependency_overrides 中挂接)后即可恢复持久化。在此之前,库的兜底设计保证运行时切换完全正常,只是不记忆。

Q4:getPhoneLanguage 返回 en-OM 是怎么回事?

en-OM 是 Dart 层的兜底值,出现它说明通道没走通。在鸿蒙上重点检查两点:① 依赖必须是本鸿蒙适配版 TAG(内含 Platform.isOhos 分支修复);② GeneratedPluginRegistrant 中已注册 AppLangPlugin(可 hdc shell hilog | grep AppLangPlugin 验证)。

Q5:真机安装报"此应用暂不支持在当前设备安装"?

检查 build-profile.json5 的 compatibleSdkVersion,必须不高于目标设备 API(API 24 设备对应 6.1.1(24),保留括号旧格式)。与插件无关。

Q6:通道名为什么叫 app_lang 而不是 app_local?

app_lang 是原库定下的原生通道契约(对应原生插件类 AppLangPlugin),Dart 包名才是 app_local。鸿蒙适配版严格沿用 app_lang,与 Android/iOS/macOS 实现保持一致。


九、结语

回顾一下:git TAG 引入依赖 → assets/lang/ 放 JSON → Locales.init() 一行初始化 → LocaleBuilder 包住 MaterialApp → LocaleText / context.localeString 取文案 / context.changeLocale 切语言。

核心结论:

  • 鸿蒙上设备语言识别、运行时切换、RTL 排版全部实测通过,getPhoneLanguage 走 i18n.System.getSystemLanguage(),与 Android/iOS 语义对齐,零权限;
  • 适配中最关键的一处修改是 Dart 层补上 Platform.isOhos 平台分支——没有它,原生通道在鸿蒙上永远不会被调用;
  • 语言偏好的跨重启持久化依赖 shared_preferences 的鸿蒙实现,当前示例未引入 shared_preferences_ohos 时切换功能不受影响,但重启后回到默认语言(已如实记录在实测结论表);
  • 已在华为真机(HarmonyOS 6.1.0.145 / API 24)完整实测,除持久化一项待补平台实现外全部通过。

欢迎提 Issue / PR 共建。


相关链接

  • 鸿蒙适配版仓库:https://atomgit.com/CPF-Flutter/fluttertpc_app_local(TAG 1.1.3-ohos-1.0.0-beta.1)
  • 原库:https://github.com/abom-me/app_local
  • OpenHarmony i18n 文档(@ohos.i18n):https://developer.huawei.com/consumer/cn/doc/
  • 鸿蒙社区 Flutter 插件仓库(含 shared_preferences_ohos):https://gitee.com/openharmony-sig/flutter_packages
  • Flutter 鸿蒙化开发环境:https://atomgit.com/oh-flutter/flutter_flutter

附:app_local 核心能力对照表

能力维度实现方式鸿蒙表现跨平台一致性
设备语言识别原生通道 getPhoneLanguage✅ i18n.System.getSystemLanguage()五端语义一致
Platform.isOhos 通道分支Dart 层(适配新增)✅ 已修复各端一致
JSON 翻译文件加载纯 Dart(rootBundle)✅ 完整可用五端一致
运行时切换(免重启)纯 Dart(InheritedWidget)✅ 完整可用五端一致
LocaleText / 扩展 / Locales.string纯 Dart✅ 完整可用五端一致
占位符参数 ## / ###纯 Dart✅ 完整可用五端一致
RTL 检测与镜像纯 Dart(intl.Bidi)✅ 完整可用五端一致
语言偏好持久化shared_preferences⚠️ 需引入 shared_preferences_ohosAndroid/iOS 开箱即用
权限要求不访问敏感能力零权限各端一致
Logo

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

更多推荐