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

参考

相关推荐
马拉萨的春天1 小时前
flutter 项目结构目录以及pubspec.ymal等文件描述
flutter
bst@微胖子17 小时前
Flutter项目之登录注册功能实现
开发语言·javascript·flutter
无知的前端21 小时前
Flutter 一文精通Isolate,使用场景以及示例
android·flutter·性能优化
yidahis21 小时前
Flutter 运行新建项目也报错?
flutter·trae
木马不在转1 天前
Flutter-权限permission_handler插件配置
flutter
江上清风山间明月1 天前
一周掌握Flutter开发--9. 与原生交互(下)
flutter·交互·原生·methodchannel
GeniuswongAir1 天前
Flutter极速接入IM聊天功能并支持鸿蒙
flutter·华为·harmonyos
sayen1 天前
记录 flutter 文本内容展示过长优化
前端·flutter
勤劳打代码1 天前
剑拔弩张——焦点竞争引的发输入失效
flutter·客户端·设计