98404c79be942e27703e9f3609a6c38a
Flutter 组件国际化(五):Intl详解

这篇文章介绍“Intl”依赖包和“intl_translation”依赖包。

Intl依赖包是什么

在《 Flutter 组件国际化(一):整体设计 》这篇文章中,我们提到过要挖掘国际化场景。而“Intl”依赖包解决了一些通用的国际化场景,其中包括:

  • 文本国际化
    Intl的message方法会根据locale返回对应语言的文本。

// 其中"Hello $name!"是需要国际化的文本,同时定义$name为动态插值。
// 根据locale返回对应的文本,对应的文本会定义在arb资源配置文件中。
greetingMessage(name) => Intl.message(
      // 需要国际化的文本,可以进行参数的插值。
      'Hello $name!',
      // 告诉Intl函数的命名,所以必须是全局唯一。
      // 可以<className>_<methodName>形式定义。
      name: 'greetingMessage',
      // 插值的值,会替换$name。
      args: [name],
      //  文本的描述,给翻译人员查看的这个资源的意义。
      desc: 'Greet the user as they first open the application',
      // 插值例子
      examples: const {'name': 'Emily'}, 
      // 指定返回什么语言环境的资源
      locale: locale.toString()
);

  • 复数国际化
    Intl的plural方法会根据不同语言的单复数表现不同需要返回不同的结果。其规则可以参考Plural Rules

// 比如乌克兰(英国)的复数就分下面一些情况:
// one(单数的情况): 1, 21, 31, 41, 51, 61...
// few(几个的情况): 2-4, 22-24, 32-34...
// other(一般复数的情况): 0, 5-20, 25-30, 35-40...; 1.31, 2.31, 5.31...
remainingEmailsMessage(int howMany, String userName) =>
    Intl.plural(
      // Intl通过howMany来判断是以下哪种情况。
      howMany,
      // zero表示0的情况
      zero: 'There are no emails left for $userName.',
      // one表示单数的情况
      one: 'There is $howMany email left for $userName.',
      // other表示一般复数的情况
      other: 'There are $howMany emails left for $userName.',
      // 告诉Intl函数的命名,所以必须是全局唯一。
      // 可以<className>_<methodName>形式定义。
      name: 'remainingEmailsMessage',
      // 插值的值。
      args: [howMany, userName],
      //  文本的描述,给翻译人员查看的这个资源的意义。
      desc: 'How many emails remain after archiving.',
      // 插值例子
      examples: const {'howMany': 42, 'userName': 'Fred'}, 
      // 指定返回什么语言环境的资源
      locale: locale.toString()
);

  • 性别国际化
    Intl的gender方法根据性别male、female,other三种情况,返回不同的结果。

// 可以看到male、female、other三种情况,英语的表达都是有区别的。
notOnlineMessage(String userName, String userGender) =>
    Intl.gender(
      userGender,
      male: '$userName is unavailable because he is not online.',
      female: '$userName is unavailable because she is not online.',
      other: '$userName is unavailable because they are not online',
      name: 'notOnlineMessage',
      args: [userName, userGender],
      desc: 'The user is not available to hangout.',
      examples: const {{'userGender': 'male', 'userName': 'Fred'},
          {'userGender': 'female', 'userName' : 'Alice'}}, 
      // 指定返回什么语言环境的资源
      locale: locale.toString()
);

  • 日期/数字格式化和解析
    Intl定义了国际化的DateFormat,直接根据locale能返回不同的表示。

  DateFormat.yMMMMEEEEd().format(aDateTime);
    ==> 'Wednesday, January 10, 2012'
  DateFormat('EEEEE', 'en_US').format(aDateTime);
    ==> 'Wednesday'
  DateFormat('EEEEE', 'ln').format(aDateTime);
    ==> 'mokɔlɔ mwa mísáto'

  • 双向排版文本
    Intl的BidiFormatter定义了处理双向文本的功能。

这里对Intl依赖包的功能做了一些理解性的介绍,详细用法参阅官方文档

intl_translation依赖包是什么

“intl_translation“依赖包主要包含一些命令行工具。通过命令能解析Dart文件,匹配包含 "intl.Intl.* 的Dart代码视为需要提取的国际化资源,转化到arb文件中,提供给翻译人员翻译成多个语言版本的arb资源文件。同时还能把翻译好的arb资源文件转化成Dart文件给“Intl”使用。就这样完成了类似Android的xml资源配置多语言的功能,优化了国际化开发流程。

arb文件是什么

arb文件全称Application Resource Bundle(abbr. ARB)是一种本地化资源格式,使用arb文件作为资源配置文件(类似Android的xml)可以提供给翻译人员翻译。

如何使用“Intl”包和“intl_translation”包

首先需要添加依赖:


//添加依赖到pubspec.yaml文件中:
dependencies:
  intl: ^0.16.0
dev_dependencies:
  intl_translation: ^0.17.9

然后自定义一个LocalizationsDelegate代理。其中有关LocalizationsDelegate的用法参考《Flutter 组件国际化(三):Localizations详解》。


import 'dart:ui';

import 'package:flutter/widgets.dart';
import 'package:intl/intl.dart' as intl;

//通过intl_translation工具从arb文件生成的代码,为了根据不同locale分发对应文本
import 'l10n/messages_all.dart';

class CustomLocalizationsDelegate
implements LocalizationsDelegate {
static const LocalizationsDelegate delegate =
CustomLocalizationsDelegate();
const CustomLocalizationsDelegate();

@override
bool isSupported(Locale locale) {
return true;
}

@override
Future load(Locale locale) {
return CustomLocalizations.load(locale);

top Created with Sketch.