@@ -92,22 +92,22 @@ String _syntheticL10nPackagePath(FileSystem fileSystem) => fileSystem.path.join(
92
92
// TODO(thkim1011): Let's store the output of this function in the Message class, so that we don't
93
93
// recompute this. See https://github.com/flutter/flutter/issues/112709
94
94
List <String > generateMethodParameters (Message message) {
95
- return message.placeholders.map ((Placeholder placeholder) {
95
+ return message.placeholders.values. map ((Placeholder placeholder) {
96
96
return '${placeholder .type } ${placeholder .name }' ;
97
97
}).toList ();
98
98
}
99
99
100
100
// Similar to above, but is used for passing arguments into helper functions.
101
101
List <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 ();
103
103
}
104
104
105
105
String generateDateFormattingLogic (Message message) {
106
106
if (message.placeholders.isEmpty || ! message.placeholdersRequireFormatting) {
107
107
return '@(none)' ;
108
108
}
109
109
110
- final Iterable <String > formatStatements = message.placeholders
110
+ final Iterable <String > formatStatements = message.placeholders.values
111
111
.where ((Placeholder placeholder) => placeholder.requiresDateFormatting)
112
112
.map ((Placeholder placeholder) {
113
113
final String ? placeholderFormat = placeholder.format;
@@ -150,7 +150,7 @@ String generateNumberFormattingLogic(Message message) {
150
150
return '@(none)' ;
151
151
}
152
152
153
- final Iterable <String > formatStatements = message.placeholders
153
+ final Iterable <String > formatStatements = message.placeholders.values
154
154
.where ((Placeholder placeholder) => placeholder.requiresNumFormatting)
155
155
.map ((Placeholder placeholder) {
156
156
final String ? placeholderFormat = placeholder.format;
@@ -502,8 +502,10 @@ class LocalizationsGenerator {
502
502
final FileSystem _fs;
503
503
Iterable <Message > _allMessages = < Message > [];
504
504
late final AppResourceBundleCollection _allBundles = AppResourceBundleCollection (inputDirectory);
505
-
506
505
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
+ );
507
509
late final LocaleInfo _templateArbLocale = _templateBundle.locale;
508
510
509
511
@visibleForTesting
@@ -843,7 +845,7 @@ class LocalizationsGenerator {
843
845
// files in inputDirectory. Also initialized: supportedLocales.
844
846
void loadResources () {
845
847
_allMessages = _templateBundle.resourceIds.map ((String id) => Message (
846
- _templateBundle.resources , id, areResourceAttributesRequired,
848
+ _templateBundle, _allBundles , id, areResourceAttributesRequired,
847
849
));
848
850
for (final String resourceId in _templateBundle.resourceIds) {
849
851
if (! _isValidGetterAndMethodName (resourceId)) {
@@ -891,21 +893,19 @@ class LocalizationsGenerator {
891
893
String className,
892
894
String fileName,
893
895
String header,
894
- AppResourceBundle bundle,
895
- AppResourceBundle templateBundle,
896
- Iterable <Message > messages,
896
+ final LocaleInfo locale,
897
897
) {
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 ) {
902
900
_addUnimplementedMessage (locale, message.resourceId);
901
+ return _generateMethod (
902
+ message,
903
+ _templateArbLocale,
904
+ );
903
905
}
904
-
905
906
return _generateMethod (
906
907
message,
907
- bundle.file.basename,
908
- bundle.translationFor (message) ?? templateBundle.translationFor (message)! ,
908
+ locale,
909
909
);
910
910
});
911
911
@@ -923,20 +923,19 @@ class LocalizationsGenerator {
923
923
String _generateSubclass (
924
924
String className,
925
925
AppResourceBundle bundle,
926
- Iterable <Message > messages,
927
926
) {
928
927
final LocaleInfo locale = bundle.locale;
929
928
final String baseClassName = '$className ${LocaleInfo .fromString (locale .languageCode ).camelCase ()}' ;
930
929
931
- messages
932
- .where ((Message message) => bundle. translationFor ( message) == null )
930
+ _allMessages
931
+ .where ((Message message) => message.messages[locale] == null )
933
932
.forEach ((Message message) {
934
933
_addUnimplementedMessage (locale, message.resourceId);
935
934
});
936
935
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 ));
940
939
941
940
return subclassTemplate
942
941
.replaceAll ('@(language)' , describeLocale (locale.toString ()))
@@ -1016,9 +1015,7 @@ class LocalizationsGenerator {
1016
1015
className,
1017
1016
outputFileName,
1018
1017
header,
1019
- _allBundles.bundleFor (locale)! ,
1020
- _allBundles.bundleFor (_templateArbLocale)! ,
1021
- _allMessages,
1018
+ locale,
1022
1019
);
1023
1020
1024
1021
// Every locale for the language except the base class.
@@ -1029,7 +1026,6 @@ class LocalizationsGenerator {
1029
1026
return _generateSubclass (
1030
1027
className,
1031
1028
_allBundles.bundleFor (locale)! ,
1032
- _allMessages,
1033
1029
);
1034
1030
});
1035
1031
@@ -1079,13 +1075,14 @@ class LocalizationsGenerator {
1079
1075
.replaceAll ('\n\n\n ' , '\n\n ' );
1080
1076
}
1081
1077
1082
- String _generateMethod (Message message, String filename, String translationForMessage ) {
1078
+ String _generateMethod (Message message, LocaleInfo locale ) {
1083
1079
// Determine if we must import intl for date or number formatting.
1084
1080
if (message.placeholdersRequireFormatting) {
1085
1081
requiresIntlImport = true ;
1086
1082
}
1087
1083
1088
- final Node node = Parser (message.resourceId, filename, translationForMessage).parse ();
1084
+ final String translationForMessage = message.messages[locale]! ;
1085
+ final Node node = message.parsedMessages[locale]! ;
1089
1086
// If parse tree is only a string, then return a getter method.
1090
1087
if (node.children.every ((Node child) => child.type == ST .string)) {
1091
1088
// Use the parsed translation to handle escaping with the same behavior.
@@ -1150,17 +1147,16 @@ class LocalizationsGenerator {
1150
1147
assert (node.children[1 ].type == ST .identifier);
1151
1148
final Node identifier = node.children[1 ];
1152
1149
// 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
+ }
1164
1160
dependentPlaceholders.add (placeholder);
1165
1161
return HelperMethod (dependentPlaceholders, placeholder: placeholder);
1166
1162
@@ -1175,25 +1171,27 @@ ${Parser.indentForError(identifier.positionInMessage)}''');
1175
1171
final Node identifier = node.children[1 ];
1176
1172
final Node pluralParts = node.children[5 ];
1177
1173
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
+ }
1188
1194
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
- // }
1197
1195
1198
1196
for (final Node pluralPart in pluralParts.children.reversed) {
1199
1197
String pluralCase;
@@ -1239,16 +1237,17 @@ ${Parser.indentForError(pluralPart.positionInMessage)}
1239
1237
assert (node.children[5 ].type == ST .selectParts);
1240
1238
1241
1239
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
+ }
1252
1251
dependentPlaceholders.add (placeholder);
1253
1252
final List <String > selectLogicArgs = < String > [];
1254
1253
final Node selectParts = node.children[5 ];
0 commit comments