Flutter International 国际化,Localization 本地化, 使用Intl
本文最后更新于 2019年11月1日 晚上
新建项目,得到一个示例工程。本例中使用intl包来管理文字资源。
项目地址: https://github.com/RustFisher/localization_demo
步骤:
- 添加依赖项 - intl
 - 创建文字资源文件
 - 生成
arb文件- 新增和修改
arb文件 
 - 新增和修改
 - 根据
arb生成dart文件 - 创建localization代理,新建一个类继承
LocalizationsDelegate,和文字资源文件联系起来 MaterialApp中添加本地化代理和语言类型- 使用文字资源
 
添加依赖项
pubspec.yaml添加依赖项flutter_localizations,然后运行一下flutter packages get。1
2
3
4
5
6
7
8dependencies:
  flutter:
    sdk: flutter
# 添加下面的依赖项
  flutter_localizations:
    sdk: flutter
  intl: 0.15.6
  intl_translation: 0.16.7
编辑dart文件
新建app_strings.dart文件。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44import 'dart:async';
import 'package:intl/intl.dart';
import 'package:flutter/widgets.dart';
class AppStrings {
  AppStrings(Locale locale) : _localeName = locale.toString();
  final String _localeName;
  static Future<AppStrings> load(Locale locale) {
    return initializeMessages(locale.toString())
        .then((Object _) {
      return new AppStrings(locale);
    });
  }
  static AppStrings of(BuildContext context) {
    return Localizations.of<AppStrings>(context, AppStrings);
  }
  String title() {
    return Intl.message(
      'Localization Demo',
      name: 'title',
      desc: '应用标题',
      locale: _localeName,
    );
  }
  String click() => Intl.message(
    'Click',
    name: 'click',
    desc: '点击',
    locale: _localeName,
  );
  String helloFromDemo() => Intl.message(
    'Hello~',
    name: 'helloFromDemo',
    desc: '一句问候',
    locale: _localeName,
  );
}
此时initializeMessages方法会显示警告,暂时不用管,生成arb文件后再添加引用。
生成arb文件
进入项目目录,运行intl的命令。1
2/e/ws/localization_demo
$ flutter pub pub run intl_translation:extract_to_arb --output-dir=lib/l10n lib/app_strings.dart
生成l10n/intl_messages.arb,内容如下。可以看出是JSON格式的文本。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21{
  "@@last_modified": "2018-07-15T22:13:19.218221",
  "title": "Localization Demo",
  "@title": {
    "description": "应用标题",
    "type": "text",
    "placeholders": {}
  },
  "click": "Click",
  "@click": {
    "description": "点击",
    "type": "text",
    "placeholders": {}
  },
  "helloFromDemo": "Hello~",
  "@helloFromDemo": {
    "description": "一句问候",
    "type": "text",
    "placeholders": {}
  }
}
新增和修改arb文件
前面生成了l10n/intl_messages.arb,我们可以把它当成模板。复制粘贴一下,同目录下得到intl_en.arb和intl_zh.arb。文件名规则可以自己定。
以intl_zh.arb为例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21{
  "@@last_modified": "2018-07-15T22:13:19.218221",
  "title": "国际化示例App",
  "@title": {
    "description": "应用标题",
    "type": "text",
    "placeholders": {}
  },
  "click": "点击",
  "@click": {
    "description": "点击",
    "type": "text",
    "placeholders": {}
  },
  "helloFromDemo": "你好呀~",
  "@helloFromDemo": {
    "description": "一句问候",
    "type": "text",
    "placeholders": {}
  }
}
这里也可以把intl_messages.arb删掉。本例保留这个文件。
根据arb生成dart文件
1  |  | 
暂时无视警告。
此时在app_strings.dart中添加对l10n/intl_messages.arb的引用。1
import 'package:localization_demo/l10n/messages_all.dart';
警告消失~

更新了arb文件后,需要重新生成dart文件。
创建localization代理
创建localizations_delegate.dart。新建AppLocalizationsDelegate类继承LocalizationsDelegate,复写方法。
泛型指定为前面的AppStrings。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:localization_demo/app_strings.dart';
class AppLocalizationsDelegate extends LocalizationsDelegate<AppStrings> {
  @override
  Future<AppStrings> load(Locale locale) {
    return AppStrings.load(locale);
  }
  @override
  bool isSupported(Locale locale) =>
      ['zh', 'en'].contains(locale.languageCode); // 支持的类型要包含App中注册的类型
  @override
  bool shouldReload(AppLocalizationsDelegate old) => false;
}
MaterialApp中添加本地化代理和语言类型
1  |  | 
使用文字资源
获取到AppStrings的实例。1
2AppStrings appStrings = AppStrings.of(context);
print(appStrings); // logcat:  I/flutter ( 7478): Instance of 'AppStrings'

注意,在MaterialApp中使用文字资源时,因为context的关系,要使用onGenerateTitle。1
2
3onGenerateTitle: (context) {
  return AppStrings.of(context).title();
},
支持语言的类型
代理isSupported方法中的语言类型最好是和App中supportedLocales的一致1
2
3
4
5
6
7
8
9  @override
  bool isSupported(Locale locale) =>
      ['zh', 'en'].contains(locale.languageCode);
// App中`supportedLocales`
      supportedLocales: [
        const Locale('en', 'US'), // English
        const Locale('zh', ''),
      ],
否则可能出现获取不到AppStrings的异常。
参考: