做(zuò)自(zì)由與創造的先行(xíng)者

Flutter 國(guó)際化

Flutter開(kāi)發手冊

設置一(yī)個國(guó)際化的應用程序: the flutter_localizations package

默認情況下(xià),Flutter僅提供美國(guó)英語本地(dì)化。要(yào)添加對其他(tā)語言的支持,應用程序必須指定其他(tā)MaterialApp屬性,并包含一(yī)個名為(wèi)的單獨包-“flutter_localizations”。 截至2017年(nián)10月,該軟件包支持15種語言。

要(yào)使用flutter_localizations,請(qǐng)将該包作(zuò)為(wèi)依賴項添加到您的pubspec.yaml文件中:

dependencies:

flutter:

sdk: flutter

flutter_localizations:

sdk: flutter

接下(xià)來,導入flutter_localizations庫,并指定MaterialApp的localizationsDelegates和(hé)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ào)GlobalMaterialLocalizations.delegate。

localizationsDelegates列表中的元素是生成本地(dì)化值集合的工(gōng)廠。GlobalMaterialLocalizations.delegate 為(wèi)Material Components庫提供了(le)本地(dì)化的字符串和(hé)其他(tā)值。 GlobalWidgetsLocalizations.delegate定義widget默認的文本方向,從(cóng)左到右或從(cóng)右到左。

有關這(zhè)些應用程序屬性的更多信息,它們所依賴的類型以及如(rú)何國(guó)際化Flutter應用程序,這(zhè)些都(dōu)可(kě)以在下(xià)面找到。

跟蹤區(qū)域設置: Locale類和(hé)Localizations widget

該Locale類是用來識别用戶的語言環境。 移動設備支持通(tōng)過系統設置菜單為(wèi)所有應用程序設置區(qū)域。國(guó)際化應用程序通(tōng)過顯示區(qū)域設置特定的值進行(xíng)響應。 例如(rú),如(rú)果用戶将設備的語言環境從(cóng)英語切換到法語,則顯示“Hello World”的文本widget将用“Bonjour le monde”重建。

Localizations小部件定義其子項的區(qū)域設置以及子項依賴的本地(dì)化資源。 如(rú)果系統的語言環境發生變化,WidgetsApp将創建一(yī)個Localizations widget并重建它。

您始終可(kě)以通(tōng)過以下(xià)方式查找應用的當前區(qū)域設置:

Locale myLocale = Localizations.localeOf(context);

加載和(hé)獲取本地(dì)化的值

Localizations widget用于加載和(hé)查找包含本地(dì)化值的集合的對象。應用程序通(tōng)過Localizations.of(context,type)來引用這(zhè)些對象。 如(rú)果設備的區(qū)域設置發生更改,則Localizations widget會自(zì)動加載新區(qū)域設置的值,然後重新構建使用它們的widget。 發生這(zhè)種情況是因為(wèi)Localizations像InheritedWidget一(yī)樣工(gōng)作(zuò) 。 當build函數(shù)引用了(le)繼承的widget時(shí),會創建對繼承的widget的隐式依賴關系。當繼承的widget發生更改(Localizations widget的區(qū)域設置發生更改時(shí)),将重建其依賴的上(shàng)下(xià)文。

本地(dì)化值由Localizations widget的 LocalizationsDelegates 列表加載 。 每個委托必須定義一(yī)個異步load() 方法,以生成封裝了(le)一(yī)系列本地(dì)化值的對象。通(tōng)常這(zhè)些對象為(wèi)每個本地(dì)化值定義一(yī)個方法。

在大型應用程序中,不同的模塊或軟件包可(kě)能(néng)會與自(zì)己的本地(dì)化捆綁在一(yī)起。 這(zhè)就是Localizations widget管理對象表的原因,每個LocalizationsDelegate都(dōu)有一(yī)個(對象表)。 要(yào)檢索由LocalizationsDelegateload方法之一(yī)産生的對象,可(kě)以指定一(yī)個BuildContext和(hé)對象的類型。

