Flutter 國際化適配實戰

xiangzhihong發表於2020-03-09

藉助App Store與Google Play,全世界任何一個國家的使用者都可以使用我們開發的應用,不過由於應用的使用者來自不同國家,所以在應用正式上架之前需要讓應用能夠支援多種語言,即應用的國際化。 在Flutter開發中,應用的國際化主要涉及語言和地區差異性配置兩個方面,它們是應用程式的組成部分之一。關於語言的國際化比較好理解,而地區差異性配置指的是根據國家風俗的不同進行的差異性配置。按照Flutter官方的適配方案,要在Flutter應用中實現語言的國際化,需要經過以下幾步。

  1. 首先,實現一個翻譯代理LocalizationsDelegate,將所有需要翻譯的文案全部宣告為它的屬性。
  2. 然後,依次為需要支援的語言新增翻譯適配檔案。
  3. 最後,在應用程式的MaterialApp中初始化,將這個代理類設定為應用程式的翻譯回撥。 可以發現,如果直接按照官方提供的國際化方案來進行應用適配,不僅工作量大而且極易出錯。為了達到快速適配,減少程式碼編寫造成的錯誤,可以使用Android Studio提供的Flutter i18n國際化外掛。如果還沒有安裝Flutter i18n外掛,可以開啟Android Studio,然後依次選擇【Preference】→【Plugins】→【Marketplace】搜尋Flutter i18n外掛進行安裝,如下圖所示。
    在這裡插入圖片描述

安裝完成之後,重啟Android Studio就可以使用它進行Flutter的國際化適配了。需要說明的是,由於最新版的Android Studio已經不支援使用應用市場的方式來安裝Flutter i18n外掛,所以需要先從Jetbrains官網下載後再從本地進行安裝,如下圖所示。

在這裡插入圖片描述
由於Flutter i18n外掛需要依賴flutter_localizations外掛包,所以執行國際化適配之前,還需要在pubspec.yaml檔案中新增flutter_localizations依賴,如下所示。

dependencies:
  flutter_localizations:
    sdk: flutter

複製程式碼

在命令列中使用flutter packages get命令拉取依賴。然後,在專案的根目錄下會自動生成一個res資料夾,該資料夾預設會包含一個strings_en.arb檔案,arb檔案的格式如下。

{
  "app_name": "Flutter App internationalization",
  "main_title": "Flutter i18n",
  "main_content" : "You have click the button many times"
}

複製程式碼

arb檔案是JSON格式的配置檔案,可以用來存放文案識別符號和文案翻譯的鍵值對。事實上,這種將字串文字分離成單獨檔案的做法,可以方便開發人員和翻譯人員分工協作,從而提高適配效率。 預設情況下,系統只會生成英文資源配置strings_en.arb檔案,如果要支援中文,則需要使用手動的方式在values目錄下增加一個strings_zh.arb檔案。在res/values資料夾上右鍵,然後依次選擇【New】→【Arb File】→【Choose language】建立一個名為strings_zh.arb的arb檔案,並新增如下內容。

{
  "app_name": "Flutter應用國際化",
  "main_title": "Flutter國際化",
  "main_content" : "點選按鈕次數: $count"
}

複製程式碼

實際使用時,只需要修改res/values目錄下的arb檔案內容,i18n外掛就會自動生成對應的Dart轉換程式碼,如下圖所示。

在這裡插入圖片描述
需要說明的是,由於i18n.dart檔案的程式碼是由外掛自動生成的,所以不要手動修改裡面的內容。接下來,還需要在應用程式的入口,即MaterialApp中設定國際化所需的兩個重要引數localizationsDelegates與supportedLocales,如下所示。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: const [         
        S.delegate,                       
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate
      ],
      supportedLocales: S.delegate.supportedLocales,
      home: MyHomePage(title: '本地化'),
    );
  }
}

複製程式碼

其中,localizationsDelegates表示應用程式的翻譯回撥,supportedLocales表示應用所支援的語言地區屬性,而S.delegate則是Flutter i18n外掛自動生成的類,包含Flutter所支援的語言地區屬性以及對應的文案翻譯對映。在上面的程式碼中,除了加入S.delegate外,還加入了GlobalMaterialLocalizations.delegate和GlobalWidgetsLocalizations.delegate這兩個回撥。

前者為Material元件庫提供的本地化的字串和其他值,它可以使元件支援多語言,而後者則是用於定義元件預設的文字方向,從左到右或從右到左。之所以要加入這兩個回撥,是因為Flutter提供的元件本身已經支援了國際化,所以沒必要再適配一遍。而引數supportedLocales則用於表示應用所支援的語言地區,它的格式如下。

const Locale('zh', 'CN')    //中文簡體
複製程式碼

其中,Locale類是用來標識使用者語言環境的,它由語言和國家兩個屬性構成。在上面的程式碼中,我們將它設定成S.delegate.supportedLocales,即當前裝置的語言。完成上述應用程式的國際化配置操作後,接下來就可以在程式中通過S.of(context)方式獲取arb檔案中的內容了。下面是使用S.of(context)方式獲取arb檔案中標題名字的例子,如下所示。

S.of(context).main_title     //獲取標題      
複製程式碼

需要說明的是,使用上面的方式獲取翻譯文案的內容需要在能獲取到上下文的前提下才能生效,也就是說只能對MaterialApp的子元件才會生效。因此,如果要對應用的標題進行國際化配置,直接使用上面的方式是不行的,不過可以使用MaterialApp提供的onGenerateTitle回撥方法來進行處理,如下所示。

onGenerateTitle: (context) {
   return S.of(context).app_name;
 },

複製程式碼

對於應用介面文案的國際化則要相對簡單許多,直接使用S.of(context)方式拿到arb檔案中翻譯文案,然後設定到介面即可。下面是對Flutter官方工程的國際化處理,程式碼如下。

Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(S.of(context).main_title),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(S.of(context).main_content),
            Text('$_counter', style: Theme.of(context).textTheme.display1),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), 
    );
  }

複製程式碼

接下來,切換系統中的英文和中文,然後執行上面的程式碼,可以看到,應用的內容會隨著系統的語言進行切換,效果下圖所示。

在這裡插入圖片描述

不過,由於iOS應用程式有一套自建的語言環境管理機制,所以使用上面的方式適配國際化對於iOS應用程式是無效的。為了讓iOS應用程式也能支援國際化,還需要在原生iOS工程中進行額外的配置。 使用Xcode開啟Flutter專案的iOS原生工程,切換到工程皮膚,然後在Localization選項配置中新增中文支援,如下圖所示。

在這裡插入圖片描述

完成上述iOS原生工程配置後,再次回到Flutter工程,選擇iOS模擬器執行程式,就可以看到可以正常的支援國際化了,如下圖所示。

在這裡插入圖片描述
可以發行,國際化的核心就是語言差異配置抽取。與Flutter的國際化處理方式不同,原生Android和iOS應用適配國際化只需要按照要求將國際化資源放到對應的資料夾目錄,然後應用層程式碼訪問國際化資源時就會自動根據語言地區進行適配。

相關文章