Unverified Commit 5848a162 authored by Ahmed Ashour's avatar Ahmed Ashour Committed by GitHub

[gen_l10n] to handle arbitrary DateFormat patterns (#86844)

parent e1485e95
......@@ -111,17 +111,25 @@ String generateDateFormattingLogic(Message message) {
'date formats.'
);
}
if (!placeholder.hasValidDateFormat) {
final bool? isCustomDateFormat = placeholder.isCustomDateFormat;
if (!placeholder.hasValidDateFormat
&& (isCustomDateFormat == null || !isCustomDateFormat)) {
throw L10nException(
'Date format "$placeholderFormat" for placeholder '
'${placeholder.name} does not have a corresponding DateFormat '
"constructor\n. Check the intl library's DateFormat class "
'constructors for allowed date formats.'
'constructors for allowed date formats, or set "isCustomDateFormat" attribute '
'to "true".'
);
}
if (placeholder.hasValidDateFormat) {
return dateFormatTemplate
.replaceAll('@(placeholder)', placeholder.name)
.replaceAll('@(format)', placeholderFormat);
}
return dateFormatCustomTemplate
.replaceAll('@(placeholder)', placeholder.name)
.replaceAll('@(format)', generateString(placeholderFormat));
});
return formatStatements.isEmpty ? '@(none)' : formatStatements.join('');
......
......@@ -126,6 +126,11 @@ const String dateFormatTemplate = '''
final String @(placeholder)String = @(placeholder)DateFormat.format(@(placeholder));
''';
const String dateFormatCustomTemplate = '''
final intl.DateFormat @(placeholder)DateFormat = intl.DateFormat(@(format), localeName);
final String @(placeholder)String = @(placeholder)DateFormat.format(@(placeholder));
''';
const String getterTemplate = '''
@override
String get @(name) => @(message);''';
......
......@@ -193,7 +193,8 @@ class Placeholder {
example = _stringAttribute(resourceId, name, attributes, 'example'),
type = _stringAttribute(resourceId, name, attributes, 'type') ?? 'Object',
format = _stringAttribute(resourceId, name, attributes, 'format'),
optionalParameters = _optionalParameters(resourceId, name, attributes);
optionalParameters = _optionalParameters(resourceId, name, attributes),
isCustomDateFormat = _boolAttribute(resourceId, name, attributes, 'isCustomDateFormat');
final String resourceId;
final String name;
......@@ -201,6 +202,7 @@ class Placeholder {
final String? type;
final String? format;
final List<OptionalParameter> optionalParameters;
final bool? isCustomDateFormat;
bool get requiresFormatting => <String>['DateTime', 'double', 'num'].contains(type) || (type == 'int' && format != null);
bool get isNumber => <String>['double', 'int', 'num'].contains(type);
......@@ -228,6 +230,25 @@ class Placeholder {
return value;
}
static bool? _boolAttribute(
String resourceId,
String name,
Map<String, Object?> attributes,
String attributeName,
) {
final Object? value = attributes[attributeName];
if (value == null) {
return null;
}
if (value != 'true' && value != 'false') {
throw L10nException(
'The "$attributeName" value of the "$name" placeholder in message $resourceId '
'must be a boolean value.',
);
}
return value == 'true';
}
static List<OptionalParameter> _optionalParameters(
String resourceId,
String name,
......
......@@ -1429,6 +1429,80 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
);
});
testWithoutContext('use standard date format whenever possible', () {
const String singleDateMessageArbFileString = '''
{
"@@locale": "en",
"springBegins": "Spring begins on {springStartDate}",
"@springBegins": {
"description": "The first day of spring",
"placeholders": {
"springStartDate": {
"type": "DateTime",
"format": "yMd",
"isCustomDateFormat": "true"
}
}
}
}''';
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
l10nDirectory.childFile(defaultTemplateArbFileName)
.writeAsStringSync(singleDateMessageArbFileString);
LocalizationsGenerator(
fileSystem: fs,
inputPathString: defaultL10nPathString,
templateArbFileName: defaultTemplateArbFileName,
outputFileString: defaultOutputFileString,
classNameString: defaultClassNameString,
)
..loadResources()
..writeOutputFiles(BufferLogger.test());
final String localizationsFile = fs.file(
fs.path.join(syntheticL10nPackagePath, 'output-localization-file_en.dart'),
).readAsStringSync();
expect(localizationsFile, contains('DateFormat.yMd(localeName)'));
});
testWithoutContext('handle arbitrary formatted date', () {
const String singleDateMessageArbFileString = '''
{
"@@locale": "en",
"springBegins": "Spring begins on {springStartDate}",
"@springBegins": {
"description": "The first day of spring",
"placeholders": {
"springStartDate": {
"type": "DateTime",
"format": "asdf o'clock",
"isCustomDateFormat": "true"
}
}
}
}''';
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
l10nDirectory.childFile(defaultTemplateArbFileName)
.writeAsStringSync(singleDateMessageArbFileString);
LocalizationsGenerator(
fileSystem: fs,
inputPathString: defaultL10nPathString,
templateArbFileName: defaultTemplateArbFileName,
outputFileString: defaultOutputFileString,
classNameString: defaultClassNameString,
)
..loadResources()
..writeOutputFiles(BufferLogger.test());
final String localizationsFile = fs.file(
fs.path.join(syntheticL10nPackagePath, 'output-localization-file_en.dart'),
).readAsStringSync();
expect(localizationsFile, contains(r"DateFormat('asdf o\'clock', localeName)"));
});
testWithoutContext('throws an exception when no format attribute is passed in', () {
const String singleDateMessageArbFileString = '''
{
......
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