https://zhuanlan.zhihu.com/p/111885959
借助App Store與Google Play,全世界任何一個國家的使用者都可以使用我們開發的應用,不過由於應用的使用者來自不同國家,所以在應用正式上架之前需要讓應用能夠支持多種語言,即應用的國際化。 在Flutter開發中,應用的國際化主要涉及語言和地區差異性配置兩個方面,它們是應用程序的組成部分之一。關於語言的國際化比較好理解,而地區差異性配置指的是根據國家風俗的不同進行的差異性配置。按照Flutter官方的適配方案,要在Flutter應用中實現語言的國際化,需要經過以下幾步。
- 首先,實現一個翻譯代理LocalizationsDelegate,將所有需要翻譯的文案全部聲明為它的屬性。
- 然后,依次為需要支持的語言添加翻譯適配文件。
- 最后,在應用程序的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應用適配國際化只需要按照要求將國際化資源放到對應的文件夾目錄,然后應用層代碼訪問國際化資源時就會自動根據語言地區進行適配。