🔥 Do not format the messages file for `gen-l10n` (#119596)
* 🔥 Do not format the messages file
* ✅ Add test
* ✅ Add the link to the test
* ✅ Respect the path separator from the file system
* ✅ Add the untranslated messages file existence test
diff --git a/packages/flutter_tools/lib/src/commands/generate_localizations.dart b/packages/flutter_tools/lib/src/commands/generate_localizations.dart
index 0cffa44..233b693 100644
--- a/packages/flutter_tools/lib/src/commands/generate_localizations.dart
+++ b/packages/flutter_tools/lib/src/commands/generate_localizations.dart
@@ -223,7 +223,8 @@
@override
Future<FlutterCommandResult> runCommand() async {
- List<String> outputFileList;
+ final List<String> outputFileList;
+ File? untranslatedMessagesFile;
bool format = boolArg('format') ?? false;
@@ -238,19 +239,21 @@
'To use the command line arguments, delete the l10n.yaml file in the '
'Flutter project.\n\n'
);
- outputFileList = generateLocalizations(
+ final LocalizationsGenerator generator = generateLocalizations(
logger: _logger,
options: options,
projectDir: _fileSystem.currentDirectory,
fileSystem: _fileSystem,
- ).outputFileList;
+ );
+ outputFileList = generator.outputFileList;
+ untranslatedMessagesFile = generator.untranslatedMessagesFile;
format = format || options.format;
} else {
final String inputPathString = stringArgDeprecated('arb-dir')!; // Has default value, cannot be null.
final String? outputPathString = stringArgDeprecated('output-dir');
final String outputFileString = stringArgDeprecated('output-localization-file')!; // Has default value, cannot be null.
final String templateArbFileName = stringArgDeprecated('template-arb-file')!; // Has default value, cannot be null.
- final String? untranslatedMessagesFile = stringArgDeprecated('untranslated-messages-file');
+ final String? untranslatedMessagesFilePath = stringArgDeprecated('untranslated-messages-file');
final String classNameString = stringArgDeprecated('output-class')!; // Has default value, cannot be null.
final List<String> preferredSupportedLocales = stringsArg('preferred-supported-locales');
final String? headerString = stringArgDeprecated('header');
@@ -267,7 +270,7 @@
precacheLanguageAndRegionTags();
try {
- outputFileList = (LocalizationsGenerator(
+ final LocalizationsGenerator generator = LocalizationsGenerator(
fileSystem: _fileSystem,
inputPathString: inputPathString,
outputPathString: outputPathString,
@@ -282,15 +285,16 @@
useSyntheticPackage: useSyntheticPackage,
projectPathString: projectPathString,
areResourceAttributesRequired: areResourceAttributesRequired,
- untranslatedMessagesFile: untranslatedMessagesFile,
+ untranslatedMessagesFile: untranslatedMessagesFilePath,
usesNullableGetter: usesNullableGetter,
useEscaping: useEscaping,
logger: _logger,
suppressWarnings: suppressWarnings,
)
..loadResources()
- ..writeOutputFiles())
- .outputFileList;
+ ..writeOutputFiles();
+ outputFileList = generator.outputFileList;
+ untranslatedMessagesFile = generator.untranslatedMessagesFile;
} on L10nException catch (e) {
throwToolExit(e.message);
}
@@ -301,8 +305,16 @@
if (outputFileList.isEmpty) {
return FlutterCommandResult.success();
}
+ final List<String> formatFileList = outputFileList.toList();
+ if (untranslatedMessagesFile != null) {
+ // Don't format the messages file using `dart format`.
+ formatFileList.remove(untranslatedMessagesFile.absolute.path);
+ }
+ if (formatFileList.isEmpty) {
+ return FlutterCommandResult.success();
+ }
final String dartBinary = _artifacts.getArtifactPath(Artifact.engineDartBinary);
- final List<String> command = <String>[dartBinary, 'format', ...outputFileList];
+ final List<String> command = <String>[dartBinary, 'format', ...formatFileList];
final ProcessResult result = await _processManager.run(command);
if (result.exitCode != 0) {
throwToolExit('Formatting failed: $result', exitCode: result.exitCode);
diff --git a/packages/flutter_tools/lib/src/localizations/gen_l10n.dart b/packages/flutter_tools/lib/src/localizations/gen_l10n.dart
index 5a31e09..820940a 100644
--- a/packages/flutter_tools/lib/src/localizations/gen_l10n.dart
+++ b/packages/flutter_tools/lib/src/localizations/gen_l10n.dart
@@ -627,7 +627,6 @@
/// A generated file that will contain the list of messages for each locale
/// that do not have a translation yet.
- @visibleForTesting
final File? untranslatedMessagesFile;
/// The file that contains the list of inputs and outputs for generating
@@ -824,7 +823,7 @@
if (untranslatedMessagesFileString == null || untranslatedMessagesFileString.isEmpty) {
return null;
}
-
+ untranslatedMessagesFileString = untranslatedMessagesFileString.replaceAll(r'\', fileSystem.path.separator);
return fileSystem.file(untranslatedMessagesFileString);
}
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/generate_localizations_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/generate_localizations_test.dart
index cd52d89..e57e5ec 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/generate_localizations_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/generate_localizations_test.dart
@@ -265,4 +265,58 @@
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(),
});
+
+ // Regression test for https://github.com/flutter/flutter/issues/119594
+ testUsingContext('dart format is working when the untranslated messages file is produced', () async {
+ final File arbFile = fileSystem.file(fileSystem.path.join('lib', 'l10n', 'app_en.arb'))
+ ..createSync(recursive: true);
+ arbFile.writeAsStringSync('''
+{
+ "helloWorld": "Hello, World!",
+ "untranslated": "Test untranslated message."
+}''');
+ fileSystem.file(fileSystem.path.join('lib', 'l10n', 'app_es.arb'))
+ ..createSync(recursive: true)
+ ..writeAsStringSync('''
+{
+ "helloWorld": "Hello, World!"
+}''');
+ final File configFile = fileSystem.file('l10n.yaml')..createSync();
+ configFile.writeAsStringSync('''
+format: true
+untranslated-messages-file: lib/l10n/untranslated.json
+''');
+ final File pubspecFile = fileSystem.file('pubspec.yaml')..createSync();
+ pubspecFile.writeAsStringSync(BasicProjectWithFlutterGen().pubspec);
+ processManager.addCommand(
+ const FakeCommand(
+ command: <String>[
+ 'Artifact.engineDartBinary',
+ 'format',
+ '/.dart_tool/flutter_gen/gen_l10n/app_localizations_en.dart',
+ '/.dart_tool/flutter_gen/gen_l10n/app_localizations_es.dart',
+ '/.dart_tool/flutter_gen/gen_l10n/app_localizations.dart',
+ ]
+ )
+ );
+ final GenerateLocalizationsCommand command = GenerateLocalizationsCommand(
+ fileSystem: fileSystem,
+ logger: logger,
+ artifacts: artifacts,
+ processManager: processManager,
+ );
+ await createTestCommandRunner(command).run(<String>['gen-l10n']);
+
+ final Directory outputDirectory = fileSystem.directory(fileSystem.path.join('.dart_tool', 'flutter_gen', 'gen_l10n'));
+ expect(outputDirectory.existsSync(), true);
+ expect(outputDirectory.childFile('app_localizations_en.dart').existsSync(), true);
+ expect(outputDirectory.childFile('app_localizations_es.dart').existsSync(), true);
+ expect(outputDirectory.childFile('app_localizations.dart').existsSync(), true);
+ final File untranslatedMessagesFile = fileSystem.file(fileSystem.path.join('lib', 'l10n', 'untranslated.json'));
+ expect(untranslatedMessagesFile.existsSync(), true);
+ expect(processManager, hasNoRemainingExpectations);
+ }, overrides: <Type, Generator>{
+ FileSystem: () => fileSystem,
+ ProcessManager: () => FakeProcessManager.any(),
+ });
}