Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
LocalizeExtension.cs
1using Microsoft.Extensions.Localization;
3using System.ComponentModel;
4using System.Globalization;
5using System.Reflection;
6using System.Runtime.CompilerServices;
7using System.Text;
8using Waher.Events;
9
11{
15 [ContentProperty(nameof(Path))]
16 public class LocalizeExtension : IMarkupExtension<BindingBase>, INotifyPropertyChanged, IDisposable
17 {
18 private static readonly Dictionary<Type, SortedDictionary<string, bool>> missingStrings = [];
19 private static Timer? timer = null;
20
21 private IStringLocalizer? localizer;
22 private bool isDisposed;
23
24 static LocalizeExtension()
25 {
26 Log.Terminating += Log_Terminating;
27 }
28
29 private static void Log_Terminating(object? sender, EventArgs e)
30 {
31 timer?.Dispose();
32 timer = null;
33 }
34
38 public IStringLocalizer Localizer
39 {
40 get
41 {
42 this.localizer ??= LocalizationManager.GetStringLocalizer(this.StringResource);
43 return this.localizer;
44 }
45 }
46
47 public string Path { get; set; } = ".";
48 public BindingMode Mode { get; set; } = BindingMode.OneWay;
49 public IValueConverter? Converter { get; set; } = null;
50 public string? ConverterParameter { get; set; } = null;
51 public string? StringFormat { get; set; } = null;
52 public Type? StringResource { get; set; } = null;
53
54 public object ProvideValue(IServiceProvider ServiceProvider)
55 {
56 return (this as IMarkupExtension<BindingBase>).ProvideValue(ServiceProvider);
57 }
58
59 BindingBase IMarkupExtension<BindingBase>.ProvideValue(IServiceProvider ServiceProvider)
60 {
61 Type ResourcesType = this.StringResource ?? typeof(AppResources);
62
63 if (ResourcesType.GetRuntimeProperties().FirstOrDefault(pi => pi.Name == this.Path) is null)
64 {
65 ReportMissingString(this.Path, ResourcesType);
66 return new Binding("Localizer[STRINGNOTDEFINED]", this.Mode, this.Converter, this.ConverterParameter, this.StringFormat, this);
67 }
68
69 return new Binding($"Localizer[{this.Path}]", this.Mode, this.Converter, this.ConverterParameter, this.StringFormat, this);
70 }
71
77 public static void ReportMissingString(string StringId, Type Type)
78 {
79 lock (missingStrings)
80 {
81 timer?.Dispose();
82 timer = null;
83
84 if (!missingStrings.TryGetValue(Type, out SortedDictionary<string, bool>? PerId))
85 {
86 PerId = [];
87 missingStrings[Type] = PerId;
88 }
89
90 PerId[StringId] = true;
91
92 timer = new Timer(LogAlert, null, 1000, Timeout.Infinite);
93 }
94 }
95
96 private static void LogAlert(object? _)
97 {
98 StringBuilder sb = new();
99
100 sb.AppendLine("Missing localized strings:");
101 sb.AppendLine();
102
103 lock (missingStrings)
104 {
105 foreach (KeyValuePair<Type, SortedDictionary<string, bool>> P in missingStrings)
106 {
107 sb.AppendLine();
108 sb.AppendLine(P.Key.FullName);
109 sb.AppendLine(new string('-', (P.Key.FullName?.Length ?? 0) + 3));
110 sb.AppendLine();
111
112 foreach (string Key in P.Value.Keys)
113 {
114 sb.Append("* ");
115 sb.AppendLine(Key);
116 }
117 }
118
119 missingStrings.Clear();
120 }
121
122 ServiceRef.LogService.LogAlert(sb.ToString());
123 }
124
125 public LocalizeExtension()
126 {
127 LocalizationManager.CurrentCultureChanged += this.OnCurrentCultureChanged;
128 }
129
130 ~LocalizeExtension()
131 {
132 this.Dispose(false);
133 }
134
135 private void OnCurrentCultureChanged(object? sender, CultureInfo culture)
136 {
137 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Localizer)));
138 }
139
143 public void Dispose()
144 {
145 this.Dispose(true);
146 GC.SuppressFinalize(this);
147 }
148
152 protected virtual void Dispose(bool disposing)
153 {
154 if (this.isDisposed)
155 return;
156
157 LocalizationManager.CurrentCultureChanged -= this.OnCurrentCultureChanged;
158
159 this.isDisposed = true;
160 }
161
162 public event PropertyChangedEventHandler? PropertyChanged;
163 }
164}
static void ReportMissingString(string StringId, Type Type)
Reports a missing string
virtual void Dispose(bool disposing)
IDisposable.Dispose
IStringLocalizer Localizer
Localizer instance reference.