|
1 |
| -using System; |
| 1 | +#nullable enable |
| 2 | + |
| 3 | +using System; |
2 | 4 | using System.Globalization;
|
3 | 5 | using System.Linq;
|
4 | 6 | using System.Text.RegularExpressions;
|
5 | 7 | using Windows.Storage;
|
| 8 | +using Uno; |
6 | 9 | using Uno.Foundation.Logging;
|
7 | 10 | using Uno.UI;
|
8 |
| -using Uno; |
| 11 | +using System.Collections.Generic; |
| 12 | +using Windows.System.UserProfile; |
| 13 | +using System.Diagnostics.CodeAnalysis; |
| 14 | + |
| 15 | +namespace Windows.Globalization; |
9 | 16 |
|
10 |
| -namespace Windows.Globalization |
| 17 | +public static partial class ApplicationLanguages |
11 | 18 | {
|
12 |
| - public static partial class ApplicationLanguages |
13 |
| - { |
14 |
| - private static string _primaryLanguageOverride = string.Empty; |
| 19 | + private static string? _primaryLanguageOverride = string.Empty; |
15 | 20 |
|
16 | 21 | #if !IS_UNIT_TESTS
|
17 |
| - private const string PrimaryLanguageOverrideSettingKey = "__Uno.PrimaryLanguageOverride"; |
| 22 | + private const string PrimaryLanguageOverrideSettingKey = "__Uno.PrimaryLanguageOverride"; |
18 | 23 | #endif
|
19 | 24 |
|
20 |
| - static ApplicationLanguages() |
| 25 | + public static string? PrimaryLanguageOverride |
| 26 | + { |
| 27 | + get => _primaryLanguageOverride; |
| 28 | + set |
21 | 29 | {
|
22 |
| -#if !IS_UNIT_TESTS |
23 |
| - if (ApplicationData.Current.LocalSettings.Values.TryGetValue(PrimaryLanguageOverrideSettingKey, out var savedValue) |
24 |
| - && savedValue is string stringSavedValue) |
| 30 | + value ??= string.Empty; |
| 31 | + if (_primaryLanguageOverride != value) |
25 | 32 | {
|
26 |
| - _primaryLanguageOverride = stringSavedValue; |
27 |
| - } |
28 |
| -#endif |
29 |
| - |
30 |
| - ApplyLanguages(); |
31 |
| - } |
| 33 | + typeof(ApplicationLanguages).Log().LogDebug($"PLO: {_primaryLanguageOverride} -> {value}"); |
| 34 | + _primaryLanguageOverride = value; |
32 | 35 |
|
33 |
| - internal static void ApplyCulture() |
34 |
| - { |
35 |
| - var primaryLanguageOverride = PrimaryLanguageOverride; |
36 |
| - if (primaryLanguageOverride.Length > 0) |
37 |
| - { |
38 |
| - if (typeof(ApplicationLanguages).Log().IsEnabled(LogLevel.Debug)) |
| 36 | + ApplyLanguages(); |
| 37 | + if (WinRTFeatureConfiguration.ApplicationLanguages.UseLegacyPrimaryLanguageOverride) |
39 | 38 | {
|
40 |
| - typeof(ApplicationLanguages).Log().Debug($"Using {primaryLanguageOverride} (from PrimaryLanguageOverride) as primary language"); |
| 39 | + ApplyCulture(); |
41 | 40 | }
|
42 | 41 |
|
43 |
| - setCulture(primaryLanguageOverride); |
| 42 | +#if !IS_UNIT_TESTS |
| 43 | + ApplicationData.Current.LocalSettings.Values[PrimaryLanguageOverrideSettingKey] = _primaryLanguageOverride; |
| 44 | +#endif |
44 | 45 | }
|
45 |
| - else if (Languages.Count > 0) |
46 |
| - { |
47 |
| - var language = Languages[0]; |
48 |
| - if (typeof(ApplicationLanguages).Log().IsEnabled(LogLevel.Debug)) |
49 |
| - { |
50 |
| - typeof(ApplicationLanguages).Log().Debug($"Using {language} (from Languages) as primary language"); |
51 |
| - } |
| 46 | + } |
| 47 | + } |
52 | 48 |
|
53 |
| - setCulture(language); |
54 |
| - } |
55 |
| - else |
56 |
| - { |
57 |
| - if (typeof(ApplicationLanguages).Log().IsEnabled(LogLevel.Warning)) |
58 |
| - { |
59 |
| - typeof(ApplicationLanguages).Log().Warn($"Unable to determine the default culture, using invariant culture"); |
60 |
| - } |
61 |
| - } |
| 49 | + public static IReadOnlyList<string> Languages { get; private set; } |
| 50 | + public static IReadOnlyList<string> ManifestLanguages { get; } |
62 | 51 |
|
63 |
| - static void setCulture(string cultureId) |
64 |
| - { |
65 |
| - var culture = CreateCulture(cultureId); |
66 |
| - CultureInfo.CurrentCulture = culture; |
67 |
| - CultureInfo.DefaultThreadCurrentCulture = culture; |
68 |
| - CultureInfo.CurrentUICulture = culture; |
69 |
| - CultureInfo.DefaultThreadCurrentUICulture = culture; |
70 |
| - } |
| 52 | + static ApplicationLanguages() |
| 53 | + { |
| 54 | +#if !IS_UNIT_TESTS |
| 55 | + if (ApplicationData.Current.LocalSettings.Values.TryGetValue(PrimaryLanguageOverrideSettingKey, out var savedValue) && |
| 56 | + savedValue is string stringSavedValue) |
| 57 | + { |
| 58 | + _primaryLanguageOverride = stringSavedValue; |
71 | 59 | }
|
| 60 | +#endif |
72 | 61 |
|
73 |
| - public static string PrimaryLanguageOverride |
| 62 | + ManifestLanguages = GetManifestLanguages(); |
| 63 | + ApplyLanguages(); |
| 64 | + } |
| 65 | + |
| 66 | + internal static void ApplyCulture() |
| 67 | + { |
| 68 | + var primaryLanguageOverride = PrimaryLanguageOverride; |
| 69 | + if (!string.IsNullOrEmpty(primaryLanguageOverride)) |
74 | 70 | {
|
75 |
| - get |
| 71 | + if (typeof(ApplicationLanguages).Log().IsEnabled(LogLevel.Debug)) |
76 | 72 | {
|
77 |
| - return _primaryLanguageOverride; |
| 73 | + typeof(ApplicationLanguages).Log().Debug($"Using {primaryLanguageOverride} (from PrimaryLanguageOverride) as primary language"); |
78 | 74 | }
|
79 |
| - set |
80 |
| - { |
81 |
| - value ??= string.Empty; |
82 | 75 |
|
83 |
| - _primaryLanguageOverride = value; |
84 |
| - ApplyLanguages(); |
85 |
| - if (WinRTFeatureConfiguration.ApplicationLanguages.UseLegacyPrimaryLanguageOverride) |
86 |
| - { |
87 |
| - ApplyCulture(); |
88 |
| - } |
| 76 | + setCulture(primaryLanguageOverride); |
| 77 | + } |
| 78 | + else if (Languages.Count > 0) |
| 79 | + { |
| 80 | + var language = Languages[0]; |
| 81 | + if (typeof(ApplicationLanguages).Log().IsEnabled(LogLevel.Debug)) |
| 82 | + { |
| 83 | + typeof(ApplicationLanguages).Log().Debug($"Using {language} (from Languages) as primary language"); |
| 84 | + } |
89 | 85 |
|
90 |
| -#if !IS_UNIT_TESTS |
91 |
| - ApplicationData.Current.LocalSettings.Values[PrimaryLanguageOverrideSettingKey] = _primaryLanguageOverride; |
92 |
| -#endif |
| 86 | + setCulture(language); |
| 87 | + } |
| 88 | + else |
| 89 | + { |
| 90 | + if (typeof(ApplicationLanguages).Log().IsEnabled(LogLevel.Warning)) |
| 91 | + { |
| 92 | + typeof(ApplicationLanguages).Log().Warn($"Unable to determine the default culture, using invariant culture"); |
93 | 93 | }
|
94 | 94 | }
|
95 | 95 |
|
96 |
| - public static global::System.Collections.Generic.IReadOnlyList<string> Languages |
| 96 | + static void setCulture(string cultureId) |
97 | 97 | {
|
98 |
| - get; |
99 |
| - private set; |
| 98 | + var culture = CreateCulture(cultureId); |
| 99 | + CultureInfo.CurrentCulture = culture; |
| 100 | + CultureInfo.DefaultThreadCurrentCulture = culture; |
| 101 | + CultureInfo.CurrentUICulture = culture; |
| 102 | + CultureInfo.DefaultThreadCurrentUICulture = culture; |
100 | 103 | }
|
| 104 | + } |
101 | 105 |
|
102 |
| -#if !(__IOS__) |
103 |
| - public static global::System.Collections.Generic.IReadOnlyList<string> ManifestLanguages |
| 106 | +#if !__IOS__ |
| 107 | + private static string[] GetManifestLanguages() |
| 108 | + { |
| 109 | + string AdjustCultureName(string? name) |
| 110 | + => string.IsNullOrEmpty(name) ? "en-US" : name; |
| 111 | + |
| 112 | + var languages = new[] |
104 | 113 | {
|
105 |
| - get; |
106 |
| - } = GetManifestLanguages(); |
| 114 | +#if __ANDROID__ |
| 115 | + ContextHelper.Current?.Resources?.Configuration?.Locales?.Get(0)?.ToLanguageTag(), |
| 116 | +#endif |
| 117 | + AdjustCultureName(CultureInfo.InstalledUICulture?.Name), |
| 118 | + AdjustCultureName(CultureInfo.CurrentUICulture?.Name), |
| 119 | + AdjustCultureName(CultureInfo.CurrentCulture?.Name) |
| 120 | + }; |
| 121 | + |
| 122 | + return languages |
| 123 | + .Where(l => !string.IsNullOrWhiteSpace(l)) |
| 124 | + .OfType<string>() |
| 125 | + .Distinct() |
| 126 | + .ToArray(); |
| 127 | + } |
| 128 | +#else |
| 129 | + private static string[] GetManifestLanguages() |
| 130 | + { |
| 131 | + var manifestLanguages = global::Foundation.NSLocale.PreferredLanguages |
| 132 | + .Concat(global::Foundation.NSBundle.MainBundle.PreferredLocalizations) |
| 133 | + .Concat(global::Foundation.NSBundle.MainBundle.Localizations) |
| 134 | + .Distinct() |
| 135 | + .ToArray(); |
107 | 136 |
|
| 137 | + return manifestLanguages; |
| 138 | + } |
| 139 | +#endif |
108 | 140 |
|
109 |
| - private static string[] GetManifestLanguages() |
| 141 | + [MemberNotNull(nameof(Languages))] |
| 142 | + private static void ApplyLanguages() |
| 143 | + { |
| 144 | +#if false |
| 145 | + Languages = GlobalizationPreferences.Languages |
| 146 | + .Cast<string?>() |
| 147 | + .Prepend(PrimaryLanguageOverride) |
| 148 | + .Where(x => !string.IsNullOrEmpty(x)) |
| 149 | + .OfType<string>() |
| 150 | +#if false // On windows, we would filter against ManifestLanguages, but it does not apply to other targets. |
| 151 | + .Intersect(ManifestLanguages, FastBaseCultureComparer.Instance) |
| 152 | +#endif |
| 153 | + .ToArray(); |
| 154 | +#else |
| 155 | + var languages = ManifestLanguages; |
| 156 | +#if __SKIA__ |
| 157 | + if (OperatingSystem.IsWindows() && GlobalizationPreferences.Languages is { Count: > 0 } preferences) |
110 | 158 | {
|
111 |
| - string AdjustCultureName(string name) |
112 |
| - => string.IsNullOrEmpty(name) ? "en-US" : name; |
113 |
| - |
114 |
| - var languages = new[] |
115 |
| - { |
116 |
| -#if __ANDROID__ |
117 |
| - ContextHelper.Current?.Resources?.Configuration?.Locales?.Get(0)?.ToLanguageTag(), |
| 159 | + languages = preferences; |
| 160 | + } |
118 | 161 | #endif
|
119 |
| - AdjustCultureName(CultureInfo.InstalledUICulture?.Name), |
120 |
| - AdjustCultureName(CultureInfo.CurrentUICulture?.Name), |
121 |
| - AdjustCultureName(CultureInfo.CurrentCulture?.Name) |
122 |
| - }; |
123 | 162 |
|
124 |
| - return languages |
125 |
| - .Where(l => !string.IsNullOrWhiteSpace(l)) |
| 163 | + var overriddenLanguage = PrimaryLanguageOverride; |
| 164 | + if (!string.IsNullOrWhiteSpace(overriddenLanguage)) |
| 165 | + { |
| 166 | + languages = languages |
| 167 | + .Prepend(overriddenLanguage) |
126 | 168 | .Distinct()
|
127 | 169 | .ToArray();
|
128 | 170 | }
|
| 171 | + |
| 172 | + Languages = languages; |
129 | 173 | #endif
|
| 174 | + } |
130 | 175 |
|
131 |
| - private static void ApplyLanguages() |
132 |
| - { |
133 |
| - var overridenLanguage = PrimaryLanguageOverride; |
| 176 | + private static Regex? _cultureFormatRegex; |
134 | 177 |
|
135 |
| - if (string.IsNullOrWhiteSpace(overridenLanguage)) |
136 |
| - { |
137 |
| - Languages = ManifestLanguages; |
138 |
| - } |
139 |
| - else |
140 |
| - { |
141 |
| - var manifestLanguages = ManifestLanguages.ToArray(); |
142 |
| - var languages = new string[ManifestLanguages.Count + 1]; |
143 |
| - languages[0] = overridenLanguage; |
144 |
| - if (manifestLanguages.Length > 0) |
145 |
| - { |
146 |
| - Array.Copy(manifestLanguages, 0, languages, 1, manifestLanguages.Length); |
147 |
| - } |
148 |
| - |
149 |
| - Languages = languages.Distinct().ToArray(); |
150 |
| - } |
| 178 | + private static CultureInfo CreateCulture(string cultureId) |
| 179 | + { |
| 180 | + try |
| 181 | + { |
| 182 | + return new CultureInfo(cultureId); |
151 | 183 | }
|
152 |
| - |
153 |
| - private static Regex _cultureFormatRegex; |
154 |
| - |
155 |
| - private static CultureInfo CreateCulture(string cultureId) |
| 184 | + catch (CultureNotFoundException) |
156 | 185 | {
|
| 186 | + _cultureFormatRegex ??= CultureRegex(); |
| 187 | + |
| 188 | + var match = _cultureFormatRegex.Match(cultureId); |
157 | 189 | try
|
158 | 190 | {
|
159 |
| - return new CultureInfo(cultureId); |
| 191 | + // If the script subtag is specified, we'll try to just remove it. |
| 192 | + // Mono is not supporting it. |
| 193 | + if (match.Groups["script"].Success && match.Groups["reg"].Success) |
| 194 | + { |
| 195 | + cultureId = $"{match.Groups["lang"].Value}-{match.Groups["reg"].Value}"; |
| 196 | + return new CultureInfo(cultureId); |
| 197 | + } |
160 | 198 | }
|
161 | 199 | catch (CultureNotFoundException)
|
162 | 200 | {
|
163 |
| - _cultureFormatRegex ??= CultureRegex(); |
164 |
| - |
165 |
| - var match = _cultureFormatRegex.Match(cultureId); |
166 |
| - try |
167 |
| - { |
168 |
| - // If the script subtag is specified, we'll try to just remove it. |
169 |
| - // Mono is not supporting it. |
170 |
| - if (match.Groups["script"].Success && match.Groups["reg"].Success) |
171 |
| - { |
172 |
| - cultureId = $"{match.Groups["lang"].Value}-{match.Groups["reg"].Value}"; |
173 |
| - return new CultureInfo(cultureId); |
174 |
| - } |
175 |
| - } |
176 |
| - catch (CultureNotFoundException) |
177 |
| - { |
178 |
| - } |
179 |
| - |
180 |
| - // If the runtime is not able to match the language + region, we'll fallback to just the language. |
181 |
| - if (match.Groups["lang"].Success) |
182 |
| - { |
183 |
| - return new CultureInfo(match.Groups["lang"].Value); |
184 |
| - } |
| 201 | + } |
185 | 202 |
|
186 |
| - // It seems not possible to resolve this culture. |
187 |
| - throw; |
| 203 | + // If the runtime is not able to match the language + region, we'll fallback to just the language. |
| 204 | + if (match.Groups["lang"].Success) |
| 205 | + { |
| 206 | + return new CultureInfo(match.Groups["lang"].Value); |
188 | 207 | }
|
189 |
| - } |
190 | 208 |
|
191 |
| - [GeneratedRegex(@"(?<lang>[a-z]{2,8})(?:(?:\-(?<script>[a-zA-Z]+))?\-(?<reg>[A-Z]+))?", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.CultureInvariant)] |
192 |
| - private static partial Regex CultureRegex(); |
| 209 | + // It seems not possible to resolve this culture. |
| 210 | + throw; |
| 211 | + } |
193 | 212 | }
|
| 213 | + |
| 214 | + [GeneratedRegex(@"(?<lang>[a-z]{2,8})(?:(?:\-(?<script>[a-zA-Z]+))?\-(?<reg>[A-Z]+))?", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.CultureInvariant)] |
| 215 | + private static partial Regex CultureRegex(); |
194 | 216 | }
|
0 commit comments