本文介绍了如何对Flutter应用进行国际化和多语言支持如果您的应用可能会给另一种语言的用户使用,那么您需要“国际化”它。这意味着您在编写应用程序时需要为应用程序支持的每种语言环境...
你将会学到什么:
1. 如何跟踪设备的区域(locale)设置(用户的首选语言)
2. 如何管理特定于区域环境(locale)的应用程序值.
3. 如何使应用程序支持多区域环境
如果您的应用可能会给另一种语言的用户使用,那么您需要“国际化”它。这意味着您在编写应用程序时需要为应用程序支持的每种语言环境, 设置“本地化”的一些值,如文本和布局。Flutter提供一些widgets和类,以帮助实现国际化,而Flutter的库本身也是国际化的。
接下来的教程主要是根据Flutter MaterialApp类编写的,因为大多数应用程序都是这样编写的。根据较低级别的WidgetsApp类编写的应用程序也可以使用相同的类和逻辑进行国际化。
国际化APP的例子:如果您想通过阅读国际化Flutter应用程序的代码开始,下面是两个小例子。第一个旨在尽可能简单,第二个使用intl包提供的API和工具。 如果您没用过Dart的intl包,请参阅使用Dart intl 工具。
默认情况下,Flutter仅提供美国英语本地化。要添加对其他语言的支持,应用程序必须指定其他MaterialApp属性,并包含一个名为的单独包-"flutter_localizations"。 截至2017年10月,该软件包支持15种语言。
要使用flutter_localizations,请将该包作为依赖项添加到您的pubspec.yaml
文件中:
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
接下来,导入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的应用程序类似,只是不需要GlobalMaterialLocalizations.delegate
。
localizationsDelegates
列表中的元素是生成本地化值集合的工厂。GlobalMaterialLocalizations.delegate
为Material Components库提供了本地化的字符串和其他值。
GlobalWidgetsLocalizations.delegate
定义widget默认的文本方向,从左到右或从右到左。
有关这些应用程序属性的更多信息,它们所依赖的类型以及如何国际化Flutter应用程序,这些都可以在下面找到。
该Locale
类是用来识别用户的语言环境。
移动设备支持通过系统设置菜单为所有应用程序设置区域。国际化应用程序通过显示区域设置特定的值进行响应。
例如,如果用户将设备的语言环境从英语切换到法语,则显示“Hello World”的文本widget将用“Bonjour le monde”重建。
Localizations
小部件定义其子项的区域设置以及子项依赖的本地化资源。
如果系统的语言环境发生变化,WidgetsApp将创建一个Localizations widget并重建它。
您始终可以通过以下方式查找应用的当前区域设置:
Locale myLocale = Localizations.localeOf(context);
Localizations widget用于加载和查找包含本地化值的集合的对象。应用程序通过Localizations.of(context,type)
来引用这些对象。
如果设备的区域设置发生更改,则Localizations widget会自动加载新区域设置的值,然后重新构建使用它们的widget。
发生这种情况是因为Localizations像InheritedWidget一样工作 。
当build函数引用了继承的widget时,会创建对继承的widget的隐式依赖关系。当继承的widget发生更改(Localizations widget的区域设置发生更改时),将重建其依赖的上下文。
本地化值由Localizations widget的 LocalizationsDelegates 列表加载 。 每个委托必须定义一个异步load() 方法,以生成封装了一系列本地化值的对象。通常这些对象为每个本地化值定义一个方法。
在大型应用程序中,不同的模块或软件包可能会与自己的本地化捆绑在一起。
这就是Localizations widget管理对象表的原因,每个LocalizationsDelegate都有一个(对象表)。
要检索由LocalizationsDelegateload
方法之一产生的对象,可以指定一个BuildContext和对象的类型。
例如,Material Component widgets的本地化字符串由MaterialLocalizations类定义。
此类的实例由MaterialApp类提供的LocalizationDelegate创建。
它们可以通过Localizations.of
被获取到:
Localizations.of<MaterialLocalizations>(context, MaterialLocalizations);
这个特殊的Localizations.of()
表达式经常使用,所以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接口的实现。 这些实现类分别称为DefaultMaterialLocalizations和DefaultWidgetsLocalizations。 除非与应用程序的localizationsDelegates参数指定了相同基本类型的不同delegate,否则它们会自动包含 。
flutter_localizations软件包包含称为GlobalMaterialLocalizations和GlobalWidgetsLocalizations的本地化接口的多语言实现。 国际化的应用程序必须按照设置国际化应用程序中的说明为这些类指定本地化代理 。
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月,国际化代理的类支持约15种语言
将所有这些放在一起用于国际化应用程序通常从封装应用程序本地化值的类开始。下面的例子是这些类的典型例子。
这个示例的完整源代码
本示例基于intl包提供的API和工具 。指定本地化资源的另一个类描述了一个不依赖于intl包的示例。
DemoLocalizations类包含应用程序的字符串(仅用于示例),该字符串被翻译为应用程序支持的语言环境。
使用Dart的intl 包生成的函数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包的类导入生成的message目录,该目录提供initializeMessages()
函数和每个语言环境的后备存储Intl.message()
。
message目录由一个intl工具生成,该工具分析包含Intl.message()调用的类的源代码。在这个示例中,这是DemoLocalizations类。
虽然Flutter的Material Components library包含对大约16种语言的支持,但默认情况下仅提供英文。 开发人员需要决定支持哪种语言,因为工具库支持与应用程序不同的一组语言环境是没有意义的。
MaterialAppsupportedLocales
参数限制语言环境更改。
当用户更改其设备上的区域设置时,新区域如果是列表的成员,则应用程序的Localizations
widget 就适用于该区域。如
果找不到设备区域设置的精确匹配项(译者语:指语言和地区同时匹配,如中文,中国),则使用第一个匹配区域设置languageCode
(译者语:只设置语言,而不指定地区)。
如果失败,则supportedLocales
使用列表的第一个元素 。
就之前的DemoApp示例而言,该应用只接受美国英语或加拿大法语语言环境,并将美国英语(列表中的第一个语言环境)替换为其他任何内容。
可以提供一个localeResolutionCallback
,在应用获取用户设置的语言区域时会被回调。
例如,要让您的应用程序无条件接受用户选择的任何区域设置:
class DemoApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
localeResolutionCallback(Locale locale, Iterable<Locale> supportedLocales) {
return locale;
}
// ...
);
}
}
之前的DemoApp示例是根据Dartintl
包定义的。为了简单起见,开发人员可以选择自己的方法来管理本地化值,也可以与不同的i18n框架进行集成。
这个示例的完整源代码
在此版本的DemoApp中,包含应用程序本地化的类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'];
}
}
在简单的国际化应用中, DemoLocalizationsDelegate略有不同。它的load方法返回一个SynchronousFuture, 因为不需要进行异步加载。
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
包构建API之前, 您需要查看intl
包的文档。以下是根据intl软件包本地化应用程序的过程摘要。
示例程序依赖于一个生成的源文件l10n/messages_all.dart
,它定义了应用程序使用的所有本地化字符串。
重新构建 l10n/messages_all.dart
需要两个步骤.
1.将应用程序的根目录作为当前目录,从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
文件是一个JSON格式的map,拥有一个在main.dart
中定义的Intl.message()
函数入口。
此文件作为英语和西班牙语翻译的一个模板,intl_en.arb
和intl_es.arb
。这些翻译是由您,开发人员创建的。
2.使用应用程序的根目录作为当前目录,为每个intl_<locale>.arb
文件生成intl_messages_<locale>.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()
函数(定义在intl_messages_all.dart
)来加载本地化的message并使用Intl.message()
来查找它们。
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。