11part of 'generate_translations.dart' ;
22
3+ const _maxSwitchCasesPerBlock = 1024 ;
4+
35/// Generates the flat map(s) containing all translations for one locale.
46String generateTranslationMap (
57 GenerateConfig config,
@@ -11,98 +13,142 @@ String generateTranslationMap(
1113 '/// The flat map containing all translations for locale <${localeData .locale .languageTag }>.' );
1214 buffer.writeln (
1315 '/// Only for edge cases! For simple maps, use the map function of this library.' );
14-
16+ buffer.writeln ('///' );
17+ buffer.writeln (
18+ '/// The Dart AOT compiler has issues with very large switch statements,' );
19+ buffer.writeln (
20+ '/// so the map is split into smaller functions ($_maxSwitchCasesPerBlock entries each).' );
1521 buffer.writeln (
1622 'extension on ${localeData .base ? config .className : getClassNameRoot (className : config .className , locale : localeData .locale )} {' );
17- buffer.writeln ('\t dynamic _flatMapFunction(String path) {' );
18- buffer.writeln ('\t\t switch (path) {' );
1923
20- _generateTranslationMapRecursive (
21- buffer: buffer,
22- curr: localeData.root,
23- config: config,
24- language: localeData.locale.language,
25- );
24+ final flatList = _toFlatList (localeData.root);
25+ final flatListSplits = < List <Node >> [];
26+ for (var i = 0 ; i < flatList.length; i += _maxSwitchCasesPerBlock) {
27+ flatListSplits.add (flatList.sublist (
28+ i,
29+ min (i + _maxSwitchCasesPerBlock, flatList.length),
30+ ));
31+ }
2632
27- buffer.writeln ('\t\t\t default: return null;' );
28- buffer.writeln ('\t\t }' );
33+ buffer.writeln ('\t dynamic _flatMapFunction(String path) {' );
34+ buffer.write ('\t\t return ' );
35+ for (var i = 0 ; i < flatListSplits.length; i++ ) {
36+ if (i == 0 ) {
37+ buffer.write ('_flatMapFunction\$ $i (path)' );
38+ } else {
39+ buffer.write ('\n\t\t\t ?? _flatMapFunction\$ $i (path)' );
40+ }
41+ }
42+ buffer.writeln (';' );
2943 buffer.writeln ('\t }' );
44+
45+ // Generate split functions
46+ for (var i = 0 ; i < flatListSplits.length; i++ ) {
47+ buffer.writeln ();
48+ buffer.writeln ('\t dynamic _flatMapFunction\$ $i (String path) {' );
49+ buffer.writeln ('\t\t switch (path) {' );
50+
51+ _generateTranslationMap (
52+ buffer: buffer,
53+ flatMap: flatListSplits[i],
54+ config: config,
55+ language: localeData.locale.language,
56+ );
57+
58+ buffer.writeln ('\t\t\t default: return null;' );
59+ buffer.writeln ('\t\t }' );
60+ buffer.writeln ('\t }' );
61+ }
62+
3063 buffer.writeln ('}' );
3164
3265 return buffer.toString ();
3366}
3467
35- void _generateTranslationMapRecursive ({
68+ void _generateTranslationMap ({
3669 required StringBuffer buffer,
37- required Node curr ,
70+ required Iterable < Node > flatMap ,
3871 required GenerateConfig config,
3972 required String language,
4073}) {
41- if (curr is StringTextNode ) {
42- final translationOverrides = config.translationOverrides
43- ? 'TranslationOverrides.string(_root.\$ meta, \' ${curr .path }\' , ${_toParameterMap (curr .params )}) ?? '
44- : '' ;
45- final stringLiteral =
46- getStringLiteral (curr.content, curr.links.length, config.obfuscation);
47- if (curr.params.isEmpty) {
48- buffer.writeln (
49- '\t\t\t case \' ${curr .path }\' : return $translationOverrides $stringLiteral ;' );
50- } else {
51- buffer.writeln (
52- '\t\t\t case \' ${curr .path }\' : return ${_toParameterList (curr .params , curr .paramTypeMap )} => $translationOverrides $stringLiteral ;' );
53- }
54- } else if (curr is RichTextNode ) {
55- buffer.write ('\t\t\t case \' ${curr .path }\' : return ' );
56- _addRichTextCall (
57- buffer: buffer,
58- config: config,
59- node: curr,
60- includeParameters: true ,
61- variableNameResolver: null ,
62- forceArrow: false ,
63- depth: 2 ,
64- forceSemicolon: true ,
65- );
66- } else if (curr is ListNode ) {
67- // recursive
68- for (final child in curr.entries) {
69- _generateTranslationMapRecursive (
74+ for (final curr in flatMap) {
75+ if (curr is StringTextNode ) {
76+ final translationOverrides = config.translationOverrides
77+ ? 'TranslationOverrides.string(_root.\$ meta, \' ${curr .path }\' , ${_toParameterMap (curr .params )}) ?? '
78+ : '' ;
79+ final stringLiteral =
80+ getStringLiteral (curr.content, curr.links.length, config.obfuscation);
81+ if (curr.params.isEmpty) {
82+ buffer.writeln (
83+ '\t\t\t case \' ${curr .path }\' : return $translationOverrides $stringLiteral ;' );
84+ } else {
85+ buffer.writeln (
86+ '\t\t\t case \' ${curr .path }\' : return ${_toParameterList (curr .params , curr .paramTypeMap )} => $translationOverrides $stringLiteral ;' );
87+ }
88+ } else if (curr is RichTextNode ) {
89+ buffer.write ('\t\t\t case \' ${curr .path }\' : return ' );
90+ _addRichTextCall (
7091 buffer: buffer,
71- curr: child,
92+ config: config,
93+ node: curr,
94+ includeParameters: true ,
95+ variableNameResolver: null ,
96+ forceArrow: false ,
97+ depth: 2 ,
98+ forceSemicolon: true ,
99+ );
100+ } else if (curr is ListNode ) {
101+ _generateTranslationMap (
102+ buffer: buffer,
103+ flatMap: curr.entries,
72104 config: config,
73105 language: language,
74106 );
75- }
76- } else if (curr is ObjectNode ) {
77- // recursive
78- for (final child in curr.entries.values) {
79- _generateTranslationMapRecursive (
107+ } else if (curr is PluralNode ) {
108+ buffer.write ('\t\t\t case \' ${curr .path }\' : return ' );
109+ _addPluralCall (
80110 buffer: buffer,
81- curr: child,
82111 config: config,
83112 language: language,
113+ node: curr,
114+ depth: 2 ,
115+ forceSemicolon: true ,
116+ );
117+ } else if (curr is ContextNode ) {
118+ buffer.write ('\t\t\t case \' ${curr .path }\' : return ' );
119+ _addContextCall (
120+ buffer: buffer,
121+ config: config,
122+ node: curr,
123+ depth: 2 ,
124+ forceSemicolon: true ,
84125 );
126+ } else {
127+ throw 'This should not happen' ;
85128 }
86- } else if (curr is PluralNode ) {
87- buffer.write ('\t\t\t case \' ${curr .path }\' : return ' );
88- _addPluralCall (
89- buffer: buffer,
90- config: config,
91- language: language,
92- node: curr,
93- depth: 2 ,
94- forceSemicolon: true ,
95- );
96- } else if (curr is ContextNode ) {
97- buffer.write ('\t\t\t case \' ${curr .path }\' : return ' );
98- _addContextCall (
99- buffer: buffer,
100- config: config,
101- node: curr,
102- depth: 2 ,
103- forceSemicolon: true ,
104- );
105- } else {
106- throw 'This should not happen' ;
107129 }
108130}
131+
132+ List <Node > _toFlatList (ObjectNode root) {
133+ final result = < Node > [];
134+
135+ void flatten (Node node) {
136+ if (node is ListNode ) {
137+ for (final entry in node.entries) {
138+ flatten (entry);
139+ }
140+ } else if (node is ObjectNode ) {
141+ for (final value in node.values) {
142+ flatten (value);
143+ }
144+ } else {
145+ result.add (node);
146+ }
147+ }
148+
149+ for (final value in root.values) {
150+ flatten (value);
151+ }
152+
153+ return result;
154+ }
0 commit comments