fixes l10n for CupertinoDatePicker in monthYear mode (#130934)
This PR fixes l10n issue when months names are being used in incorrect form in CupertinoDatePicker in CupertinoDatePickerMode.yearMonth (#130930). The idea of this proposal is to add an optional parameter `standalone` for `CupertinoLocalizations.datePickerMonth` to be able to choose when to use months names in base form (intl DateSymbols.STANDALONEMONTHS) and when in day-dependent form (intl DateSymbols.MONTHS) <details> <summary>Before</summary> <img width="366" alt="image" src="https://github.com/flutter/flutter/assets/32621121/1dd54fa7-6dd9-4053-889b-57134c145432"> <img width="387" alt="image" src="https://github.com/flutter/flutter/assets/32621121/c176070e-73e4-49d3-883b-ba31eca6d1d7"> </details> <details> <summary>After</summary> <img width="369" alt="image" src="https://github.com/flutter/flutter/assets/32621121/255594f1-219d-4bd4-9b75-1012912f8ab0"> <img width="378" alt="image" src="https://github.com/flutter/flutter/assets/32621121/16bbb41f-3f62-4446-bf41-e27140b649a9"> </details>
This commit is contained in:
parent
5a556f8ecd
commit
1cfba2620a
@ -438,8 +438,9 @@ class CupertinoDatePicker extends StatefulWidget {
|
||||
_PickerColumnType columnType,
|
||||
CupertinoLocalizations localizations,
|
||||
BuildContext context,
|
||||
bool showDayOfWeek
|
||||
) {
|
||||
bool showDayOfWeek, {
|
||||
bool standaloneMonth = false,
|
||||
}) {
|
||||
String longestText = '';
|
||||
|
||||
switch (columnType) {
|
||||
@ -491,8 +492,10 @@ class CupertinoDatePicker extends StatefulWidget {
|
||||
}
|
||||
}
|
||||
case _PickerColumnType.month:
|
||||
for (int i = 1; i <=12; i++) {
|
||||
final String month = localizations.datePickerMonth(i);
|
||||
for (int i = 1; i <= 12; i++) {
|
||||
final String month = standaloneMonth
|
||||
? localizations.datePickerStandaloneMonth(i)
|
||||
: localizations.datePickerMonth(i);
|
||||
if (longestText.length < month.length) {
|
||||
longestText = month;
|
||||
}
|
||||
@ -1280,11 +1283,12 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
|
||||
final int month = index + 1;
|
||||
final bool isInvalidMonth = (widget.minimumDate?.year == selectedYear && widget.minimumDate!.month > month)
|
||||
|| (widget.maximumDate?.year == selectedYear && widget.maximumDate!.month < month);
|
||||
final String monthName = (widget.mode == CupertinoDatePickerMode.monthYear) ? localizations.datePickerStandaloneMonth(month) : localizations.datePickerMonth(month);
|
||||
|
||||
return itemPositioningBuilder(
|
||||
context,
|
||||
Text(
|
||||
localizations.datePickerMonth(month),
|
||||
monthName,
|
||||
style: _themeTextStyle(context, isValid: !isInvalidMonth),
|
||||
),
|
||||
);
|
||||
@ -1577,7 +1581,8 @@ class _CupertinoDatePickerMonthYearState extends State<CupertinoDatePicker> {
|
||||
}
|
||||
|
||||
void _refreshEstimatedColumnWidths() {
|
||||
estimatedColumnWidths[_PickerColumnType.month.index] = CupertinoDatePicker._getColumnWidth(_PickerColumnType.month, localizations, context, false);
|
||||
estimatedColumnWidths[_PickerColumnType.month.index] =
|
||||
CupertinoDatePicker._getColumnWidth(_PickerColumnType.month, localizations, context, false, standaloneMonth: widget.mode == CupertinoDatePickerMode.monthYear);
|
||||
estimatedColumnWidths[_PickerColumnType.year.index] = CupertinoDatePicker._getColumnWidth(_PickerColumnType.year, localizations, context, false);
|
||||
}
|
||||
|
||||
@ -1613,11 +1618,12 @@ class _CupertinoDatePickerMonthYearState extends State<CupertinoDatePicker> {
|
||||
final int month = index + 1;
|
||||
final bool isInvalidMonth = (widget.minimumDate?.year == selectedYear && widget.minimumDate!.month > month)
|
||||
|| (widget.maximumDate?.year == selectedYear && widget.maximumDate!.month < month);
|
||||
final String monthName = (widget.mode == CupertinoDatePickerMode.monthYear) ? localizations.datePickerStandaloneMonth(month) : localizations.datePickerMonth(month);
|
||||
|
||||
return itemPositioningBuilder(
|
||||
context,
|
||||
Text(
|
||||
localizations.datePickerMonth(month),
|
||||
monthName,
|
||||
style: _themeTextStyle(context, isValid: !isInvalidMonth),
|
||||
),
|
||||
);
|
||||
|
@ -76,9 +76,25 @@ abstract class CupertinoLocalizations {
|
||||
///
|
||||
/// - US English: January
|
||||
/// - Korean: 1월
|
||||
/// - Russian: января
|
||||
// The global version uses date symbols data from the intl package.
|
||||
String datePickerMonth(int monthIndex);
|
||||
|
||||
/// Month that is shown in [CupertinoDatePicker] spinner corresponding to
|
||||
/// the given month index in [CupertinoDatePickerMode.monthYear] mode.
|
||||
///
|
||||
/// This is distinct from [datePickerMonth] because in some languages, like Russian,
|
||||
/// the name of a month takes a different form depending
|
||||
/// on whether it is preceded by a day or whether it stands alone.
|
||||
///
|
||||
/// Examples: datePickerMonth(1) in:
|
||||
///
|
||||
/// - US English: January
|
||||
/// - Korean: 1월
|
||||
/// - Russian: Январь
|
||||
// The global version uses date symbols data from the intl package.
|
||||
String datePickerStandaloneMonth(int monthIndex);
|
||||
|
||||
/// Day of month that is shown in [CupertinoDatePicker] spinner corresponding
|
||||
/// to the given day index.
|
||||
///
|
||||
@ -367,6 +383,9 @@ class DefaultCupertinoLocalizations implements CupertinoLocalizations {
|
||||
@override
|
||||
String datePickerMonth(int monthIndex) => _months[monthIndex - 1];
|
||||
|
||||
@override
|
||||
String datePickerStandaloneMonth(int monthIndex) => _months[monthIndex - 1];
|
||||
|
||||
@override
|
||||
String datePickerDayOfMonth(int dayIndex, [int? weekDay]) {
|
||||
if (weekDay != null) {
|
||||
|
@ -100,6 +100,18 @@ abstract class GlobalCupertinoLocalizations implements CupertinoLocalizations {
|
||||
return _fullYearFormat.dateSymbols.MONTHS[monthIndex - 1];
|
||||
}
|
||||
|
||||
@override
|
||||
String datePickerStandaloneMonth(int monthIndex) {
|
||||
// It doesn't actually have anything to do with _fullYearFormat. It's just
|
||||
// taking advantage of the fact that _fullYearFormat loaded the needed
|
||||
// locale's symbols.
|
||||
//
|
||||
// Because this will be used without specifying any day of month,
|
||||
// in most cases it should be capitalized (according to rules in specific language).
|
||||
return intl.toBeginningOfSentenceCase(_fullYearFormat.dateSymbols.STANDALONEMONTHS[monthIndex - 1]) ??
|
||||
_fullYearFormat.dateSymbols.STANDALONEMONTHS[monthIndex - 1];
|
||||
}
|
||||
|
||||
@override
|
||||
String datePickerDayOfMonth(int dayIndex, [int? weekDay]) {
|
||||
if (weekDay != null) {
|
||||
|
@ -0,0 +1,47 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// 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_localizations/flutter_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Test correct month form for CupertinoDatePicker in monthYear mode', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
CupertinoApp(
|
||||
home: CupertinoPageScaffold(
|
||||
child: Center(
|
||||
child: CupertinoDatePicker(
|
||||
initialDateTime: DateTime(2023, 5),
|
||||
onDateTimeChanged: (_) {},
|
||||
mode: CupertinoDatePickerMode.monthYear,
|
||||
)),
|
||||
),
|
||||
supportedLocales: const <Locale>[Locale('ru', 'RU')],
|
||||
localizationsDelegates: GlobalCupertinoLocalizations.delegates,
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('Май'), findsWidgets);
|
||||
});
|
||||
|
||||
testWidgets('Test correct month form for CupertinoDatePicker in date mode', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
CupertinoApp(
|
||||
home: CupertinoPageScaffold(
|
||||
child: Center(
|
||||
child: CupertinoDatePicker(
|
||||
initialDateTime: DateTime(2023, 5),
|
||||
onDateTimeChanged: (_) {},
|
||||
mode: CupertinoDatePickerMode.date,
|
||||
)),
|
||||
),
|
||||
supportedLocales: const <Locale>[Locale('ru', 'RU')],
|
||||
localizationsDelegates: GlobalCupertinoLocalizations.delegates,
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('мая'), findsWidgets);
|
||||
});
|
||||
}
|
@ -34,6 +34,11 @@ void main() {
|
||||
expect(localizations.datePickerMonth(11), isNotNull);
|
||||
expect(localizations.datePickerMonth(12), isNotNull);
|
||||
|
||||
expect(localizations.datePickerStandaloneMonth(1), isNotNull);
|
||||
expect(localizations.datePickerStandaloneMonth(2), isNotNull);
|
||||
expect(localizations.datePickerStandaloneMonth(11), isNotNull);
|
||||
expect(localizations.datePickerStandaloneMonth(12), isNotNull);
|
||||
|
||||
expect(localizations.datePickerDayOfMonth(0), isNotNull);
|
||||
expect(localizations.datePickerDayOfMonth(1), isNotNull);
|
||||
expect(localizations.datePickerDayOfMonth(2), isNotNull);
|
||||
|
Loading…
x
Reference in New Issue
Block a user