diff --git a/packages/flutter/lib/src/cupertino/app.dart b/packages/flutter/lib/src/cupertino/app.dart index 362c043151..c951e53b5b 100644 --- a/packages/flutter/lib/src/cupertino/app.dart +++ b/packages/flutter/lib/src/cupertino/app.dart @@ -8,6 +8,7 @@ import 'package:flutter/widgets.dart'; import 'button.dart'; import 'colors.dart'; import 'icons.dart'; +import 'localizations.dart'; import 'route.dart'; // Based on specs from https://developer.apple.com/design/resources/ for @@ -246,6 +247,17 @@ class _CupertinoAppState extends State { } } + // Combine the default localization for Cupertino with the ones contributed + // by the localizationsDelegates parameter, if any. Only the first delegate + // of a particular LocalizationsDelegate.type is loaded so the + // localizationsDelegate parameter can be used to override + // _CupertinoLocalizationsDelegate. + Iterable> get _localizationsDelegates sync* { + if (widget.localizationsDelegates != null) + yield* widget.localizationsDelegates; + yield DefaultCupertinoLocalizations.delegate; + } + @override Widget build(BuildContext context) { return ScrollConfiguration( @@ -269,7 +281,7 @@ class _CupertinoAppState extends State { textStyle: _kDefaultTextStyle, color: widget.color ?? CupertinoColors.activeBlue, locale: widget.locale, - localizationsDelegates: widget.localizationsDelegates, + localizationsDelegates: _localizationsDelegates, localeResolutionCallback: widget.localeResolutionCallback, supportedLocales: widget.supportedLocales, showPerformanceOverlay: widget.showPerformanceOverlay, diff --git a/packages/flutter/lib/src/cupertino/date_picker.dart b/packages/flutter/lib/src/cupertino/date_picker.dart index 1233e1a19d..30420c9836 100644 --- a/packages/flutter/lib/src/cupertino/date_picker.dart +++ b/packages/flutter/lib/src/cupertino/date_picker.dart @@ -397,7 +397,7 @@ class _CupertinoDatePickerDateTimeState extends State { super.didChangeDependencies(); textDirectionFactor = Directionality.of(context) == TextDirection.ltr ? 1 : -1; - localizations = CupertinoLocalizations.of(context) ?? const DefaultCupertinoLocalizations(); + localizations = CupertinoLocalizations.of(context); alignCenterLeft = textDirectionFactor == 1 ? Alignment.centerLeft : Alignment.centerRight; alignCenterRight = textDirectionFactor == 1 ? Alignment.centerRight : Alignment.centerLeft; @@ -694,7 +694,7 @@ class _CupertinoDatePickerDateState extends State { super.didChangeDependencies(); textDirectionFactor = Directionality.of(context) == TextDirection.ltr ? 1 : -1; - localizations = CupertinoLocalizations.of(context) ?? const DefaultCupertinoLocalizations(); + localizations = CupertinoLocalizations.of(context); alignCenterLeft = textDirectionFactor == 1 ? Alignment.centerLeft : Alignment.centerRight; alignCenterRight = textDirectionFactor == 1 ? Alignment.centerRight : Alignment.centerLeft; @@ -1033,7 +1033,7 @@ class _CupertinoTimerPickerState extends State { super.didChangeDependencies(); textDirectionFactor = Directionality.of(context) == TextDirection.ltr ? 1 : -1; - localizations = CupertinoLocalizations.of(context) ?? const DefaultCupertinoLocalizations(); + localizations = CupertinoLocalizations.of(context); alignCenterLeft = textDirectionFactor == 1 ? Alignment.centerLeft : Alignment.centerRight; alignCenterRight = textDirectionFactor == 1 ? Alignment.centerRight : Alignment.centerLeft; diff --git a/packages/flutter/lib/src/cupertino/dialog.dart b/packages/flutter/lib/src/cupertino/dialog.dart index 4f5c7ce6d6..c420762164 100644 --- a/packages/flutter/lib/src/cupertino/dialog.dart +++ b/packages/flutter/lib/src/cupertino/dialog.dart @@ -219,8 +219,7 @@ class CupertinoAlertDialog extends StatelessWidget { @override Widget build(BuildContext context) { - final CupertinoLocalizations localizations = CupertinoLocalizations.of(context) - ?? const DefaultCupertinoLocalizations(); + final CupertinoLocalizations localizations = CupertinoLocalizations.of(context); final bool isInAccessibilityMode = _isInAccessibilityMode(context); final double textScaleFactor = MediaQuery.of(context).textScaleFactor; return MediaQuery( diff --git a/packages/flutter/lib/src/material/app.dart b/packages/flutter/lib/src/material/app.dart index e1b6274e77..db8ee12fb0 100644 --- a/packages/flutter/lib/src/material/app.dart +++ b/packages/flutter/lib/src/material/app.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:flutter/cupertino.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; @@ -366,6 +367,7 @@ class _MaterialAppState extends State { if (widget.localizationsDelegates != null) yield* widget.localizationsDelegates; yield DefaultMaterialLocalizations.delegate; + yield DefaultCupertinoLocalizations.delegate; } @override diff --git a/packages/flutter/test/cupertino/app_test.dart b/packages/flutter/test/cupertino/app_test.dart index 14c186fb55..1ebca963d1 100644 --- a/packages/flutter/test/cupertino/app_test.dart +++ b/packages/flutter/test/cupertino/app_test.dart @@ -40,4 +40,26 @@ void main() { expect(find.widgetWithText(CupertinoPageRoute, 'foo'), findsNothing); expect(find.widgetWithText(Navigator, 'foo'), findsOneWidget); }); + + testWidgets('Has default cupertino localizations', (WidgetTester tester) async { + await tester.pumpWidget( + CupertinoApp( + home: Builder( + builder: (BuildContext context) { + return Column( + children: [ + Text(CupertinoLocalizations.of(context).selectAllButtonLabel), + Text(CupertinoLocalizations.of(context).datePickerMediumDate( + DateTime(2018, 10, 4), + )), + ], + ); + }, + ), + ), + ); + + expect(find.text('Select All'), findsOneWidget); + expect(find.text('Thu Oct 4 '), findsOneWidget); + }); } diff --git a/packages/flutter/test/cupertino/date_picker_test.dart b/packages/flutter/test/cupertino/date_picker_test.dart index cc04c8ba4d..b92eda3246 100644 --- a/packages/flutter/test/cupertino/date_picker_test.dart +++ b/packages/flutter/test/cupertino/date_picker_test.dart @@ -99,9 +99,8 @@ void main() { testWidgets('columns are ordered correctly when text direction is ltr', (WidgetTester tester) async { await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: CupertinoTimerPicker( + CupertinoApp( + home: CupertinoTimerPicker( onTimerDurationChanged: (_) {}, initialTimerDuration: const Duration(hours: 12, minutes: 30, seconds: 59), ), @@ -127,11 +126,13 @@ void main() { testWidgets('columns are ordered correctly when text direction is rtl', (WidgetTester tester) async { await tester.pumpWidget( - Directionality( - textDirection: TextDirection.rtl, - child: CupertinoTimerPicker( - onTimerDurationChanged: (_) {}, - initialTimerDuration: const Duration(hours: 12, minutes: 30, seconds: 59), + CupertinoApp( + home: Directionality( + textDirection: TextDirection.rtl, + child: CupertinoTimerPicker( + onTimerDurationChanged: (_) {}, + initialTimerDuration: const Duration(hours: 12, minutes: 30, seconds: 59), + ), ), ), ); @@ -155,11 +156,10 @@ void main() { testWidgets('width of picker is consistent', (WidgetTester tester) async { await tester.pumpWidget( - SizedBox( - height: 400.0, - width: 400.0, - child: Directionality( - textDirection: TextDirection.ltr, + CupertinoApp( + home: SizedBox( + height: 400.0, + width: 400.0, child: CupertinoTimerPicker( onTimerDurationChanged: (_) {}, initialTimerDuration: const Duration(hours: 12, minutes: 30, seconds: 59), @@ -173,11 +173,10 @@ void main() { tester.getCenter(find.text('sec')).dx - tester.getCenter(find.text('12')).dx; await tester.pumpWidget( - SizedBox( - height: 400.0, - width: 800.0, - child: Directionality( - textDirection: TextDirection.ltr, + CupertinoApp( + home: SizedBox( + height: 400.0, + width: 800.0, child: CupertinoTimerPicker( onTimerDurationChanged: (_) {}, initialTimerDuration: const Duration(hours: 12, minutes: 30, seconds: 59), @@ -246,11 +245,10 @@ void main() { testWidgets('changing initialDateTime after first build does not do anything', (WidgetTester tester) async { DateTime selectedDateTime; await tester.pumpWidget( - SizedBox( - height: 400.0, - width: 400.0, - child: Directionality( - textDirection: TextDirection.ltr, + CupertinoApp( + home: SizedBox( + height: 400.0, + width: 400.0, child: CupertinoDatePicker( mode: CupertinoDatePickerMode.dateAndTime, onDateTimeChanged: (DateTime dateTime) => selectedDateTime = dateTime, @@ -267,11 +265,10 @@ void main() { expect(selectedDateTime, DateTime(2018, 1, 1, 9, 30)); await tester.pumpWidget( - SizedBox( - height: 400.0, - width: 400.0, - child: Directionality( - textDirection: TextDirection.ltr, + CupertinoApp( + home: SizedBox( + height: 400.0, + width: 400.0, child: CupertinoDatePicker( mode: CupertinoDatePickerMode.dateAndTime, onDateTimeChanged: (DateTime dateTime) => selectedDateTime = dateTime, @@ -292,11 +289,10 @@ void main() { testWidgets('date picker has expected string', (WidgetTester tester) async { await tester.pumpWidget( - SizedBox( - height: 400.0, - width: 400.0, - child: Directionality( - textDirection: TextDirection.ltr, + CupertinoApp( + home: SizedBox( + height: 400.0, + width: 400.0, child: CupertinoDatePicker( mode: CupertinoDatePickerMode.date, onDateTimeChanged: (_) {}, @@ -313,11 +309,10 @@ void main() { testWidgets('datetime picker has expected string', (WidgetTester tester) async { await tester.pumpWidget( - SizedBox( - height: 400.0, - width: 400.0, - child: Directionality( - textDirection: TextDirection.ltr, + CupertinoApp( + home: SizedBox( + height: 400.0, + width: 400.0, child: CupertinoDatePicker( mode: CupertinoDatePickerMode.dateAndTime, onDateTimeChanged: (_) {}, @@ -335,10 +330,8 @@ void main() { testWidgets('width of picker in date and time mode is consistent', (WidgetTester tester) async { await tester.pumpWidget( - SizedBox( - height: 400.0, - width: 400.0, - child: Directionality( + CupertinoApp( + home: Directionality( textDirection: TextDirection.ltr, child: CupertinoDatePicker( mode: CupertinoDatePickerMode.dateAndTime, @@ -354,11 +347,10 @@ void main() { tester.getCenter(find.text('Mon Jan 1 ')).dx - tester.getCenter(find.text('AM')).dx; await tester.pumpWidget( - SizedBox( - height: 400.0, - width: 800.0, - child: Directionality( - textDirection: TextDirection.ltr, + CupertinoApp( + home: SizedBox( + height: 400.0, + width: 800.0, child: CupertinoDatePicker( mode: CupertinoDatePickerMode.dateAndTime, onDateTimeChanged: (_) {}, @@ -377,11 +369,10 @@ void main() { testWidgets('width of picker in date mode is consistent', (WidgetTester tester) async { await tester.pumpWidget( - SizedBox( - height: 400.0, - width: 400.0, - child: Directionality( - textDirection: TextDirection.ltr, + CupertinoApp( + home: SizedBox( + height: 400.0, + width: 400.0, child: CupertinoDatePicker( mode: CupertinoDatePickerMode.date, onDateTimeChanged: (_) {}, @@ -396,11 +387,10 @@ void main() { tester.getCenter(find.text('January')).dx - tester.getCenter(find.text('2018')).dx; await tester.pumpWidget( - SizedBox( - height: 400.0, - width: 800.0, - child: Directionality( - textDirection: TextDirection.ltr, + CupertinoApp( + home: SizedBox( + height: 400.0, + width: 800.0, child: CupertinoDatePicker( mode: CupertinoDatePickerMode.date, onDateTimeChanged: (_) {}, @@ -419,11 +409,10 @@ void main() { testWidgets('width of picker in time mode is consistent', (WidgetTester tester) async { await tester.pumpWidget( - SizedBox( - height: 400.0, - width: 400.0, - child: Directionality( - textDirection: TextDirection.ltr, + CupertinoApp( + home: SizedBox( + height: 400.0, + width: 400.0, child: CupertinoDatePicker( mode: CupertinoDatePickerMode.time, onDateTimeChanged: (_) {}, @@ -438,11 +427,10 @@ void main() { tester.getCenter(find.text('10')).dx - tester.getCenter(find.text('AM')).dx; await tester.pumpWidget( - SizedBox( - height: 400.0, - width: 800.0, - child: Directionality( - textDirection: TextDirection.ltr, + CupertinoApp( + home: SizedBox( + height: 400.0, + width: 800.0, child: CupertinoDatePicker( mode: CupertinoDatePickerMode.time, onDateTimeChanged: (_) {}, @@ -462,11 +450,10 @@ void main() { testWidgets('picker automatically scrolls away from invalid date on month change', (WidgetTester tester) async { DateTime date; await tester.pumpWidget( - SizedBox( - height: 400.0, - width: 400.0, - child: Directionality( - textDirection: TextDirection.ltr, + CupertinoApp( + home: SizedBox( + height: 400.0, + width: 400.0, child: CupertinoDatePicker( mode: CupertinoDatePickerMode.date, onDateTimeChanged: (DateTime newDate) { @@ -501,11 +488,10 @@ void main() { testWidgets('picker automatically scrolls away from invalid date on day change', (WidgetTester tester) async { DateTime date; await tester.pumpWidget( - SizedBox( - height: 400.0, - width: 400.0, - child: Directionality( - textDirection: TextDirection.ltr, + CupertinoApp( + home: SizedBox( + height: 400.0, + width: 400.0, child: CupertinoDatePicker( mode: CupertinoDatePickerMode.date, onDateTimeChanged: (DateTime newDate) { @@ -555,11 +541,10 @@ void main() { testWidgets('picker automatically scrolls the am/pm column when the hour column changes enough', (WidgetTester tester) async { DateTime date; await tester.pumpWidget( - SizedBox( - height: 400.0, - width: 400.0, - child: Directionality( - textDirection: TextDirection.ltr, + CupertinoApp( + home: SizedBox( + height: 400.0, + width: 400.0, child: CupertinoDatePicker( mode: CupertinoDatePickerMode.time, onDateTimeChanged: (DateTime newDate) { diff --git a/packages/flutter/test/material/app_test.dart b/packages/flutter/test/material/app_test.dart index bbd05e7760..36c2233372 100644 --- a/packages/flutter/test/material/app_test.dart +++ b/packages/flutter/test/material/app_test.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class StateMarker extends StatefulWidget { @@ -412,4 +413,26 @@ void main() { )); expect(key.currentState, isInstanceOf()); }); + + testWidgets('Has default material and cupertino localizations', (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp( + home: Builder( + builder: (BuildContext context) { + return Column( + children: [ + Text(MaterialLocalizations.of(context).selectAllButtonLabel), + Text(CupertinoLocalizations.of(context).selectAllButtonLabel), + ], + ); + }, + ), + ), + ); + + // Default US "select all" text. + expect(find.text('SELECT ALL'), findsOneWidget); + // Default Cupertino US "select all" text. + expect(find.text('Select All'), findsOneWidget); + }); }