@@ -153,22 +153,146 @@ private static ImmutableArray<LocalizableString> ParseXamlFile(AdditionalText fi
153
153
154
154
if ( key != null )
155
155
{
156
- localizableStrings . Add ( ParseLocalizableString ( key , value , comment ) ) ;
156
+ var formatParams = GetParameters ( value ) ;
157
+ var ( summary , updatedFormatParams ) = ParseCommentAndUpdateParameters ( comment , formatParams ) ;
158
+ localizableStrings . Add ( new LocalizableString ( key , value , summary , updatedFormatParams ) ) ;
157
159
}
158
160
}
159
161
160
162
return localizableStrings . ToImmutableArray ( ) ;
161
163
}
162
164
163
- private static LocalizableString ParseLocalizableString ( string key , string value , XComment comment )
165
+ /// <summary>
166
+ /// Analyzes the format string and returns a list of its parameters.
167
+ /// </summary>
168
+ /// <param name="format"></param>
169
+ /// <returns></returns>
170
+ private static List < LocalizableStringParam > GetParameters ( string format )
164
171
{
165
- var ( summary , parameters ) = ParseComment ( comment ) ;
166
- return new LocalizableString ( key , value , summary , parameters ) ;
172
+ var parameters = new Dictionary < int , string > ( ) ;
173
+ int maxIndex = - 1 ;
174
+ int i = 0 ;
175
+ int len = format . Length ;
176
+
177
+ while ( i < len )
178
+ {
179
+ if ( format [ i ] == '{' )
180
+ {
181
+ if ( i + 1 < len && format [ i + 1 ] == '{' )
182
+ {
183
+ // Escaped '{', skip both
184
+ i += 2 ;
185
+ continue ;
186
+ }
187
+ else
188
+ {
189
+ // Start of a format item, parse index and format
190
+ i ++ ; // Move past '{'
191
+ int index = 0 ;
192
+ bool hasIndex = false ;
193
+ // Parse index
194
+ while ( i < len && char . IsDigit ( format [ i ] ) )
195
+ {
196
+ hasIndex = true ;
197
+ index = index * 10 + ( format [ i ] - '0' ) ;
198
+ i ++ ;
199
+ }
200
+ if ( ! hasIndex )
201
+ {
202
+ // Skip invalid format item
203
+ while ( i < len && format [ i ] != '}' )
204
+ {
205
+ i ++ ;
206
+ }
207
+ if ( i < len )
208
+ {
209
+ i ++ ; // Move past '}'
210
+ }
211
+ continue ;
212
+ }
213
+ // Check for colon to parse format
214
+ string formatPart = null ;
215
+ if ( i < len && format [ i ] == ':' )
216
+ {
217
+ i ++ ; // Move past ':'
218
+ int start = i ;
219
+ while ( i < len && format [ i ] != '}' )
220
+ {
221
+ i ++ ;
222
+ }
223
+ formatPart = i < len ? format . Substring ( start , i - start ) : format . Substring ( start ) ;
224
+ if ( i < len )
225
+ {
226
+ i ++ ; // Move past '}'
227
+ }
228
+ }
229
+ else if ( i < len && format [ i ] == '}' )
230
+ {
231
+ // No format part
232
+ i ++ ; // Move past '}'
233
+ }
234
+ else
235
+ {
236
+ // Invalid characters after index, skip to '}'
237
+ while ( i < len && format [ i ] != '}' )
238
+ {
239
+ i ++ ;
240
+ }
241
+ if ( i < len )
242
+ {
243
+ i ++ ; // Move past '}'
244
+ }
245
+ }
246
+ parameters [ index ] = formatPart ;
247
+ if ( index > maxIndex )
248
+ {
249
+ maxIndex = index ;
250
+ }
251
+ }
252
+ }
253
+ else if ( format [ i ] == '}' )
254
+ {
255
+ // Handle possible escaped '}}'
256
+ if ( i + 1 < len && format [ i + 1 ] == '}' )
257
+ {
258
+ i += 2 ;
259
+ }
260
+ else
261
+ {
262
+ i ++ ;
263
+ }
264
+ }
265
+ else
266
+ {
267
+ i ++ ;
268
+ }
269
+ }
270
+
271
+ // Generate the result list from 0 to maxIndex
272
+ var result = new List < LocalizableStringParam > ( ) ;
273
+ if ( maxIndex == - 1 )
274
+ {
275
+ return result ;
276
+ }
277
+
278
+ for ( int idx = 0 ; idx <= maxIndex ; idx ++ )
279
+ {
280
+ var formatValue = parameters . TryGetValue ( idx , out var value ) ? value : null ;
281
+ result . Add ( new LocalizableStringParam { Index = idx , Format = formatValue , Name = $ "arg{ idx } ", Type = "object?" } ) ;
282
+ }
283
+
284
+ return result ;
167
285
}
168
286
169
- private static ( string Summary , ImmutableArray < LocalizableStringParam > Parameters ) ParseComment ( XComment comment )
287
+ /// <summary>
288
+ /// Parses the comment and updates the format parameter names and types.
289
+ /// </summary>
290
+ /// <param name="comment"></param>
291
+ /// <param name="parameters"></param>
292
+ /// <returns></returns>
293
+ private static ( string Summary , ImmutableArray < LocalizableStringParam > Parameters ) ParseCommentAndUpdateParameters ( XComment comment , List < LocalizableStringParam > parameters )
170
294
{
171
- if ( comment == null || comment . Value == null )
295
+ if ( comment == null || comment . Value == null || parameters . Count == 0 )
172
296
{
173
297
return ( null , ImmutableArray < LocalizableStringParam > . Empty ) ;
174
298
}
@@ -177,13 +301,26 @@ private static (string Summary, ImmutableArray<LocalizableStringParam> Parameter
177
301
{
178
302
var doc = XDocument . Parse ( $ "<root>{ comment . Value } </root>") ;
179
303
var summary = doc . Descendants ( "summary" ) . FirstOrDefault ( ) ? . Value . Trim ( ) ;
180
- var parameters = doc . Descendants ( "param" )
181
- . Select ( p => new LocalizableStringParam (
182
- int . Parse ( p . Attribute ( "index" ) . Value ) ,
183
- p . Attribute ( "name" ) . Value ,
184
- p . Attribute ( "type" ) . Value ) )
185
- . ToImmutableArray ( ) ;
186
- return ( summary , parameters ) ;
304
+
305
+ // Update parameter names and types of the format string
306
+ foreach ( var p in doc . Descendants ( "param" ) )
307
+ {
308
+ var index = int . TryParse ( p . Attribute ( "index" ) . Value , out var intValue ) ? intValue : - 1 ;
309
+ var name = p . Attribute ( "name" ) . Value ;
310
+ var type = p . Attribute ( "type" ) . Value ;
311
+ if ( index >= 0 && index < parameters . Count )
312
+ {
313
+ if ( ! string . IsNullOrEmpty ( name ) )
314
+ {
315
+ parameters [ index ] . Name = name ;
316
+ }
317
+ if ( ! string . IsNullOrEmpty ( type ) )
318
+ {
319
+ parameters [ index ] . Type = type ;
320
+ }
321
+ }
322
+ }
323
+ return ( summary , parameters . ToImmutableArray ( ) ) ;
187
324
}
188
325
catch
189
326
{
@@ -472,7 +609,7 @@ private static void GenerateLocalizationMethod(
472
609
string tabString )
473
610
{
474
611
sb . Append ( $ "{ tabString } public static string { ls . Key } (") ;
475
- var parameters = BuildParameters ( ls ) ;
612
+ var parameters = ls . Params . ToList ( ) ;
476
613
sb . Append ( string . Join ( ", " , parameters . Select ( p => $ "{ p . Type } { p . Name } ") ) ) ;
477
614
sb . Append ( ") => " ) ;
478
615
@@ -500,24 +637,6 @@ private static void GenerateLocalizationMethod(
500
637
sb . AppendLine ( ) ;
501
638
}
502
639
503
- private static List < MethodParameter > BuildParameters ( LocalizableString ls )
504
- {
505
- var parameters = new List < MethodParameter > ( ) ;
506
- for ( var i = 0 ; i < 10 ; i ++ )
507
- {
508
- if ( ! ls . Value . Contains ( $ "{{{i}}}") )
509
- {
510
- continue ;
511
- }
512
-
513
- var param = ls . Params . FirstOrDefault ( p => p . Index == i ) ;
514
- parameters . Add ( param is null
515
- ? new MethodParameter ( $ "arg{ i } ", "object?" )
516
- : new MethodParameter ( param . Name , param . Type ) ) ;
517
- }
518
- return parameters ;
519
- }
520
-
521
640
private static string Spacing ( int n )
522
641
{
523
642
Span < char > spaces = stackalloc char [ n * 4 ] ;
@@ -536,30 +655,12 @@ private static string Spacing(int n)
536
655
537
656
#region Classes
538
657
539
- public class MethodParameter
540
- {
541
- public string Name { get ; }
542
- public string Type { get ; }
543
-
544
- public MethodParameter ( string name , string type )
545
- {
546
- Name = name ;
547
- Type = type ;
548
- }
549
- }
550
-
551
658
public class LocalizableStringParam
552
659
{
553
- public int Index { get ; }
554
- public string Name { get ; }
555
- public string Type { get ; }
556
-
557
- public LocalizableStringParam ( int index , string name , string type )
558
- {
559
- Index = index ;
560
- Name = name ;
561
- Type = type ;
562
- }
660
+ public int Index { get ; set ; }
661
+ public string Format { get ; set ; }
662
+ public string Name { get ; set ; }
663
+ public string Type { get ; set ; }
563
664
}
564
665
565
666
public class LocalizableString
0 commit comments