鑑於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上的開發經驗。閃點清單,一款懸浮清單軟件: