Skip to content

Commit 244f5ab

Browse files
author
Shi-Hao Hong
authored
Expose date symbols and patterns for en_US in framework (flutter#67900)
* Expose date symbols and patterns for en_US in framework
1 parent 8aee75f commit 244f5ab

File tree

4 files changed

+279
-10
lines changed

4 files changed

+279
-10
lines changed

dev/tools/localization/bin/gen_date_localizations.dart

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ Future<void> main(List<String> rawArgs) async {
7575
final Directory datePatternsDirectory = Directory(path.join(pathToIntl, 'src', 'data', 'dates', 'patterns'));
7676
final Map<String, File> patternFiles = _listIntlData(datePatternsDirectory);
7777
final StringBuffer buffer = StringBuffer();
78+
final Set<String> supportedLocales = _supportedLocales();
7879

7980
buffer.writeln(
8081
'''
@@ -94,7 +95,7 @@ Future<void> main(List<String> rawArgs) async {
9495
buffer.writeln('const Map<String, dynamic> dateSymbols = <String, dynamic> {');
9596
symbolFiles.forEach((String locale, File data) {
9697
currentLocale = locale;
97-
if (_supportedLocales().contains(locale))
98+
if (supportedLocales.contains(locale))
9899
buffer.writeln(_jsonToMapEntry(locale, json.decode(data.readAsStringSync())));
99100
});
100101
currentLocale = null;
@@ -107,7 +108,7 @@ Future<void> main(List<String> rawArgs) async {
107108
/// supported by flutter_localizations.''');
108109
buffer.writeln('const Map<String, Map<String, String>> datePatterns = <String, Map<String, String>> {');
109110
patternFiles.forEach((String locale, File data) {
110-
if (_supportedLocales().contains(locale)) {
111+
if (supportedLocales.contains(locale)) {
111112
final Map<String, dynamic> patterns = json.decode(data.readAsStringSync()) as Map<String, dynamic>;
112113
buffer.writeln("'$locale': <String, String>{");
113114
patterns.forEach((String key, dynamic value) {
@@ -164,13 +165,21 @@ String _jsonToMap(dynamic json) {
164165
}
165166

166167
Set<String> _supportedLocales() {
167-
final Set<String> supportedLocales = <String>{};
168+
// Assumes that en_US is a supported locale by default. Without this, usage
169+
// of the intl package APIs before Flutter populates its set of supported i18n
170+
// date patterns and symbols may cause problems.
171+
//
172+
// For more context, see https://github.com/flutter/flutter/issues/67644.
173+
final Set<String> supportedLocales = <String>{
174+
'en_US',
175+
};
168176
final RegExp filenameRE = RegExp(r'(?:material|cupertino)_(\w+)\.arb$');
169177
final Directory supportedLocalesDirectory = Directory(path.join('packages', 'flutter_localizations', 'lib', 'src', 'l10n'));
170178
for (final FileSystemEntity entity in supportedLocalesDirectory.listSync()) {
171179
final String filePath = entity.path;
172-
if (FileSystemEntity.isFileSync(filePath) && filenameRE.hasMatch(filePath))
180+
if (FileSystemEntity.isFileSync(filePath) && filenameRE.hasMatch(filePath)) {
173181
supportedLocales.add(filenameRE.firstMatch(filePath)[1]);
182+
}
174183
}
175184

176185
return supportedLocales;

packages/flutter_localizations/lib/src/l10n/generated_date_localizations.dart

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4001,6 +4001,196 @@ const Map<String, dynamic> dateSymbols = <String, dynamic>{
40014001
'{1}, {0}',
40024002
],
40034003
},
4004+
'en_US': <String, dynamic>{
4005+
'NAME': 'en_US',
4006+
'ERAS': <dynamic>[
4007+
'BC',
4008+
'AD',
4009+
],
4010+
'ERANAMES': <dynamic>[
4011+
'Before Christ',
4012+
'Anno Domini',
4013+
],
4014+
'NARROWMONTHS': <dynamic>[
4015+
'J',
4016+
'F',
4017+
'M',
4018+
'A',
4019+
'M',
4020+
'J',
4021+
'J',
4022+
'A',
4023+
'S',
4024+
'O',
4025+
'N',
4026+
'D',
4027+
],
4028+
'STANDALONENARROWMONTHS': <dynamic>[
4029+
'J',
4030+
'F',
4031+
'M',
4032+
'A',
4033+
'M',
4034+
'J',
4035+
'J',
4036+
'A',
4037+
'S',
4038+
'O',
4039+
'N',
4040+
'D',
4041+
],
4042+
'MONTHS': <dynamic>[
4043+
'January',
4044+
'February',
4045+
'March',
4046+
'April',
4047+
'May',
4048+
'June',
4049+
'July',
4050+
'August',
4051+
'September',
4052+
'October',
4053+
'November',
4054+
'December',
4055+
],
4056+
'STANDALONEMONTHS': <dynamic>[
4057+
'January',
4058+
'February',
4059+
'March',
4060+
'April',
4061+
'May',
4062+
'June',
4063+
'July',
4064+
'August',
4065+
'September',
4066+
'October',
4067+
'November',
4068+
'December',
4069+
],
4070+
'SHORTMONTHS': <dynamic>[
4071+
'Jan',
4072+
'Feb',
4073+
'Mar',
4074+
'Apr',
4075+
'May',
4076+
'Jun',
4077+
'Jul',
4078+
'Aug',
4079+
'Sep',
4080+
'Oct',
4081+
'Nov',
4082+
'Dec',
4083+
],
4084+
'STANDALONESHORTMONTHS': <dynamic>[
4085+
'Jan',
4086+
'Feb',
4087+
'Mar',
4088+
'Apr',
4089+
'May',
4090+
'Jun',
4091+
'Jul',
4092+
'Aug',
4093+
'Sep',
4094+
'Oct',
4095+
'Nov',
4096+
'Dec',
4097+
],
4098+
'WEEKDAYS': <dynamic>[
4099+
'Sunday',
4100+
'Monday',
4101+
'Tuesday',
4102+
'Wednesday',
4103+
'Thursday',
4104+
'Friday',
4105+
'Saturday',
4106+
],
4107+
'STANDALONEWEEKDAYS': <dynamic>[
4108+
'Sunday',
4109+
'Monday',
4110+
'Tuesday',
4111+
'Wednesday',
4112+
'Thursday',
4113+
'Friday',
4114+
'Saturday',
4115+
],
4116+
'SHORTWEEKDAYS': <dynamic>[
4117+
'Sun',
4118+
'Mon',
4119+
'Tue',
4120+
'Wed',
4121+
'Thu',
4122+
'Fri',
4123+
'Sat',
4124+
],
4125+
'STANDALONESHORTWEEKDAYS': <dynamic>[
4126+
'Sun',
4127+
'Mon',
4128+
'Tue',
4129+
'Wed',
4130+
'Thu',
4131+
'Fri',
4132+
'Sat',
4133+
],
4134+
'NARROWWEEKDAYS': <dynamic>[
4135+
'S',
4136+
'M',
4137+
'T',
4138+
'W',
4139+
'T',
4140+
'F',
4141+
'S',
4142+
],
4143+
'STANDALONENARROWWEEKDAYS': <dynamic>[
4144+
'S',
4145+
'M',
4146+
'T',
4147+
'W',
4148+
'T',
4149+
'F',
4150+
'S',
4151+
],
4152+
'SHORTQUARTERS': <dynamic>[
4153+
'Q1',
4154+
'Q2',
4155+
'Q3',
4156+
'Q4',
4157+
],
4158+
'QUARTERS': <dynamic>[
4159+
'1st quarter',
4160+
'2nd quarter',
4161+
'3rd quarter',
4162+
'4th quarter',
4163+
],
4164+
'AMPMS': <dynamic>[
4165+
'AM',
4166+
'PM',
4167+
],
4168+
'DATEFORMATS': <dynamic>[
4169+
'EEEE, MMMM d, y',
4170+
'MMMM d, y',
4171+
'MMM d, y',
4172+
'M/d/yy',
4173+
],
4174+
'TIMEFORMATS': <dynamic>[
4175+
'h:mm:ss a zzzz',
4176+
'h:mm:ss a z',
4177+
'h:mm:ss a',
4178+
'h:mm a',
4179+
],
4180+
'AVAILABLEFORMATS': null,
4181+
'FIRSTDAYOFWEEK': 6,
4182+
'WEEKENDRANGE': <dynamic>[
4183+
5,
4184+
6,
4185+
],
4186+
'FIRSTWEEKCUTOFFDAY': 5,
4187+
'DATETIMEFORMATS': <dynamic>[
4188+
'{1} \'at\' {0}',
4189+
'{1} \'at\' {0}',
4190+
'{1}, {0}',
4191+
'{1}, {0}',
4192+
],
4193+
},
40044194
'en_ZA': <String, dynamic>{
40054195
'NAME': 'en_ZA',
40064196
'ERAS': <dynamic>[
@@ -18658,6 +18848,52 @@ const Map<String, Map<String, String>> datePatterns =
1865818848
'zzzz': 'zzzz',
1865918849
'ZZZZ': 'ZZZZ',
1866018850
},
18851+
'en_US': <String, String>{
18852+
'd': 'd',
18853+
'E': 'ccc',
18854+
'EEEE': 'cccc',
18855+
'LLL': 'LLL',
18856+
'LLLL': 'LLLL',
18857+
'M': 'L',
18858+
'Md': 'M/d',
18859+
'MEd': 'EEE, M/d',
18860+
'MMM': 'LLL',
18861+
'MMMd': 'MMM d',
18862+
'MMMEd': 'EEE, MMM d',
18863+
'MMMM': 'LLLL',
18864+
'MMMMd': 'MMMM d',
18865+
'MMMMEEEEd': 'EEEE, MMMM d',
18866+
'QQQ': 'QQQ',
18867+
'QQQQ': 'QQQQ',
18868+
'y': 'y',
18869+
'yM': 'M/y',
18870+
'yMd': 'M/d/y',
18871+
'yMEd': 'EEE, M/d/y',
18872+
'yMMM': 'MMM y',
18873+
'yMMMd': 'MMM d, y',
18874+
'yMMMEd': 'EEE, MMM d, y',
18875+
'yMMMM': 'MMMM y',
18876+
'yMMMMd': 'MMMM d, y',
18877+
'yMMMMEEEEd': 'EEEE, MMMM d, y',
18878+
'yQQQ': 'QQQ y',
18879+
'yQQQQ': 'QQQQ y',
18880+
'H': 'HH',
18881+
'Hm': 'HH:mm',
18882+
'Hms': 'HH:mm:ss',
18883+
'j': 'h a',
18884+
'jm': 'h:mm a',
18885+
'jms': 'h:mm:ss a',
18886+
'jmv': 'h:mm a v',
18887+
'jmz': 'h:mm a z',
18888+
'jz': 'h a z',
18889+
'm': 'm',
18890+
'ms': 'mm:ss',
18891+
's': 's',
18892+
'v': 'v',
18893+
'z': 'z',
18894+
'zzzz': 'zzzz',
18895+
'ZZZZ': 'ZZZZ',
18896+
},
1866118897
'en_ZA': <String, String>{
1866218898
'd': 'd',
1866318899
'E': 'ccc',

packages/flutter_localizations/lib/src/utils/date_localizations.dart

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,18 @@ import '../l10n/generated_date_localizations.dart' as date_localizations;
99
/// Tracks if date i18n data has been loaded.
1010
bool _dateIntlDataInitialized = false;
1111

12-
/// Loads i18n data for dates if it hasn't be loaded yet.
12+
/// Loads i18n data for dates if it hasn't been loaded yet.
1313
///
14-
/// Only the first invocation of this function has the effect of loading the
15-
/// data. Subsequent invocations have no effect.
14+
/// Only the first invocation of this function loads the data. Subsequent
15+
/// invocations have no effect.
1616
void loadDateIntlDataIfNotLoaded() {
1717
if (!_dateIntlDataInitialized) {
1818
// TODO(garyq): Add support for scriptCodes. Do not strip scriptCode from string.
1919

20-
// Keep track of initialzed locales, or will fail on attempted double init.
21-
// This can only happen if a locale with a stripped scriptCode has already
22-
// been initialzed. This should be removed when scriptCode stripping is removed.
20+
// Keeps track of initialized locales. This can only happen if a locale
21+
// with a stripped scriptCode has already been initialzed. The set of
22+
// initialized locales should be removed when scriptCode stripping is
23+
// removed.
2324
final Set<String> initializedLocales = <String>{};
2425
date_localizations.dateSymbols
2526
.cast<String, Map<String, dynamic>>()

packages/flutter_localizations/test/material/date_time_test.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'dart:async';
77
import 'package:flutter/material.dart';
88
import 'package:flutter_localizations/flutter_localizations.dart';
99
import 'package:flutter_test/flutter_test.dart';
10+
import 'package:intl/intl.dart';
1011

1112
void main() {
1213
group(GlobalMaterialLocalizations, () {
@@ -159,6 +160,28 @@ void main() {
159160
});
160161
});
161162
});
163+
164+
// Regression test for https://github.com/flutter/flutter/issues/67644.
165+
testWidgets('en_US is initialized correctly by Flutter when DateFormat is used', (WidgetTester tester) async {
166+
DateFormat dateFormat;
167+
168+
await tester.pumpWidget(MaterialApp(
169+
supportedLocales: const <Locale>[
170+
Locale('en', 'US'),
171+
],
172+
locale: const Locale('en', 'US'),
173+
localizationsDelegates: const <LocalizationsDelegate<dynamic>>[
174+
GlobalMaterialLocalizations.delegate,
175+
],
176+
home: Builder(builder: (BuildContext context) {
177+
dateFormat = DateFormat('EEE, d MMM yyyy HH:mm:ss', 'en_US');
178+
179+
return Container();
180+
}),
181+
));
182+
183+
expect(dateFormat?.locale, 'en_US');
184+
});
162185
}
163186

164187
enum DateType { year, medium, full, monthYear }

0 commit comments

Comments
 (0)