2019/08/01 追記
現在は、GlobalCupertinoLocalizations.delegateが実装されているので、こちらを使えば以下の処理をしなくても大丈夫そうです。
Flutterで多言語対応をした場合にiosで言語を日本語にして、TextFieldで長押しするとクラッシュします。
こんなやつです。
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に追記するだけです。
MaterialApp(
localizationsDelegates: [
MyLocalizationsDelegate.delegate,
+ JapaneseCupertinoLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: supportedLocales
ちなみに上記の MyLocalizationsDelegate
は多言語対応の時に作成したクラスです。詳細はこちらの記事が参考になります。