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的异常。
参考: