@@ -123,23 +123,36 @@ String _syntheticL10nPackagePath(FileSystem fileSystem) => fileSystem.path.join(
123123// For example, if placeholders are used for plurals and no type was specified, then the type will
124124// automatically set to 'num'. Similarly, if such placeholders are used for selects, then the type
125125// will be set to 'String'. For such placeholders that are used for both, we should throw an error.
126- List <String > generateMethodParameters (Message message, bool useNamedParameters) {
127- return message.placeholders.values.map ((Placeholder placeholder) {
126+ List <String > generateMethodParameters (Message message, LocaleInfo ? locale, bool useNamedParameters) {
127+
128+ // Check the compatibility of template placeholders and locale placeholders.
129+ final Map <String , Placeholder >? localePlaceholders = message.localePlaceholders[locale];
130+
131+ return message.templatePlaceholders.entries.map ((MapEntry <String , Placeholder > e) {
132+ final Placeholder placeholder = e.value;
133+ final Placeholder ? localePlaceholder = localePlaceholders? [e.key];
134+ if (localePlaceholder != null && placeholder.type != localePlaceholder.type) {
135+ throw L10nException (
136+ 'The placeholder, ${placeholder .name }, has its "type" resource attribute set to '
137+ 'the "${localePlaceholder .type }" type in locale "$locale ", but it is "${placeholder .type }" '
138+ 'in the template placeholder. For compatibility with template placeholder, change '
139+ 'the "type" attribute to "${placeholder .type }".' );
140+ }
128141 return '${useNamedParameters ? 'required ' : '' }${placeholder .type } ${placeholder .name }' ;
129142 }).toList ();
130143}
131144
132145// Similar to above, but is used for passing arguments into helper functions.
133146List <String > generateMethodArguments (Message message) {
134- return message.placeholders .values.map ((Placeholder placeholder) => placeholder.name).toList ();
147+ return message.templatePlaceholders .values.map ((Placeholder placeholder) => placeholder.name).toList ();
135148}
136149
137- String generateDateFormattingLogic (Message message) {
138- if (message.placeholders .isEmpty || ! message.placeholdersRequireFormatting ) {
150+ String generateDateFormattingLogic (Message message, LocaleInfo locale ) {
151+ if (message.templatePlaceholders .isEmpty) {
139152 return '@(none)' ;
140153 }
141154
142- final Iterable <String > formatStatements = message.placeholders.values
155+ final Iterable <String > formatStatements = message.getPlaceholders (locale)
143156 .where ((Placeholder placeholder) => placeholder.requiresDateFormatting)
144157 .map ((Placeholder placeholder) {
145158 final String ? placeholderFormat = placeholder.format;
@@ -177,12 +190,12 @@ String generateDateFormattingLogic(Message message) {
177190 return formatStatements.isEmpty ? '@(none)' : formatStatements.join ();
178191}
179192
180- String generateNumberFormattingLogic (Message message) {
181- if (message.placeholders .isEmpty || ! message.placeholdersRequireFormatting ) {
193+ String generateNumberFormattingLogic (Message message, LocaleInfo locale ) {
194+ if (message.templatePlaceholders .isEmpty) {
182195 return '@(none)' ;
183196 }
184197
185- final Iterable <String > formatStatements = message.placeholders.values
198+ final Iterable <String > formatStatements = message.getPlaceholders (locale)
186199 .where ((Placeholder placeholder) => placeholder.requiresNumFormatting)
187200 .map ((Placeholder placeholder) {
188201 final String ? placeholderFormat = placeholder.format;
@@ -242,12 +255,12 @@ String generateBaseClassMethod(Message message, LocaleInfo? templateArbLocale, b
242255 /// In $templateArbLocale , this message translates to:
243256 /// **'${generateString (message .value )}'**''' ;
244257
245- if (message.placeholders .isNotEmpty) {
258+ if (message.templatePlaceholders .isNotEmpty) {
246259 return (useNamedParameters ? baseClassMethodWithNamedParameterTemplate : baseClassMethodTemplate)
247260 .replaceAll ('@(comment)' , comment)
248261 .replaceAll ('@(templateLocaleTranslationComment)' , templateLocaleTranslationComment)
249262 .replaceAll ('@(name)' , message.resourceId)
250- .replaceAll ('@(parameters)' , generateMethodParameters (message, useNamedParameters).join (', ' ));
263+ .replaceAll ('@(parameters)' , generateMethodParameters (message, null , useNamedParameters).join (', ' ));
251264 }
252265 return baseClassGetterTemplate
253266 .replaceAll ('@(comment)' , comment)
@@ -610,10 +623,6 @@ class LocalizationsGenerator {
610623 /// ['es', 'en'] is passed in, the 'es' locale will take priority over 'en'.
611624 final List <LocaleInfo > preferredSupportedLocales;
612625
613- // Whether we need to import intl or not. This flag is updated after parsing
614- // all of the messages.
615- bool requiresIntlImport = false ;
616-
617626 // Whether we want to use escaping for ICU messages.
618627 bool useEscaping = false ;
619628
@@ -993,8 +1002,7 @@ class LocalizationsGenerator {
9931002 .replaceAll ('@(fileName)' , fileName)
9941003 .replaceAll ('@(class)' , '$className ${locale .camelCase ()}' )
9951004 .replaceAll ('@(localeName)' , locale.toString ())
996- .replaceAll ('@(methods)' , methods.join ('\n\n ' ))
997- .replaceAll ('@(requiresIntlImport)' , requiresIntlImport ? "import 'package:intl/intl.dart' as intl;\n\n " : '' );
1005+ .replaceAll ('@(methods)' , methods.join ('\n\n ' ));
9981006 }
9991007
10001008 String _generateSubclass (
@@ -1143,7 +1151,6 @@ class LocalizationsGenerator {
11431151 .replaceAll ('@(messageClassImports)' , sortedClassImports.join ('\n ' ))
11441152 .replaceAll ('@(delegateClass)' , delegateClass)
11451153 .replaceAll ('@(requiresFoundationImport)' , useDeferredLoading ? '' : "import 'package:flutter/foundation.dart';" )
1146- .replaceAll ('@(requiresIntlImport)' , requiresIntlImport ? "import 'package:intl/intl.dart' as intl;" : '' )
11471154 .replaceAll ('@(canBeNullable)' , usesNullableGetter ? '?' : '' )
11481155 .replaceAll ('@(needsNullCheck)' , usesNullableGetter ? '' : '!' )
11491156 // Removes all trailing whitespace from the generated file.
@@ -1154,15 +1161,10 @@ class LocalizationsGenerator {
11541161
11551162 String _generateMethod (Message message, LocaleInfo locale) {
11561163 try {
1157- // Determine if we must import intl for date or number formatting.
1158- if (message.placeholdersRequireFormatting) {
1159- requiresIntlImport = true ;
1160- }
1161-
11621164 final String translationForMessage = message.messages[locale]! ;
11631165 final Node node = message.parsedMessages[locale]! ;
11641166 // If the placeholders list is empty, then return a getter method.
1165- if (message.placeholders .isEmpty) {
1167+ if (message.templatePlaceholders .isEmpty) {
11661168 // Use the parsed translation to handle escaping with the same behavior.
11671169 return getterTemplate
11681170 .replaceAll ('@(name)' , message.resourceId)
@@ -1196,14 +1198,13 @@ class LocalizationsGenerator {
11961198 case ST .placeholderExpr:
11971199 assert (node.children[1 ].type == ST .identifier);
11981200 final String identifier = node.children[1 ].value! ;
1199- final Placeholder placeholder = message.placeholders [identifier]! ;
1201+ final Placeholder placeholder = message.localePlaceholders[locale] ? [identifier] ?? message.templatePlaceholders [identifier]! ;
12001202 if (placeholder.requiresFormatting) {
12011203 return '\$ ${node .children [1 ].value }String' ;
12021204 }
12031205 return '\$ ${node .children [1 ].value }' ;
12041206
12051207 case ST .pluralExpr:
1206- requiresIntlImport = true ;
12071208 final Map <String , String > pluralLogicArgs = < String , String > {};
12081209 // Recall that pluralExpr are of the form
12091210 // pluralExpr := "{" ID "," "plural" "," pluralParts "}"
@@ -1259,7 +1260,6 @@ The plural cases must be one of "=0", "=1", "=2", "zero", "one", "two", "few", "
12591260 return '\$ $tempVarName ' ;
12601261
12611262 case ST .selectExpr:
1262- requiresIntlImport = true ;
12631263 // Recall that pluralExpr are of the form
12641264 // pluralExpr := "{" ID "," "plural" "," pluralParts "}"
12651265 assert (node.children[1 ].type == ST .identifier);
@@ -1284,7 +1284,6 @@ The plural cases must be one of "=0", "=1", "=2", "zero", "one", "two", "few", "
12841284 );
12851285 return '\$ $tempVarName ' ;
12861286 case ST .argumentExpr:
1287- requiresIntlImport = true ;
12881287 assert (node.children[1 ].type == ST .identifier);
12891288 assert (node.children[3 ].type == ST .argType);
12901289 assert (node.children[7 ].type == ST .identifier);
@@ -1320,9 +1319,9 @@ The plural cases must be one of "=0", "=1", "=2", "zero", "one", "two", "few", "
13201319 final String tempVarLines = tempVariables.isEmpty ? '' : '${tempVariables .join ('\n ' )}\n ' ;
13211320 return (useNamedParameters ? methodWithNamedParameterTemplate : methodTemplate)
13221321 .replaceAll ('@(name)' , message.resourceId)
1323- .replaceAll ('@(parameters)' , generateMethodParameters (message, useNamedParameters).join (', ' ))
1324- .replaceAll ('@(dateFormatting)' , generateDateFormattingLogic (message))
1325- .replaceAll ('@(numberFormatting)' , generateNumberFormattingLogic (message))
1322+ .replaceAll ('@(parameters)' , generateMethodParameters (message, locale, useNamedParameters).join (', ' ))
1323+ .replaceAll ('@(dateFormatting)' , generateDateFormattingLogic (message, locale ))
1324+ .replaceAll ('@(numberFormatting)' , generateNumberFormattingLogic (message, locale ))
13261325 .replaceAll ('@(tempVars)' , tempVarLines)
13271326 .replaceAll ('@(message)' , messageString)
13281327 .replaceAll ('@(none)\n ' , '' );
0 commit comments