Flutter实战(二)---多语言跨平台

前言

去年12月份,Flutter1.0正式版发布,标志着Flutter已经达到可以投入商用项目的状态,我们可以看到Google的野心,不止步于移动端,已经向桌面端(Flutter Desktop Embedding)和Web端(Hummingbird)逐步拓展,大有一统天下之趋势。

时隔三月,在2019 MWC 世界移动通信大会上,Flutter1.2发布,除了UI组件更新、动画优化和Dart语言特性改进外,我们惊喜的发现,Flutter正朝着轻应用的方向迈开强有力的步伐,支持Android APP Bundles,意味着Flutter不仅支持热重载,也开始支持热更新,代码动态交付,应用体积更小。
Flutter实战(二)---多语言跨平台

进入正题

本文主要介绍Flutter应用国际化,通常我们新建的 Flutter 应用是默认不支持多语言的,即使用户在中文环境下,显示的文字仍然是英文,比如下图所示的日期选择对话框:
Flutter实战(二)---多语言跨平台
那么怎么样将系统的这些组件国际化呢?首先需要在 pubspec.yaml 中添加如下依赖:
Flutter实战(二)---多语言跨平台
接着运行:
Flutter实战(二)---多语言跨平台
以获取依赖库。

当上面两部完成后在 main.dart 中 import 如下:

import 'package:flutter_localizations/flutter_localizations.dart’;

然后在 MaterialApp 的构造方法中给 localizationsDelegates 和 supportedLocales 两个可选参数赋值:

 supportedLocales: [
        const Locale('zh', 'CH'),
        const Locale('en', 'US'),
      ],
 localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        MyLocalizationsDelegate.delegate,
      ],

此时该应用已经支持中文和英文两种语言了,接下来就是字符串的翻译,我们知道Android原生多语言翻译是在对应语言的string.xml资源里配置相应的字符串,但是xml方式无法做到跨平台,那么Flutter的做法是自定义一个类似GlobalMaterialLocalizations的MyLocalizationsDelegate类来实现多语言:

  1. 定义一个静态Map,key为国家代号,value也是一个Map,value的map键为资源名,值为字符串
 static Map<String, Map<String, String>> _localizedValues = {
    'en’: {
      'cancel': ‘cancel',
      'confirm': ‘confirm’,
    },
    'zh': {
      'cancel': '取消',
      'confirm': '确定’,
    }
}
  1. 为每个资源名定义get方法
get cancel {
    return _localizedValues[locale.languageCode]['cancel'];
  }
get confirm {
    return _localizedValues[locale.languageCode]['confirm'];
  }
  1. 定义一个静态初始化方法
 static MyLocalizations of(BuildContext context) {
    return Localizations.of(context, MyLocalizations);
  }
  1. 实现delegate
class MyLocalizationsDelegate extends LocalizationsDelegate<MyLocalizations> {
  const MyLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) {
    return ['en', 'zh'].contains(locale.languageCode);
  }

  @override
  Future<MyLocalizations> load(Locale locale) {
    return new SynchronousFuture<MyLocalizations>(new MyLocalizations(locale));
  }

  @override
  bool shouldReload(LocalizationsDelegate<MyLocalizations> old) {
    return false;
  }

  static MyLocalizationsDelegate delegate = const MyLocalizationsDelegate();
}
  1. 使用方法
label: new Text(MyLocalizations.of(context).cancel),

至此,Flutter多语言问题就解决了。