做自(zì)由與創造的先行者

Flutter 國際化

Flutter開(kāi)發手冊

設置一個國際化的應用(yòng)程序: the flutter_localizations package

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

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

dependencies:

flutter:

sdk: flutter

flutter_localizations:

sdk: flutter

接下(xià)來(lái),導入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òng)程序類似,隻是不需要GlobalMaterialLocalizations.delegate。

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

有關這(zhè)些(xiē)應用(yòng)程序屬性的更多信息,它們所依賴的類型以及如何國際化Flutter應用(yòng)程序,這(zhè)些(xiē)都可以在下(xià)面找到(dào)。

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

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

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

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

Locale myLocale = Localizations.localeOf(context);

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

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

本地化值由Localizations widget的 LocalizationsDelegates 列表加載 。 每個委托必須定義一個異步load() 方法,以生成封裝了(le)一系列本地化值的對(duì)象。通常這(zhè)些(xiē)對(duì)象爲每個本地化值定義一個方法。

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

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

Localizations.of(context, MaterialLocalizations);

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

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,

使用(yòng)打包好(hǎo)的LocalizationsDelegates

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

flutter_localizations軟件包包含稱爲GlobalMaterialLocalizations和(hé)GlobalWidgetsLocalizations的本地化接口的多語言實現(xiàn)。 國際化的應用(yòng)程序必須按照設置國際化應用(yòng)程序中的說明(míng)爲這(zhè)些(xiē)類指定本地化代理(lǐ) 。

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構造相應類的特定于語言環境的實例。例如,GlobalMaterialLocalizations.delegate是一個産生GlobalMaterialLocalizations實例的LocalizationsDelegate。

截至2017年10月,國際化代理(lǐ)的類支持約15種語言

爲應用(yòng)的本地化資源定義一個類

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

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

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

DemoLocalizations類包含應用(yòng)程序的字符串(僅用(yòng)于示例),該字符串被翻譯爲應用(yòng)程序支持的語言環境。 使用(yòng)Dart的intl 包生成的函數initializeMessages()來(lái)加載翻譯的字符串,并使用(yòng)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()函數和(hé)每個語言環境的後備存儲Intl.message()。 message目錄由一個intl工(gōng)具生成,該工(gōng)具分析包含Intl.message()調用(yòng)的類的源代碼。在這(zhè)個示例中,這(zhè)是DemoLocalizations類。

指定應用(yòng)程序的supportedLocales參數

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

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

就之前的DemoApp示例而言,該應用(yòng)隻接受美(měi)國英語或加拿大(dà)法語語言環境,并将美(měi)國英語(列表中的第一個語言環境)替換爲其他(tā)任何内容。

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

class DemoApp extends StatelessWidget {

@override

Widget build(BuildContext context) {

return new MaterialApp(

localeResolutionCallback(Locale locale, Iterable supportedLocales) {

return locale;

}

// ...

);

}

}

指定本地化資源的另一個類

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

在此版本的DemoApp中,包含應用(yòng)程序本地化的類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'];

}

}

在簡單的國際化應用(yòng)中, DemoLocalizationsDelegate略有不同。它的load方法返回一個SynchronousFuture, 因爲不需要進行異步加載。

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;

}

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

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

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

重新構建 l10n/messages_all.dart 需要兩個步驟.

将應用(yòng)程序的根目錄作(zuò)爲當前目錄,從(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文(wén)件是一個JSON格式的map,擁有一個在main.dart中定義的Intl.message()函數入口。 此文(wén)件作(zuò)爲英語和(hé)西班牙語翻譯的一個模闆,intl_en.arb和(hé)intl_es.arb。這(zhè)些(xiē)翻譯是由您,開(kāi)發人員創建的。

使用(yòng)應用(yòng)程序的根目錄作(zuò)爲當前目錄,爲每個intl_.arb文(wén)件生成intl_messages_.dart,并在intl_messages_all.dart中導入所有message文(wén)件:

$ 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類使用(yòng)生成的initializeMessages() 函數(定義在intl_messages_all.dart)來(lái)加載本地化的message并使用(yòng)Intl.message()來(lái)查找它們。

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