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

[gen-l10n] Fix untranslated messages (#68553)

parent dd8820bc
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
/// Runs `flutter generate_localizations with arguments passed in.
///
/// This script exists as a legacy entrypoint, since existing users of
/// gen_l10n tool used to call
/// `dart ${FLUTTER}/dev/tools/localizations/bin/gen_l10n.dart <options>` to
/// generate their Flutter project's localizations resources.
///
/// Now, the appropriate way to use this tool is to either define an `l10n.yaml`
/// file in the Flutter project repository, or call
/// `flutter generate_localizations <options>`, since the code has moved
/// into `flutter_tools`.
Future<void> main(List<String> rawArgs) async {
final ProcessResult result = await Process.run(
'flutter',
<String>[
'generate_localizations',
...rawArgs,
],
);
stdout.write(result.stdout);
stderr.write(result.stderr);
}
......@@ -62,13 +62,10 @@ void generateLocalizations({
useDeferredLoading: options.deferredLoading ?? false,
useSyntheticPackage: options.useSyntheticPackage ?? true,
areResourceAttributesRequired: options.areResourceAttributesRequired ?? false,
untranslatedMessagesFile: options?.untranslatedMessagesFile?.toFilePath(),
)
..loadResources()
..writeOutputFiles()
..outputUnimplementedMessages(
options?.untranslatedMessagesFile?.toFilePath(),
logger,
);
..writeOutputFiles(logger);
} on L10nException catch (e) {
logger.printError(e.message);
throw Exception();
......
......@@ -206,10 +206,10 @@ class GenerateLocalizationsCommand extends FlutterCommand {
useSyntheticPackage: useSyntheticPackage,
projectPathString: projectPathString,
areResourceAttributesRequired: areResourceAttributesRequired,
untranslatedMessagesFile: untranslatedMessagesFile,
)
..loadResources()
..writeOutputFiles()
..outputUnimplementedMessages(untranslatedMessagesFile, globals.logger);
..writeOutputFiles(globals.logger);
} on L10nException catch (e) {
throwToolExit(e.message);
}
......
......@@ -520,6 +520,10 @@ class LocalizationsGenerator {
/// classes.
String _generatedLocalizationsFile;
/// A generated file that will contain the list of messages for each locale
/// that do not have a translation yet.
File _untranslatedMessagesFile;
/// The file that contains the list of inputs and outputs for generating
/// localizations.
File _inputsAndOutputsListFile;
......@@ -554,6 +558,7 @@ class LocalizationsGenerator {
bool useSyntheticPackage = true,
String projectPathString,
bool areResourceAttributesRequired = false,
String untranslatedMessagesFile,
}) {
_useSyntheticPackage = useSyntheticPackage;
setProjectDir(projectPathString);
......@@ -564,6 +569,7 @@ class LocalizationsGenerator {
setPreferredSupportedLocales(preferredSupportedLocale);
_setHeader(headerString, headerFile);
_setUseDeferredLoading(useDeferredLoading);
_setUntranslatedMessagesFile(untranslatedMessagesFile);
className = classNameString;
_setInputsAndOutputsListFile(inputsAndOutputsListPath);
_areResourceAttributesRequired = areResourceAttributesRequired;
......@@ -763,6 +769,16 @@ class LocalizationsGenerator {
_useDeferredLoading = useDeferredLoading;
}
void _setUntranslatedMessagesFile(String untranslatedMessagesFileString) {
if (untranslatedMessagesFileString == null || untranslatedMessagesFileString.isEmpty) {
return;
}
_untranslatedMessagesFile = _fs.file(
globals.fs.path.join(untranslatedMessagesFileString),
);
}
void _setInputsAndOutputsListFile(String inputsAndOutputsListPath) {
if (inputsAndOutputsListPath == null) {
return;
......@@ -1017,7 +1033,7 @@ class LocalizationsGenerator {
.replaceAll('@(delegateClass)', delegateClass);
}
void writeOutputFiles() {
void writeOutputFiles(Logger logger) {
// First, generate the string contents of all necessary files.
_generateCode();
......@@ -1054,6 +1070,20 @@ class LocalizationsGenerator {
});
baseOutputFile.writeAsStringSync(_generatedLocalizationsFile);
if (_untranslatedMessagesFile != null) {
_generateUntranslatedMessagesFile(logger);
} else if (_unimplementedMessages.isNotEmpty) {
_unimplementedMessages.forEach((LocaleInfo locale, List<String> messages) {
logger.printStatus('"$locale": ${messages.length} untranslated message(s).');
});
logger.printStatus(
'To see a detailed report, use the --untranslated-messages-file \n'
'option in the tool to generate a JSON format file containing \n'
'all messages that need to be translated.'
);
}
if (_inputsAndOutputsListFile != null) {
_outputFileList.add(baseOutputFile.absolute.path);
......@@ -1071,34 +1101,21 @@ class LocalizationsGenerator {
}
}
void outputUnimplementedMessages(String untranslatedMessagesFile, Logger logger) {
void _generateUntranslatedMessagesFile(Logger logger) {
if (logger == null) {
throw L10nException(
'Logger must be defined when generating untranslated messages file.'
);
}
if (untranslatedMessagesFile == null || untranslatedMessagesFile == '') {
_unimplementedMessages.forEach((LocaleInfo locale, List<String> messages) {
logger.printStatus('"$locale": ${messages.length} untranslated message(s).');
});
logger.printStatus(
'To see a detailed report, use the --untranslated-messages-file \n'
'option in the tool to generate a JSON format file containing \n'
'all messages that need to be translated.'
);
} else {
_writeUnimplementedMessagesFile(untranslatedMessagesFile);
}
}
void _writeUnimplementedMessagesFile(String untranslatedMessagesFile) {
if (_unimplementedMessages.isEmpty) {
_untranslatedMessagesFile.writeAsStringSync('{}');
if (_inputsAndOutputsListFile != null) {
_outputFileList.add(_untranslatedMessagesFile.absolute.path);
}
return;
}
final File unimplementedMessageTranslationsFile = _fs.file(untranslatedMessagesFile);
String resultingFile = '{\n';
int count = 0;
final int numberOfLocales = _unimplementedMessages.length;
......@@ -1122,6 +1139,9 @@ class LocalizationsGenerator {
});
resultingFile += '}\n';
unimplementedMessageTranslationsFile.writeAsStringSync(resultingFile);
_untranslatedMessagesFile.writeAsStringSync(resultingFile);
if (_inputsAndOutputsListFile != null) {
_outputFileList.add(_untranslatedMessagesFile.absolute.path);
}
}
}
......@@ -66,11 +66,11 @@ void main() {
useSyntheticPackage: false,
projectPathString: '/',
areResourceAttributesRequired: true,
untranslatedMessagesFile: 'untranslated',
),
).called(1);
verify(mockLocalizationsGenerator.loadResources()).called(1);
verify(mockLocalizationsGenerator.writeOutputFiles()).called(1);
verify(mockLocalizationsGenerator.outputUnimplementedMessages('untranslated', logger)).called(1);
verify(mockLocalizationsGenerator.writeOutputFiles(logger)).called(1);
});
testUsingContext('generateLocalizations throws exception on missing flutter: generate: true flag', () async {
......
......@@ -1444,7 +1444,7 @@ void main() {
await residentRunner.runSourceGenerators();
expect(testLogger.errorText, isEmpty);
expect(testLogger.statusText, contains('use the --untranslated-messages-file'));
expect(testLogger.statusText, isEmpty);
}));
testUsingContext('ResidentRunner can run source generation - generation fails', () => testbed.run(() async {
......
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