例如(rú),Material Component widgets的本地(dì)化字符串由MaterialLocalizations類定義。 此類的實例由MaterialApp類提供的LocalizationDelegate創建。 它們可(kě)以通(tōng)過Localizations.of被獲取到:

Localizations.of(context, MaterialLocalizations);

這(zhè)個特殊的Localizations.of()表達式經常使用,所以MaterialLocalizations類提供了(le)一(yī)個方便的簡寫:

static MaterialLocalizations of(BuildContext context) {

return Localizations.of(context, MaterialLocalizations);

}

/// References to the localized values defined by MaterialLocalizations

/// are typically written like this:

tooltip: MaterialLocalizations.of(context).backButtonTooltip,

使用打包好的LocalizationsDelegates

為(wèi)了(le)盡可(kě)能(néng)小而且簡單,flutter軟件包中僅提供美國(guó)英語值的MaterialLocalizations和(hé)WidgetsLocalizations接口的實現。 這(zhè)些實現類分别稱為(wèi)DefaultMaterialLocalizations和(hé)DefaultWidgetsLocalizations。 除非與應用程序的localizationsDelegates參數(shù)指定了(le)相同基本類型的不同delegate,否則它們會自(zì)動包含 。

flutter_localizations軟件包包含稱為(wèi)GlobalMaterialLocalizations和(hé)GlobalWidgetsLocalizations的本地(dì)化接口的多語言實現。 國(guó)際化的應用程序必須按照設置國(guó)際化應用程序中的說明(míng)為(wèi)這(zhè)些類指定本地(dì)化代理 。

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

],

// ...

)

全局本地(dì)化delegates構造相應類的特定于語言環境的實例。例如(rú),GlobalMaterialLocalizations.delegate是一(yī)個産生GlobalMaterialLocalizations實例的LocalizationsDelegate。

截至2017年(nián)10月,國(guó)際化代理的類支持約15種語言

為(wèi)應用的本地(dì)化資源定義一(yī)個類

将所有這(zhè)些放在一(yī)起用于國(guó)際化應用程序通(tōng)常從(cóng)封裝應用程序本地(dì)化值的類開(kāi)始。下(xià)面的例子是這(zhè)些類的典型例子。

這(zhè)個示例的完整源代碼

本示例基于intl包提供的API和(hé)工(gōng)具 。指定本地(dì)化資源的另一(yī)個類描述了(le)一(yī)個不依賴于intl包的示例。

DemoLocalizations類包含應用程序的字符串(僅用于示例),該字符串被翻譯為(wèi)應用程序支持的語言環境。 使用Dart的intl 包生成的函數(shù)initializeMessages()來加載翻譯的字符串,并使用Intl.message()查找它們。

class DemoLocalizations {

static Future 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(context, DemoLocalizations);

}

String get title {

return Intl.message(

'Hello World',

name: 'title',

desc: 'Title for the Demo application',

);

}

}

基于intl包的類導入生成的message目錄,該目錄提供initializeMessages()函數(shù)和(hé)每個語言環境的後備存儲Intl.message()。 message目錄由一(yī)個intl工(gōng)具生成,該工(gōng)具分析包含Intl.message()調用的類的源代碼。在這(zhè)個示例中,這(zhè)是DemoLocalizations類。

指定應用程序的supportedLocales參數(shù)

雖然Flutter的Material Components library包含對大約16種語言的支持,但(dàn)默認情況下(xià)僅提供英文。 開(kāi)發人(rén)員(yuán)需要(yào)決定支持哪種語言,因為(wèi)工(gōng)具庫支持與應用程序不同的一(yī)組語言環境是沒有意義的。

MaterialAppsupportedLocales參數(shù)限制語言環境更改。 當用戶更改其設備上(shàng)的區(qū)域設置時(shí),新區(qū)域如(rú)果是列表的成員(yuán),則應用程序的Localizations widget 就适用于該區(qū)域。如(rú) 果找不到設備區(qū)域設置的精确匹配項(譯者語:指語言和(hé)地(dì)區(qū)同時(shí)匹配,如(rú)中文,中國(guó)),則使用第一(yī)個匹配區(qū)域設置languageCode(譯者語:隻設置語言,而不指定地(dì)區(qū))。 如(rú)果失敗,則supportedLocales使用列表的第一(yī)個元素 。

