鑑於Flutter高性能渲染和跨平臺的優點,閃點清單在移動端APP上,使用了完整的Flutter框架來開發。既然是完整APP,架構搭建徹底不受歷史Native APP的影響,沒有歷史包袱的沉澱,設計也能更靈活和健壯。
國際化語言的支持,是不少APP都有的一個強需求,APP不管大小,只要還不想放棄國外的客戶,通常就須要支持國際化。segmentfault
Flutter官方方案提供了國際化的基礎支持,如Flutter內置組件的國際化、語言代理、Widget使用語言包、語言設置回調等,並支持自定義第三方類來擴展,能夠參考Flutter國際化文檔。
官方支持代碼示例:架構
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']; } }
官方的支持有幾個缺陷:app
鑑於Flutter官方支持的缺陷,咱們調研了不少第三方庫,最終發現了i18n,並在此基礎上、結合Flutter官方支持和自身封裝,實現了更靈活易用的方案。框架
i18n使用yaml格式來定義語言包,同時提供構建腳本一鍵生成Dart語言包Class。以下:ide
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
函數:優化
debugPrint(m.users.welcome('World'));
參數定義基本沒有限制,能夠隨意定義參數個數和類型。ui
i18n支持了一些內置函數,用於作不一樣語言解析的體驗優化,如:plural、cardinal、ordinal。具體規則和使用,能夠參考這裏:http://cldr.unicode.org/index...
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上的開發經驗。閃點清單,一款懸浮清單軟件: