Flutter - International 國際化,Localization 本地化刻伊, 使用Intl

新建項目露戒,得到一個示例工程。本例中使用intl包來管理文字資源捶箱。

項目地址: https://github.com/RustFisher/localization_demo

步驟:

  • 添加依賴項 - intl
  • 創(chuàng)建文字資源文件
  • 生成arb文件
    • 新增和修改arb文件
  • 根據(jù)arb生成dart文件
  • 創(chuàng)建localization代理智什,新建一個類繼承LocalizationsDelegate,和文字資源文件聯(lián)系起來
  • MaterialApp中添加本地化代理和語言類型
  • 使用文字資源

添加依賴項

pubspec.yaml添加依賴項flutter_localizations丁屎,然后運行一下flutter packages get荠锭。

dependencies:
  flutter:
    sdk: flutter
# 添加下面的依賴項
  flutter_localizations:
    sdk: flutter
  intl: 0.15.6
  intl_translation: 0.16.7

編輯dart文件

新建app_strings.dart文件。

import '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的命令愧怜。

/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,內(nèi)容如下妈拌〗懈椋可以看出是JSON格式的文本。

{
  "@@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.arbintl_zh.arb音诫。文件名規(guī)則可以自己定。
intl_zh.arb為例:

{
  "@@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刪掉雪位。本例保留這個文件竭钝。

根據(jù)arb生成dart文件

$ flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/l10n \
   --no-use-deferred-loading lib/app_strings.dart lib/l10n/intl_*.arb

No @@locale or _locale field found in intl_en, assuming 'en' based on the file name.
No @@locale or _locale field found in intl_messages, assuming 'messages' based on the file name.
No @@locale or _locale field found in intl_zh, assuming 'zh' based on the file name.

暫時無視警告。

注意雹洗,Windows并不一定會識別*通配符香罐。上面寫的intl_*.arb,可能會遇到錯誤

FileSystemException: Cannot open file, path = 'lib/*.dart' (OS Error..

這個錯誤是系統(tǒng)拋出來的时肿”用#可以嘗試用git bash來運行命令◇Τ桑可以把那個換行轉(zhuǎn)義符號去掉旦签。

$ flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/l10n --no-use-deferred-loading lib/app_strings.dart lib/l10n/intl_*.arb

若還是不行查坪,建議參考https://github.com/dart-lang/intl_translation/issues/21,不用通配符宁炫,而是一個個生成文件偿曙。

此時在app_strings.dart中添加對l10n/intl_messages.arb的引用。

import 'package:localization_demo/l10n/messages_all.dart';

警告消失~


生成的文件

更新了arb文件后羔巢,需要重新生成dart文件望忆。

創(chuàng)建localization代理

創(chuàng)建localizations_delegate.dart。新建AppLocalizationsDelegate類繼承LocalizationsDelegate竿秆,復寫方法启摄。
泛型指定為前面的AppStrings

import '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中添加本地化代理和語言類型

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      localizationsDelegates: [
        AppLocalizationsDelegate(), // 我們定義的代理
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: [ // 支持的語言類型
        const Locale('en', 'US'), // English
        const Locale('zh', ''),
      ],
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

使用文字資源

獲取到AppStrings的實例袍辞。

    AppStrings appStrings = AppStrings.of(context);
    print(appStrings); // logcat:  I/flutter ( 7478): Instance of 'AppStrings'
示例工程結(jié)構(gòu)

注意鞋仍,在MaterialApp中使用文字資源時,因為context的關系搅吁,要使用onGenerateTitle威创。

      onGenerateTitle: (context) {
        return AppStrings.of(context).title();
      },

支持語言的類型

代理isSupported方法中的語言類型最好是和App中supportedLocales的一致

  @override
  bool isSupported(Locale locale) =>
      ['zh', 'en'].contains(locale.languageCode);

// App中`supportedLocales`
      supportedLocales: [
        const Locale('en', 'US'), // English
        const Locale('zh', ''),
      ],

否則可能出現(xiàn)獲取不到AppStrings的異常。

參考:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谎懦,一起剝皮案震驚了整個濱河市肚豺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌界拦,老刑警劉巖吸申,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異享甸,居然都是意外死亡截碴,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門蛉威,熙熙樓的掌柜王于貴愁眉苦臉地迎上來日丹,“玉大人,你說我怎么就攤上這事蚯嫌≌芟海” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵择示,是天一觀的道長束凑。 經(jīng)常有香客問我,道長栅盲,這世上最難降的妖魔是什么汪诉? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮谈秫,結(jié)果婚禮上摩瞎,老公的妹妹穿的比我還像新娘拴签。我一直安慰自己,他們只是感情好旗们,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布蚓哩。 她就那樣靜靜地躺著,像睡著了一般上渴。 火紅的嫁衣襯著肌膚如雪岸梨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天稠氮,我揣著相機與錄音曹阔,去河邊找鬼。 笑死隔披,一個胖子當著我的面吹牛赃份,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播奢米,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼抓韩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了鬓长?” 一聲冷哼從身側(cè)響起谒拴,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎涉波,沒想到半個月后英上,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡啤覆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年苍日,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窗声。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡相恃,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嫌佑,到底是詐尸還是另有隱情,我是刑警寧澤侨歉,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布屋摇,位于F島的核電站,受9級特大地震影響幽邓,放射性物質(zhì)發(fā)生泄漏炮温。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一牵舵、第九天 我趴在偏房一處隱蔽的房頂上張望柒啤。 院中可真熱鬧倦挂,春花似錦、人聲如沸担巩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽涛癌。三九已至犯戏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拳话,已是汗流浹背先匪。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留弃衍,地道東北人呀非。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像镜盯,于是被迫代替她去往敵國和親岸裙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容