就之前的DemoApp示例而言,該應用隻接受美國(guó)英語或加拿(ná)大法語語言環境,并将美國(guó)英語(列表中的第一(yī)個語言環境)替換為(wèi)其他(tā)任何內(nèi)容。

可(kě)以提供一(yī)個localeResolutionCallback,在應用獲取用戶設置的語言區(qū)域時(shí)會被回調。 例如(rú),要(yào)讓您的應用程序無條件接受用戶選擇的任何區(qū)域設置:

class DemoApp extends StatelessWidget {

@override

Widget build(BuildContext context) {

return new MaterialApp(

localeResolutionCallback(Locale locale, Iterable supportedLocales) {

return locale;

}

// ...

);

}

}

指定本地(dì)化資源的另一(yī)個類

之前的DemoApp示例是根據Dartintl包定義的。為(wèi)了(le)簡單起見(jiàn),開(kāi)發人(rén)員(yuán)可(kě)以選擇自(zì)己的方法來管理本地(dì)化值,也可(kě)以與不同的i18n框架進行(xíng)集成。 這(zhè)個示例的完整源代碼

在此版本的DemoApp中,包含應用程序本地(dì)化的類DemoLocalizations将直接在每種語言Map中包含其所有的翻譯:

class DemoLocalizations {

DemoLocalizations(this.locale);

final Locale locale;

static DemoLocalizations of(BuildContext context) {

return Localizations.of(context, DemoLocalizations);

}

static Map> _localizedValues = {

'en': {

'title': 'Hello World',

},

'es': {

'title': 'Hola Mundo',

},

};

String get title {

return _localizedValues[locale.languageCode]['title'];

}

}

在簡單的國(guó)際化應用中, DemoLocalizationsDelegate略有不同。它的load方法返回一(yī)個SynchronousFuture, 因為(wèi)不需要(yào)進行(xíng)異步加載。

class DemoLocalizationsDelegate extends LocalizationsDelegate {

const DemoLocalizationsDelegate();

@override

bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);

@override

Future load(Locale locale) {

return new SynchronousFuture(new DemoLocalizations(locale));

}

@override

bool shouldReload(DemoLocalizationsDelegate old) => false;

}

附錄: 使用Dart intl工(gōng)具

在使用Dart intl包構建API之前, 您需要(yào)查看(kàn)intl包的文檔。以下(xià)是根據intl軟件包本地(dì)化應用程序的過程摘要(yào)。

示例程序依賴于一(yī)個生成的源文件l10n/messages_all.dart ,它定義了(le)應用程序使用的所有本地(dì)化字符串。

重新構建 l10n/messages_all.dart 需要(yào)兩個步驟.

将應用程序的根目錄作(zuò)為(wèi)當前目錄,從(cóng)lib/main.dart生成l10n/intl_messages.arb

$ flutter pub pub run intl_translation:extract_to_arb --output-dir=lib/i10n lib/main.dart

該intl_messages.arb文件是一(yī)個JSON格式的map,擁有一(yī)個在main.dart中定義的Intl.message()函數(shù)入口。 此文件作(zuò)為(wèi)英語和(hé)西(xī)班牙語翻譯的一(yī)個模闆,intl_en.arb和(hé)intl_es.arb。這(zhè)些翻譯是由您,開(kāi)發人(rén)員(yuán)創建的。

使用應用程序的根目錄作(zuò)為(wèi)當前目錄,為(wèi)每個intl_.arb文件生成intl_messages_.dart,并在intl_messages_all.dart中導入所有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)來加載本地(dì)化的message并使用Intl.message()來查找它們。

網站建設開(kāi)發|APP設計開(kāi)發|小程序建設開(kāi)發
下(xià)一(yī)篇:Flutter 使用 packages
上(shàng)一(yī)篇:Flutter 路由和(hé)導航