飞道的博客

Flutter Intl的使用

714人阅读  评论(0)

前言

Intl是flutter中用于支持多语言操作的一个库,方便开发者通过arb文件来进行本地化操作,省去一些既定步骤的操作。

Flutter Intl则是针对Intl库开发的插件,主要功能为自动生成代码,简化前置操作,让开发者能更专注arb的编写;

Flutter Intl插件目前有VSCode版IDEA/Android Studio版,使用步骤大致相同。

arb文件全称Application Resource Bundle(abbr. ARB)是一种本地化资源格式,遵循json规范,arb文件可以提供给翻译人员翻译完毕后,再另行导入。

Intl使用的是l10n标准(l10n即localization的缩写),库的目前版本为0.17.0,操作步骤可能与之前版本有所差异,注意鉴别。

本文就VSCode环境中演示一下Flutter Intl插件的使用,Flutter SDK版本为3.0.3,Dart版本为2.17.5。

插件的启用

安装插件

在扩展应用市场搜索"Intl",选择“Flutter Intl"安装:

启用插件

安装完成后,Ctrl+Shift+P打开包命令窗口,选择“Flutter Intl:初始化”:

自动生成相关文件

插件会在flutter工程目录下自动生成以下目录及文件:

--lib
  --l10n
    --intl_en.arb
  --generated
  	--l10n.dart
  	--intl
      --messages_all.dart
   	  --messages_en.dart

intl_en.arb即对应的英文翻译文档;
l10n.dart中自动生成了本地化相关的类,类名默认为S
messages_en.dart映射了intl_en.arb的对应字段;
messages_all.dart编写了管理messages_en.dart以及其他对应地区的messages_xx.dart的工厂类;

可以简单把调用链理解为:

l10n.dart <--messages_all.dart <--message_xx.dart <--intl_xx.arb

除了生成对应文件以外,插件也会在pubspec.yaml文件末尾自动添加intl的启用标识:

flutter_intl:
  enabled: true

本地化配置

添加依赖

本地化的依赖需要自行在pubspec.yaml中添加:

dependencies:
  flutter_localizations:
    sdk: flutter 

添加在dependencies节点或dev_dependencies节点视情况而定,dependencies意为项目依赖,dev_dependencies意为开发环境依赖;
这里依照官方的Flutter本地化应用介绍添加在dependencies节点下;

Intl库的依赖在插件的作用下已经添加到pubspec.lock文件中:

  intl:
    dependency: transitive
    description:
      name: intl
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "0.17.0"

但考虑到pubspec.lock官方不建议作为项目提交文件,因此在pubspec.yaml文件再进行直接依赖也是极好的,最终依赖是这样的:

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: ^0.17.0

(添加依赖后理应执行pub get packages命令远程导入相关库,不过大多智能IDE都自行执行了这一过程)

添加中文支持

Ctrl+Shift+P打开包命令,选择"Add Locale":

填入对应区域代码"zh":

执行后会自动生成intl_zh.arbmessages_zh.dart文件,目录结构变为:

--lib
  --l10n
    --intl_en.arb
    --intl_zh.arb
  --generated
  	--l10n.dart
  	--intl
      --messages_all.dart
   	  --messages_en.dart
   	  --messages_zh.dart
arb文件操作

intl_en.arb文件中添加需要映射的字段,如下:

{
   
    "home": "Home",
    "about": "About",
    "greet": "Hi, {name}",
    "askChoice": "There are two choices:{one}? or {two}",
    "@askChoice": {
   
        "description": "Give someone two choice and wait for selection",
        "placeHolder": {
   
            "one": {
   },
            "two": {
   }
        }
    },
    "customDateFormat": "current date: {date}",
    "@customDateFormat": {
   
        "placeholders": {
   
            "date": {
   
                "type": "DateTime",
                "format": "EEE, MM/dd/yyyy",
                "isCustomDateFormat": "true"
            }
        }
    }
}

 

并在intl_zh.arb添加对应的字段,如下:

{
   
    "home": "首页",
    "about": "关于",
    "greet": "你好, {name}",
    "askChoice": "这里有两个选择:{one}?或是 {two}",
    "@askChoice": {
   
        "description": "给某人两个选择,然后等待他的选择",
        "placeHolder": {
   
            "one": {
   },
            "two": {
   }
        }
    },
    "customDateFormat": "当前日期: {date}",
    "@customDateFormat": {
   
        "placeholders": {
   
            "date": {
   
                "type": "DateTime",
                "format": "EEE, MM/dd/yyyy",
                "isCustomDateFormat": "true"
            }
        }
    }
}

 

普通的字段就相当于【资源引用符】,而以"@”符号开头的字段代表着规则与注释;
每次更新intl_xx.arb文件后,对应的messages_xx.dart以及l10n.dart中的S类就会自动更新相应的字段方法,也因此最终调用S类的方法即可获取映射字段;

本地化入口配置

要在程序入口或者说UI顶层,一般是MaterialAppWidgetsApp的入口处配置本地化的字段;
localizationsDelegatessupportedLocales两个字段;
前者为代理,可以理解处理字段映射的委托,后者为区域,即支持的区域代码列表;

上文提到过l10n.dart中生成的默认本地化相关类S,就是在这里使用的:

return MaterialApp(
      localizationsDelegates: const [
        S.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: S.delegate.supportedLocales,
      //...其他代码
}

关于ios的本地化配置,同样可以参考官方文档的Flutter本地化应用iOS 本地化:更新 iOS app bundle一小节的介绍。

使用

不同语言环境的输出

最终调用S.current或S.of(context)的对应arb字段即可:

print(S.current.about);
print(S.current.greet("老哥"));
print(S.current.askChoice("确定", "取消"));
print(S.current.customDateFormat(DateTime.now()));

中文环境下输出:

关于
你好, 老哥
这里有两个选择:确定?或是 取消
当前日期: 周五, 07/15/2022

英文环境下输出:

About
Hi, 老哥
There are two choices:确定? or 取消
current date: Fri, 07/15/2022

当然,以上输出中的“确定”“取消”等字段最好也在arb文件中提前定义。

以上例举的均是对应着Intl库中message方法的使用,更多其他用法可以参考Intl API

手动指定语言环境

程序会根据系统的设置选择Locale,也可以自行指定;
比如可建立全局类,指定Intl的defaultLocale属性来改变语言环境:

class Application {
   
  static Future init() async {
   
    Intl.defaultLocale = 'en';
  }
}

然后在程序入口处包裹:

Application.init().then((value) => runApp(MyApp()));

Intl.defaultLocale可能在某些平台下无法生效,可以尝试localeResolutionCallback强行指定默认的语言环境(这种方法相较稳定一些);

return MaterialApp(
      localeResolutionCallback:
          (Locale? locale, Iterable<Locale> supportedLocales) {
   
        var result = supportedLocales
            .where((element) => element.languageCode == locale?.languageCode);
        if (result.isNotEmpty) {
   
          print(locale?.languageCode);
          // return locale;
          return Locale('en');
        }
        return Locale('en');
      },
      //...其他
}

转载:https://blog.csdn.net/ifmylove2011/article/details/125797598
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场