Skip to content

Commit af15a1e

Browse files
authored
Add localization for Back and Cancel buttons in CupertinoNavigationBar (#162581)
### Description This PR adds localization support for the **"Back"** and **"Cancel"** buttons used in `CupertinoNavigationBar`. #### Changes: - Introduced `cancelButtonLabel` and `backButtonLabel` in `CupertinoLocalizations`. - ~Updated all ARB files with appropriate translations.~ - Modified `_NavigationBarStaticComponents` and `_BackLabel` to use these labels. - Ensured all localization tests pass. - Fixed the test `Auto back/close button` in the `packages/flutter/test/cupertino/localizations_test.dart`. ### Why is this needed? Currently, the **"Back"** and **"Cancel"** (prev. **"Close"**) buttons in `CupertinoNavigationBar` are hardcoded in English. This update ensures they are properly localized across supported languages. ### Tests One test failed (even before my changes): `Saturation is applied before blur` ![Screenshot from 2025-02-02 17-02-20](https://github.com/user-attachments/assets/466df00a-6c28-4bb4-959b-9eee5533d5e3) #### Manual Testing with the `modal_bottom_sheet` Package I tested the change using [my custom mini app](https://gist.github.com/Michae1Weiss/9afee8c425d03e3d41e331fdbf21344f) and the `modal_bottom_sheet` package. I verified that the button is correctly translated into German localization. ##### Before ![cupertino_modal_cancel_button_before_change](https://github.com/user-attachments/assets/7bb41909-43c8-4ece-a885-b17c24193b51) ##### After ![cupertino_modal_cancel_button_after_change](https://github.com/user-attachments/assets/bf5f8904-71e8-4b39-8cee-8c8eb8de7c77) ### Button Name Change: From "Close" to "Cancel" I have renamed the button from **"Close"** to **"Cancel"** to align with the iOS native naming convention for buttons in modal dialogs. #### Example: ![cancel_button](https://github.com/user-attachments/assets/32d3ac7e-8d18-4ba0-b13d-aa54f61a476a) ### Related Issues [CupertinoNavigationBar's "Close", "Back", and "Cancel" buttons are not localized. **#48616** ](flutter/flutter#48616) [CupertinoNavigationBar's "Back" button is not localized **#120722** ](flutter/flutter#120722) ## Pre-launch Checklist - [X] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [X] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [X] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [X] I signed the [CLA]. - [X] I listed at least one issue that this PR fixes in the description above. - [X] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [X] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [X] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord].
1 parent 8b3f5f4 commit af15a1e

File tree

85 files changed

+759
-91
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+759
-91
lines changed

packages/flutter/lib/src/cupertino/localizations.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,12 @@ abstract class CupertinoLocalizations {
302302
/// indicate that a tap outside dismisses the context menu.
303303
String get menuDismissLabel;
304304

305+
/// The label for the cancel button in modal views, used in [CupertinoNavigationBar] and [CupertinoSliverNavigationBar].
306+
String get cancelButtonLabel;
307+
308+
/// The label for the back button, used in [CupertinoNavigationBar] and [CupertinoSliverNavigationBar].
309+
String get backButtonLabel;
310+
305311
/// The `CupertinoLocalizations` from the closest [Localizations] instance
306312
/// that encloses the given context.
307313
///
@@ -520,6 +526,12 @@ class DefaultCupertinoLocalizations implements CupertinoLocalizations {
520526
@override
521527
String get menuDismissLabel => 'Dismiss menu';
522528

529+
@override
530+
String get cancelButtonLabel => 'Cancel';
531+
532+
@override
533+
String get backButtonLabel => 'Back';
534+
523535
/// Creates an object that provides US English resource values for the
524536
/// cupertino library widgets.
525537
///

packages/flutter/lib/src/cupertino/nav_bar.dart

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import 'button.dart';
1717
import 'colors.dart';
1818
import 'constants.dart';
1919
import 'icons.dart';
20+
import 'localizations.dart';
2021
import 'page_scaffold.dart';
2122
import 'route.dart';
2223
import 'search_field.dart';
@@ -241,7 +242,7 @@ bool _isTransitionable(BuildContext context) {
241242
/// toolbar, typically for actions and navigation.
242243
///
243244
/// The [leading] widget will automatically be a back chevron icon button (or a
244-
/// close button in case of a fullscreen dialog) to pop the current route if none
245+
/// cancel button in case of a fullscreen dialog) to pop the current route if none
245246
/// is provided and [automaticallyImplyLeading] is true (true by default).
246247
///
247248
/// This toolbar should be placed at top of the screen where it will
@@ -412,7 +413,7 @@ class CupertinoNavigationBar extends StatefulWidget implements ObstructingPrefer
412413
///
413414
/// Specifically this navigation bar will:
414415
///
415-
/// 1. Show a 'Close' button if the current route is a `fullscreenDialog`.
416+
/// 1. Show a 'Cancel' button if the current route is a `fullscreenDialog`.
416417
/// 2. Show a back chevron with [previousPageTitle] if [previousPageTitle] is
417418
/// not null.
418419
/// 3. Show a back chevron with the previous route's `title` if the current
@@ -729,6 +730,7 @@ class _CupertinoNavigationBarState extends State<CupertinoNavigationBar> {
729730
userLargeTitle: widget.largeTitle,
730731
large: widget.largeTitle != null,
731732
staticBar: true, // This one does not scroll
733+
context: context,
732734
);
733735

734736
// Standard persistent components
@@ -840,7 +842,7 @@ class _CupertinoNavigationBarState extends State<CupertinoNavigationBar> {
840842
/// widget on the static section on top that remains while scrolling.
841843
///
842844
/// The [leading] widget will automatically be a back chevron icon button (or a
843-
/// close button in case of a fullscreen dialog) to pop the current route if none
845+
/// cancel button in case of a fullscreen dialog) to pop the current route if none
844846
/// is provided and [automaticallyImplyLeading] is true (true by default).
845847
///
846848
/// The [largeTitle] widget will automatically be a title text from the current
@@ -1266,6 +1268,7 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation
12661268
padding: widget.padding,
12671269
large: true,
12681270
staticBar: false, // This one scrolls.
1271+
context: context,
12691272
);
12701273

12711274
return MediaQuery.withNoTextScaling(
@@ -1802,12 +1805,14 @@ class _NavigationBarStaticComponents {
18021805
required EdgeInsetsDirectional? padding,
18031806
required bool large,
18041807
required bool staticBar,
1808+
required BuildContext context,
18051809
}) : leading = createLeading(
18061810
leadingKey: keys.leadingKey,
18071811
userLeading: userLeading,
18081812
route: route,
18091813
automaticallyImplyLeading: automaticallyImplyLeading,
18101814
padding: padding,
1815+
context: context,
18111816
),
18121817
backChevron = createBackChevron(
18131818
backChevronKey: keys.backChevronKey,
@@ -1865,6 +1870,7 @@ class _NavigationBarStaticComponents {
18651870
required ModalRoute<dynamic>? route,
18661871
required bool automaticallyImplyLeading,
18671872
required EdgeInsetsDirectional? padding,
1873+
required BuildContext context,
18681874
}) {
18691875
Widget? leadingContent;
18701876

@@ -1879,7 +1885,7 @@ class _NavigationBarStaticComponents {
18791885
onPressed: () {
18801886
route.navigator!.maybePop();
18811887
},
1882-
child: const Text('Close'),
1888+
child: Text(CupertinoLocalizations.of(context).cancelButtonLabel),
18831889
);
18841890
}
18851891

@@ -2094,12 +2100,13 @@ class CupertinoNavigationBarBackButton extends StatelessWidget {
20942100
);
20952101
}
20962102

2103+
final CupertinoLocalizations localizations = CupertinoLocalizations.of(context);
20972104
return CupertinoButton(
20982105
padding: EdgeInsets.zero,
20992106
child: Semantics(
21002107
container: true,
21012108
excludeSemantics: true,
2102-
label: 'Back',
2109+
label: localizations.backButtonLabel,
21032110
button: true,
21042111
child: DefaultTextStyle(
21052112
style: actionTextStyle,
@@ -2191,7 +2198,7 @@ class _BackLabel extends StatelessWidget {
21912198
Text textWidget = Text(previousTitle, maxLines: 1, overflow: TextOverflow.ellipsis);
21922199

21932200
if (previousTitle.length > 12) {
2194-
textWidget = const Text('Back');
2201+
textWidget = Text(CupertinoLocalizations.of(context).backButtonLabel);
21952202
}
21962203

21972204
return Align(alignment: AlignmentDirectional.centerStart, widthFactor: 1.0, child: textWidget);
@@ -2227,16 +2234,15 @@ class _CancelButton extends StatelessWidget {
22272234

22282235
@override
22292236
Widget build(BuildContext context) {
2237+
final CupertinoLocalizations localizations = CupertinoLocalizations.of(context);
22302238
return Align(
22312239
alignment: Alignment.centerLeft,
22322240
child: Opacity(
22332241
opacity: opacity,
22342242
child: CupertinoButton(
22352243
padding: EdgeInsets.zero,
22362244
onPressed: onPressed,
2237-
// TODO(victorsanni): Localize this string.
2238-
// See https://github.com/flutter/flutter/issues/48616.
2239-
child: const Text('Cancel', maxLines: 1, overflow: TextOverflow.clip),
2245+
child: Text(localizations.cancelButtonLabel, maxLines: 1, overflow: TextOverflow.clip),
22402246
),
22412247
),
22422248
);

packages/flutter/test/cupertino/localizations_test.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ void main() {
3737
expect(localizations.searchTextFieldPlaceholderLabel, isNotNull);
3838
expect(localizations.noSpellCheckReplacementsLabel, isNotNull);
3939
expect(localizations.clearButtonLabel, isNotNull);
40+
expect(localizations.cancelButtonLabel, isNotNull);
41+
expect(localizations.backButtonLabel, isNotNull);
4042
});
4143

4244
testWidgets('CupertinoLocalizations.of throws', (WidgetTester tester) async {

packages/flutter/test/cupertino/nav_bar_test.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,7 @@ void main() {
739739
expect(tester.getBottomLeft(find.text('Title')).dy, 44.0); // Extension gone.
740740
});
741741

742-
testWidgets('Auto back/close button', (WidgetTester tester) async {
742+
testWidgets('Auto back/cancel button', (WidgetTester tester) async {
743743
await tester.pumpWidget(
744744
const CupertinoApp(home: CupertinoNavigationBar(middle: Text('Home page'))),
745745
);
@@ -776,10 +776,10 @@ void main() {
776776
await tester.pump();
777777
await tester.pump(const Duration(milliseconds: 600));
778778

779-
expect(find.widgetWithText(CupertinoButton, 'Close'), findsOneWidget);
779+
expect(find.widgetWithText(CupertinoButton, 'Cancel'), findsOneWidget);
780780

781781
// Test popping goes back correctly.
782-
await tester.tap(find.text('Close'));
782+
await tester.tap(find.text('Cancel'));
783783

784784
await tester.pump();
785785
await tester.pump(const Duration(milliseconds: 600));

packages/flutter_localizations/lib/src/l10n/cupertino_af.arb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,7 @@
2727
"lookUpButtonLabel": "Kyk op",
2828
"searchWebButtonLabel": "Deursoek web",
2929
"shareButtonLabel": "Deel …",
30-
"clearButtonLabel": "Vee uit"
30+
"clearButtonLabel": "Vee uit",
31+
"cancelButtonLabel": "Cancel",
32+
"backButtonLabel": "Back"
3133
}

packages/flutter_localizations/lib/src/l10n/cupertino_am.arb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,7 @@
2727
"lookUpButtonLabel": "ይመልከቱ",
2828
"searchWebButtonLabel": "ድርን ፈልግ",
2929
"shareButtonLabel": "አጋራ...",
30-
"clearButtonLabel": "አጽዳ"
30+
"clearButtonLabel": "አጽዳ",
31+
"cancelButtonLabel": "Cancel",
32+
"backButtonLabel": "Back"
3133
}

packages/flutter_localizations/lib/src/l10n/cupertino_ar.arb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,7 @@
4747
"menuDismissLabel": "إغلاق القائمة",
4848
"lookUpButtonLabel": "بحث عام",
4949
"searchWebButtonLabel": "البحث على الويب",
50-
"shareButtonLabel": "مشاركة…"
50+
"shareButtonLabel": "مشاركة…",
51+
"cancelButtonLabel": "Cancel",
52+
"backButtonLabel": "Back"
5153
}

packages/flutter_localizations/lib/src/l10n/cupertino_as.arb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,7 @@
2727
"menuDismissLabel": "অগ্ৰাহ্য কৰাৰ মেনু",
2828
"lookUpButtonLabel": "ওপৰলৈ চাওক",
2929
"searchWebButtonLabel": "ৱেবত সন্ধান কৰক",
30-
"shareButtonLabel": "শ্বেয়াৰ কৰক…"
30+
"shareButtonLabel": "শ্বেয়াৰ কৰক…",
31+
"cancelButtonLabel": "Cancel",
32+
"backButtonLabel": "Back"
3133
}

packages/flutter_localizations/lib/src/l10n/cupertino_az.arb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,7 @@
2727
"menuDismissLabel": "Menyunu qapadın",
2828
"lookUpButtonLabel": "Axtarın",
2929
"searchWebButtonLabel": "Vebdə axtarın",
30-
"shareButtonLabel": "Paylaşın..."
30+
"shareButtonLabel": "Paylaşın...",
31+
"cancelButtonLabel": "Cancel",
32+
"backButtonLabel": "Back"
3133
}

packages/flutter_localizations/lib/src/l10n/cupertino_be.arb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,7 @@
3737
"menuDismissLabel": "Закрыць меню",
3838
"lookUpButtonLabel": "Знайсці",
3939
"searchWebButtonLabel": "Пошук у сетцы",
40-
"shareButtonLabel": "Абагуліць..."
40+
"shareButtonLabel": "Абагуліць...",
41+
"cancelButtonLabel": "Cancel",
42+
"backButtonLabel": "Back"
4143
}

0 commit comments

Comments
 (0)