默認(rèn)情況下,F(xiàn)lutter僅提供美國英語本地化。要添加對其他語言的支持,應(yīng)用程序必須指定其他MaterialApp屬性,并包含一個名為的單獨(dú)包-“flutter_localizations”。 截至2017年10月,該軟件包支持15種語言。
要使用flutter_localizations,請將該包作為依賴項添加到您的pubspec.yaml文件中:
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
接下來,導(dǎo)入flutter_localizations庫,并指定MaterialApp的localizationsDelegates和supportedLocales:
import 'package:flutter_localizations/flutter_localizations.dart';
new MaterialApp(
localizationsDelegates: [
// ... app-specific localization delegate[s] here
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('en', 'US'), // English
const Locale('he', 'IL'), // Hebrew
// ... other locales the app supports
],
// ...
)
基于WidgetsApp的應(yīng)用程序類似,只是不需要GlobalMaterialLocalizations.delegate。
localizationsDelegates列表中的元素是生成本地化值集合的工廠。GlobalMaterialLocalizations.delegate 為Material Components庫提供了本地化的字符串和其他值。 GlobalWidgetsLocalizations.delegate定義widget默認(rèn)的文本方向,從左到右或從右到左。
有關(guān)這些應(yīng)用程序?qū)傩缘母嘈畔?,它們所依賴的類型以及如何國際化Flutter應(yīng)用程序,這些都可以在下面找到。
該Locale類是用來識別用戶的語言環(huán)境。 移動設(shè)備支持通過系統(tǒng)設(shè)置菜單為所有應(yīng)用程序設(shè)置區(qū)域。國際化應(yīng)用程序通過顯示區(qū)域設(shè)置特定的值進(jìn)行響應(yīng)。 例如,如果用戶將設(shè)備的語言環(huán)境從英語切換到法語,則顯示“Hello World”的文本widget將用“Bonjour le monde”重建。
Localizations小部件定義其子項的區(qū)域設(shè)置以及子項依賴的本地化資源。 如果系統(tǒng)的語言環(huán)境發(fā)生變化,WidgetsApp將創(chuàng)建一個Localizations widget并重建它。
您始終可以通過以下方式查找應(yīng)用的當(dāng)前區(qū)域設(shè)置:
Locale myLocale = Localizations.localeOf(context);
Localizations widget用于加載和查找包含本地化值的集合的對象。應(yīng)用程序通過Localizations.of(context,type)來引用這些對象。 如果設(shè)備的區(qū)域設(shè)置發(fā)生更改,則Localizations widget會自動加載新區(qū)域設(shè)置的值,然后重新構(gòu)建使用它們的widget。 發(fā)生這種情況是因為Localizations像InheritedWidget一樣工作 。 當(dāng)build函數(shù)引用了繼承的widget時,會創(chuàng)建對繼承的widget的隱式依賴關(guān)系。當(dāng)繼承的widget發(fā)生更改(Localizations widget的區(qū)域設(shè)置發(fā)生更改時),將重建其依賴的上下文。
本地化值由Localizations widget的 LocalizationsDelegates 列表加載 。 每個委托必須定義一個異步load() 方法,以生成封裝了一系列本地化值的對象。通常這些對象為每個本地化值定義一個方法。
在大型應(yīng)用程序中,不同的模塊或軟件包可能會與自己的本地化捆綁在一起。 這就是Localizations widget管理對象表的原因,每個LocalizationsDelegate都有一個(對象表)。 要檢索由LocalizationsDelegateload方法之一產(chǎn)生的對象,可以指定一個BuildContext和對象的類型。
例如,Material Component widgets的本地化字符串由MaterialLocalizations類定義。 此類的實(shí)例由MaterialApp類提供的LocalizationDelegate創(chuàng)建。 它們可以通過Localizations.of被獲取到:
Localizations.of<MaterialLocalizations>(context, MaterialLocalizations);
這個特殊的Localizations.of()表達(dá)式經(jīng)常使用,所以MaterialLocalizations類提供了一個方便的簡寫:
static MaterialLocalizations of(BuildContext context) {
return Localizations.of<MaterialLocalizations>(context, MaterialLocalizations);
}
/// References to the localized values defined by MaterialLocalizations
/// are typically written like this:
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
為了盡可能小而且簡單,flutter軟件包中僅提供美國英語值的MaterialLocalizations和WidgetsLocalizations接口的實(shí)現(xiàn)。 這些實(shí)現(xiàn)類分別稱為DefaultMaterialLocalizations和DefaultWidgetsLocalizations。 除非與應(yīng)用程序的localizationsDelegates參數(shù)指定了相同基本類型的不同delegate,否則它們會自動包含 。
flutter_localizations軟件包包含稱為GlobalMaterialLocalizations和GlobalWidgetsLocalizations的本地化接口的多語言實(shí)現(xiàn)。 國際化的應(yīng)用程序必須按照設(shè)置國際化應(yīng)用程序中的說明為這些類指定本地化代理 。
import 'package:flutter_localizations/flutter_localizations.dart';
new MaterialApp(
localizationsDelegates: [
// ... app-specific localization delegate[s] here
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('en', 'US'), // English
const Locale('fr', 'CA'), // canadian French
// ... other locales the app supports
],
// ...
)
全局本地化delegates構(gòu)造相應(yīng)類的特定于語言環(huán)境的實(shí)例。例如,GlobalMaterialLocalizations.delegate是一個產(chǎn)生GlobalMaterialLocalizations實(shí)例的LocalizationsDelegate。
截至2017年10月,國際化代理的類支持約15種語言
將所有這些放在一起用于國際化應(yīng)用程序通常從封裝應(yīng)用程序本地化值的類開始。下面的例子是這些類的典型例子。
這個示例的完整源代碼
本示例基于intl包提供的API和工具 。指定本地化資源的另一個類描述了一個不依賴于intl包的示例。
DemoLocalizations類包含應(yīng)用程序的字符串(僅用于示例),該字符串被翻譯為應(yīng)用程序支持的語言環(huán)境。 使用Dart的intl 包生成的函數(shù)initializeMessages()來加載翻譯的字符串,并使用Intl.message()查找它們。
class DemoLocalizations {
static Future<DemoLocalizations> load(Locale locale) {
final String name = locale.countryCode.isEmpty ? locale.languageCode : locale.toString();
final String localeName = Intl.canonicalizedLocale(name);
return initializeMessages(localeName).then((Null _) {
Intl.defaultLocale = localeName;
return new DemoLocalizations();
});
}
static DemoLocalizations of(BuildContext context) {
return Localizations.of<DemoLocalizations>(context, DemoLocalizations);
}
String get title {
return Intl.message(
'Hello World',
name: 'title',
desc: 'Title for the Demo application',
);
}
}
基于intl包的類導(dǎo)入生成的message目錄,該目錄提供initializeMessages()函數(shù)和每個語言環(huán)境的后備存儲Intl.message()。 message目錄由一個intl工具生成,該工具分析包含Intl.message()調(diào)用的類的源代碼。在這個示例中,這是DemoLocalizations類。
雖然Flutter的Material Components library包含對大約16種語言的支持,但默認(rèn)情況下僅提供英文。 開發(fā)人員需要決定支持哪種語言,因為工具庫支持與應(yīng)用程序不同的一組語言環(huán)境是沒有意義的。
MaterialAppsupportedLocales參數(shù)限制語言環(huán)境更改。 當(dāng)用戶更改其設(shè)備上的區(qū)域設(shè)置時,新區(qū)域如果是列表的成員,則應(yīng)用程序的Localizations widget 就適用于該區(qū)域。如 果找不到設(shè)備區(qū)域設(shè)置的精確匹配項(譯者語:指語言和地區(qū)同時匹配,如中文,中國),則使用第一個匹配區(qū)域設(shè)置languageCode(譯者語:只設(shè)置語言,而不指定地區(qū))。 如果失敗,則supportedLocales使用列表的第一個元素 。
就之前的DemoApp示例而言,該應(yīng)用只接受美國英語或加拿大法語語言環(huán)境,并將美國英語(列表中的第一個語言環(huán)境)替換為其他任何內(nèi)容。
可以提供一個localeResolutionCallback,在應(yīng)用獲取用戶設(shè)置的語言區(qū)域時會被回調(diào)。 例如,要讓您的應(yīng)用程序無條件接受用戶選擇的任何區(qū)域設(shè)置:
class DemoApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
localeResolutionCallback(Locale locale, Iterable<Locale> supportedLocales) {
return locale;
}
// ...
);
}
}
之前的DemoApp示例是根據(jù)Dartintl包定義的。為了簡單起見,開發(fā)人員可以選擇自己的方法來管理本地化值,也可以與不同的i18n框架進(jìn)行集成。 這個示例的完整源代碼
在此版本的DemoApp中,包含應(yīng)用程序本地化的類DemoLocalizations將直接在每種語言Map中包含其所有的翻譯:
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'];
}
}
在簡單的國際化應(yīng)用中, DemoLocalizationsDelegate略有不同。它的load方法返回一個SynchronousFuture, 因為不需要進(jìn)行異步加載。
class DemoLocalizationsDelegate extends LocalizationsDelegate<DemoLocalizations> {
const DemoLocalizationsDelegate();
@override
bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);
@override
Future<DemoLocalizations> load(Locale locale) {
return new SynchronousFuture<DemoLocalizations>(new DemoLocalizations(locale));
}
@override
bool shouldReload(DemoLocalizationsDelegate old) => false;
}
在使用Dart intl包構(gòu)建API之前, 您需要查看intl包的文檔。以下是根據(jù)intl軟件包本地化應(yīng)用程序的過程摘要。
示例程序依賴于一個生成的源文件l10n/messages_all.dart ,它定義了應(yīng)用程序使用的所有本地化字符串。
重新構(gòu)建 l10n/messages_all.dart 需要兩個步驟.
$ flutter pub pub run intl_translation:extract_to_arb --output-dir=lib/i10n lib/main.dart
該intl_messages.arb文件是一個JSON格式的map,擁有一個在main.dart中定義的Intl.message()函數(shù)入口。 此文件作為英語和西班牙語翻譯的一個模板,intl_en.arb和intl_es.arb。這些翻譯是由您,開發(fā)人員創(chuàng)建的。
使用應(yīng)用程序的根目錄作為當(dāng)前目錄,為每個intl_<locale>.arb文件生成intl_messages_<locale>.dart,并在intl_messages_all.dart中導(dǎo)入所有message文件:
$ flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/l10n \
--no-use-deferred-loading lib/main.dart lib/l10n/intl_*.arb
DemoLocalizations類使用生成的initializeMessages() 函數(shù)(定義在intl_messages_all.dart)來加載本地化的message并使用Intl.message()來查找它們。
更多建議: