Unverified Commit 244f5ab5 authored by Shi-Hao Hong's avatar Shi-Hao Hong Committed by GitHub

Expose date symbols and patterns for en_US in framework (#67900)

* Expose date symbols and patterns for en_US in framework
parent 8aee75f6
......@@ -75,6 +75,7 @@ Future<void> main(List<String> rawArgs) async {
final Directory datePatternsDirectory = Directory(path.join(pathToIntl, 'src', 'data', 'dates', 'patterns'));
final Map<String, File> patternFiles = _listIntlData(datePatternsDirectory);
final StringBuffer buffer = StringBuffer();
final Set<String> supportedLocales = _supportedLocales();
buffer.writeln(
'''
......@@ -94,7 +95,7 @@ Future<void> main(List<String> rawArgs) async {
buffer.writeln('const Map<String, dynamic> dateSymbols = <String, dynamic> {');
symbolFiles.forEach((String locale, File data) {
currentLocale = locale;
if (_supportedLocales().contains(locale))
if (supportedLocales.contains(locale))
buffer.writeln(_jsonToMapEntry(locale, json.decode(data.readAsStringSync())));
});
currentLocale = null;
......@@ -107,7 +108,7 @@ Future<void> main(List<String> rawArgs) async {
/// supported by flutter_localizations.''');
buffer.writeln('const Map<String, Map<String, String>> datePatterns = <String, Map<String, String>> {');
patternFiles.forEach((String locale, File data) {
if (_supportedLocales().contains(locale)) {
if (supportedLocales.contains(locale)) {
final Map<String, dynamic> patterns = json.decode(data.readAsStringSync()) as Map<String, dynamic>;
buffer.writeln("'$locale': <String, String>{");
patterns.forEach((String key, dynamic value) {
......@@ -164,13 +165,21 @@ String _jsonToMap(dynamic json) {
}
Set<String> _supportedLocales() {
final Set<String> supportedLocales = <String>{};
// Assumes that en_US is a supported locale by default. Without this, usage
// of the intl package APIs before Flutter populates its set of supported i18n
// date patterns and symbols may cause problems.
//
// For more context, see https://github.com/flutter/flutter/issues/67644.
final Set<String> supportedLocales = <String>{
'en_US',
};
final RegExp filenameRE = RegExp(r'(?:material|cupertino)_(\w+)\.arb$');
final Directory supportedLocalesDirectory = Directory(path.join('packages', 'flutter_localizations', 'lib', 'src', 'l10n'));
for (final FileSystemEntity entity in supportedLocalesDirectory.listSync()) {
final String filePath = entity.path;
if (FileSystemEntity.isFileSync(filePath) && filenameRE.hasMatch(filePath))
if (FileSystemEntity.isFileSync(filePath) && filenameRE.hasMatch(filePath)) {
supportedLocales.add(filenameRE.firstMatch(filePath)[1]);
}
}
return supportedLocales;
......
......@@ -4001,6 +4001,196 @@ const Map<String, dynamic> dateSymbols = <String, dynamic>{
'{1}, {0}',
],
},
'en_US': <String, dynamic>{
'NAME': 'en_US',
'ERAS': <dynamic>[
'BC',
'AD',
],
'ERANAMES': <dynamic>[
'Before Christ',
'Anno Domini',
],
'NARROWMONTHS': <dynamic>[
'J',
'F',
'M',
'A',
'M',
'J',
'J',
'A',
'S',
'O',
'N',
'D',
],
'STANDALONENARROWMONTHS': <dynamic>[
'J',
'F',
'M',
'A',
'M',
'J',
'J',
'A',
'S',
'O',
'N',
'D',
],
'MONTHS': <dynamic>[
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
],
'STANDALONEMONTHS': <dynamic>[
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
],
'SHORTMONTHS': <dynamic>[
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
],
'STANDALONESHORTMONTHS': <dynamic>[
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
],
'WEEKDAYS': <dynamic>[
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
],
'STANDALONEWEEKDAYS': <dynamic>[
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
],
'SHORTWEEKDAYS': <dynamic>[
'Sun',
'Mon',
'Tue',
'Wed',
'Thu',
'Fri',
'Sat',
],
'STANDALONESHORTWEEKDAYS': <dynamic>[
'Sun',
'Mon',
'Tue',
'Wed',
'Thu',
'Fri',
'Sat',
],
'NARROWWEEKDAYS': <dynamic>[
'S',
'M',
'T',
'W',
'T',
'F',
'S',
],
'STANDALONENARROWWEEKDAYS': <dynamic>[
'S',
'M',
'T',
'W',
'T',
'F',
'S',
],
'SHORTQUARTERS': <dynamic>[
'Q1',
'Q2',
'Q3',
'Q4',
],
'QUARTERS': <dynamic>[
'1st quarter',
'2nd quarter',
'3rd quarter',
'4th quarter',
],
'AMPMS': <dynamic>[
'AM',
'PM',
],
'DATEFORMATS': <dynamic>[
'EEEE, MMMM d, y',
'MMMM d, y',
'MMM d, y',
'M/d/yy',
],
'TIMEFORMATS': <dynamic>[
'h:mm:ss a zzzz',
'h:mm:ss a z',
'h:mm:ss a',
'h:mm a',
],
'AVAILABLEFORMATS': null,
'FIRSTDAYOFWEEK': 6,
'WEEKENDRANGE': <dynamic>[
5,
6,
],
'FIRSTWEEKCUTOFFDAY': 5,
'DATETIMEFORMATS': <dynamic>[
'{1} \'at\' {0}',
'{1} \'at\' {0}',
'{1}, {0}',
'{1}, {0}',
],
},
'en_ZA': <String, dynamic>{
'NAME': 'en_ZA',
'ERAS': <dynamic>[
......@@ -18658,6 +18848,52 @@ const Map<String, Map<String, String>> datePatterns =
'zzzz': 'zzzz',
'ZZZZ': 'ZZZZ',
},
'en_US': <String, String>{
'd': 'd',
'E': 'ccc',
'EEEE': 'cccc',
'LLL': 'LLL',
'LLLL': 'LLLL',
'M': 'L',
'Md': 'M/d',
'MEd': 'EEE, M/d',
'MMM': 'LLL',
'MMMd': 'MMM d',
'MMMEd': 'EEE, MMM d',
'MMMM': 'LLLL',
'MMMMd': 'MMMM d',
'MMMMEEEEd': 'EEEE, MMMM d',
'QQQ': 'QQQ',
'QQQQ': 'QQQQ',
'y': 'y',
'yM': 'M/y',
'yMd': 'M/d/y',
'yMEd': 'EEE, M/d/y',
'yMMM': 'MMM y',
'yMMMd': 'MMM d, y',
'yMMMEd': 'EEE, MMM d, y',
'yMMMM': 'MMMM y',
'yMMMMd': 'MMMM d, y',
'yMMMMEEEEd': 'EEEE, MMMM d, y',
'yQQQ': 'QQQ y',
'yQQQQ': 'QQQQ y',
'H': 'HH',
'Hm': 'HH:mm',
'Hms': 'HH:mm:ss',
'j': 'h a',
'jm': 'h:mm a',
'jms': 'h:mm:ss a',
'jmv': 'h:mm a v',
'jmz': 'h:mm a z',
'jz': 'h a z',
'm': 'm',
'ms': 'mm:ss',
's': 's',
'v': 'v',
'z': 'z',
'zzzz': 'zzzz',
'ZZZZ': 'ZZZZ',
},
'en_ZA': <String, String>{
'd': 'd',
'E': 'ccc',
......
......@@ -9,17 +9,18 @@ import '../l10n/generated_date_localizations.dart' as date_localizations;
/// Tracks if date i18n data has been loaded.
bool _dateIntlDataInitialized = false;
/// Loads i18n data for dates if it hasn't be loaded yet.
/// Loads i18n data for dates if it hasn't been loaded yet.
///
/// Only the first invocation of this function has the effect of loading the
/// data. Subsequent invocations have no effect.
/// Only the first invocation of this function loads the data. Subsequent
/// invocations have no effect.
void loadDateIntlDataIfNotLoaded() {
if (!_dateIntlDataInitialized) {
// TODO(garyq): Add support for scriptCodes. Do not strip scriptCode from string.
// Keep track of initialzed locales, or will fail on attempted double init.
// This can only happen if a locale with a stripped scriptCode has already
// been initialzed. This should be removed when scriptCode stripping is removed.
// Keeps track of initialized locales. This can only happen if a locale
// with a stripped scriptCode has already been initialzed. The set of
// initialized locales should be removed when scriptCode stripping is
// removed.
final Set<String> initializedLocales = <String>{};
date_localizations.dateSymbols
.cast<String, Map<String, dynamic>>()
......
......@@ -7,6 +7,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:intl/intl.dart';
void main() {
group(GlobalMaterialLocalizations, () {
......@@ -159,6 +160,28 @@ 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;
await tester.pumpWidget(MaterialApp(
supportedLocales: const <Locale>[
Locale('en', 'US'),
],
locale: const Locale('en', 'US'),
localizationsDelegates: const <LocalizationsDelegate<dynamic>>[
GlobalMaterialLocalizations.delegate,
],
home: Builder(builder: (BuildContext context) {
dateFormat = DateFormat('EEE, d MMM yyyy HH:mm:ss', 'en_US');
return Container();
}),
));
expect(dateFormat?.locale, 'en_US');
});
}
enum DateType { year, medium, full, monthYear }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment