Flutter 教程(十一)多语言支持

flutter_localizations

在 Flutter 中如果需要支持多语言 ,则须添加 flutter_localizations 包,代码示例如下:

yaml 复制代码
dependencies:
  flutter_localizations:
    sdk: flutter

包下载完成后,就可以指定 MaterialApplocalizationsDelegatessupportedLocales。其中 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_localizationintl

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),
),

参考

相关推荐
桃花仙丶37 分钟前
iOS/Flutter混合开发之PlatformView配置与使用
flutter·ios·xcode·swift·dart
一名普通的程序员4 小时前
Flutter GetX 核心技巧:GetWidget 的深度解析
flutter
一名普通的程序员5 小时前
Flutter GetX 核心技巧:GetView / GetWidget 的魔法解密
flutter
只可远观5 小时前
Mac搭建Flutter IOS环境详细指南
前端·flutter·macos·ios
一名普通的程序员6 小时前
Flutter GetX 状态管理新姿势:Rx扩展方法实践指南
flutter
一名普通的程序员6 小时前
GetX框架里容易被忽略的那些小知识(六)
flutter
孤鸿玉6 小时前
[Flutter小试牛刀] 低配版signals,添加局部刷新
前端·flutter
louisgeek7 小时前
Flutter ChangeNotifier 和 ValueNotifier 的区别
flutter
zhujiaming7 小时前
鸿蒙端应用适配使用开源flutter值得注意的一些问题
前端·flutter·harmonyos
ZhuAiQuan11 小时前
[flutter]切换国内源(window)
flutter