Throw error when plural case had undefined behavior (#116622)
* init
* add comment
* make error more actionable
diff --git a/packages/flutter_tools/lib/src/localizations/gen_l10n.dart b/packages/flutter_tools/lib/src/localizations/gen_l10n.dart
index 51d6e53..30bb27f 100644
--- a/packages/flutter_tools/lib/src/localizations/gen_l10n.dart
+++ b/packages/flutter_tools/lib/src/localizations/gen_l10n.dart
@@ -1167,7 +1167,20 @@
}
if (!pluralLogicArgs.containsKey(pluralCases[pluralCase])) {
final String pluralPartExpression = generateVariables(pluralMessage);
- pluralLogicArgs[pluralCases[pluralCase]!] = ' ${pluralCases[pluralCase]}: $pluralPartExpression,';
+ final String? transformedPluralCase = pluralCases[pluralCase];
+ // A valid plural case is one of "=0", "=1", "=2", "zero", "one", "two", "few", "many", or "other".
+ if (transformedPluralCase == null) {
+ throw L10nParserException(
+ '''
+The plural cases must be one of "=0", "=1", "=2", "zero", "one", "two", "few", "many", or "other.
+ $pluralCase is not a valid plural case.''',
+ _inputFileNames[locale]!,
+ message.resourceId,
+ translationForMessage,
+ pluralPart.positionInMessage,
+ );
+ }
+ pluralLogicArgs[transformedPluralCase] = ' ${pluralCases[pluralCase]}: $pluralPartExpression,';
} else if (!suppressWarnings) {
logger.printWarning('''
[${_inputFileNames[locale]}:${message.resourceId}] ICU Syntax Warning: The plural part specified below is overridden by a later plural part.
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 9da376b..604b821 100644
--- a/packages/flutter_tools/test/general.shard/generate_localizations_test.dart
+++ b/packages/flutter_tools/test/general.shard/generate_localizations_test.dart
@@ -2027,6 +2027,38 @@
^'''));
});
+ testWithoutContext('undefined plural cases throws syntax error', () {
+ const String pluralMessageWithUndefinedParts = '''
+{
+ "count": "{count,plural, =0{None} =1{One} =2{Two} =3{Undefined Behavior!} other{Hmm...}}"
+}''';
+ final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
+ ..createSync(recursive: true);
+ l10nDirectory.childFile(defaultTemplateArbFileName)
+ .writeAsStringSync(pluralMessageWithUndefinedParts);
+ try {
+ LocalizationsGenerator(
+ fileSystem: fs,
+ inputPathString: defaultL10nPathString,
+ outputPathString: defaultL10nPathString,
+ templateArbFileName: defaultTemplateArbFileName,
+ outputFileString: defaultOutputFileString,
+ classNameString: defaultClassNameString,
+ logger: logger,
+ )
+ ..loadResources()
+ ..writeOutputFiles();
+ } on L10nException catch (error) {
+ expect(error.message, contains('Found syntax errors.'));
+ expect(logger.hadErrorOutput, isTrue);
+ expect(logger.errorText, contains('''
+[app_en.arb:count] The plural cases must be one of "=0", "=1", "=2", "zero", "one", "two", "few", "many", or "other.
+ 3 is not a valid plural case.
+ {count,plural, =0{None} =1{One} =2{Two} =3{Undefined Behavior!} other{Hmm...}}
+ ^'''));
+ }
+ });
+
testWithoutContext('should automatically infer plural placeholders that are not explicitly defined', () {
const String pluralMessageWithoutPlaceholdersAttribute = '''
{