flutter_localizations
在 Flutter 中如果需要支持多语言 ,则须添加 flutter_localizations
包,代码示例如下:
yaml
dependencies:
flutter_localizations:
sdk: flutter
包下载完成后,就可以指定 MaterialApp
的 localizationsDelegates
和 supportedLocales
。其中 localizationsDelegates
表示本地化委托,用于更改Flutter Widget默认的提示语,按钮text等;而 supportedLocales
表示我们的应用支持的语言列表。代码示例如下:
csharp
import 'package:flutter_localizations/flutter_localizations.dart';
MaterialApp(
localizationsDelegates: [
// 本地化的代理类
// GlobalMaterialLocalizations.delegate 为Material 组件库提供的本地化
// 的字符串和其他值,它可以使Material 组件支持多语言
GlobalMaterialLocalizations.delegate,
// GlobalWidgetsLocalizations.delegate 定义组件默认的文本方向,
// 从左到右或从右到左,这是因为有些语言的阅读习惯并不是从左到右,比如如阿拉伯语就是从右向左的
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
// Locale 用来标识用户的语言环境
const Locale('en', 'US'), // 美国英语
const Locale('zh', 'CN'), // 中文简体
//其他Locales
],
// ...
)
添加完上述代码后,默认组件(即Material组件库)的文本内容根据系统的语言进行了转换。但是,我们自己代码中设置的文本并不会转换。如果要让我们自己的组件支持多语言,则需要自定义 Localizations
。
自定义 Localizations
第一步创建我们自己的 Localizations 类,该类会根据不同的语言返回不同的标题字符串值,代码示例如下:
arduino
//Locale资源类
class DemoLocalizations {
DemoLocalizations(this.isZh);
//是否为中文
bool isZh = false;
//为了使用方便,我们定义一个静态方法
static DemoLocalizations of(BuildContext context) {
return Localizations.of<DemoLocalizations>(context, DemoLocalizations);
}
//Locale相关值,title为应用标题
String get title {
return isZh ? "Flutter应用" : "Flutter APP";
}
//... 其他的值
}
第二步,实现Delegate类。Delegate类的职责是在Locale改变时加载新的Locale资源,代码示例如下:
dart
class DemoLocalizationsDelegate
extends LocalizationsDelegate<DemoLocalizations> {
const DemoLocalizationsDelegate();
// 判断是否支持某个Local
@override
bool isSupported(Locale locale) => ['en', 'zh'].contains(locale.languageCode);
// Flutter会调用此类加载相应的Locale资源类
@override
Future<DemoLocalizations> load(Locale locale) {
print("$locale");
return SynchronousFuture<DemoLocalizations>(
DemoLocalizations(locale.languageCode == "zh"),
);
}
// shouldReload的返回值决定当Localizations组件重新build时,是否调用load方法重新加载Locale资源
// 但事实上,每当Locale改变时Flutter都会再调用load方法加载新的Locale,
// 无论shouldReload返回true还是false
@override
bool shouldReload(DemoLocalizationsDelegate old) => false;
}
第三步,往代码中添加多语言的支持
csharp
// 设置代理
localizationsDelegates: [
// 本地化的代理类
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
// 注册我们的Delegate
DemoLocalizationsDelegate()
],
// 使用 DemoLocalizations 获取语言的值
Scaffold(
appBar: AppBar(
//使用Locale title
title: Text(DemoLocalizations.of(context).title),
),
... //省略无关代码
)
三方库
从上面可以看到,使用默认的库实现多语言支持非常麻烦。这里推荐使用三方的多语言库,这里介绍两种,分别是 easy_localization 和 intl。
easy_localization
easy_localization 的配置
首先添加依赖
yaml
dependencies:
easy_localization: ^3.0.7+1
添加完成之后,在Android设备上就可以直接使用easy_localization库了。但如果你使用的是iOS设备的话,还需要在其ios/Runner/Info.plist目录中添加如下代码:
xml
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>nb</string>
</array>
使用easy_localization国际化库,必须为它提供一个可用的翻译文件目录,就像配置图片资源文件一样。这里,我们将翻译文件放置在asset/langs目录下
需要注意:翻译文件的命名格式为 / <math xmlns="http://www.w3.org/1998/Math/MathML"> 语言码 − {语言码}- </math>语言码−{国家/地区码}.json,如果还需要配置其他语言,可以按照这个格式进行相应的配置。然后,我们还需要将翻译文件配置到pubspec.yaml文件中,代码如下所示:
bash
flutter:
assets:
- asset/langs/en-US.json
- asset/langs/zh-CN.json
最后,我们在 main.dart 文件中增加 easy_localization 的配置,代码如下所示:
less
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:easy_localization/easy_localization.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
runApp(
EasyLocalization(
supportedLocales: [Locale('en', 'US'), Locale('de', 'DE')],
path: 'assets/translations', // 语言资源包目录
fallbackLocale: Locale('en', 'US'),
child: MyApp()
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
home: MyHomePage()
);
}
}
easy_localization 的使用
我们首先在 en-US.json与zh-CN.json 中设置对应的数据,示例如下:
json
//en-US.json文件数据
{
"materialapp title": "Flutter Demo"
}
//zh-CN.json文件数据
{
"materialapp title": "Flutter示例",
}
然后我们可以在项目中使用 tr
组件,该组件会把当前语言对应的文本传递给 Text 组件。代码示例如下:
bash
Text(tr('materialapp title'))
我们可以使用 EasyLocalization.of(context).locale =Locale('en', 'US')
手动切换语言来查看效果。
intl
如下代码所示,先添加依赖
yaml
dependencies:
intl: ^0.20.2
然后在 pubspec.yaml 文件中,启用 generate 标志。代码示例如下:
yaml
# The following section is specific to Flutter.
flutter:
generate: true # Add this line
之后再 Flutter 项目的根目录下创建一个 l10n.yaml 的文件,文件内容如下:
makefile
# 将应用资源包 (.arb) 的输入路径指定为 ${FLUTTER_PROJECT}/lib/l10n
arb-dir: lib/l10n
# 将英文的语言模板设定为 app_en.arb
template-arb-file: app_en.arb
# 指定 Flutter 生成本地化内容到 app_localizations.dart 文件
output-localization-file: app_localizations.dart
在 ${FLUTTER_PROJECT}/lib/l10n
中,添加 app_en.arb
模板文件。如下
perl
{
"helloWorld": "Hello World!",
"@helloWorld": {
"description": "The conventional newborn programmer greeting"
}
}
然后在同一目录,添加一个 app_es.arb 文件,对同一条消息做西班牙语的翻译
json
{
"helloWorld": "¡Hola Mundo!"
}
完成上述步骤后,执行 flutter run
或者 flutter gen-l10n
命令来生成本地化文件 AppLocalizations.dart
。最后,我们需要在 main.drat 文件中增加对应的配置。代码示例如下:
csharp
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
...
const MaterialApp(
title: 'Localizations Sample App',
localizationsDelegates: [
AppLocalizations.delegate, // Add this line
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: [
Locale('en'), // English
Locale('es'), // Spanish
],
home: MyHomePage(),
);
完成上述配置后,我们就可以使用 AppLocalizations 文件了,代码示例如下:
arduino
appBar: AppBar(
// The [AppBar] title text should update its message
// according to the system locale of the target platform.
// Switching between English and Spanish locales should
// cause this text to update.
title: Text(AppLocalizations.of(context)!.helloWorld),
),