@@ -92,22 +92,22 @@ String _syntheticL10nPackagePath(FileSystem fileSystem) => fileSystem.path.join(
9292// TODO(thkim1011): Let's store the output of this function in the Message class, so that we don't
9393// recompute this. See https://github.com/flutter/flutter/issues/112709
9494List <String > generateMethodParameters (Message message) {
95- return message.placeholders.map ((Placeholder placeholder) {
95+ return message.placeholders.values. map ((Placeholder placeholder) {
9696 return '${placeholder .type } ${placeholder .name }' ;
9797 }).toList ();
9898}
9999
100100// Similar to above, but is used for passing arguments into helper functions.
101101List <String > generateMethodArguments (Message message) {
102- return message.placeholders.map ((Placeholder placeholder) => placeholder.name).toList ();
102+ return message.placeholders.values. map ((Placeholder placeholder) => placeholder.name).toList ();
103103}
104104
105105String generateDateFormattingLogic (Message message) {
106106 if (message.placeholders.isEmpty || ! message.placeholdersRequireFormatting) {
107107 return '@(none)' ;
108108 }
109109
110- final Iterable <String > formatStatements = message.placeholders
110+ final Iterable <String > formatStatements = message.placeholders.values
111111 .where ((Placeholder placeholder) => placeholder.requiresDateFormatting)
112112 .map ((Placeholder placeholder) {
113113 final String ? placeholderFormat = placeholder.format;
@@ -150,7 +150,7 @@ String generateNumberFormattingLogic(Message message) {
150150 return '@(none)' ;
151151 }
152152
153- final Iterable <String > formatStatements = message.placeholders
153+ final Iterable <String > formatStatements = message.placeholders.values
154154 .where ((Placeholder placeholder) => placeholder.requiresNumFormatting)
155155 .map ((Placeholder placeholder) {
156156 final String ? placeholderFormat = placeholder.format;
@@ -502,8 +502,10 @@ class LocalizationsGenerator {
502502 final FileSystem _fs;
503503 Iterable <Message > _allMessages = < Message > [];
504504 late final AppResourceBundleCollection _allBundles = AppResourceBundleCollection (inputDirectory);
505-
506505 late final AppResourceBundle _templateBundle = AppResourceBundle (templateArbFile);
506+ late final Map <LocaleInfo , String > _inputFileNames = Map <LocaleInfo , String >.fromEntries (
507+ _allBundles.bundles.map ((AppResourceBundle bundle) => MapEntry <LocaleInfo , String >(bundle.locale, bundle.file.basename))
508+ );
507509 late final LocaleInfo _templateArbLocale = _templateBundle.locale;
508510
509511 @visibleForTesting
@@ -843,7 +845,7 @@ class LocalizationsGenerator {
843845 // files in inputDirectory. Also initialized: supportedLocales.
844846 void loadResources () {
845847 _allMessages = _templateBundle.resourceIds.map ((String id) => Message (
846- _templateBundle.resources , id, areResourceAttributesRequired,
848+ _templateBundle, _allBundles , id, areResourceAttributesRequired,
847849 ));
848850 for (final String resourceId in _templateBundle.resourceIds) {
849851 if (! _isValidGetterAndMethodName (resourceId)) {
@@ -891,21 +893,19 @@ class LocalizationsGenerator {
891893 String className,
892894 String fileName,
893895 String header,
894- AppResourceBundle bundle,
895- AppResourceBundle templateBundle,
896- Iterable <Message > messages,
896+ final LocaleInfo locale,
897897 ) {
898- final LocaleInfo locale = bundle.locale;
899-
900- final Iterable <String > methods = messages.map ((Message message) {
901- if (bundle.translationFor (message) == null ) {
898+ final Iterable <String > methods = _allMessages.map ((Message message) {
899+ if (message.messages[locale] == null ) {
902900 _addUnimplementedMessage (locale, message.resourceId);
901+ return _generateMethod (
902+ message,
903+ _templateArbLocale,
904+ );
903905 }
904-
905906 return _generateMethod (
906907 message,
907- bundle.file.basename,
908- bundle.translationFor (message) ?? templateBundle.translationFor (message)! ,
908+ locale,
909909 );
910910 });
911911
@@ -923,20 +923,19 @@ class LocalizationsGenerator {
923923 String _generateSubclass (
924924 String className,
925925 AppResourceBundle bundle,
926- Iterable <Message > messages,
927926 ) {
928927 final LocaleInfo locale = bundle.locale;
929928 final String baseClassName = '$className ${LocaleInfo .fromString (locale .languageCode ).camelCase ()}' ;
930929
931- messages
932- .where ((Message message) => bundle. translationFor ( message) == null )
930+ _allMessages
931+ .where ((Message message) => message.messages[locale] == null )
933932 .forEach ((Message message) {
934933 _addUnimplementedMessage (locale, message.resourceId);
935934 });
936935
937- final Iterable <String > methods = messages
938- .where ((Message message) => bundle. translationFor ( message) != null )
939- .map ((Message message) => _generateMethod (message, bundle.file.basename, bundle. translationFor (message) ! ));
936+ final Iterable <String > methods = _allMessages
937+ .where ((Message message) => message.messages[locale] != null )
938+ .map ((Message message) => _generateMethod (message, locale ));
940939
941940 return subclassTemplate
942941 .replaceAll ('@(language)' , describeLocale (locale.toString ()))
@@ -1016,9 +1015,7 @@ class LocalizationsGenerator {
10161015 className,
10171016 outputFileName,
10181017 header,
1019- _allBundles.bundleFor (locale)! ,
1020- _allBundles.bundleFor (_templateArbLocale)! ,
1021- _allMessages,
1018+ locale,
10221019 );
10231020
10241021 // Every locale for the language except the base class.
@@ -1029,7 +1026,6 @@ class LocalizationsGenerator {
10291026 return _generateSubclass (
10301027 className,
10311028 _allBundles.bundleFor (locale)! ,
1032- _allMessages,
10331029 );
10341030 });
10351031
@@ -1079,13 +1075,14 @@ class LocalizationsGenerator {
10791075 .replaceAll ('\n\n\n ' , '\n\n ' );
10801076 }
10811077
1082- String _generateMethod (Message message, String filename, String translationForMessage ) {
1078+ String _generateMethod (Message message, LocaleInfo locale ) {
10831079 // Determine if we must import intl for date or number formatting.
10841080 if (message.placeholdersRequireFormatting) {
10851081 requiresIntlImport = true ;
10861082 }
10871083
1088- final Node node = Parser (message.resourceId, filename, translationForMessage).parse ();
1084+ final String translationForMessage = message.messages[locale]! ;
1085+ final Node node = message.parsedMessages[locale]! ;
10891086 // If parse tree is only a string, then return a getter method.
10901087 if (node.children.every ((Node child) => child.type == ST .string)) {
10911088 // Use the parsed translation to handle escaping with the same behavior.
@@ -1150,17 +1147,16 @@ class LocalizationsGenerator {
11501147 assert (node.children[1 ].type == ST .identifier);
11511148 final Node identifier = node.children[1 ];
11521149 // Check that placeholders exist.
1153- // TODO(thkim1011): Make message.placeholders a map so that we don't need to do linear time search.
1154- // See https://github.com/flutter/flutter/issues/112709
1155- final Placeholder placeholder = message.placeholders.firstWhere (
1156- (Placeholder placeholder) => placeholder.name == identifier.value,
1157- orElse: () {
1158- throw L10nException ('''
1159- Make sure that the specified placeholder is defined in your arb file.
1160- $translationForMessage
1161- ${Parser .indentForError (identifier .positionInMessage )}''' );
1162- }
1163- );
1150+ final Placeholder ? placeholder = message.placeholders[identifier.value];
1151+ if (placeholder == null ) {
1152+ throw L10nParserException (
1153+ 'Make sure that the specified placeholder is defined in your arb file.' ,
1154+ _inputFileNames[locale]! ,
1155+ message.resourceId,
1156+ translationForMessage,
1157+ identifier.positionInMessage,
1158+ );
1159+ }
11641160 dependentPlaceholders.add (placeholder);
11651161 return HelperMethod (dependentPlaceholders, placeholder: placeholder);
11661162
@@ -1175,25 +1171,27 @@ ${Parser.indentForError(identifier.positionInMessage)}''');
11751171 final Node identifier = node.children[1 ];
11761172 final Node pluralParts = node.children[5 ];
11771173
1178- // Check that identifier exists and is of type int or num.
1179- final Placeholder placeholder = message.placeholders.firstWhere (
1180- (Placeholder placeholder) => placeholder.name == identifier.value,
1181- orElse: () {
1182- throw L10nException ('''
1183- Make sure that the specified plural placeholder is defined in your arb file.
1184- $translationForMessage
1185- ${List <String >.filled (identifier .positionInMessage , ' ' ).join ()}^''' );
1186- }
1187- );
1174+ // Check that placeholders exist and is of type int or num.
1175+ final Placeholder ? placeholder = message.placeholders[identifier.value];
1176+ if (placeholder == null ) {
1177+ throw L10nParserException (
1178+ 'Make sure that the specified placeholder is defined in your arb file.' ,
1179+ _inputFileNames[locale]! ,
1180+ message.resourceId,
1181+ translationForMessage,
1182+ identifier.positionInMessage,
1183+ );
1184+ }
1185+ if (placeholder.type != 'num' && placeholder.type != 'int' ) {
1186+ throw L10nParserException (
1187+ 'The specified placeholder must be of type int or num.' ,
1188+ _inputFileNames[locale]! ,
1189+ message.resourceId,
1190+ translationForMessage,
1191+ identifier.positionInMessage,
1192+ );
1193+ }
11881194 dependentPlaceholders.add (placeholder);
1189- // TODO(thkim1011): Uncomment the following lines after Message refactor.
1190- // See https://github.com/flutter/flutter/issues/112709.
1191- // if (placeholder.type != 'num' && placeholder.type != 'int') {
1192- // throw L10nException('''
1193- // The specified placeholder must be of type int or num.
1194- // $translationForMessage
1195- // ${List<String>.filled(identifier.positionInMessage, ' ').join()}^''');
1196- // }
11971195
11981196 for (final Node pluralPart in pluralParts.children.reversed) {
11991197 String pluralCase;
@@ -1239,16 +1237,17 @@ ${Parser.indentForError(pluralPart.positionInMessage)}
12391237 assert (node.children[5 ].type == ST .selectParts);
12401238
12411239 final Node identifier = node.children[1 ];
1242- // Check that identifier exists
1243- final Placeholder placeholder = message.placeholders.firstWhere (
1244- (Placeholder placeholder) => placeholder.name == identifier.value,
1245- orElse: () {
1246- throw L10nException ('''
1247- Make sure that the specified select placeholder is defined in your arb file.
1248- $translationForMessage
1249- ${Parser .indentForError (identifier .positionInMessage )}''' );
1250- }
1251- );
1240+ // Check that placeholders exist.
1241+ final Placeholder ? placeholder = message.placeholders[identifier.value];
1242+ if (placeholder == null ) {
1243+ throw L10nParserException (
1244+ 'Make sure that the specified placeholder is defined in your arb file.' ,
1245+ _inputFileNames[locale]! ,
1246+ message.resourceId,
1247+ translationForMessage,
1248+ identifier.positionInMessage,
1249+ );
1250+ }
12521251 dependentPlaceholders.add (placeholder);
12531252 final List <String > selectLogicArgs = < String > [];
12541253 final Node selectParts = node.children[5 ];
0 commit comments