Migrate flutter_localizations to null safety. (#68645)
Migrate flutter_localizations to null safety.
This commit is contained in:
parent
2a5aa29442
commit
1c7e34bb20
@ -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]
|
||||
|
11
packages/flutter_localizations/analysis_options.yaml
Normal file
11
packages/flutter_localizations/analysis_options.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
# 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,
|
||||
));
|
||||
)!);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,42 @@
|
||||
{
|
||||
"@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.",
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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.",
|
||||
|
@ -1,7 +1,9 @@
|
||||
{
|
||||
"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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user