鉴于Flutter高性能渲染和跨平台的优点,闪点清单在移动端APP上,使用了完整的Flutter框架来开发。既然是完整APP,架构搭建彻底不受历史Native APP的影响,没有历史包袱的沉淀,设计也能更灵活和健壮。markdown
国际化语言的支持,是不少APP都有的一个强需求,APP不管大小,只要还不想放弃国外的客户,通常就须要支持国际化。 架构
Flutter官方方案提供了国际化的基础支持,如Flutter内置组件的国际化、语言代理、Widget使用语言包、语言设置回调等,并支持自定义第三方类来扩展,能够参考Flutter国际化文档。 官方支持代码示例:app
class DemoLocalizations {
DemoLocalizations(this.locale);
final Locale locale;
static DemoLocalizations of(BuildContext context) {
return Localizations.of<DemoLocalizations>(context, DemoLocalizations);
}
static Map<String, Map<String, String>> _localizedValues = {
'en': {
'title': 'Hello World',
},
'es': {
'title': 'Hola Mundo',
},
};
String get title {
return _localizedValues[locale.languageCode]['title'];
}
}
复制代码
官方的支持有几个缺陷:框架
鉴于Flutter官方支持的缺陷,咱们调研了不少第三方库,最终发现了i18n,并在此基础上、结合Flutter官方支持和自身封装,实现了更灵活易用的方案。ide
i18n使用yaml格式来定义语言包,同时提供构建脚本一键生成Dart语言包Class。以下:函数
lib/messages.i18n.yaml
button:
save: Save
load: Load
users:
welcome(String name): "Hello $name!"
logout: Logout
复制代码
该配置会生成几个Class:Messages、ButtonMessages、UserMessages,生成后的Dart文件使用方式以下:工具
Messages m = Messages();
debugPrint(m.users.logout);
debugPrint(m.users.welcome('World'));
复制代码
生成的Dart文件预览(开发时无需关心):性能
class Messages {
const Messages();
ButtonMessages get button => ButtonExampleMessages(this);
UsersMessages get users => UsersExampleMessages(this);
}
class ButtonMessages {
final Messages _parent;
const ButtonMessages(this._parent);
String get save => "Save";
String get load => "Load";
}
class UsersMessages {
final Messages _parent;
const UsersMessages(this._parent);
String get logout => "Logout";
String welcome(String name) => "Hello $name!";
}
复制代码
下面讲解一些进阶用法。优化
i18n支持函数定义,并支持传参,如上述的welcome
函数:ui
debugPrint(m.users.welcome('World'));
复制代码
参数定义基本没有限制,能够随意定义参数个数和类型。
i18n支持了一些内置函数,用于作不一样语言解析的体验优化,如:plural、cardinal、ordinal。具体规则和使用,能够参考这里:cldr.unicode.org/index/cldr-…
Dart字符串模板是很是强大的,而在i18n中,你可使用字符串模板(这点很是赞),如:
count(int cnt): "You have created $cnt ${_plural(cnt, one:'invoice', many:'invoices')}."
复制代码
i18n依然依赖了Dart官方提供的builder_runner工具,来从yaml文件生成Dart文件,使用方式: flutter pub run build_runner build
。
前置编译后,每一个语言包会生成N个Class(语言包的每个分类或组合会生成一个Class文件),而后会生成一个根Class,咱们能够直接使用根Class(固然也可使用任何一个分类层级的Class)。
好比两个语言包文件: AppMessages.i18n.yaml
和AppMessages_en.i18n.yaml
(未加语言后缀的,会认为是默认语言包,所以AppMessages.i18n.yaml是默认语言包),会生成2个根Dart Class: class AppMessages
和class AppMessages_en extends AppMessages
。
AppMessages_en
自动继承自AppMessages
,所以咱们能够直接使用AppMessages
类型来存储语言包,并在语言切换时从新为其实例化对应的子类:
AppMessages appMessages = new AppMessages();
resetLocalLang(String localeName) {
switch (localeName) {
case 'en':
appMessages = AppMessages_en();
break;
case 'zh':
default:
appMessages = AppMessages();
break;
}
}
复制代码
而后你能够在任意地方使用语言包:
debugPrint('Load Button: ${appMessages.button.load}');
FlatButton(
child: Text(appMessages.button.save),
onPressed: () {
/// 干点什么
},
)
复制代码
集成到Flutter,依然要依赖于官方的支持,在MaterialApp中设置和监听本地语言包:
@override
Widget build(BuildContext context) {
return MaterialApp(
localeResolutionCallback:
(Locale locale, Iterable<Locale> supportedLocales) {
/// Local changed
},
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: ['zh', 'en']
.map((loc) => new Locale(loc))
.toList(growable: false),
/// ...
);
}
复制代码
国际化支持,是一个移动端APP框架层的基础能力,设计原则应该是使用无感知、灵活易扩展;但维护成本是不免有增长的,好比每次改文案要全部语言包同时更改。
讲到这里,还并无完成基础框架的搭建,后面咱们会讲解更多的Flutter架构设计内容,好比:通知、分享、UI设计等等。
持续分享闪点清单在Flutter上的开发经验。闪点清单,一款悬浮清单软件: