From 485c409184777c9a5eac0d65c362e00d080ea310 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Fri, 21 May 2021 19:04:04 -0700 Subject: [PATCH] import pkg:intl when DateFormat or NumberFormat is used (#83122) --- .../lib/src/localizations/gen_l10n.dart | 6 +- .../generate_localizations_test.dart | 73 +++++++++++++++++++ 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/packages/flutter_tools/lib/src/localizations/gen_l10n.dart b/packages/flutter_tools/lib/src/localizations/gen_l10n.dart index 11180ade492..461c4bdd32a 100644 --- a/packages/flutter_tools/lib/src/localizations/gen_l10n.dart +++ b/packages/flutter_tools/lib/src/localizations/gen_l10n.dart @@ -1020,7 +1020,7 @@ class LocalizationsGenerator { .replaceAll('@(class)', '$className${locale.camelCase()}') .replaceAll('@(localeName)', locale.toString()) .replaceAll('@(methods)', methods.join('\n\n')) - .replaceAll('@(requiresIntlImport)', _containsPluralMessage() ? "import 'package:intl/intl.dart' as intl;" : ''); + .replaceAll('@(requiresIntlImport)', _requiresIntlImport() ? "import 'package:intl/intl.dart' as intl;" : ''); } String _generateSubclass( @@ -1159,7 +1159,7 @@ class LocalizationsGenerator { .replaceAll('@(messageClassImports)', sortedClassImports.join('\n')) .replaceAll('@(delegateClass)', delegateClass) .replaceAll('@(requiresFoundationImport)', useDeferredLoading ? '' : "import 'package:flutter/foundation.dart';") - .replaceAll('@(requiresIntlImport)', _containsPluralMessage() ? "import 'package:intl/intl.dart' as intl;" : '') + .replaceAll('@(requiresIntlImport)', _requiresIntlImport() ? "import 'package:intl/intl.dart' as intl;" : '') .replaceAll('@(canBeNullable)', usesNullableGetter ? '?' : '') .replaceAll('@(needsNullCheck)', usesNullableGetter ? '' : '!') // Removes all trailing whitespace from the generated file. @@ -1168,7 +1168,7 @@ class LocalizationsGenerator { .replaceAll('\n\n\n', '\n\n'); } - bool _containsPluralMessage() => _allMessages.any((Message message) => message.isPlural); + bool _requiresIntlImport() => _allMessages.any((Message message) => message.isPlural || message.placeholdersRequireFormatting); void writeOutputFiles(Logger logger, { bool isFromYaml = false }) { // First, generate the string contents of all necessary files. diff --git a/packages/flutter_tools/test/general.shard/generate_localizations_test.dart b/packages/flutter_tools/test/general.shard/generate_localizations_test.dart index 24b82ea5efc..d95ceac2922 100644 --- a/packages/flutter_tools/test/general.shard/generate_localizations_test.dart +++ b/packages/flutter_tools/test/general.shard/generate_localizations_test.dart @@ -1489,6 +1489,41 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e }); group('DateTime tests', () { + testWithoutContext('imports package:intl', () { + const String singleDateMessageArbFileString = ''' +{ + "@@locale": "en", + "springBegins": "Spring begins on {springStartDate}", + "@springBegins": { + "description": "The first day of spring", + "placeholders": { + "springStartDate": { + "type": "DateTime", + "format": "yMd" + } + } + } +}'''; + fs.currentDirectory.childDirectory('lib').childDirectory('l10n')..createSync(recursive: true) + ..childFile(defaultTemplateArbFileName).writeAsStringSync(singleDateMessageArbFileString); + + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: 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(intlImportDartCode)); + }); + testWithoutContext('throws an exception when improperly formatted date is passed in', () { const String singleDateMessageArbFileString = ''' { @@ -1565,6 +1600,44 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e fail('Improper date formatting should throw an exception'); }); + }); + + group('NumberFormat tests', () { + testWithoutContext('imports package:intl', () { + const String singleDateMessageArbFileString = ''' +{ + "courseCompletion": "You have completed {progress} of the course.", + "@courseCompletion": { + "description": "The amount of progress the student has made in their class.", + "placeholders": { + "progress": { + "type": "double", + "format": "percentPattern" + } + } + } +}'''; + fs.currentDirectory.childDirectory('lib').childDirectory('l10n') + ..createSync(recursive: true) + ..childFile(defaultTemplateArbFileName).writeAsStringSync( + singleDateMessageArbFileString); + + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: 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(intlImportDartCode)); + }); testWithoutContext('throws an exception when improperly formatted number is passed in', () { const String singleDateMessageArbFileString = '''