IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> flutter解决方案:支持动态多语言资源 -> 正文阅读

[移动开发]flutter解决方案:支持动态多语言资源

通常对于一个flutter组件来说,其多语言支持有两种情况:一是仅支持中文不支持多语言,二是多语言仅支持英文。当涉及到组件需要提供给海外业务使用时,就不能满足需求了,但我们在编码时就在组件提供所有语言资源是不现实的,理想情况是像原生一样支持在打包时通过添加多语言资源文件的方式,在不修改组件代码的前提下增加多更多语种的支持。本文提供了一种实现方案,介绍如下。

flutter宿主添加多语言资源

演示动态添加多语言资源

在flutter宿主module工程的main.dart中:

void main() {
  // 方式一:逐个添加多语言资源
  CommonIntl.add(Locale('ja'), XXXResourceJA());   //XXXResource是具体组件的资源文件,下节会有介绍
  CommonIntl.add(Locale('ja'), YYYResourceJA());
  CommonIntl.add(Locale('ja'), ZZZResourceJA());
  CommonIntl.add(Locale('tv'), XXXResourceTV());
  CommonIntl.add(Locale('tv'), YYYResourceTV());
  CommonIntl.add(Locale('tv'), ZZZResourceTV());

  // 方式二:批量添加某种语言的资源文件
  CommonIntl.addAll(Locale('ja'), [
    XXXResourceJA(),
    YYYResourceJA(),
    ZZZResourceJA(),
  ]);
  CommonIntl.addAll(Locale('tv'), [
    XXXResourceTV(),
    YYYResourceTV(),
    ZZZResourceTV(),
  ]);

  ....
  
  runApp(MyApp());
}

MaterialApp中注册对应的区域及组件多语言代理

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      supportedLocales: [
        // 假设我们原本组件中仅支持zh、en,ja和tv是动态添加的
        const Locale('zh'),
        const Locale('en'),
        const Locale('ja'),
        const Locale('tv'),
      ],
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        FallbackCupertinoLocalisationsDelegate.delegate,
        XXXLocalizationDelegate.delegate,
      ],
      home: HomePage(
        ......
      ),
    );
  }

让你的flutter组件支持动态多语言

由于flutter的intl库及相应插件生成的多语言代码只适用于单体APP,当存在多个有多语言资源的flutter组件时存在资源相互覆盖的问题,因此推荐多语言采用flutter官方的实现方式:

1. 定义多语言资源

第一步:定义多语言资源类:

abstract class XXXResource {
  String get app_ok;

  String get app_cancel;

  String get app_empty;

  String get app_retry_click;

  ......
}

第二步:实现各个语言的具体资源:

  • 提供英文资源:
class XXXResourceEn implements XXXResource {
  @override
  String get app_about => 'About';

  @override
  String get app_back_tip => 'Exit?';

  @override
  String get app_cancel => 'cancel';

  @override
  String get app_retry_click => 'try again';

  ....
}
  • 提供中文资源:
class XXXResourceZh implements XXXResource {
  @override
  String get app_about => '关于';

  @override
  String get app_back_tip => '确定要退出应用?';

  @override
  String get app_cancel => '取消';

  @override
  String get app_retry_click => '点击重试';

  ......
}

2. 实现多语言加载接口

///
/// 组件多语言加载器
///
class XXXResourceLoader {
  final Locale locale;
  final Map<String, XXXResource> _resourceMap = {'en': XXXResourceEn(), 'zh': XXXResourceZh()};

  XXXResourceLoader(this.locale);

  XXXResource get localizedResource {
    // 在这里增加以下两行,使组件支持动态资源文件
    final cr = CommonIntl.findIntlResourceOfType<XXXResource>(locale);
    if (cr != null) return cr;
    // 常规的多语言资源加载
    return _resourceMap[locale.languageCode] ?? _resourceMap['en'];
  }

  /// 获取[XXXResourceLoader]实例
  static XXXResourceLoader of(BuildContext context) => Localizations.of(context, XXXResourceLoader);

  /// 获取[XXXResource]资源
  static XXXResource i10n(BuildContext context) => of(context).localizedResource;
}

///
/// 组件多语言适配代理
///
class XXXLocalizationDelegate extends LocalizationsDelegate<XXXResourceLoader>{

  @override
  bool isSupported(Locale locale) =>true;

  @override
  Future<XXXResourceLoader> load(Locale locale) {
    Log.d(runtimeType.toString(),'load: locale = $locale, ${locale.countryCode}, ${locale.languageCode}');
    return SynchronousFuture<XXXResourceLoader>(XXXResourceLoader(locale));
  }

  @override
  bool shouldReload(LocalizationsDelegate<XXXResourceLoader> old) => false;

  /// 需在app入口注册
  static XXXLocalizationDelegate delegate = XXXLocalizationDelegate();
}

原理简介

上述动态导入和加载动态资源文件的过程主要涉及到两个接口:CommonIntl.add(Locale locale, dynamic resource)T CommonIntl.findIntlResourceOfType<T>(Locale locale)。其实原理也比较简单,直接看下源码:

final Map<Locale, Map<Type, dynamic>> _additionalIntls = {};

class CommonIntl {
  static T findIntlResourceOfType<T>(Locale locale)  {
    assert(locale != null);
    final res = _additionalIntls[locale];
    if (res != null && res.isNotEmpty) {
      for (var entry in res.entries) {
        if (entry.value is T) {
          return entry.value;
        }
      }
    }
    return null;
  }

  static T findIntlResourceOfExactType<T>(Locale locale)  {
    assert(locale != null);
    final res = _additionalIntls[locale];
    if (res != null && res.isNotEmpty) {
      for (var entry in res.entries) {
        if (entry.key == T) {
          return entry.value;
        }
      }
    }
    return null;
  }

  static Iterable<T> findIntlResourcesOfType<T>(Locale locale) sync* {
    assert(locale != null);
    final res = _additionalIntls[locale];
    if (res != null && res.isNotEmpty) {
      for (var entry in res.entries) {
        if (entry.value is T) {
          yield entry.value;
        }
      }
    }
  }

  static void addAll(Locale locale, List intlResources) {
    assert(locale != null);
    var res = _additionalIntls[locale];
    if (res == null) {
      res = {};
      _additionalIntls[locale] = res;
    }
    for (var intl in intlResources) {
      res[intl.runtimeType] = intl;
    }
  }

  static void add(Locale locale, intlResource) {
    assert(locale != null);
    var res = _additionalIntls[locale];
    if (res == null) {
      res = {};
      _additionalIntls[locale] = res;
    }
    res[intlResource.runtimeType] = intlResource;
  }
}

其实就是用一个map来保存和获取对应语言区域的资源文件,比较简单就不赘述了。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 18:36:39  更:2022-03-30 18:37:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年9日历 -2024/9/20 14:57:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码