Unverified Commit 1c7e34bb authored by Darren Austin's avatar Darren Austin Committed by GitHub

Migrate flutter_localizations to null safety. (#68645)

Migrate flutter_localizations to null safety.
parent 2a5aa294
......@@ -704,7 +704,7 @@ Future<void> _runFrameworkTests() async {
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_driver'), tableData: bigqueryApi?.tabledata, tests: <String>[path.join('test', 'src', 'real_tests')]);
await _runFlutterTest(path.join(flutterRoot, 'packages', 'integration_test'), tableData: bigqueryApi?.tabledata);
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_goldens'), tableData: bigqueryApi?.tabledata);
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_localizations'), tableData: bigqueryApi?.tabledata);
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_localizations'), tableData: bigqueryApi?.tabledata, options: soundNullSafetyOptions);
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_test'), tableData: bigqueryApi?.tabledata, options: soundNullSafetyOptions);
await _runFlutterTest(path.join(flutterRoot, 'packages', 'fuchsia_remote_debug_protocol'), tableData: bigqueryApi?.tabledata);
await _runFlutterTest(path.join(flutterRoot, 'dev', 'integration_tests', 'non_nullable'), options: mixedModeNullSafetyOptions);
......
......@@ -382,15 +382,20 @@ $factoryDeclaration
///
/// Used by [generateGetter] below.
String generateType(Map<String, dynamic> attributes) {
bool optional = false;
String type = 'String';
if (attributes != null) {
optional = attributes.containsKey('optional');
switch (attributes['x-flutter-type'] as String) {
case 'icuShortTimePattern':
return 'TimeOfDayFormat';
type = 'TimeOfDayFormat';
break;
case 'scriptCategory':
return 'ScriptCategory';
type = 'ScriptCategory';
break;
}
}
return 'String';
return type + (optional ? '?' : '');
}
/// Returns the appropriate name for getters with the given attributes.
......
......@@ -16,7 +16,6 @@ HeaderGenerator generateCupertinoHeader = (String regenerateInstructions) {
import 'dart:collection';
import 'package:flutter/foundation.dart';
import 'package:flutter/cupertino.dart';
import 'package:intl/intl.dart' as intl;
......@@ -40,14 +39,14 @@ ConstructorGenerator generateCupertinoConstructor = (LocaleInfo locale) {
/// For details on the meaning of the arguments, see [GlobalCupertinoLocalizations].
const CupertinoLocalization${locale.camelCase()}({
String localeName = '$localeName',
@required intl.DateFormat fullYearFormat,
@required intl.DateFormat dayFormat,
@required intl.DateFormat mediumDateFormat,
@required intl.DateFormat singleDigitHourFormat,
@required intl.DateFormat singleDigitMinuteFormat,
@required intl.DateFormat doubleDigitMinuteFormat,
@required intl.DateFormat singleDigitSecondFormat,
@required intl.NumberFormat decimalFormat,
required intl.DateFormat fullYearFormat,
required intl.DateFormat dayFormat,
required intl.DateFormat mediumDateFormat,
required intl.DateFormat singleDigitHourFormat,
required intl.DateFormat singleDigitMinuteFormat,
required intl.DateFormat doubleDigitMinuteFormat,
required intl.DateFormat singleDigitSecondFormat,
required intl.NumberFormat decimalFormat,
}) : super(
localeName: localeName,
fullYearFormat: fullYearFormat,
......@@ -64,7 +63,7 @@ ConstructorGenerator generateCupertinoConstructor = (LocaleInfo locale) {
const String cupertinoFactoryName = 'getCupertinoTranslation';
const String cupertinoFactoryDeclaration = '''
GlobalCupertinoLocalizations getCupertinoTranslation(
GlobalCupertinoLocalizations? getCupertinoTranslation(
Locale locale,
intl.DateFormat fullYearFormat,
intl.DateFormat dayFormat,
......
......@@ -16,7 +16,6 @@ HeaderGenerator generateMaterialHeader = (String regenerateInstructions) {
import 'dart:collection';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart' as intl;
......@@ -40,15 +39,15 @@ ConstructorGenerator generateMaterialConstructor = (LocaleInfo locale) {
/// For details on the meaning of the arguments, see [GlobalMaterialLocalizations].
const MaterialLocalization${locale.camelCase()}({
String localeName = '$localeName',
@required intl.DateFormat fullYearFormat,
@required intl.DateFormat compactDateFormat,
@required intl.DateFormat shortDateFormat,
@required intl.DateFormat mediumDateFormat,
@required intl.DateFormat longDateFormat,
@required intl.DateFormat yearMonthFormat,
@required intl.DateFormat shortMonthDayFormat,
@required intl.NumberFormat decimalFormat,
@required intl.NumberFormat twoDigitZeroPaddedFormat,
required intl.DateFormat fullYearFormat,
required intl.DateFormat compactDateFormat,
required intl.DateFormat shortDateFormat,
required intl.DateFormat mediumDateFormat,
required intl.DateFormat longDateFormat,
required intl.DateFormat yearMonthFormat,
required intl.DateFormat shortMonthDayFormat,
required intl.NumberFormat decimalFormat,
required intl.NumberFormat twoDigitZeroPaddedFormat,
}) : super(
localeName: localeName,
fullYearFormat: fullYearFormat,
......@@ -66,7 +65,7 @@ ConstructorGenerator generateMaterialConstructor = (LocaleInfo locale) {
const String materialFactoryName = 'getMaterialTranslation';
const String materialFactoryDeclaration = '''
GlobalMaterialLocalizations getMaterialTranslation(
GlobalMaterialLocalizations? getMaterialTranslation(
Locale locale,
intl.DateFormat fullYearFormat,
intl.DateFormat compactDateFormat,
......
......@@ -67,8 +67,9 @@ void validateEnglishLocalizations(File file) {
continue;
}
final bool optional = atResource.containsKey('optional');
final String description = atResource['description'] as String;
if (description == null)
if (description == null && !optional)
errorMessages.writeln('No description specified for $atResourceId');
final String plural = atResource['plural'] as String;
......@@ -78,7 +79,7 @@ void validateEnglishLocalizations(File file) {
if (!bundle.containsKey(resourceIdOther))
errorMessages.writeln('Default plural resource $resourceIdOther undefined');
} else {
if (!bundle.containsKey(resourceId))
if (!optional && !bundle.containsKey(resourceId))
errorMessages.writeln('No matching $resourceId defined for $atResourceId');
}
}
......
......@@ -1763,9 +1763,10 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
});
},
children: List<Widget>.generate(24, (int index) {
final String label = localizations.timerPickerHourLabel(index) ?? '';
final String semanticsLabel = textDirectionFactor == 1
? localizations.timerPickerHour(index) + localizations.timerPickerHourLabel(index)
: localizations.timerPickerHourLabel(index) + localizations.timerPickerHour(index);
? localizations.timerPickerHour(index) + label
: label + localizations.timerPickerHour(index);
return Semantics(
label: semanticsLabel,
......@@ -1793,7 +1794,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
child: _buildHourPicker(additionalPadding, selectionOverlay),
),
_buildLabel(
localizations.timerPickerHourLabel(lastSelectedHour ?? selectedHour!),
localizations.timerPickerHourLabel(lastSelectedHour ?? selectedHour!) ?? '',
additionalPadding,
),
],
......@@ -1826,10 +1827,10 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
},
children: List<Widget>.generate(60 ~/ widget.minuteInterval, (int index) {
final int minute = index * widget.minuteInterval;
final String label = localizations.timerPickerMinuteLabel(minute) ?? '';
final String semanticsLabel = textDirectionFactor == 1
? localizations.timerPickerMinute(minute) + localizations.timerPickerMinuteLabel(minute)
: localizations.timerPickerMinuteLabel(minute) + localizations.timerPickerMinute(minute);
? localizations.timerPickerMinute(minute) + label
: label + localizations.timerPickerMinute(minute);
return Semantics(
label: semanticsLabel,
......@@ -1857,7 +1858,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
child: _buildMinutePicker(additionalPadding, selectionOverlay),
),
_buildLabel(
localizations.timerPickerMinuteLabel(lastSelectedMinute ?? selectedMinute),
localizations.timerPickerMinuteLabel(lastSelectedMinute ?? selectedMinute) ?? '',
additionalPadding,
),
],
......@@ -1890,10 +1891,10 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
},
children: List<Widget>.generate(60 ~/ widget.secondInterval, (int index) {
final int second = index * widget.secondInterval;
final String label = localizations.timerPickerSecondLabel(second) ?? '';
final String semanticsLabel = textDirectionFactor == 1
? localizations.timerPickerSecond(second) + localizations.timerPickerSecondLabel(second)
: localizations.timerPickerSecondLabel(second) + localizations.timerPickerSecond(second);
? localizations.timerPickerSecond(second) + label
: label + localizations.timerPickerSecond(second);
return Semantics(
label: semanticsLabel,
......@@ -1921,7 +1922,7 @@ class _CupertinoTimerPickerState extends State<CupertinoTimerPicker> {
child: _buildSecondPicker(additionalPadding, selectionOverlay),
),
_buildLabel(
localizations.timerPickerSecondLabel(lastSelectedSecond ?? selectedSecond!),
localizations.timerPickerSecondLabel(lastSelectedSecond ?? selectedSecond!) ?? '',
additionalPadding,
),
],
......
......@@ -108,7 +108,7 @@ abstract class CupertinoLocalizations {
/// Semantics label for the given hour value in [CupertinoDatePicker].
// The global version uses the translated string from the arb file.
String datePickerHourSemanticsLabel(int hour);
String? datePickerHourSemanticsLabel(int hour);
/// Minute that is shown in [CupertinoDatePicker] spinner corresponding
/// to the given minute value.
......@@ -122,7 +122,7 @@ abstract class CupertinoLocalizations {
/// Semantics label for the given minute value in [CupertinoDatePicker].
// The global version uses the translated string from the arb file.
String datePickerMinuteSemanticsLabel(int minute);
String? datePickerMinuteSemanticsLabel(int minute);
/// The order of the date elements that will be shown in [CupertinoDatePicker].
// The global version uses the translated string from the arb file.
......@@ -190,7 +190,7 @@ abstract class CupertinoLocalizations {
/// [CupertinoTimerPicker] when selected hour value is `hour`.
/// This function will deal with pluralization based on the `hour` parameter.
// The global version uses the translated string from the arb file.
String timerPickerHourLabel(int hour);
String? timerPickerHourLabel(int hour);
/// All possible hour labels that appears next to the hour picker in
/// [CupertinoTimerPicker]
......@@ -200,7 +200,7 @@ abstract class CupertinoLocalizations {
/// [CupertinoTimerPicker] when selected minute value is `minute`.
/// This function will deal with pluralization based on the `minute` parameter.
// The global version uses the translated string from the arb file.
String timerPickerMinuteLabel(int minute);
String? timerPickerMinuteLabel(int minute);
/// All possible minute labels that appears next to the minute picker in
/// [CupertinoTimerPicker]
......@@ -210,7 +210,7 @@ abstract class CupertinoLocalizations {
/// [CupertinoTimerPicker] when selected minute value is `second`.
/// This function will deal with pluralization based on the `second` parameter.
// The global version uses the translated string from the arb file.
String timerPickerSecondLabel(int second);
String? timerPickerSecondLabel(int second);
/// All possible second labels that appears next to the second picker in
/// [CupertinoTimerPicker]
......
# Use the parent analysis options settings and enable null-experiment.
include: ../analysis_options.yaml
analyzer:
errors:
always_require_non_null_named_parameters: false # not needed with nnbd
type_init_formals: false # https://github.com/dart-lang/linter/issues/2192
unrelated_type_equality_checks: false # https://github.com/dart-lang/linter/issues/2196
void_checks: false # https://github.com/dart-lang/linter/issues/2185
unnecessary_null_comparison: false # Turned off until null-safe rollout is complete.
......@@ -54,15 +54,15 @@ abstract class GlobalCupertinoLocalizations implements CupertinoLocalizations {
/// The remaining '*Format' arguments uses the intl package to provide
/// [DateFormat] configurations for the `localeName`.
const GlobalCupertinoLocalizations({
@required String localeName,
@required intl.DateFormat fullYearFormat,
@required intl.DateFormat dayFormat,
@required intl.DateFormat mediumDateFormat,
@required intl.DateFormat singleDigitHourFormat,
@required intl.DateFormat singleDigitMinuteFormat,
@required intl.DateFormat doubleDigitMinuteFormat,
@required intl.DateFormat singleDigitSecondFormat,
@required intl.NumberFormat decimalFormat,
required String localeName,
required intl.DateFormat fullYearFormat,
required intl.DateFormat dayFormat,
required intl.DateFormat mediumDateFormat,
required intl.DateFormat singleDigitHourFormat,
required intl.DateFormat singleDigitMinuteFormat,
required intl.DateFormat doubleDigitMinuteFormat,
required intl.DateFormat singleDigitSecondFormat,
required intl.NumberFormat decimalFormat,
}) : assert(localeName != null),
_localeName = localeName,
assert(fullYearFormat != null),
......@@ -127,20 +127,20 @@ abstract class GlobalCupertinoLocalizations implements CupertinoLocalizations {
}
/// Subclasses should provide the optional zero pluralization of [datePickerHourSemanticsLabel] based on the ARB file.
@protected String get datePickerHourSemanticsLabelZero => null;
@protected String? get datePickerHourSemanticsLabelZero => null;
/// Subclasses should provide the optional one pluralization of [datePickerHourSemanticsLabel] based on the ARB file.
@protected String get datePickerHourSemanticsLabelOne => null;
@protected String? get datePickerHourSemanticsLabelOne => null;
/// Subclasses should provide the optional two pluralization of [datePickerHourSemanticsLabel] based on the ARB file.
@protected String get datePickerHourSemanticsLabelTwo => null;
@protected String? get datePickerHourSemanticsLabelTwo => null;
/// Subclasses should provide the optional few pluralization of [datePickerHourSemanticsLabel] based on the ARB file.
@protected String get datePickerHourSemanticsLabelFew => null;
@protected String? get datePickerHourSemanticsLabelFew => null;
/// Subclasses should provide the optional many pluralization of [datePickerHourSemanticsLabel] based on the ARB file.
@protected String get datePickerHourSemanticsLabelMany => null;
@protected String? get datePickerHourSemanticsLabelMany => null;
/// Subclasses should provide the required other pluralization of [datePickerHourSemanticsLabel] based on the ARB file.
@protected String get datePickerHourSemanticsLabelOther;
@protected String? get datePickerHourSemanticsLabelOther;
@override
String datePickerHourSemanticsLabel(int hour) {
String? datePickerHourSemanticsLabel(int hour) {
return intl.Intl.pluralLogic(
hour,
zero: datePickerHourSemanticsLabelZero,
......@@ -150,24 +150,24 @@ abstract class GlobalCupertinoLocalizations implements CupertinoLocalizations {
many: datePickerHourSemanticsLabelMany,
other: datePickerHourSemanticsLabelOther,
locale: _localeName,
).replaceFirst(r'$hour', _decimalFormat.format(hour));
)?.replaceFirst(r'$hour', _decimalFormat.format(hour));
}
/// Subclasses should provide the optional zero pluralization of [datePickerMinuteSemanticsLabel] based on the ARB file.
@protected String get datePickerMinuteSemanticsLabelZero => null;
@protected String? get datePickerMinuteSemanticsLabelZero => null;
/// Subclasses should provide the optional one pluralization of [datePickerMinuteSemanticsLabel] based on the ARB file.
@protected String get datePickerMinuteSemanticsLabelOne => null;
@protected String? get datePickerMinuteSemanticsLabelOne => null;
/// Subclasses should provide the optional two pluralization of [datePickerMinuteSemanticsLabel] based on the ARB file.
@protected String get datePickerMinuteSemanticsLabelTwo => null;
@protected String? get datePickerMinuteSemanticsLabelTwo => null;
/// Subclasses should provide the optional few pluralization of [datePickerMinuteSemanticsLabel] based on the ARB file.
@protected String get datePickerMinuteSemanticsLabelFew => null;
@protected String? get datePickerMinuteSemanticsLabelFew => null;
/// Subclasses should provide the optional many pluralization of [datePickerMinuteSemanticsLabel] based on the ARB file.
@protected String get datePickerMinuteSemanticsLabelMany => null;
@protected String? get datePickerMinuteSemanticsLabelMany => null;
/// Subclasses should provide the required other pluralization of [datePickerMinuteSemanticsLabel] based on the ARB file.
@protected String get datePickerMinuteSemanticsLabelOther;
@protected String? get datePickerMinuteSemanticsLabelOther;
@override
String datePickerMinuteSemanticsLabel(int minute) {
String? datePickerMinuteSemanticsLabel(int minute) {
return intl.Intl.pluralLogic(
minute,
zero: datePickerMinuteSemanticsLabelZero,
......@@ -177,7 +177,7 @@ abstract class GlobalCupertinoLocalizations implements CupertinoLocalizations {
many: datePickerMinuteSemanticsLabelMany,
other: datePickerMinuteSemanticsLabelOther,
locale: _localeName,
).replaceFirst(r'$minute', _decimalFormat.format(minute));
)?.replaceFirst(r'$minute', _decimalFormat.format(minute));
}
/// A string describing the [DatePickerDateOrder] enum value.
......@@ -210,7 +210,7 @@ abstract class GlobalCupertinoLocalizations implements CupertinoLocalizations {
"locale $_localeName.\nNon conforming string for $_localeName's "
'.arb file',
);
return null;
return DatePickerDateOrder.mdy;
}
}
......@@ -244,7 +244,7 @@ abstract class GlobalCupertinoLocalizations implements CupertinoLocalizations {
"for locale $_localeName.\nNon conforming string for $_localeName's "
'.arb file',
);
return null;
return DatePickerDateTimeOrder.date_time_dayPeriod;
}
}
......@@ -254,7 +254,7 @@ abstract class GlobalCupertinoLocalizations implements CupertinoLocalizations {
String get tabSemanticsLabelRaw;
@override
String tabSemanticsLabel({ int tabIndex, int tabCount }) {
String tabSemanticsLabel({ required int tabIndex, required int tabCount }) {
assert(tabIndex >= 1);
assert(tabCount >= 1);
final String template = tabSemanticsLabelRaw;
......@@ -279,20 +279,20 @@ abstract class GlobalCupertinoLocalizations implements CupertinoLocalizations {
}
/// Subclasses should provide the optional zero pluralization of [timerPickerHourLabel] based on the ARB file.
@protected String get timerPickerHourLabelZero => null;
@protected String? get timerPickerHourLabelZero => null;
/// Subclasses should provide the optional one pluralization of [timerPickerHourLabel] based on the ARB file.
@protected String get timerPickerHourLabelOne => null;
@protected String? get timerPickerHourLabelOne => null;
/// Subclasses should provide the optional two pluralization of [timerPickerHourLabel] based on the ARB file.
@protected String get timerPickerHourLabelTwo => null;
@protected String? get timerPickerHourLabelTwo => null;
/// Subclasses should provide the optional few pluralization of [timerPickerHourLabel] based on the ARB file.
@protected String get timerPickerHourLabelFew => null;
@protected String? get timerPickerHourLabelFew => null;
/// Subclasses should provide the optional many pluralization of [timerPickerHourLabel] based on the ARB file.
@protected String get timerPickerHourLabelMany => null;
@protected String? get timerPickerHourLabelMany => null;
/// Subclasses should provide the required other pluralization of [timerPickerHourLabel] based on the ARB file.
@protected String get timerPickerHourLabelOther;
@protected String? get timerPickerHourLabelOther;
@override
String timerPickerHourLabel(int hour) {
String? timerPickerHourLabel(int hour) {
return intl.Intl.pluralLogic(
hour,
zero: timerPickerHourLabelZero,
......@@ -302,34 +302,34 @@ abstract class GlobalCupertinoLocalizations implements CupertinoLocalizations {
many: timerPickerHourLabelMany,
other: timerPickerHourLabelOther,
locale: _localeName,
).replaceFirst(r'$hour', _decimalFormat.format(hour));
)?.replaceFirst(r'$hour', _decimalFormat.format(hour));
}
@override
List<String> get timerPickerHourLabels => <String>[
timerPickerHourLabelZero,
timerPickerHourLabelOne,
timerPickerHourLabelTwo,
timerPickerHourLabelFew,
timerPickerHourLabelMany,
timerPickerHourLabelOther,
if (timerPickerHourLabelZero != null) timerPickerHourLabelZero!,
if (timerPickerHourLabelOne != null) timerPickerHourLabelOne!,
if (timerPickerHourLabelTwo != null) timerPickerHourLabelTwo!,
if (timerPickerHourLabelFew != null) timerPickerHourLabelFew!,
if (timerPickerHourLabelMany != null) timerPickerHourLabelMany!,
if (timerPickerHourLabelOther != null) timerPickerHourLabelOther!,
];
/// Subclasses should provide the optional zero pluralization of [timerPickerMinuteLabel] based on the ARB file.
@protected String get timerPickerMinuteLabelZero => null;
@protected String? get timerPickerMinuteLabelZero => null;
/// Subclasses should provide the optional one pluralization of [timerPickerMinuteLabel] based on the ARB file.
@protected String get timerPickerMinuteLabelOne => null;
@protected String? get timerPickerMinuteLabelOne => null;
/// Subclasses should provide the optional two pluralization of [timerPickerMinuteLabel] based on the ARB file.
@protected String get timerPickerMinuteLabelTwo => null;
@protected String? get timerPickerMinuteLabelTwo => null;
/// Subclasses should provide the optional few pluralization of [timerPickerMinuteLabel] based on the ARB file.
@protected String get timerPickerMinuteLabelFew => null;
@protected String? get timerPickerMinuteLabelFew => null;
/// Subclasses should provide the optional many pluralization of [timerPickerMinuteLabel] based on the ARB file.
@protected String get timerPickerMinuteLabelMany => null;
@protected String? get timerPickerMinuteLabelMany => null;
/// Subclasses should provide the required other pluralization of [timerPickerMinuteLabel] based on the ARB file.
@protected String get timerPickerMinuteLabelOther;
@protected String? get timerPickerMinuteLabelOther;
@override
String timerPickerMinuteLabel(int minute) {
String? timerPickerMinuteLabel(int minute) {
return intl.Intl.pluralLogic(
minute,
zero: timerPickerMinuteLabelZero,
......@@ -339,34 +339,34 @@ abstract class GlobalCupertinoLocalizations implements CupertinoLocalizations {
many: timerPickerMinuteLabelMany,
other: timerPickerMinuteLabelOther,
locale: _localeName,
).replaceFirst(r'$minute', _decimalFormat.format(minute));
)?.replaceFirst(r'$minute', _decimalFormat.format(minute));
}
@override
List<String> get timerPickerMinuteLabels => <String>[
timerPickerMinuteLabelZero,
timerPickerMinuteLabelOne,
timerPickerMinuteLabelTwo,
timerPickerMinuteLabelFew,
timerPickerMinuteLabelMany,
timerPickerMinuteLabelOther,
if (timerPickerMinuteLabelZero != null) timerPickerMinuteLabelZero!,
if (timerPickerMinuteLabelOne != null) timerPickerMinuteLabelOne!,
if (timerPickerMinuteLabelTwo != null) timerPickerMinuteLabelTwo!,
if (timerPickerMinuteLabelFew != null) timerPickerMinuteLabelFew!,
if (timerPickerMinuteLabelMany != null) timerPickerMinuteLabelMany!,
if (timerPickerMinuteLabelOther != null) timerPickerMinuteLabelOther!,
];
/// Subclasses should provide the optional zero pluralization of [timerPickerSecondLabel] based on the ARB file.
@protected String get timerPickerSecondLabelZero => null;
@protected String? get timerPickerSecondLabelZero => null;
/// Subclasses should provide the optional one pluralization of [timerPickerSecondLabel] based on the ARB file.
@protected String get timerPickerSecondLabelOne => null;
@protected String? get timerPickerSecondLabelOne => null;
/// Subclasses should provide the optional two pluralization of [timerPickerSecondLabel] based on the ARB file.
@protected String get timerPickerSecondLabelTwo => null;
@protected String? get timerPickerSecondLabelTwo => null;
/// Subclasses should provide the optional few pluralization of [timerPickerSecondLabel] based on the ARB file.
@protected String get timerPickerSecondLabelFew => null;
@protected String? get timerPickerSecondLabelFew => null;
/// Subclasses should provide the optional many pluralization of [timerPickerSecondLabel] based on the ARB file.
@protected String get timerPickerSecondLabelMany => null;
@protected String? get timerPickerSecondLabelMany => null;
/// Subclasses should provide the required other pluralization of [timerPickerSecondLabel] based on the ARB file.
@protected String get timerPickerSecondLabelOther;
@protected String? get timerPickerSecondLabelOther;
@override
String timerPickerSecondLabel(int second) {
String? timerPickerSecondLabel(int second) {
return intl.Intl.pluralLogic(
second,
zero: timerPickerSecondLabelZero,
......@@ -376,17 +376,17 @@ abstract class GlobalCupertinoLocalizations implements CupertinoLocalizations {
many: timerPickerSecondLabelMany,
other: timerPickerSecondLabelOther,
locale: _localeName,
).replaceFirst(r'$second', _decimalFormat.format(second));
)?.replaceFirst(r'$second', _decimalFormat.format(second));
}
@override
List<String> get timerPickerSecondLabels => <String>[
timerPickerSecondLabelZero,
timerPickerSecondLabelOne,
timerPickerSecondLabelTwo,
timerPickerSecondLabelFew,
timerPickerSecondLabelMany,
timerPickerSecondLabelOther,
if (timerPickerSecondLabelZero != null) timerPickerSecondLabelZero!,
if (timerPickerSecondLabelOne != null) timerPickerSecondLabelOne!,
if (timerPickerSecondLabelTwo != null) timerPickerSecondLabelTwo!,
if (timerPickerSecondLabelFew != null) timerPickerSecondLabelFew!,
if (timerPickerSecondLabelMany != null) timerPickerSecondLabelMany!,
if (timerPickerSecondLabelOther != null) timerPickerSecondLabelOther!,
];
/// A [LocalizationsDelegate] for [CupertinoLocalizations].
......@@ -444,18 +444,18 @@ class _GlobalCupertinoLocalizationsDelegate extends LocalizationsDelegate<Cupert
'might be $localeName',
);
intl.DateFormat fullYearFormat;
intl.DateFormat dayFormat;
intl.DateFormat mediumDateFormat;
late intl.DateFormat fullYearFormat;
late intl.DateFormat dayFormat;
late intl.DateFormat mediumDateFormat;
// We don't want any additional decoration here. The am/pm is handled in
// the date picker. We just want an hour number localized.
intl.DateFormat singleDigitHourFormat;
intl.DateFormat singleDigitMinuteFormat;
intl.DateFormat doubleDigitMinuteFormat;
intl.DateFormat singleDigitSecondFormat;
intl.NumberFormat decimalFormat;
late intl.DateFormat singleDigitHourFormat;
late intl.DateFormat singleDigitMinuteFormat;
late intl.DateFormat doubleDigitMinuteFormat;
late intl.DateFormat singleDigitSecondFormat;
late intl.NumberFormat decimalFormat;
void loadFormats(String locale) {
void loadFormats(String? locale) {
fullYearFormat = intl.DateFormat.y(locale);
dayFormat = intl.DateFormat.d(locale);
mediumDateFormat = intl.DateFormat.MMMEd(locale);
......@@ -485,7 +485,7 @@ class _GlobalCupertinoLocalizationsDelegate extends LocalizationsDelegate<Cupert
doubleDigitMinuteFormat,
singleDigitSecondFormat,
decimalFormat,
));
)!);
});
}
......
{
"@datePickerHourSemanticsLabelZero": {
"optional": true
},
"datePickerHourSemanticsLabelOne": "$hour o'clock",
"@datePickerHourSemanticsLabelOne": {
"optional": true
},
"@datePickerHourSemanticsLabelTwo": {
"optional": true
},
"@datePickerHourSemanticsLabelFew": {
"optional": true
},
"@datePickerHourSemanticsLabelMany": {
"optional": true
},
"datePickerHourSemanticsLabelOther": "$hour o'clock",
"@datePickerHourSemanticsLabel": {
"description": "Accessibility announcement for the selected hour on a time picker such as '5 o'clock' or '5点'",
"plural": "hour"
},
"@datePickerMinuteSemanticsLabelZero": {
"optional": true
},
"datePickerMinuteSemanticsLabelOne": "1 minute",
"@datePickerMinuteSemanticsLabelOne": {
"optional": true
},
"@datePickerMinuteSemanticsLabelTwo": {
"optional": true
},
"@datePickerMinuteSemanticsLabelFew": {
"optional": true
},
"@datePickerMinuteSemanticsLabelMany": {
"optional": true
},
"datePickerMinuteSemanticsLabelOther": "$minute minutes",
"@datePickerMinuteSemanticsLabel": {
"description": "Accessibility announcement for the selected minute on a time picker such as '15 minutes' or '15分'",
......@@ -49,21 +79,66 @@
"parameters": "tabIndex, tabCount"
},
"@timerPickerHourLabelZero": {
"optional": true
},
"timerPickerHourLabelOne": "hour",
"@timerPickerHourLabelOne": {
"optional": true
},
"@timerPickerHourLabelTwo": {
"optional": true
},
"@timerPickerHourLabelFew": {
"optional": true
},
"@timerPickerHourLabelMany": {
"optional": true
},
"timerPickerHourLabelOther": "hours",
"@timerPickerHourLabel": {
"description": "The label adjacent to an hour integer number in a countdown timer. The reference abbreviation is what iOS does in the stock clock app's countdown timer.",
"plural": "hour"
},
"@timerPickerMinuteLabelZero": {
"optional": true
},
"timerPickerMinuteLabelOne": "min.",
"@timerPickerMinuteLabelOne": {
"optional": true
},
"@timerPickerMinuteLabelTwo": {
"optional": true
},
"@timerPickerMinuteLabelFew": {
"optional": true
},
"@timerPickerMinuteLabelMany": {
"optional": true
},
"timerPickerMinuteLabelOther": "min.",
"@timerPickerMinuteLabel": {
"description": "The label adjacent to a minute integer number in a countdown timer. The reference abbreviation is what iOS does in the stock clock app's countdown timer.",
"plural": "minute"
},
"@timerPickerSecondLabelZero": {
"optional": true
},
"timerPickerSecondLabelOne": "sec.",
"@timerPickerSecondLabelOne": {
"optional": true
},
"@timerPickerSecondLabelTwo": {
"optional": true
},
"@timerPickerSecondLabelFew": {
"optional": true
},
"@timerPickerSecondLabelMany": {
"optional": true
},
"timerPickerSecondLabelOther": "sec.",
"@timerPickerSecondLabel": {
"description": "The label adjacent to a second integer number in a countdown timer. The reference abbreviation is what iOS does in the stock clock app's countdown timer.",
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -73,7 +73,22 @@
},
"licensesPackageDetailTextZero": "No licenses",
"@licensesPackageDetailTextZero": {
"optional": true
},
"licensesPackageDetailTextOne": "1 license",
"@licensesPackageDetailTextOne": {
"optional": true
},
"@licensesPackageDetailTextTwo": {
"optional": true
},
"@licensesPackageDetailTextFew": {
"optional": true
},
"@licensesPackageDetailTextMany": {
"optional": true
},
"licensesPackageDetailTextOther": "$licenseCount licenses",
"@licensesPackageDetailText": {
"description": "The subtitle and detail text for a package displayed on the Flutter licenses page. The value of $licenseCount is an integer which indicates the number of licenses the package has.",
......@@ -104,7 +119,22 @@
},
"selectedRowCountTitleZero": "No items selected",
"@selectedRowCountTitleZero": {
"optional": true
},
"selectedRowCountTitleOne": "1 item selected",
"@selectedRowCountTitleOne": {
"optional": true
},
"@selectedRowCountTitleTwo": {
"optional": true
},
"@selectedRowCountTitleFew": {
"optional": true
},
"@selectedRowCountTitleMany": {
"optional": true
},
"selectedRowCountTitleOther": "$selectedRowCount items selected",
"@selectedRowCountTitle": {
"description": "The title for the header of a paginated data table when the user is selecting rows. The value of $selectedRowCount is an integer which indicates the number of data table row elements that have been selected.",
......@@ -389,7 +419,22 @@
},
"remainingTextFieldCharacterCountZero": "No characters remaining",
"@remainingTextFieldCharacterCountZero": {
"optional": true
},
"remainingTextFieldCharacterCountOne": "1 character remaining",
"@remainingTextFieldCharacterCountOne": {
"optional": true
},
"@remainingTextFieldCharacterCountTwo": {
"optional": true
},
"@remainingTextFieldCharacterCountFew": {
"optional": true
},
"@remainingTextFieldCharacterCountMany": {
"optional": true
},
"remainingTextFieldCharacterCountOther": "$remainingCount characters remaining",
"@remainingTextFieldCharacterCount": {
"description": "The label for the TextField's character counter. remainingCharacters is a integer representing how many more characters the user can type into the text field before using up a given budget. All values are greater than or equal to zero.",
......
{
"scriptCategory": "tall",
"timeOfDayFormat": "HH:mm",
"anteMeridiemAbbreviation": "AM",
"@anteMeridiemAbbreviation": {"notUsed":"Pashto time format does not use a.m. indicator"},
"postMeridiemAbbreviation": "PM",
"@postMeridiemAbbreviation": {"notUsed":"Pashto time format does not use p.m. indicator"},
"openAppDrawerTooltip": "د پرانیستی نیینګ مینو",
"backButtonTooltip": "شاته",
......
......@@ -87,16 +87,16 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// The [narrowWeekdays] and [firstDayOfWeekIndex] properties use the values
/// from the [intl.DateFormat] used by [formatFullDate].
const GlobalMaterialLocalizations({
@required String localeName,
@required intl.DateFormat fullYearFormat,
@required intl.DateFormat compactDateFormat,
@required intl.DateFormat shortDateFormat,
@required intl.DateFormat mediumDateFormat,
@required intl.DateFormat longDateFormat,
@required intl.DateFormat yearMonthFormat,
@required intl.DateFormat shortMonthDayFormat,
@required intl.NumberFormat decimalFormat,
@required intl.NumberFormat twoDigitZeroPaddedFormat,
required String localeName,
required intl.DateFormat fullYearFormat,
required intl.DateFormat compactDateFormat,
required intl.DateFormat shortDateFormat,
required intl.DateFormat mediumDateFormat,
required intl.DateFormat longDateFormat,
required intl.DateFormat yearMonthFormat,
required intl.DateFormat shortMonthDayFormat,
required intl.NumberFormat decimalFormat,
required intl.NumberFormat twoDigitZeroPaddedFormat,
}) : assert(localeName != null),
_localeName = localeName,
assert(fullYearFormat != null),
......@@ -140,7 +140,6 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
final int hour = timeOfDay.hourOfPeriod;
return formatDecimal(hour == 0 ? 12 : hour);
}
return null;
}
@override
......@@ -184,9 +183,9 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
}
@override
DateTime parseCompactDate(String inputString) {
DateTime? parseCompactDate(String? inputString) {
try {
return _compactDateFormat.parseStrict(inputString);
return inputString != null ? _compactDateFormat.parseStrict(inputString) : null;
} on FormatException {
return null;
}
......@@ -219,28 +218,26 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
final String minute = formatMinute(timeOfDay);
switch (timeOfDayFormat(alwaysUse24HourFormat: alwaysUse24HourFormat)) {
case TimeOfDayFormat.h_colon_mm_space_a:
return '$hour:$minute ${_formatDayPeriod(timeOfDay)}';
return '$hour:$minute ${_formatDayPeriod(timeOfDay)!}';
case TimeOfDayFormat.H_colon_mm:
case TimeOfDayFormat.HH_colon_mm:
return '$hour:$minute';
case TimeOfDayFormat.HH_dot_mm:
return '$hour.$minute';
case TimeOfDayFormat.a_space_h_colon_mm:
return '${_formatDayPeriod(timeOfDay)} $hour:$minute';
return '${_formatDayPeriod(timeOfDay)!} $hour:$minute';
case TimeOfDayFormat.frenchCanadian:
return '$hour h $minute';
}
return null;
}
String _formatDayPeriod(TimeOfDay timeOfDay) {
String? _formatDayPeriod(TimeOfDay timeOfDay) {
switch (timeOfDay.period) {
case DayPeriod.am:
return anteMeridiemAbbreviation;
case DayPeriod.pm:
return postMeridiemAbbreviation;
}
return null;
}
/// The raw version of [dateRangeStartDateSemanticLabel], with `$formattedDate` verbatim
......@@ -288,7 +285,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
@override
String pageRowsInfoTitle(int firstRow, int lastRow, int rowCount, bool rowCountIsApproximate) {
String text = rowCountIsApproximate ? pageRowsInfoTitleApproximateRaw : null;
String? text = rowCountIsApproximate ? pageRowsInfoTitleApproximateRaw : null;
text ??= pageRowsInfoTitleRaw;
assert(text != null, 'A $_localeName localization was not found for pageRowsInfoTitle or pageRowsInfoTitleApproximate');
return text
......@@ -303,7 +300,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
String get tabLabelRaw;
@override
String tabLabel({ int tabIndex, int tabCount }) {
String tabLabel({ required int tabIndex, required int tabCount }) {
assert(tabIndex >= 1);
assert(tabCount >= 1);
final String template = tabLabelRaw;
......@@ -325,7 +322,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// * [selectedRowCountTitleMany], the "many" form
/// * [selectedRowCountTitleOther], the "other" form
@protected
String get selectedRowCountTitleZero => null;
String? get selectedRowCountTitleZero => null;
/// The "one" form of [selectedRowCountTitle].
///
......@@ -340,7 +337,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// * [selectedRowCountTitleMany], the "many" form
/// * [selectedRowCountTitleOther], the "other" form
@protected
String get selectedRowCountTitleOne => null;
String? get selectedRowCountTitleOne => null;
/// The "two" form of [selectedRowCountTitle].
///
......@@ -355,7 +352,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// * [selectedRowCountTitleMany], the "many" form
/// * [selectedRowCountTitleOther], the "other" form
@protected
String get selectedRowCountTitleTwo => null;
String? get selectedRowCountTitleTwo => null;
/// The "few" form of [selectedRowCountTitle].
///
......@@ -370,7 +367,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// * [selectedRowCountTitleMany], the "many" form
/// * [selectedRowCountTitleOther], the "other" form
@protected
String get selectedRowCountTitleFew => null;
String? get selectedRowCountTitleFew => null;
/// The "many" form of [selectedRowCountTitle].
///
......@@ -385,7 +382,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// * [selectedRowCountTitleFew], the "few" form
/// * [selectedRowCountTitleOther], the "other" form
@protected
String get selectedRowCountTitleMany => null;
String? get selectedRowCountTitleMany => null;
/// The "other" form of [selectedRowCountTitle].
///
......@@ -458,7 +455,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// * [licensesPackageDetailTextMany], the "many" form
/// * [licensesPackageDetailTextOther], the "other" form
@protected
String get licensesPackageDetailTextZero => null;
String? get licensesPackageDetailTextZero => null;
/// The "one" form of [licensesPackageDetailText].
///
......@@ -473,7 +470,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// * [licensesPackageDetailTextMany], the "many" form
/// * [licensesPackageDetailTextOther], the "other" form
@protected
String get licensesPackageDetailTextOne => null;
String? get licensesPackageDetailTextOne => null;
/// The "two" form of [licensesPackageDetailText].
///
......@@ -489,7 +486,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// * [licensesPackageDetailTextMany], the "many" form
/// * [licensesPackageDetailTextOther], the "other" form
@protected
String get licensesPackageDetailTextTwo => null;
String? get licensesPackageDetailTextTwo => null;
/// The "many" form of [licensesPackageDetailText].
///
......@@ -505,7 +502,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// * [licensesPackageDetailTextMany], the "many" form
/// * [licensesPackageDetailTextOther], the "other" form
@protected
String get licensesPackageDetailTextMany => null;
String? get licensesPackageDetailTextMany => null;
/// The "few" form of [licensesPackageDetailText].
///
......@@ -521,7 +518,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// * [licensesPackageDetailTextMany], the "many" form
/// * [licensesPackageDetailTextOther], the "other" form
@protected
String get licensesPackageDetailTextFew => null;
String? get licensesPackageDetailTextFew => null;
/// The "other" form of [licensesPackageDetailText].
///
......@@ -555,7 +552,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// The "zero" form of [remainingTextFieldCharacterCount].
///
/// This form is required.
/// This form is optional.
///
/// See also:
///
......@@ -567,7 +564,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// * [remainingTextFieldCharacterCountMany], the "many" form
/// * [remainingTextFieldCharacterCountOther], the "other" form
@protected
String get remainingTextFieldCharacterCountZero;
String? get remainingTextFieldCharacterCountZero => null;
/// The "one" form of [remainingTextFieldCharacterCount].
///
......@@ -582,7 +579,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// * [remainingTextFieldCharacterCountMany], the "many" form
/// * [remainingTextFieldCharacterCountOther], the "other" form
@protected
String get remainingTextFieldCharacterCountOne => null;
String? get remainingTextFieldCharacterCountOne => null;
/// The "two" form of [remainingTextFieldCharacterCount].
///
......@@ -598,7 +595,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// * [remainingTextFieldCharacterCountMany], the "many" form
/// * [remainingTextFieldCharacterCountOther], the "other" form
@protected
String get remainingTextFieldCharacterCountTwo => null;
String? get remainingTextFieldCharacterCountTwo => null;
/// The "many" form of [remainingTextFieldCharacterCount].
///
......@@ -614,7 +611,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// * [remainingTextFieldCharacterCountMany], the "many" form
/// * [remainingTextFieldCharacterCountOther], the "other" form
@protected
String get remainingTextFieldCharacterCountMany => null;
String? get remainingTextFieldCharacterCountMany => null;
/// The "few" form of [remainingTextFieldCharacterCount].
///
......@@ -630,7 +627,7 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
/// * [remainingTextFieldCharacterCountMany], the "many" form
/// * [remainingTextFieldCharacterCountOther], the "other" form
@protected
String get remainingTextFieldCharacterCountFew => null;
String? get remainingTextFieldCharacterCountFew => null;
/// The "other" form of [remainingTextFieldCharacterCount].
///
......@@ -714,7 +711,6 @@ TimeOfDayFormat _get24HourVersionOf(TimeOfDayFormat original) {
case TimeOfDayFormat.a_space_h_colon_mm:
return TimeOfDayFormat.HH_colon_mm;
}
return TimeOfDayFormat.HH_colon_mm;
}
class _MaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLocalizations> {
......@@ -795,7 +791,7 @@ class _MaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLocal
shortMonthDayFormat,
decimalFormat,
twoDigitZeroPaddedFormat,
));
)!);
});
}
......
......@@ -28,7 +28,7 @@ void loadDateIntlDataIfNotLoaded() {
// Strip scriptCode from the locale, as we do not distinguish between scripts
// for dates.
final List<String> codes = locale.split('_');
String countryCode;
String? countryCode;
if (codes.length == 2) {
countryCode = codes[1].length < 4 ? codes[1] : null;
} else if (codes.length == 3) {
......
......@@ -43,7 +43,7 @@ class GlobalWidgetsLocalizations implements WidgetsLocalizations {
@override
TextDirection get textDirection => _textDirection;
TextDirection _textDirection;
late TextDirection _textDirection;
/// Creates an object that provides localized resource values for the
/// lowest levels of the Flutter framework.
......
......@@ -2,7 +2,7 @@ name: flutter_localizations
environment:
# The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite.
sdk: ">=2.2.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
dependencies:
# To update these, use "flutter update-packages --force-upgrade".
......
......@@ -63,7 +63,7 @@ void main() {
)
);
await tester.binding.setLocale('zh', null);
await tester.binding.setLocale('zh', '');
await tester.pump();
await tester.binding.setLocale('es', 'US');
await tester.pump();
......@@ -87,18 +87,18 @@ class _DummyLocalizationsDelegate extends LocalizationsDelegate<DummyLocalizatio
class DummyLocalizations {}
class LocalizationTracker extends StatefulWidget {
const LocalizationTracker({Key key}) : super(key: key);
const LocalizationTracker({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => LocalizationTrackerState();
}
class LocalizationTrackerState extends State<LocalizationTracker> {
double captionFontSize;
late double captionFontSize;
@override
Widget build(BuildContext context) {
captionFontSize = Theme.of(context).textTheme.caption.fontSize;
captionFontSize = Theme.of(context).textTheme.caption!.fontSize!;
return Container();
}
}
......@@ -9,9 +9,9 @@ import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
DateTime firstDate;
DateTime lastDate;
DateTime initialDate;
late DateTime firstDate;
late DateTime lastDate;
late DateTime initialDate;
setUp(() {
firstDate = DateTime(2001, DateTime.january, 1);
......@@ -53,10 +53,10 @@ void main() {
for (final Locale locale in testLocales.keys) {
testWidgets('shows dates for $locale', (WidgetTester tester) async {
final List<String> expectedDaysOfWeek = testLocales[locale]['expectedDaysOfWeek'] as List<String>;
final List<String> expectedDaysOfMonth = testLocales[locale]['expectedDaysOfMonth'] as List<String>;
final String expectedMonthYearHeader = testLocales[locale]['expectedMonthYearHeader'] as String;
final TextDirection textDirection = testLocales[locale]['textDirection'] as TextDirection;
final List<String> expectedDaysOfWeek = testLocales[locale]!['expectedDaysOfWeek'] as List<String>;
final List<String> expectedDaysOfMonth = testLocales[locale]!['expectedDaysOfMonth'] as List<String>;
final String expectedMonthYearHeader = testLocales[locale]!['expectedMonthYearHeader'] as String;
final TextDirection textDirection = testLocales[locale]!['textDirection'] as TextDirection;
final DateTime baseDate = DateTime(2017, 9, 27);
await _pumpBoilerplate(tester, CalendarDatePicker(
......@@ -72,7 +72,7 @@ void main() {
expect(find.text(dayOfWeek), findsWidgets);
}
Offset previousCellOffset;
Offset? previousCellOffset;
for (final String dayOfMonth in expectedDaysOfMonth) {
final Finder dayCell = find.descendant(of: find.byType(GridView), matching: find.text(dayOfMonth));
expect(dayCell, findsOneWidget);
......
......@@ -163,7 +163,7 @@ void main() {
// Regression test for https://github.com/flutter/flutter/issues/67644.
testWidgets('en_US is initialized correctly by Flutter when DateFormat is used', (WidgetTester tester) async {
DateFormat dateFormat;
late DateFormat dateFormat;
await tester.pumpWidget(MaterialApp(
supportedLocales: const <Locale>[
......@@ -180,7 +180,7 @@ void main() {
}),
));
expect(dateFormat?.locale, 'en_US');
expect(dateFormat.locale, 'en_US');
});
}
......
......@@ -9,13 +9,13 @@ import 'package:flutter_test/flutter_test.dart';
class _TimePickerLauncher extends StatelessWidget {
const _TimePickerLauncher({
Key key,
Key? key,
this.onChanged,
this.locale,
required this.locale,
this.entryMode = TimePickerEntryMode.dial,
}) : super(key: key);
final ValueChanged<TimeOfDay> onChanged;
final ValueChanged<TimeOfDay?>? onChanged;
final Locale locale;
final TimePickerEntryMode entryMode;
......@@ -32,7 +32,7 @@ class _TimePickerLauncher extends StatelessWidget {
return ElevatedButton(
child: const Text('X'),
onPressed: () async {
onChanged(await showTimePicker(
onChanged?.call(await showTimePicker(
context: context,
initialEntryMode: entryMode,
initialTime: const TimeOfDay(hour: 7, minute: 0),
......@@ -49,7 +49,7 @@ class _TimePickerLauncher extends StatelessWidget {
Future<Offset> startPicker(
WidgetTester tester,
ValueChanged<TimeOfDay> onChanged, {
ValueChanged<TimeOfDay?> onChanged, {
Locale locale = const Locale('en', 'US'),
}) async {
await tester.pumpWidget(_TimePickerLauncher(onChanged: onChanged, locale: locale,));
......@@ -89,7 +89,7 @@ void main() {
];
for (final Locale locale in locales) {
final Offset center = await startPicker(tester, (TimeOfDay time) { }, locale: locale);
final Offset center = await startPicker(tester, (TimeOfDay? time) { }, locale: locale);
final Text stringFragmentText = tester.widget(stringFragmentTextFinder);
final double hourLeftOffset = tester.getTopLeft(hourControlFinder).dx;
final double minuteLeftOffset = tester.getTopLeft(minuteControlFinder).dx;
......@@ -133,8 +133,8 @@ void main() {
await finishPicker(tester);
}
tester.binding.window.physicalSizeTestValue = null;
tester.binding.window.devicePixelRatioTestValue = null;
tester.binding.window.clearPhysicalSizeTestValue();
tester.binding.window.clearDevicePixelRatioTestValue();
});
testWidgets('can localize the header in all known formats - landscape', (WidgetTester tester) async {
......@@ -161,7 +161,7 @@ void main() {
];
for (final Locale locale in locales) {
final Offset center = await startPicker(tester, (TimeOfDay time) { }, locale: locale);
final Offset center = await startPicker(tester, (TimeOfDay? time) { }, locale: locale);
final Text stringFragmentText = tester.widget(stringFragmentTextFinder);
final double hourLeftOffset = tester.getTopLeft(hourControlFinder).dx;
final double hourTopOffset = tester.getTopLeft(hourControlFinder).dy;
......@@ -210,8 +210,8 @@ void main() {
await finishPicker(tester);
}
tester.binding.window.physicalSizeTestValue = null;
tester.binding.window.devicePixelRatioTestValue = null;
tester.binding.window.clearPhysicalSizeTestValue();
tester.binding.window.clearDevicePixelRatioTestValue();
});
testWidgets('can localize input mode in all known formats', (WidgetTester tester) async {
......@@ -234,7 +234,7 @@ void main() {
];
for (final Locale locale in locales) {
await tester.pumpWidget(_TimePickerLauncher(onChanged: (TimeOfDay time) { }, locale: locale, entryMode: TimePickerEntryMode.input));
await tester.pumpWidget(_TimePickerLauncher(onChanged: (TimeOfDay? time) { }, locale: locale, entryMode: TimePickerEntryMode.input));
await tester.tap(find.text('X'));
await tester.pumpAndSettle(const Duration(seconds: 1));
......@@ -292,8 +292,8 @@ void main() {
// 12:00 AM position. Because there's only one ring, no matter where you
// tap the time will be the same.
for (int i = 1; i < 10; i++) {
TimeOfDay result;
final Offset center = await startPicker(tester, (TimeOfDay time) { result = time; }, locale: locale);
TimeOfDay? result;
final Offset center = await startPicker(tester, (TimeOfDay? time) { result = time; }, locale: locale);
final Size size = tester.getSize(find.byKey(const Key('time-picker-dial')));
final double dy = (size.height / 2.0 / 10) * i;
await tester.tapAt(Offset(center.dx, center.dy - dy));
......@@ -348,13 +348,13 @@ void main() {
final dynamic dialPainter = dialPaint.painter;
final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>;
expect(
primaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text as TextSpan).text),
primaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text! as TextSpan).text!),
labels12To11,
);
final List<dynamic> secondaryLabels = dialPainter.secondaryLabels as List<dynamic>;
expect(
secondaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text as TextSpan).text),
secondaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text! as TextSpan).text!),
labels12To11,
);
});
......@@ -366,13 +366,13 @@ void main() {
final dynamic dialPainter = dialPaint.painter;
final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>;
expect(
primaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text as TextSpan).text),
primaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text! as TextSpan).text!),
labels00To22TwoDigit,
);
final List<dynamic> secondaryLabels = dialPainter.secondaryLabels as List<dynamic>;
expect(
secondaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text as TextSpan).text),
secondaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text! as TextSpan).text!),
labels00To22TwoDigit,
);
});
......
......@@ -53,10 +53,10 @@ class FooMaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLoc
}
Widget buildFrame({
Locale locale,
Locale? locale,
Iterable<LocalizationsDelegate<dynamic>> delegates = GlobalMaterialLocalizations.delegates,
WidgetBuilder buildContent,
LocaleResolutionCallback localeResolutionCallback,
required WidgetBuilder buildContent,
LocaleResolutionCallback? localeResolutionCallback,
Iterable<Locale> supportedLocales = const <Locale>[
Locale('en', 'US'),
Locale('es', 'ES'),
......@@ -210,7 +210,7 @@ void main() {
await tester.pumpWidget(
buildFrame(
// Accept whatever locale we're given
localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) => locale,
localeResolutionCallback: (Locale? locale, Iterable<Locale> supportedLocales) => locale,
delegates: <FooMaterialLocalizationsDelegate>[
const FooMaterialLocalizationsDelegate(supportedLanguage: 'allLanguages'),
],
......
......@@ -92,7 +92,7 @@ void main() {
expect(topRight, const Offset(477.0, 347.5));
expect(bottomLeft, const Offset(392.0, 364.5));
expect(bottomRight, const Offset(477.0, 364.5));
}, skip: !isLinux);
});
testWidgets('Text baseline with EN locale', (WidgetTester tester) async {
// This test in combination with 'Text baseline with CJK locale' verify the baselines
......@@ -164,7 +164,6 @@ void main() {
Offset bottomLeft = tester.getBottomLeft(find.text('hello, world'));
Offset bottomRight = tester.getBottomRight(find.text('hello, world'));
expect(topLeft, const Offset(392.0, 300.0));
expect(topRight, const Offset(584.0, 300.0));
expect(bottomLeft, const Offset(392.0, 316));
......@@ -179,5 +178,5 @@ void main() {
expect(topRight, const Offset(472.0, 348.0));
expect(bottomLeft, const Offset(392.0, 364.0));
expect(bottomRight, const Offset(472.0, 364.0));
}, skip: !isLinux);
});
}
......@@ -13,19 +13,21 @@ class TestLocalizations {
TestLocalizations(this.locale, this.prefix);
final Locale locale;
final String prefix;
final String? prefix;
static Future<TestLocalizations> loadSync(Locale locale, String prefix) {
static Future<TestLocalizations> loadSync(Locale locale, String? prefix) {
return SynchronousFuture<TestLocalizations>(TestLocalizations(locale, prefix));
}
static Future<TestLocalizations> loadAsync(Locale locale, String prefix) {
return Future<TestLocalizations>.delayed(const Duration(milliseconds: 100))
.then((_) => TestLocalizations(locale, prefix));
static Future<TestLocalizations> loadAsync(Locale locale, String? prefix) {
return Future<TestLocalizations>.delayed(
const Duration(milliseconds: 100),
() => TestLocalizations(locale, prefix)
);
}
static TestLocalizations of(BuildContext context) {
return Localizations.of<TestLocalizations>(context, TestLocalizations);
return Localizations.of<TestLocalizations>(context, TestLocalizations)!;
}
String get message => '${prefix ?? ""}$locale';
......@@ -34,7 +36,7 @@ class TestLocalizations {
class SyncTestLocalizationsDelegate extends LocalizationsDelegate<TestLocalizations> {
SyncTestLocalizationsDelegate([this.prefix]);
final String prefix; // Changing this value triggers a rebuild
final String? prefix; // Changing this value triggers a rebuild
final List<bool> shouldReloadValues = <bool>[];
@override
......@@ -56,7 +58,7 @@ class SyncTestLocalizationsDelegate extends LocalizationsDelegate<TestLocalizati
class AsyncTestLocalizationsDelegate extends LocalizationsDelegate<TestLocalizations> {
AsyncTestLocalizationsDelegate([this.prefix]);
final String prefix; // Changing this value triggers a rebuild
final String? prefix; // Changing this value triggers a rebuild
final List<bool> shouldReloadValues = <bool>[];
@override
......@@ -85,12 +87,14 @@ class MoreLocalizations {
}
static Future<MoreLocalizations> loadAsync(Locale locale) {
return Future<MoreLocalizations>.delayed(const Duration(milliseconds: 100))
.then((_) => MoreLocalizations(locale));
return Future<MoreLocalizations>.delayed(
const Duration(milliseconds: 100),
() => MoreLocalizations(locale)
);
}
static MoreLocalizations of(BuildContext context) {
return Localizations.of<MoreLocalizations>(context, MoreLocalizations);
return Localizations.of<MoreLocalizations>(context, MoreLocalizations)!;
}
String get message => '$locale';
......@@ -139,10 +143,10 @@ class OnlyRTLDefaultWidgetsLocalizationsDelegate extends LocalizationsDelegate<W
}
Widget buildFrame({
Locale locale,
Iterable<LocalizationsDelegate<dynamic>> delegates,
WidgetBuilder buildContent,
LocaleResolutionCallback localeResolutionCallback,
Locale? locale,
Iterable<LocalizationsDelegate<dynamic>>? delegates,
required WidgetBuilder buildContent,
LocaleResolutionCallback? localeResolutionCallback,
List<Locale> supportedLocales = const <Locale>[
Locale('en', 'US'),
Locale('en', 'GB'),
......@@ -183,7 +187,7 @@ class SyncLoadTestState extends State<SyncLoadTest> {
void main() {
testWidgets('Localizations.localeFor in a WidgetsApp with system locale', (WidgetTester tester) async {
BuildContext pageContext;
late BuildContext pageContext;
await tester.pumpWidget(
buildFrame(
......@@ -205,7 +209,7 @@ void main() {
testWidgets('Localizations.localeFor in a WidgetsApp with an explicit locale', (WidgetTester tester) async {
const Locale locale = Locale('en', 'US');
BuildContext pageContext;
late BuildContext pageContext;
await tester.pumpWidget(
buildFrame(
......@@ -477,7 +481,7 @@ void main() {
});
testWidgets('Directionality tracks system locale', (WidgetTester tester) async {
BuildContext pageContext;
late BuildContext pageContext;
await tester.pumpWidget(
buildFrame(
......@@ -507,7 +511,7 @@ void main() {
testWidgets('localeResolutionCallback override', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
localeResolutionCallback: (Locale newLocale, Iterable<Locale> supportedLocales) {
localeResolutionCallback: (Locale? newLocale, Iterable<Locale> supportedLocales) {
return const Locale('foo', 'BAR');
},
buildContent: (BuildContext context) {
......@@ -562,7 +566,7 @@ void main() {
await tester.pumpWidget(
buildFrame(
// Accept whatever locale we're given
localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) => locale,
localeResolutionCallback: (Locale? locale, Iterable<Locale> supportedLocales) => locale,
delegates: const <LocalizationsDelegate<dynamic>>[
GlobalWidgetsLocalizations.delegate,
],
......@@ -571,7 +575,7 @@ void main() {
context: context,
child: Builder(
builder: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
final Locale locale = Localizations.localeOf(context)!;
final TextDirection direction = WidgetsLocalizations.of(context).textDirection;
return Text('$locale $direction');
},
......@@ -602,7 +606,7 @@ void main() {
await tester.pumpWidget(
buildFrame(
// Accept whatever locale we're given
localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) => locale,
localeResolutionCallback: (Locale? locale, Iterable<Locale> supportedLocales) => locale,
buildContent: (BuildContext context) {
return Localizations.override(
context: context,
......@@ -612,7 +616,7 @@ void main() {
],
child: Builder(
builder: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
final Locale locale = Localizations.localeOf(context)!;
final TextDirection direction = WidgetsLocalizations.of(context).textDirection;
return Text('$locale $direction');
},
......@@ -643,12 +647,12 @@ void main() {
await tester.pumpWidget(
buildFrame(
// Accept whatever locale we're given
localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) => locale,
localeResolutionCallback: (Locale? locale, Iterable<Locale> supportedLocales) => locale,
delegates: <OnlyRTLDefaultWidgetsLocalizationsDelegate>[
const OnlyRTLDefaultWidgetsLocalizationsDelegate(),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
final Locale locale = Localizations.localeOf(context)!;
final TextDirection direction = WidgetsLocalizations.of(context).textDirection;
return Text('$locale $direction');
},
......@@ -680,13 +684,13 @@ void main() {
await tester.pumpWidget(
buildFrame(
// Accept whatever locale we're given
localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) => locale,
localeResolutionCallback: (Locale? locale, Iterable<Locale> supportedLocales) => locale,
delegates: <OnlyRTLDefaultWidgetsLocalizationsDelegate>[
const OnlyRTLDefaultWidgetsLocalizationsDelegate(),
],
buildContent: (BuildContext context) {
final Locale locale1 = ui.window.locales.first;
final Locale locale2 = ui.window.locales[1];
final Locale locale1 = ui.window.locales!.first;
final Locale locale2 = ui.window.locales![1];
return Text('$locale1 $locale2');
},
)
......@@ -756,7 +760,7 @@ void main() {
Locale('ja'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
final Locale locale = Localizations.localeOf(context)!;
return Text('$locale');
},
)
......@@ -779,7 +783,7 @@ void main() {
Locale('zh', 'TW'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
final Locale locale = Localizations.localeOf(context)!;
return Text('$locale');
},
)
......@@ -811,7 +815,7 @@ void main() {
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'HK'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
final Locale locale = Localizations.localeOf(context)!;
return Text('$locale');
},
)
......@@ -952,7 +956,7 @@ void main() {
Locale.fromSubtags(languageCode: 'zh'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
final Locale locale = Localizations.localeOf(context)!;
return Text('$locale');
},
)
......@@ -1092,7 +1096,7 @@ void main() {
Locale('it', 'IT'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
final Locale locale = Localizations.localeOf(context)!;
return Text('$locale');
},
)
......@@ -1115,7 +1119,7 @@ void main() {
Locale('it', 'IT'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
final Locale locale = Localizations.localeOf(context)!;
return Text('$locale');
},
)
......@@ -1148,7 +1152,7 @@ void main() {
Locale('pt', 'PT'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
final Locale locale = Localizations.localeOf(context)!;
return Text('$locale');
},
)
......@@ -1215,7 +1219,7 @@ void main() {
Locale('de', 'DE'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
final Locale locale = Localizations.localeOf(context)!;
return Text('$locale');
},
)
......@@ -1279,7 +1283,7 @@ void main() {
Locale('vi'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
final Locale locale = Localizations.localeOf(context)!;
return Text('$locale');
},
)
......@@ -1425,13 +1429,13 @@ void main() {
Locale('en', 'AU'),
Locale('de', 'DE'),
],
localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) {
localeResolutionCallback: (Locale? locale, Iterable<Locale> supportedLocales) {
if (locale == null)
return const Locale('und', 'US');
return const Locale('en', 'US');
},
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
final Locale locale = Localizations.localeOf(context)!;
return Text('$locale');
},
)
......@@ -1443,10 +1447,6 @@ void main() {
await tester.pumpAndSettle();
expect(find.text('en_US'), findsOneWidget);
await tester.binding.setLocales(null);
await tester.pumpAndSettle();
expect(find.text('und_US'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[]);
await tester.pumpAndSettle();
expect(find.text('und_US'), findsOneWidget);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment