從0開始設(shè)計Flutter獨立APP | 第二篇: 完整的國際化語言支持

鑒于Flutter高性能渲染和跨平臺的優(yōu)勢雏赦,閃點清單在移動端APP上奴潘,使用了完整的Flutter框架來開發(fā)凳鬓。既然是完整APP呼巴,架構(gòu)搭建完全不受歷史Native APP的影響,沒有歷史包袱的沉淀御蒲,設(shè)計也能更靈活和健壯衣赶。

國際化語言的支持,是很多APP都有的一個強需求厚满,APP無論大小府瞄,只要還不想放棄國外的客戶,一般就需要支持國際化碘箍。


flutter國際化

官方支持

Flutter官方方案提供了國際化的基礎(chǔ)支持遵馆,如Flutter內(nèi)置組件的國際化、語言代理丰榴、Widget使用語言包货邓、語言設(shè)置回調(diào)等,并支持自定義第三方類來擴展四濒,可以參考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'];
  }
}

官方方案的缺陷

官方的支持有幾個缺陷:

  1. 依賴于BuildContext對象,在非Widget中調(diào)用時盗蟆,需要層層傳遞BuildContext對象戈二,或存儲全局BuildContext對象。
  2. 在MaterialApp初始化前無法使用國際化(原因也是依賴于BuildContext對象)喳资。
  3. 語言包定義推薦使用Map方式觉吭,無法利用靜態(tài)語言的優(yōu)勢(語法提示、錯誤檢查等)仆邓;而為語言包每個屬性自定義類和類字段鲜滩,成本較高伴鳖、使用和更新靈活性差。

i18n介紹

鑒于Flutter官方支持的缺陷绒北,我們調(diào)研了很多第三方庫黎侈,最終發(fā)現(xiàn)了i18n,并在此基礎(chǔ)上闷游、結(jié)合Flutter官方支持和自身封裝峻汉,實現(xiàn)了更靈活易用的方案。

flutter國際化

基礎(chǔ)使用

i18n使用yaml格式來定義語言包脐往,同時提供構(gòu)建腳本一鍵生成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文件預(yù)覽(開發(fā)時無需關(guān)心):

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!";
}

進階功能

下面講解一些進階用法。

函數(shù)定義

i18n支持函數(shù)定義梅尤,并支持傳參柜思,如上述的welcome函數(shù):

debugPrint(m.users.welcome('World'));

參數(shù)定義基本沒有限制,可以隨意定義參數(shù)個數(shù)和類型巷燥。

內(nèi)置函數(shù)

i18n支持了一些內(nèi)置函數(shù)赡盘,用于做不同語言解析的體驗優(yōu)化,如:plural缰揪、cardinal陨享、ordinal。具體規(guī)則和使用钝腺,可以參考這里:http://cldr.unicode.org/index/cldr-spec/plural-rules

使用Dart字符串模板

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毫目。

flutter國際化

語言包使用

前置編譯后喷斋,每個語言包會生成N個Class(語言包的每一個分類或組合會生成一個Class文件),然后會生成一個根Class蒜茴,我們可以直接使用根Class(當(dāng)然也可以使用任何一個分類層級的Class)星爪。

比如兩個語言包文件: AppMessages.i18n.yamlAppMessages_en.i18n.yaml(未加語言后綴的,會認為是默認語言包粉私,因此AppMessages.i18n.yaml是默認語言包)顽腾,會生成2個根Dart Class: class AppMessagesclass AppMessages_en extends AppMessages

AppMessages_en自動繼承自AppMessages,因此我們可以直接使用AppMessages類型來存儲語言包抄肖,并在語言切換時重新為其實例化對應(yīng)的子類:

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集成

集成到Flutter久信,依然要依賴于官方的支持,在MaterialApp中設(shè)置和監(jiān)聽本地語言包:

@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),
    /// ...
  );
}

結(jié)尾

國際化支持漓摩,是一個移動端APP框架層的基礎(chǔ)能力裙士,設(shè)計原則應(yīng)該是使用無感知、靈活易擴展管毙;但維護成本是難免有增加的腿椎,比如每次改文案要所有語言包同時更改。

講到這里夭咬,還并沒有完成基礎(chǔ)框架的搭建啃炸,后面我們會講解更多的Flutter架構(gòu)設(shè)計內(nèi)容,比如:通知卓舵、分享南用、UI設(shè)計等等。


持續(xù)分享閃點清單在Flutter上的開發(fā)經(jīng)驗掏湾。閃點清單裹虫,一款懸浮清單軟件:

閃點清單,一款懸浮清單軟件
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末融击,一起剝皮案震驚了整個濱河市筑公,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌砚嘴,老刑警劉巖十酣,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涩拙,死亡現(xiàn)場離奇詭異际长,居然都是意外死亡,警方通過查閱死者的電腦和手機兴泥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門工育,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人搓彻,你說我怎么就攤上這事如绸。” “怎么了旭贬?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵怔接,是天一觀的道長。 經(jīng)常有香客問我稀轨,道長扼脐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮瓦侮,結(jié)果婚禮上艰赞,老公的妹妹穿的比我還像新娘。我一直安慰自己肚吏,他們只是感情好方妖,可當(dāng)我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著罚攀,像睡著了一般党觅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上坞生,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天仔役,我揣著相機與錄音,去河邊找鬼是己。 笑死又兵,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的卒废。 我是一名探鬼主播沛厨,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼摔认!你這毒婦竟也來了逆皮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤参袱,失蹤者是張志新(化名)和其女友劉穎电谣,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抹蚀,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡剿牺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了环壤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晒来。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖郑现,靈堂內(nèi)的尸體忽然破棺而出湃崩,到底是詐尸還是另有隱情,我是刑警寧澤接箫,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布攒读,位于F島的核電站,受9級特大地震影響辛友,放射性物質(zhì)發(fā)生泄漏薄扁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望泌辫。 院中可真熱鬧随夸,春花似錦、人聲如沸震放。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽殿遂。三九已至诈铛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間墨礁,已是汗流浹背幢竹。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留恩静,地道東北人焕毫。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像驶乾,于是被迫代替她去往敵國和親邑飒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,077評論 2 355