Flutter實戰(zhàn) 實現(xiàn)Localizations使用Intl包

2021-03-09 14:37 更新

前面講了 Material 組件庫如何支持國際化,本節(jié)我們將介紹一下我們自己的 UI 中如何支持多語言。根據(jù)上節(jié)所述,我們需要實現(xiàn)兩個類:一個Delegate類一個Localizations類,下面我們通過一個實例說明。

#實現(xiàn)Localizations類

我們已經(jīng)知道Localizations類中主要實現(xiàn)提供了本地化值,如文本:

//Locale資源類
class DemoLocalizations {
  DemoLocalizations(this.isZh);
  //是否為中文
  bool isZh = false;
  //為了使用方便,我們定義一個靜態(tài)方法
  static DemoLocalizations of(BuildContext context) {
    return Localizations.of<DemoLocalizations>(context, DemoLocalizations);
  }
  //Locale相關(guān)值,title為應(yīng)用標(biāo)題
  String get title {
    return isZh ? "Flutter應(yīng)用" : "Flutter APP";
  }
  //... 其它的值  
}

DemoLocalizations中會根據(jù)當(dāng)前的語言來返回不同的文本,如title,我們可以將所有需要支持多語言的文本都在此類中定義。DemoLocalizations的實例將會在 Delegate 類的load方法中創(chuàng)建。

#實現(xiàn)Delegate類

Delegate 類的職責(zé)是在 Locale 改變時加載新的 Locale 資源,所以它有一個load方法,Delegate 類需要繼承自LocalizationsDelegate類,實現(xiàn)相應(yīng)的接口,示例如下:

//Locale代理類
class DemoLocalizationsDelegate extends LocalizationsDelegate<DemoLocalizations> {
  const DemoLocalizationsDelegate();


  //是否支持某個Local
  @override
  bool isSupported(Locale locale) => ['en', 'zh'].contains(locale.languageCode);


  // Flutter會調(diào)用此類加載相應(yīng)的Locale資源類
  @override
  Future<DemoLocalizations> load(Locale locale) {
    print("$locale");
    return SynchronousFuture<DemoLocalizations>(
        DemoLocalizations(locale.languageCode == "zh")
    );
  }


  @override
  bool shouldReload(DemoLocalizationsDelegate old) => false;
}

shouldReload的返回值決定當(dāng) Localizations 組件重新 build 時,是否調(diào)用load方法重新加載 Locale 資源。一般情況下,Locale 資源只應(yīng)該在 Locale 切換時加載一次,不需要每次在Localizations重新 build 時都加載,所以返回false即可??赡苡行┤藭?dān)心返回false的話在 APP 啟動后用戶再改變系統(tǒng)語言時load方法將不會被調(diào)用,所以 Locale 資源將不會被加載。事實上,每當(dāng) Locale 改變時 Flutter 都會再調(diào)用load方法加載新的 Locale,無論shouldReload返回true還是false。

#最后一步:添加多語言支持

和上一節(jié)中介紹的相同,我們現(xiàn)在需要先注冊DemoLocalizationsDelegate類,然后再通過DemoLocalizations.of(context)來動態(tài)獲取當(dāng)前 Locale 文本。

只需要在 MaterialApp 或 WidgetsApp 的localizationsDelegates列表中添加我們的 Delegate 實例即可完成注冊:

localizationsDelegates: [
 // 本地化的代理類
 GlobalMaterialLocalizations.delegate,
 GlobalWidgetsLocalizations.delegate,
 // 注冊我們的Delegate
 DemoLocalizationsDelegate()
],

接下來我們可以在 Widget 中使用 Locale 值:

return Scaffold(
  appBar: AppBar(
    //使用Locale title  
    title: Text(DemoLocalizations.of(context).title),
  ),
  ... //省略無關(guān)代碼
 ) 

這樣,當(dāng)在美國英語和中文簡體之間切換系統(tǒng)語言時,APP 的標(biāo)題將會分別為“Flutter APP”和“Flutter應(yīng)用”。

#總結(jié)

本節(jié)我們通過一個簡單的示例說明了 Flutter 應(yīng)用國際化的基本過程及原理。但是上面的實例還有一個嚴(yán)重的不足就是我們需要在 DemoLocalizations 類中獲取title時手動的判斷當(dāng)前語言 Locale,然后返回合適的文本。試想一下,當(dāng)我們要支持的語言不是兩種而是8種甚至20幾種時,如果為每個文本屬性都要分別去判斷到底是哪種 Locale 從而獲取相應(yīng)語言的文本將會是一件非常復(fù)雜的事。還有,通常情況下翻譯人員并不是開發(fā)人員,能不能像 i18n 或 l10n 標(biāo)準(zhǔn)那樣可以將翻譯單獨保存為一個 arb 文件交由翻譯人員去翻譯,翻譯好之后開發(fā)人員再通過工具將 arb 文件轉(zhuǎn)為代碼。答案是肯定的!我們將在下一節(jié)介紹如何通過 Dart intl 包來實現(xiàn)這些。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號