TextFieldの長押しでクラッシュする問題の対応方法

__2019/08/01 追記__
__現在は、GlobalCupertinoLocalizations.delegateが実装されているので、こちらを使えば以下の処理をしなくても大丈夫そうです。__


Flutterで多言語対応をした場合にiosで言語を日本語にして、TextFieldで長押しするとクラッシュします。
こんなやつです。

<img width="250" alt="error.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/10494/bde0a324-fad7-3931-fd1b-9c5e1e1175ff.png">

```
flutter: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
flutter: The following NoSuchMethodError was thrown building _TextSelectionToolbar(dirty):
flutter: The getter 'pasteButtonLabel' was called on null.
flutter: Receiver: null
flutter: Tried calling: pasteButtonLabel
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0      Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
flutter: #1      _TextSelectionToolbar.build (package:flutter/src/cupertino/text_selection.dart:94:51)
・・・
```

原因は、長押ししたときに表示されるポップアップメニューに対応するラベルがないためです。

# 解決策

新たにios用のdelegateを作成して、MaterialAppのlocalizationsDelegatesに指定します。
CupertinoLocalizationsを実装します。

```japanese_cupertino_localizations.dart
class JapaneseCupertinoLocalizations implements CupertinoLocalizations {
  final _materialDelegate = GlobalMaterialLocalizations.delegate;

  MaterialLocalizations materialLocalizations;

  static const LocalizationsDelegate<CupertinoLocalizations> delegate = _JapaneseDelegate();

  static Future<CupertinoLocalizations> load(Locale locale) async {
    var localizations = JapaneseCupertinoLocalizations();
    await localizations._init();
    return SynchronousFuture<CupertinoLocalizations>(localizations);
  }

  Future _init() async {
    materialLocalizations = await _materialDelegate.load(const Locale('ja'));
  }

  @override
  String get alertDialogLabel => materialLocalizations.alertDialogLabel;

  @override
  String get anteMeridiemAbbreviation => materialLocalizations.anteMeridiemAbbreviation;

  @override
  String get copyButtonLabel => materialLocalizations.copyButtonLabel;

  @override
  String get cutButtonLabel => materialLocalizations.cutButtonLabel;

  @override
  DatePickerDateOrder get datePickerDateOrder => DatePickerDateOrder.mdy;

  @override
  DatePickerDateTimeOrder get datePickerDateTimeOrder => DatePickerDateTimeOrder.date_time_dayPeriod;

  @override
  String datePickerDayOfMonth(int dayIndex) => dayIndex.toString();

  @override
  String datePickerHour(int hour) => hour.toString().padLeft(2, "0");

  @override
  String datePickerHourSemanticsLabel(int hour) => "$hour時";

  @override
  String datePickerMediumDate(DateTime date) => materialLocalizations.formatMediumDate(date);

  @override
  String datePickerMinute(int minute) => minute.toString().padLeft(2, '0');

  @override
  String datePickerMinuteSemanticsLabel(int minute) => "$minute分";

  @override
  String datePickerMonth(int monthIndex) => "$monthIndex";

  @override
  String datePickerYear(int yearIndex) => yearIndex.toString();

  @override
  String get pasteButtonLabel => materialLocalizations.pasteButtonLabel;

  @override
  String get postMeridiemAbbreviation => materialLocalizations.postMeridiemAbbreviation;

  @override
  String get selectAllButtonLabel => materialLocalizations.selectAllButtonLabel;

  @override
  String timerPickerHour(int hour) => hour.toString().padLeft(2, "0");

  @override
  String timerPickerHourLabel(int hour) => "${hour.toString().padLeft(2, '0')}時";

  @override
  String timerPickerMinute(int minute) => minute.toString().padLeft(2, "0");

  @override
  String timerPickerMinuteLabel(int minute) => "${minute.toString().padLeft(2, '0')}分";

  @override
  String timerPickerSecond(int second) => second.toString().padLeft(2, "0");

  @override
  String timerPickerSecondLabel(int second) => "${second.toString().padLeft(2, '0')}秒";
}

class _JapaneseDelegate extends LocalizationsDelegate<CupertinoLocalizations> {
  const _JapaneseDelegate();

  @override
  bool isSupported(Locale locale) {
    return locale.languageCode == 'ja';
  }

  @override
  Future<CupertinoLocalizations> load(Locale locale) {
    return JapaneseCupertinoLocalizations.load(locale);
  }

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

多言語対応で指定しているdelegateに追記するだけです。

```diff
 MaterialApp(
         localizationsDelegates: [
           MyLocalizationsDelegate.delegate,
+          JapaneseCupertinoLocalizations.delegate,
           GlobalMaterialLocalizations.delegate,
           GlobalWidgetsLocalizations.delegate,
         ],
         supportedLocales: supportedLocales
```

ちなみに上記の ```MyLocalizationsDelegate``` は多言語対応の時に作成したクラスです。詳細は[こちらの記事](https://qiita.com/jiro-aqua/items/fd9896682ca09018fdd3)が参考になります。