一、国际化配置

国际化中文文档:https://flutter-io.cn/docs/development/accessibility-and-localization/internationalization

默认情况下,Flutter 支持的是美式英语的本地化,因此如果要实现其他语言,可以借助 flutter_localizations 这个库

官方文档说明:在 ios 上可能还需要借助 flutter_cupertino_localizations,但实际上如果两个库都引入会报错误

1、加入库依赖

虽然我加入了 flutter_cupertino_localizations 这个库,但如果在代码中引用了,会报错误

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  flutter_cupertino_localizations: ^1.0.1

2、引入库

import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_cupertino_localizations/flutter_cupertino_localizations.dart'; // 会引起错误

3、在 MaterialApp 中配置国际化

下面的配置中,在 MaterialApp 结构的 APP 中可以配置 localizationsDelegatessupportedLocales ,其中 delegate 用来初始化本地化的字符串和一些值,以及文本的排列等。

supportedLocales 则是可以支持具体的语言,本身 Locale 支持直接通过 new Locale('zh') 的方式创建实例,当然官方还是建议通过 fromSubtags 的方式去创建,因为支持设置文字代码。

const Locale.fromSubtags({
  String languageCode = 'und',
  this.scriptCode,
  String countryCode,
})
return MaterialApp(
  localizationsDelegates: [
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],
  supportedLocales: [
    const Locale.fromSubtags(languageCode: 'zh'),
    const Locale.fromSubtags(languageCode: 'en'),
  ],
  home: Scaffold(
    appBar: AppBar(
      title: Text('日期时间选择'),
      backgroundColor: Colors.pink,
    ),
    body: HomeContent(),
  ),
);

当然上面的代码其实是没有用到 import 'package:flutter_cupertino_localizations/flutter_cupertino_localizations.dart'; 这个包的,因为 GlobalCupertinoLocalizations.delegate,,如果引入了,就会报错:在 flutter_localizations 和 flutter_cupertino_localizations 两个包中都有声明

这其实是一个很大的坑,因为本身 flutter_localizations 内部已经实现了 export 'src/l10n/generated_cupertino_localizations.dart';

flutter_localizations 的入口:

// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// Localizations for the Flutter library
library flutter_localizations;

export 'src/cupertino_localizations.dart';
export 'src/l10n/generated_cupertino_localizations.dart';
export 'src/l10n/generated_material_localizations.dart';
export 'src/material_localizations.dart';
export 'src/widgets_localizations.dart';

flutter_cupertino_localizations 的入口:

// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// Localizations for the Flutter library
library flutter_cupertino_localizations;

export 'src/l10n/localizations.dart';
export 'src/cupertino_localizations.dart';

二、Flutter 的日期选择

为什么给先说国际化,因为 Flutter 的日期选择方法 showDatePicker 默认是因为的, 需要国际化配置才能生效

showDatePicker 的构造函数

Future<DateTime> showDatePicker({
  @required BuildContext context,
  @required DateTime initialDate,
  @required DateTime firstDate,
  @required DateTime lastDate,
  SelectableDayPredicate selectableDayPredicate,
  DatePickerMode initialDatePickerMode = DatePickerMode.day,
  Locale locale,
  TextDirection textDirection,
  TransitionBuilder builder,
})

1、打开日期选择弹框

showDatePicker 是异步方法,需要通过 async 指定操作,通过 locale 可以指定具体的语言。

如果没有触发选择就关掉了弹框,可能返回值是 null,因此需要判断下。

  void _showDatePicker() async {
    DateTime tmpDate = await showDatePicker(
      context: this.context,
      initialDate: this._date,
      firstDate: DateTime(1900),
      lastDate: DateTime(3000),
      locale: Locale.fromSubtags(languageCode: 'zh'),
    );
    if (tmpDate != null) {
      setState(() {
        this._date = tmpDate;
      });
    }
  }

2、打开时间选择弹框

showTimePicker 这个方法让人无语,因为他并不支持传入 Locale,在调用的时候指定 locale。

而是在组件实现的时候,依赖了 MaterialLocalizations APP 层级的 locale 配置

因此当你只配置了本地化是中文时,就可以直接显示中文:

      supportedLocales: [
//        const Locale.fromSubtags(languageCode: 'en'),
        const Locale.fromSubtags(languageCode: 'zh'),
      ],
  void _showTimePicker() async {
    TimeOfDay tmpTime = await showTimePicker(
      context: this.context,
      initialTime: TimeOfDay.fromDateTime(this._date),
    );
    if (tmpTime != null) {
      setState(() {
        this._time = tmpTime;
      });
    }
  }

4、实现简单的 UI

return Column(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        InkWell(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(this._formatDate()),
              Icon(Icons.arrow_drop_down)
            ],
          ),
          onTap: this._showDatePicker,
        ),
        InkWell(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(this._formatTime()),
              Icon(Icons.arrow_drop_down)
            ],
          ),
          onTap: this._showTimePicker,
        ),
      ],
    )
  ],
);

三、中文日期选择效果

04743-6mbmgsn6byo.png

91032-srateqdkf6b.png

四、完整代码

https://github.com/postbird/FlutterHelloWorldDemo/blob/dev1/demo1/lib/bak/main.44%E6%97%A5%E6%9C%9F%E9%80%89%E6%8B%A9%26%E5%9B%BD%E9%99%85%E5%8C%96.dart