11using MahApps . Metro . IconPacks ;
22using MvcVisionSystem . Yolo ;
3+ using OpenVisionLab ;
34using System ;
45using System . Collections . Generic ;
56using System . ComponentModel ;
@@ -143,6 +144,10 @@ public string DetectStatus
143144 set => SetField ( ref detectStatus , value ?? string . Empty ) ;
144145 }
145146
147+ public string LocalizedLabelStatus => LocalizeStatus ( labelStatus , "WpfImageQueue.Row.SavePrefix" ) ;
148+
149+ public string LocalizedDetectStatus => LocalizeStatus ( detectStatus , "WpfImageQueue.Row.InspectPrefix" ) ;
150+
146151 public string Dimensions
147152 {
148153 get => dimensions ;
@@ -159,6 +164,10 @@ public string Detail
159164
160165 public string QueueRowAccessibleName => BuildQueueRowText ( " / " ) ;
161166
167+ public string LocalizedQueueRowToolTip => BuildLocalizedQueueRowText ( Environment . NewLine ) ;
168+
169+ public string LocalizedQueueRowAccessibleName => BuildLocalizedQueueRowText ( " / " ) ;
170+
162171 public string QueueStatusSummary
163172 {
164173 get => queueStatusSummary ;
@@ -171,6 +180,10 @@ public string QueueBadgeText
171180 set => SetField ( ref queueBadgeText , value ?? string . Empty ) ;
172181 }
173182
183+ public string LocalizedQueueBadgeText => LocalizeBadgeText ( queueBadgeText ) ;
184+
185+ public string LocalizedQueueStatusSummary => LocalizeSummary ( queueStatusSummary ) ;
186+
174187 public PackIconMaterialKind QueueIconKind
175188 {
176189 get => queueIconKind ;
@@ -225,6 +238,16 @@ public AnomalyImageReviewState AnomalyReviewState
225238 set => SetField ( ref anomalyReviewState , value ) ;
226239 }
227240
241+ internal void RefreshLocalizedPresentation ( )
242+ {
243+ PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( LocalizedLabelStatus ) ) ) ;
244+ PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( LocalizedDetectStatus ) ) ) ;
245+ PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( LocalizedQueueBadgeText ) ) ) ;
246+ PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( LocalizedQueueStatusSummary ) ) ) ;
247+ PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( LocalizedQueueRowToolTip ) ) ) ;
248+ PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( LocalizedQueueRowAccessibleName ) ) ) ;
249+ }
250+
228251 public static WpfImageQueueItem CreateShell ( string imagePath )
229252 {
230253 return CreateShell ( WpfImageQueueCatalogEntry . Create ( imagePath ) ) ;
@@ -255,11 +278,171 @@ private bool SetField<T>(ref T field, T value, [CallerMemberName] string propert
255278 {
256279 PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( QueueRowToolTip ) ) ) ;
257280 PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( QueueRowAccessibleName ) ) ) ;
281+ PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( LocalizedLabelStatus ) ) ) ;
282+ PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( LocalizedDetectStatus ) ) ) ;
283+ PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( LocalizedQueueStatusSummary ) ) ) ;
284+ PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( LocalizedQueueRowToolTip ) ) ) ;
285+ PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( LocalizedQueueRowAccessibleName ) ) ) ;
286+ }
287+
288+ if ( string . Equals ( propertyName , nameof ( QueueBadgeText ) , StringComparison . Ordinal ) )
289+ {
290+ PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( LocalizedQueueBadgeText ) ) ) ;
258291 }
259292
260293 return true ;
261294 }
262295
296+ private string BuildLocalizedQueueRowText ( string separator )
297+ {
298+ string normalizedSeparator = string . IsNullOrEmpty ( separator ) ? " / " : separator ;
299+ var parts = new List < string > ( ) ;
300+ if ( ! string . IsNullOrWhiteSpace ( FileName ) )
301+ {
302+ parts . Add ( string . Format ( CultureInfo . InvariantCulture , "{0}: {1}" , T ( "WpfImageQueue.Row.FilePrefix" ) , FileName . Trim ( ) ) ) ;
303+ }
304+
305+ parts . Add ( string . Format ( CultureInfo . InvariantCulture , "{0}: {1}" , T ( "WpfImageQueue.Row.SavePrefix" ) , LocalizedLabelStatus ) ) ;
306+ parts . Add ( string . Format ( CultureInfo . InvariantCulture , "{0}: {1}" , T ( "WpfImageQueue.Row.InspectPrefix" ) , LocalizedDetectStatus ) ) ;
307+ if ( ! string . IsNullOrWhiteSpace ( Dimensions ) )
308+ {
309+ parts . Add ( string . Format ( CultureInfo . InvariantCulture , "{0}: {1}" , T ( "WpfImageQueue.Row.SizePrefix" ) , Dimensions . Trim ( ) ) ) ;
310+ }
311+
312+ if ( ! string . IsNullOrWhiteSpace ( LocalizedQueueStatusSummary ) )
313+ {
314+ parts . Add ( string . Format ( CultureInfo . InvariantCulture , "{0}: {1}" , T ( "WpfImageQueue.Row.StatusPrefix" ) , LocalizedQueueStatusSummary ) ) ;
315+ }
316+
317+ if ( ! string . IsNullOrWhiteSpace ( Detail ) )
318+ {
319+ parts . Add ( string . Format ( CultureInfo . InvariantCulture , "{0}: {1}" , T ( "WpfImageQueue.Row.DetailPrefix" ) , LocalizeSummary ( Detail ) ) ) ;
320+ }
321+
322+ return string . Join ( normalizedSeparator , parts ) ;
323+ }
324+
325+ private static string LocalizeStatus ( string value , string prefixKey )
326+ {
327+ string normalized = string . IsNullOrWhiteSpace ( value ) ? string . Empty : NormalizeInlineText ( value ) ;
328+ if ( OpenVisionLanguageService . CurrentLanguage == OpenVisionLanguage . Korean )
329+ {
330+ if ( ! string . IsNullOrWhiteSpace ( normalized ) )
331+ {
332+ return normalized ;
333+ }
334+
335+ return string . Equals ( prefixKey , "WpfImageQueue.Row.SavePrefix" , StringComparison . Ordinal )
336+ ? "없음"
337+ : "대기" ;
338+ }
339+
340+ if ( string . IsNullOrWhiteSpace ( normalized ) )
341+ {
342+ return string . Equals ( prefixKey , "WpfImageQueue.Row.SavePrefix" , StringComparison . Ordinal )
343+ ? "None"
344+ : "Waiting" ;
345+ }
346+
347+ return TranslateKnownStatus ( normalized ) ;
348+ }
349+
350+ private static string LocalizeBadgeText ( string value )
351+ {
352+ string normalized = string . IsNullOrWhiteSpace ( value ) ? string . Empty : NormalizeInlineText ( value ) ;
353+ if ( OpenVisionLanguageService . CurrentLanguage == OpenVisionLanguage . Korean )
354+ {
355+ return normalized ;
356+ }
357+
358+ return TranslateKnownStatus ( normalized ) ;
359+ }
360+
361+ private static string LocalizeSummary ( string value )
362+ {
363+ string normalized = NormalizeInlineText ( value ) ;
364+ if ( OpenVisionLanguageService . CurrentLanguage == OpenVisionLanguage . Korean
365+ || string . IsNullOrWhiteSpace ( normalized ) )
366+ {
367+ return normalized ;
368+ }
369+
370+ string localized = normalized
371+ . Replace ( "상태 확인 중" , "Checking status" , StringComparison . Ordinal )
372+ . Replace ( "수정 필요: 라벨" , "Needs fix: labels" , StringComparison . Ordinal )
373+ . Replace ( "검수 완료: 라벨" , "Reviewed: labels" , StringComparison . Ordinal )
374+ . Replace ( "저장 완료: 라벨" , "Saved: labels" , StringComparison . Ordinal )
375+ . Replace ( "객체 없음 완료: 라벨" , "No object: labels" , StringComparison . Ordinal )
376+ . Replace ( "후보 숨김 완료: 라벨" , "Candidate hidden: labels" , StringComparison . Ordinal )
377+ . Replace ( "저장 라벨" , "Saved labels" , StringComparison . Ordinal )
378+ . Replace ( "AI 후보" , "AI candidates" , StringComparison . Ordinal )
379+ . Replace ( "검사 실패" , "Inspection failed" , StringComparison . Ordinal )
380+ . Replace ( "검사중" , "Inspecting" , StringComparison . Ordinal )
381+ . Replace ( "저장 필요" , "Save required" , StringComparison . Ordinal )
382+ . Replace ( "수정 필요" , "Needs fix" , StringComparison . Ordinal )
383+ . Replace ( "검수 완료" , "Reviewed" , StringComparison . Ordinal )
384+ . Replace ( "객체 없음" , "No object" , StringComparison . Ordinal )
385+ . Replace ( "후보 숨김" , "Candidate hidden" , StringComparison . Ordinal )
386+ . Replace ( "완료" , "Complete" , StringComparison . Ordinal )
387+ . Replace ( "대기" , "Waiting" , StringComparison . Ordinal )
388+ . Replace ( "없음" , "None" , StringComparison . Ordinal )
389+ . Replace ( "확인 필요" , "Review needed" , StringComparison . Ordinal ) ;
390+ return localized ;
391+ }
392+
393+ private static string TranslateKnownStatus ( string value )
394+ {
395+ if ( string . IsNullOrWhiteSpace ( value ) )
396+ {
397+ return string . Empty ;
398+ }
399+
400+ if ( value . StartsWith ( "AI 후보 " , StringComparison . Ordinal ) )
401+ {
402+ return "AI candidates " + value . Substring ( "AI 후보 " . Length ) ;
403+ }
404+
405+ if ( value . StartsWith ( "실패 x" , StringComparison . Ordinal ) )
406+ {
407+ return "Failed x" + value . Substring ( "실패 x" . Length ) ;
408+ }
409+
410+ if ( value . StartsWith ( "실패 " , StringComparison . Ordinal ) )
411+ {
412+ return "Failed " + value . Substring ( "실패 " . Length ) ;
413+ }
414+
415+ if ( value . EndsWith ( "개" , StringComparison . Ordinal )
416+ && value . Length > 1
417+ && value . Substring ( 0 , value . Length - 1 ) . All ( char . IsDigit ) )
418+ {
419+ return value . Substring ( 0 , value . Length - 1 ) + " items" ;
420+ }
421+
422+ return value switch
423+ {
424+ "확인중" => "Checking" ,
425+ "대기" => "Waiting" ,
426+ "없음" => "None" ,
427+ "객체 없음" => "No object" ,
428+ "객체없음" => "No object" ,
429+ "저장 필요" => "Save required" ,
430+ "검사중" => "Inspecting" ,
431+ "실패" => "Failed" ,
432+ "저장됨" => "Saved" ,
433+ "후보 숨김" => "Candidate hidden" ,
434+ "수정 필요" => "Needs fix" ,
435+ "검수 완료" => "Reviewed" ,
436+ "미판정" => "Unreviewed" ,
437+ "완료" => "Complete" ,
438+ "확인 필요" => "Review needed" ,
439+ "작업" => "Work" ,
440+ _ => value
441+ } ;
442+ }
443+
444+ private static string T ( string key ) => OpenVisionLanguageService . T ( key ) ;
445+
263446 private string BuildQueueRowText ( string separator )
264447 {
265448 string normalizedSeparator = string . IsNullOrEmpty ( separator ) ? " / " : separator ;
@@ -374,11 +557,17 @@ private static Brush CreateFrozenBrush(string color)
374557 }
375558 }
376559
377- public sealed class WpfImageQueueFilterOption
560+ public sealed class WpfImageQueueFilterOption : INotifyPropertyChanged
378561 {
379562 public WpfImageQueueFilter Filter { get ; set ; }
380563
381- public string Text { get ; set ; } = string . Empty ;
564+ public string TextKey { get ; set ; } = string . Empty ;
565+
566+ public string Text => string . IsNullOrWhiteSpace ( TextKey )
567+ ? string . Empty
568+ : OpenVisionLanguageService . T ( TextKey ) ;
569+
570+ public event PropertyChangedEventHandler PropertyChanged ;
382571
383572 public static IReadOnlyList < WpfImageQueueFilterOption > CreateDefaults ( )
384573 {
@@ -387,26 +576,36 @@ public static IReadOnlyList<WpfImageQueueFilterOption> CreateDefaults()
387576 . Select ( filter => new WpfImageQueueFilterOption
388577 {
389578 Filter = filter ,
390- Text = GetDisplayName ( filter )
579+ TextKey = GetTextKey ( filter )
391580 } )
392581 . ToList ( ) ;
393582 }
394583
395- public static string GetDisplayName ( WpfImageQueueFilter filter )
584+ internal void RefreshLocalizedPresentation ( )
585+ {
586+ PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( Text ) ) ) ;
587+ }
588+
589+ private static string GetTextKey ( WpfImageQueueFilter filter )
396590 {
397591 return filter switch
398592 {
399- WpfImageQueueFilter . Unlabeled => "확인 필요 " ,
400- WpfImageQueueFilter . NeedsFix => "수정 필요 " ,
401- WpfImageQueueFilter . Requested => "검사중 " ,
402- WpfImageQueueFilter . Candidate => "AI 후보 " ,
403- WpfImageQueueFilter . Confirmed => "저장됨 " ,
404- WpfImageQueueFilter . Skipped => "숨김 " ,
405- WpfImageQueueFilter . NoCandidate => "객체없음 " ,
406- WpfImageQueueFilter . Failed => "실패 " ,
407- _ => "전체 "
593+ WpfImageQueueFilter . Unlabeled => "WpfImageQueue.FilterOption.Unfinished " ,
594+ WpfImageQueueFilter . NeedsFix => "WpfImageQueue.FilterOption.NeedsFix " ,
595+ WpfImageQueueFilter . Requested => "WpfImageQueue.FilterOption.Requested " ,
596+ WpfImageQueueFilter . Candidate => "WpfImageQueue.FilterOption.Candidate " ,
597+ WpfImageQueueFilter . Confirmed => "WpfImageQueue.FilterOption.Confirmed " ,
598+ WpfImageQueueFilter . Skipped => "WpfImageQueue.FilterOption.Skipped " ,
599+ WpfImageQueueFilter . NoCandidate => "WpfImageQueue.FilterOption.NoCandidate " ,
600+ WpfImageQueueFilter . Failed => "WpfImageQueue.FilterOption.Failed " ,
601+ _ => "WpfImageQueue.FilterOption.All "
408602 } ;
409603 }
604+
605+ public static string GetDisplayName ( WpfImageQueueFilter filter )
606+ {
607+ return OpenVisionLanguageService . T ( GetTextKey ( filter ) ) ;
608+ }
410609 }
411610
412611 public enum WpfImageQueueFilter
0 commit comments