@@ -192,22 +192,166 @@ private static ImmutableArray<LocalizableString> ParseXamlFile(AdditionalText fi
192
192
193
193
if ( key != null )
194
194
{
195
- localizableStrings . Add ( ParseLocalizableString ( key , value , comment ) ) ;
195
+ var formatParams = GetParameters ( value ) ;
196
+ var ( summary , updatedFormatParams ) = ParseCommentAndUpdateParameters ( comment , formatParams ) ;
197
+ localizableStrings . Add ( new LocalizableString ( key , value , summary , updatedFormatParams ) ) ;
196
198
}
197
199
}
198
200
199
201
return localizableStrings . ToImmutableArray ( ) ;
200
202
}
201
203
202
- private static LocalizableString ParseLocalizableString ( string key , string value , XComment comment )
204
+ /// <summary>
205
+ /// Analyzes the format string and returns a list of its parameters.
206
+ /// </summary>
207
+ /// <param name="format"></param>
208
+ /// <returns></returns>
209
+ private static List < LocalizableStringParam > GetParameters ( string format )
203
210
{
204
- var ( summary , parameters ) = ParseComment ( comment ) ;
205
- return new LocalizableString ( key , value , summary , parameters ) ;
211
+ var parameters = new Dictionary < int , string > ( ) ;
212
+ int maxIndex = - 1 ;
213
+ int i = 0 ;
214
+ int len = format . Length ;
215
+
216
+ while ( i < len )
217
+ {
218
+ if ( format [ i ] == '{' )
219
+ {
220
+ if ( i + 1 < len && format [ i + 1 ] == '{' )
221
+ {
222
+ // Escaped '{', skip both
223
+ i += 2 ;
224
+ continue ;
225
+ }
226
+ else
227
+ {
228
+ // Start of a format item, parse index and format
229
+ i ++ ; // Move past '{'
230
+ int index = 0 ;
231
+ bool hasIndex = false ;
232
+
233
+ // Parse index
234
+ while ( i < len && char . IsDigit ( format [ i ] ) )
235
+ {
236
+ hasIndex = true ;
237
+ index = index * 10 + ( format [ i ] - '0' ) ;
238
+ i ++ ;
239
+ }
240
+
241
+ if ( ! hasIndex )
242
+ {
243
+ // Skip invalid format item
244
+ while ( i < len && format [ i ] != '}' )
245
+ {
246
+ i ++ ;
247
+ }
248
+ if ( i < len )
249
+ {
250
+ i ++ ; // Move past '}'
251
+ }
252
+ continue ;
253
+ }
254
+
255
+ // Check for alignment (comma followed by optional sign and digits)
256
+ if ( i < len && format [ i ] == ',' )
257
+ {
258
+ i ++ ; // Skip comma and optional sign
259
+ if ( i < len && ( format [ i ] == '+' || format [ i ] == '-' ) )
260
+ {
261
+ i ++ ;
262
+ }
263
+ // Skip digits
264
+ while ( i < len && char . IsDigit ( format [ i ] ) )
265
+ {
266
+ i ++ ;
267
+ }
268
+ }
269
+
270
+ string formatPart = null ;
271
+
272
+ // Check for format (after colon)
273
+ if ( i < len && format [ i ] == ':' )
274
+ {
275
+ i ++ ; // Move past ':'
276
+ int start = i ;
277
+ while ( i < len && format [ i ] != '}' )
278
+ {
279
+ i ++ ;
280
+ }
281
+ formatPart = i < len ? format . Substring ( start , i - start ) : format . Substring ( start ) ;
282
+ if ( i < len )
283
+ {
284
+ i ++ ; // Move past '}'
285
+ }
286
+ }
287
+ else if ( i < len && format [ i ] == '}' )
288
+ {
289
+ // No format part
290
+ i ++ ; // Move past '}'
291
+ }
292
+ else
293
+ {
294
+ // Invalid characters after index, skip to '}'
295
+ while ( i < len && format [ i ] != '}' )
296
+ {
297
+ i ++ ;
298
+ }
299
+ if ( i < len )
300
+ {
301
+ i ++ ; // Move past '}'
302
+ }
303
+ }
304
+
305
+ parameters [ index ] = formatPart ;
306
+ if ( index > maxIndex )
307
+ {
308
+ maxIndex = index ;
309
+ }
310
+ }
311
+ }
312
+ else if ( format [ i ] == '}' )
313
+ {
314
+ // Handle possible escaped '}}'
315
+ if ( i + 1 < len && format [ i + 1 ] == '}' )
316
+ {
317
+ i += 2 ; // Skip escaped '}}'
318
+ }
319
+ else
320
+ {
321
+ i ++ ; // Move past '}'
322
+ }
323
+ }
324
+ else
325
+ {
326
+ i ++ ;
327
+ }
328
+ }
329
+
330
+ // Generate the result list from 0 to maxIndex
331
+ var result = new List < LocalizableStringParam > ( ) ;
332
+ if ( maxIndex == - 1 )
333
+ {
334
+ return result ;
335
+ }
336
+
337
+ for ( int idx = 0 ; idx <= maxIndex ; idx ++ )
338
+ {
339
+ var formatValue = parameters . TryGetValue ( idx , out var value ) ? value : null ;
340
+ result . Add ( new LocalizableStringParam { Index = idx , Format = formatValue , Name = $ "arg{ idx } ", Type = "object?" } ) ;
341
+ }
342
+
343
+ return result ;
206
344
}
207
345
208
- private static ( string Summary , ImmutableArray < LocalizableStringParam > Parameters ) ParseComment ( XComment comment )
346
+ /// <summary>
347
+ /// Parses the comment and updates the format parameter names and types.
348
+ /// </summary>
349
+ /// <param name="comment"></param>
350
+ /// <param name="parameters"></param>
351
+ /// <returns></returns>
352
+ private static ( string Summary , ImmutableArray < LocalizableStringParam > Parameters ) ParseCommentAndUpdateParameters ( XComment comment , List < LocalizableStringParam > parameters )
209
353
{
210
- if ( comment == null || comment . Value == null )
354
+ if ( comment == null || comment . Value == null || parameters . Count == 0 )
211
355
{
212
356
return ( null , _emptyLocalizableStringParams ) ;
213
357
}
@@ -216,13 +360,26 @@ private static (string Summary, ImmutableArray<LocalizableStringParam> Parameter
216
360
{
217
361
var doc = XDocument . Parse ( $ "<root>{ comment . Value } </root>") ;
218
362
var summary = doc . Descendants ( "summary" ) . FirstOrDefault ( ) ? . Value . Trim ( ) ;
219
- var parameters = doc . Descendants ( "param" )
220
- . Select ( p => new LocalizableStringParam (
221
- int . Parse ( p . Attribute ( "index" ) . Value ) ,
222
- p . Attribute ( "name" ) . Value ,
223
- p . Attribute ( "type" ) . Value ) )
224
- . ToImmutableArray ( ) ;
225
- return ( summary , parameters ) ;
363
+
364
+ // Update parameter names and types of the format string
365
+ foreach ( var p in doc . Descendants ( "param" ) )
366
+ {
367
+ var index = int . TryParse ( p . Attribute ( "index" ) . Value , out var intValue ) ? intValue : - 1 ;
368
+ var name = p . Attribute ( "name" ) . Value ;
369
+ var type = p . Attribute ( "type" ) . Value ;
370
+ if ( index >= 0 && index < parameters . Count )
371
+ {
372
+ if ( ! string . IsNullOrEmpty ( name ) )
373
+ {
374
+ parameters [ index ] . Name = name ;
375
+ }
376
+ if ( ! string . IsNullOrEmpty ( type ) )
377
+ {
378
+ parameters [ index ] . Type = type ;
379
+ }
380
+ }
381
+ }
382
+ return ( summary , parameters . ToImmutableArray ( ) ) ;
226
383
}
227
384
catch
228
385
{
@@ -521,25 +678,32 @@ private static void GenerateLocalizationMethod(
521
678
string tabString )
522
679
{
523
680
sb . Append ( $ "{ tabString } public static string { ls . Key } (") ;
524
- var parameters = BuildParameters ( ls ) ;
681
+
682
+ // Get parameter string
683
+ var parameters = ls . Params . ToList ( ) ;
525
684
sb . Append ( string . Join ( ", " , parameters . Select ( p => $ "{ p . Type } { p . Name } ") ) ) ;
526
685
sb . Append ( ") => " ) ;
527
-
528
686
var formatArgs = parameters . Count > 0
529
687
? $ ", { string . Join ( ", " , parameters . Select ( p => p . Name ) ) } "
530
688
: string . Empty ;
531
689
532
690
if ( isCoreAssembly )
533
691
{
692
+ var getTranslation = "InternationalizationManager.Instance.GetTranslation" ;
534
693
sb . AppendLine ( parameters . Count > 0
535
- ? $ "string.Format(InternationalizationManager.Instance.GetTranslation(\" { ls . Key } \" ){ formatArgs } );"
536
- : $ "InternationalizationManager.Instance.GetTranslation(\" { ls . Key } \" );") ;
694
+ ? ! ls . Format ?
695
+ $ "string.Format({ getTranslation } (\" { ls . Key } \" ){ formatArgs } );"
696
+ : $ "string.Format(System.Globalization.CultureInfo.CurrentCulture, { getTranslation } (\" { ls . Key } \" ){ formatArgs } );"
697
+ : $ "{ getTranslation } (\" { ls . Key } \" );") ;
537
698
}
538
699
else if ( pluginInfo ? . IsValid == true )
539
700
{
701
+ var getTranslation = $ "{ pluginInfo . ContextAccessor } .API.GetTranslation";
540
702
sb . AppendLine ( parameters . Count > 0
541
- ? $ "string.Format({ pluginInfo . ContextAccessor } .API.GetTranslation(\" { ls . Key } \" ){ formatArgs } );"
542
- : $ "{ pluginInfo . ContextAccessor } .API.GetTranslation(\" { ls . Key } \" );") ;
703
+ ? ! ls . Format ?
704
+ $ "string.Format({ getTranslation } (\" { ls . Key } \" ){ formatArgs } );"
705
+ : $ "string.Format(System.Globalization.CultureInfo.CurrentCulture, { getTranslation } (\" { ls . Key } \" ){ formatArgs } );"
706
+ : $ "{ getTranslation } (\" { ls . Key } \" );") ;
543
707
}
544
708
else
545
709
{
@@ -549,24 +713,6 @@ private static void GenerateLocalizationMethod(
549
713
sb . AppendLine ( ) ;
550
714
}
551
715
552
- private static List < MethodParameter > BuildParameters ( LocalizableString ls )
553
- {
554
- var parameters = new List < MethodParameter > ( ) ;
555
- for ( var i = 0 ; i < 10 ; i ++ )
556
- {
557
- if ( ! ls . Value . Contains ( $ "{{{i}}}") )
558
- {
559
- continue ;
560
- }
561
-
562
- var param = ls . Params . FirstOrDefault ( p => p . Index == i ) ;
563
- parameters . Add ( param is null
564
- ? new MethodParameter ( $ "arg{ i } ", "object?" )
565
- : new MethodParameter ( param . Name , param . Type ) ) ;
566
- }
567
- return parameters ;
568
- }
569
-
570
716
private static string Spacing ( int n )
571
717
{
572
718
Span < char > spaces = stackalloc char [ n * 4 ] ;
@@ -585,30 +731,12 @@ private static string Spacing(int n)
585
731
586
732
#region Classes
587
733
588
- public class MethodParameter
589
- {
590
- public string Name { get ; }
591
- public string Type { get ; }
592
-
593
- public MethodParameter ( string name , string type )
594
- {
595
- Name = name ;
596
- Type = type ;
597
- }
598
- }
599
-
600
734
public class LocalizableStringParam
601
735
{
602
- public int Index { get ; }
603
- public string Name { get ; }
604
- public string Type { get ; }
605
-
606
- public LocalizableStringParam ( int index , string name , string type )
607
- {
608
- Index = index ;
609
- Name = name ;
610
- Type = type ;
611
- }
736
+ public int Index { get ; set ; }
737
+ public string Format { get ; set ; }
738
+ public string Name { get ; set ; }
739
+ public string Type { get ; set ; }
612
740
}
613
741
614
742
public class LocalizableString
@@ -617,6 +745,8 @@ public class LocalizableString
617
745
public string Value { get ; }
618
746
public string Summary { get ; }
619
747
public IEnumerable < LocalizableStringParam > Params { get ; }
748
+
749
+ public bool Format => Params . Any ( p => ! string . IsNullOrEmpty ( p . Format ) ) ;
620
750
621
751
public LocalizableString ( string key , string value , string summary , IEnumerable < LocalizableStringParam > @params )
622
752
{
0 commit comments