默認(rèn)情況下,F(xiàn)lutter僅提供美國(guó)英語(yǔ)本地化。要添加對(duì)其他語(yǔ)言的支持,應(yīng)用程序必須指定其他MaterialApp屬性,并包含一個(gè)名為的單獨(dú)包-“flutter_localizations”。 截至2017年10月,該軟件包支持15種語(yǔ)言。
要使用flutter_localizations,請(qǐng)將該包作為依賴項(xiàng)添加到您的pubspec.yaml文件中:
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
接下來,導(dǎo)入flutter_localizations庫(kù),并指定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庫(kù)提供了本地化的字符串和其他值。 GlobalWidgetsLocalizations.delegate定義widget默認(rèn)的文本方向,從左到右或從右到左。
有關(guān)這些應(yīng)用程序?qū)傩缘母嘈畔?,它們所依賴的類型以及如何?guó)際化Flutter應(yīng)用程序,這些都可以在下面找到。
該Locale類是用來識(shí)別用戶的語(yǔ)言環(huán)境。 移動(dòng)設(shè)備支持通過系統(tǒng)設(shè)置菜單為所有應(yīng)用程序設(shè)置區(qū)域。國(guó)際化應(yīng)用程序通過顯示區(qū)域設(shè)置特定的值進(jìn)行響應(yīng)。 例如,如果用戶將設(shè)備的語(yǔ)言環(huán)境從英語(yǔ)切換到法語(yǔ),則顯示“Hello World”的文本widget將用“Bonjour le monde”重建。
Localizations小部件定義其子項(xiàng)的區(qū)域設(shè)置以及子項(xiàng)依賴的本地化資源。 如果系統(tǒng)的語(yǔ)言環(huán)境發(fā)生變化,WidgetsApp將創(chuàng)建一個(gè)Localizations widget并重建它。
您始終可以通過以下方式查找應(yīng)用的當(dāng)前區(qū)域設(shè)置:
Locale myLocale = Localizations.localeOf(context);
Localizations widget用于加載和查找包含本地化值的集合的對(duì)象。應(yīng)用程序通過Localizations.of(context,type)來引用這些對(duì)象。 如果設(shè)備的區(qū)域設(shè)置發(fā)生更改,則Localizations widget會(huì)自動(dòng)加載新區(qū)域設(shè)置的值,然后重新構(gòu)建使用它們的widget。 發(fā)生這種情況是因?yàn)長(zhǎng)ocalizations像InheritedWidget一樣工作 。 當(dāng)build函數(shù)引用了繼承的widget時(shí),會(huì)創(chuàng)建對(duì)繼承的widget的隱式依賴關(guān)系。當(dāng)繼承的widget發(fā)生更改(Localizations widget的區(qū)域設(shè)置發(fā)生更改時(shí)),將重建其依賴的上下文。
本地化值由Localizations widget的 LocalizationsDelegates 列表加載 。 每個(gè)委托必須定義一個(gè)異步load() 方法,以生成封裝了一系列本地化值的對(duì)象。通常這些對(duì)象為每個(gè)本地化值定義一個(gè)方法。
在大型應(yīng)用程序中,不同的模塊或軟件包可能會(huì)與自己的本地化捆綁在一起。 這就是Localizations widget管理對(duì)象表的原因,每個(gè)LocalizationsDelegate都有一個(gè)(對(duì)象表)。 要檢索由LocalizationsDelegateload方法之一產(chǎn)生的對(duì)象,可以指定一個(gè)BuildContext和對(duì)象的類型。
例如,Material Component widgets的本地化字符串由MaterialLocalizations類定義。 此類的實(shí)例由MaterialApp類提供的LocalizationDelegate創(chuàng)建。 它們可以通過Localizations.of被獲取到:
Localizations.of<MaterialLocalizations>(context, MaterialLocalizations);
這個(gè)特殊的Localizations.of()表達(dá)式經(jīng)常使用,所以MaterialLocalizations類提供了一個(gè)方便的簡(jiǎn)寫:
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,
為了盡可能小而且簡(jiǎn)單,flutter軟件包中僅提供美國(guó)英語(yǔ)值的MaterialLocalizations和WidgetsLocalizations接口的實(shí)現(xiàn)。 這些實(shí)現(xiàn)類分別稱為DefaultMaterialLocalizations和DefaultWidgetsLocalizations。 除非與應(yīng)用程序的localizationsDelegates參數(shù)指定了相同基本類型的不同delegate,否則它們會(huì)自動(dòng)包含 。
flutter_localizations軟件包包含稱為GlobalMaterialLocalizations和GlobalWidgetsLocalizations的本地化接口的多語(yǔ)言實(shí)現(xiàn)。 國(guó)際化的應(yīng)用程序必須按照設(shè)置國(guó)際化應(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)類的特定于語(yǔ)言環(huán)境的實(shí)例。例如,GlobalMaterialLocalizations.delegate是一個(gè)產(chǎn)生GlobalMaterialLocalizations實(shí)例的LocalizationsDelegate。
截至2017年10月,國(guó)際化代理的類支持約15種語(yǔ)言
將所有這些放在一起用于國(guó)際化應(yīng)用程序通常從封裝應(yīng)用程序本地化值的類開始。下面的例子是這些類的典型例子。
這個(gè)示例的完整源代碼
本示例基于intl包提供的API和工具 。指定本地化資源的另一個(gè)類描述了一個(gè)不依賴于intl包的示例。
DemoLocalizations類包含應(yīng)用程序的字符串(僅用于示例),該字符串被翻譯為應(yīng)用程序支持的語(yǔ)言環(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ù)和每個(gè)語(yǔ)言環(huán)境的后備存儲(chǔ)Intl.message()。 message目錄由一個(gè)intl工具生成,該工具分析包含Intl.message()調(diào)用的類的源代碼。在這個(gè)示例中,這是DemoLocalizations類。
雖然Flutter的Material Components library包含對(duì)大約16種語(yǔ)言的支持,但默認(rèn)情況下僅提供英文。 開發(fā)人員需要決定支持哪種語(yǔ)言,因?yàn)楣ぞ邘?kù)支持與應(yīng)用程序不同的一組語(yǔ)言環(huán)境是沒有意義的。
MaterialAppsupportedLocales參數(shù)限制語(yǔ)言環(huán)境更改。 當(dāng)用戶更改其設(shè)備上的區(qū)域設(shè)置時(shí),新區(qū)域如果是列表的成員,則應(yīng)用程序的Localizations widget 就適用于該區(qū)域。如 果找不到設(shè)備區(qū)域設(shè)置的精確匹配項(xiàng)(譯者語(yǔ):指語(yǔ)言和地區(qū)同時(shí)匹配,如中文,中國(guó)),則使用第一個(gè)匹配區(qū)域設(shè)置languageCode(譯者語(yǔ):只設(shè)置語(yǔ)言,而不指定地區(qū))。 如果失敗,則supportedLocales使用列表的第一個(gè)元素 。
就之前的DemoApp示例而言,該應(yīng)用只接受美國(guó)英語(yǔ)或加拿大法語(yǔ)語(yǔ)言環(huán)境,并將美國(guó)英語(yǔ)(列表中的第一個(gè)語(yǔ)言環(huán)境)替換為其他任何內(nèi)容。
可以提供一個(gè)localeResolutionCallback,在應(yīng)用獲取用戶設(shè)置的語(yǔ)言區(qū)域時(shí)會(huì)被回調(diào)。 例如,要讓您的應(yīng)用程序無(wú)條件接受用戶選擇的任何區(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包定義的。為了簡(jiǎn)單起見,開發(fā)人員可以選擇自己的方法來管理本地化值,也可以與不同的i18n框架進(jìn)行集成。 這個(gè)示例的完整源代碼
在此版本的DemoApp中,包含應(yīng)用程序本地化的類DemoLocalizations將直接在每種語(yǔ)言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'];
}
}
在簡(jiǎn)單的國(guó)際化應(yīng)用中, DemoLocalizationsDelegate略有不同。它的load方法返回一個(gè)SynchronousFuture, 因?yàn)椴恍枰M(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)用程序的過程摘要。
示例程序依賴于一個(gè)生成的源文件l10n/messages_all.dart ,它定義了應(yīng)用程序使用的所有本地化字符串。
重新構(gòu)建 l10n/messages_all.dart 需要兩個(gè)步驟.
$ flutter pub pub run intl_translation:extract_to_arb --output-dir=lib/i10n lib/main.dart
該intl_messages.arb文件是一個(gè)JSON格式的map,擁有一個(gè)在main.dart中定義的Intl.message()函數(shù)入口。 此文件作為英語(yǔ)和西班牙語(yǔ)翻譯的一個(gè)模板,intl_en.arb和intl_es.arb。這些翻譯是由您,開發(fā)人員創(chuàng)建的。
使用應(yīng)用程序的根目錄作為當(dāng)前目錄,為每個(gè)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()來查找它們。
更多建議: