Merge pull request #681 from irihitech/fix-679

Using ResourceDictionary.SetItems to improve Locale switching
This commit is contained in:
Dong Bin
2025-10-17 07:25:19 +08:00
committed by GitHub
2 changed files with 76 additions and 55 deletions

View File

@@ -90,97 +90,97 @@ public partial class MainViewModel : ObservableObject
{ {
Header = "简体中文", Header = "简体中文",
Command = SelectLocaleCommand, Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("zh-cn") CommandParameter = new CultureInfo("zh-CN")
}, },
new MenuItemViewModel new MenuItemViewModel
{ {
Header = "English", Header = "English",
Command = SelectLocaleCommand, Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("en-us") CommandParameter = new CultureInfo("en-US")
}, },
new MenuItemViewModel new MenuItemViewModel
{ {
Header = "日本語", Header = "日本語",
Command = SelectLocaleCommand, Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("ja-jp") CommandParameter = new CultureInfo("ja-JP")
}, },
new MenuItemViewModel new MenuItemViewModel
{ {
Header = "한국어", Header = "한국어",
Command = SelectLocaleCommand, Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("ko-kr") CommandParameter = new CultureInfo("ko-KR")
}, },
new MenuItemViewModel new MenuItemViewModel
{ {
Header = "English (UK)", Header = "English (UK)",
Command = SelectLocaleCommand, Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("en-gb") CommandParameter = new CultureInfo("en-GB")
}, },
new MenuItemViewModel new MenuItemViewModel
{ {
Header = "Italiano", Header = "Italiano",
Command = SelectLocaleCommand, Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("it-it") CommandParameter = new CultureInfo("it-IT")
}, },
new MenuItemViewModel new MenuItemViewModel
{ {
Header = "Italiano (Switzerland)", Header = "Italiano (Switzerland)",
Command = SelectLocaleCommand, Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("it-ch") CommandParameter = new CultureInfo("it-CH")
}, },
new MenuItemViewModel new MenuItemViewModel
{ {
Header = "Nederlands", Header = "Nederlands",
Command = SelectLocaleCommand, Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("nl-nl") CommandParameter = new CultureInfo("nl-NL")
}, },
new MenuItemViewModel new MenuItemViewModel
{ {
Header = "Nederlands (Belgium)", Header = "Nederlands (Belgium)",
Command = SelectLocaleCommand, Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("nl-be") CommandParameter = new CultureInfo("nl-BE")
}, },
new MenuItemViewModel new MenuItemViewModel
{ {
Header = "Українська", Header = "Українська",
Command = SelectLocaleCommand, Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("uk-ua") CommandParameter = new CultureInfo("uk-UA")
}, },
new MenuItemViewModel new MenuItemViewModel
{ {
Header = "Русский", Header = "Русский",
Command = SelectLocaleCommand, Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("ru-ru") CommandParameter = new CultureInfo("ru-RU")
}, },
new MenuItemViewModel new MenuItemViewModel
{ {
Header = "繁體中文", Header = "繁體中文",
Command = SelectLocaleCommand, Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("zh-tw") CommandParameter = new CultureInfo("zh-TW")
}, },
new MenuItemViewModel new MenuItemViewModel
{ {
Header = "Deutsch", Header = "Deutsch",
Command = SelectLocaleCommand, Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("de-de") CommandParameter = new CultureInfo("de-DE")
}, },
new MenuItemViewModel new MenuItemViewModel
{ {
Header = "Español", Header = "Español",
Command = SelectLocaleCommand, Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("es-es") CommandParameter = new CultureInfo("es-ES")
}, },
new MenuItemViewModel new MenuItemViewModel
{ {
Header = "Polski", Header = "Polski",
Command = SelectLocaleCommand, Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("pl-pl") CommandParameter = new CultureInfo("pl-PL")
}, },
new MenuItemViewModel new MenuItemViewModel
{ {
Header = "Français", Header = "Français",
Command = SelectLocaleCommand, Command = SelectLocaleCommand,
CommandParameter = new CultureInfo("fr-fr") CommandParameter = new CultureInfo("fr-FR")
}, },
] ]
} }

View File

@@ -1,9 +1,7 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Styling; using Avalonia.Styling;
using Semi.Avalonia.Locale; using Semi.Avalonia.Locale;
@@ -11,35 +9,35 @@ namespace Semi.Avalonia;
public class SemiTheme : Styles public class SemiTheme : Styles
{ {
private static readonly Dictionary<CultureInfo, ResourceDictionary> _localeToResource = new()
{
{ new CultureInfo("zh-cn"), new zh_cn() },
{ new CultureInfo("en-us"), new en_us() },
{ new CultureInfo("en-gb"), new en_gb() },
{ new CultureInfo("it-it"), new it_it() },
{ new CultureInfo("it-ch"), new it_ch() },
{ new CultureInfo("nl-be"), new nl_be() },
{ new CultureInfo("nl-nl"), new nl_nl() },
{ new CultureInfo("ja-jp"), new ja_jp() },
{ new CultureInfo("ko-kr"), new ko_kr() },
{ new CultureInfo("uk-ua"), new uk_ua() },
{ new CultureInfo("ru-ru"), new ru_ru() },
{ new CultureInfo("zh-tw"), new zh_tw() },
{ new CultureInfo("de-de"), new de_de() },
{ new CultureInfo("es-es"), new es_es() },
{ new CultureInfo("pl-pl"), new pl_pl() },
{ new CultureInfo("fr-fr"), new fr_fr() },
};
private static readonly ResourceDictionary _defaultResource = new zh_cn();
private CultureInfo? _locale;
public static ThemeVariant Aquatic => new(nameof(Aquatic), ThemeVariant.Dark); public static ThemeVariant Aquatic => new(nameof(Aquatic), ThemeVariant.Dark);
public static ThemeVariant Desert => new(nameof(Desert), ThemeVariant.Light); public static ThemeVariant Desert => new(nameof(Desert), ThemeVariant.Light);
public static ThemeVariant Dusk => new(nameof(Dusk), ThemeVariant.Dark); public static ThemeVariant Dusk => new(nameof(Dusk), ThemeVariant.Dark);
public static ThemeVariant NightSky => new(nameof(NightSky), ThemeVariant.Dark); public static ThemeVariant NightSky => new(nameof(NightSky), ThemeVariant.Dark);
private static readonly Dictionary<CultureInfo, ResourceDictionary> LocaleToResource = new()
{
{ new CultureInfo("zh-CN"), new zh_cn() },
{ new CultureInfo("en-US"), new en_us() },
{ new CultureInfo("en-GB"), new en_gb() },
{ new CultureInfo("it-IT"), new it_it() },
{ new CultureInfo("it-CH"), new it_ch() },
{ new CultureInfo("nl-BE"), new nl_be() },
{ new CultureInfo("nl-NL"), new nl_nl() },
{ new CultureInfo("ja-JP"), new ja_jp() },
{ new CultureInfo("ko-KR"), new ko_kr() },
{ new CultureInfo("uk-UA"), new uk_ua() },
{ new CultureInfo("ru-RU"), new ru_ru() },
{ new CultureInfo("zh-TW"), new zh_tw() },
{ new CultureInfo("de-DE"), new de_de() },
{ new CultureInfo("es-ES"), new es_es() },
{ new CultureInfo("pl-PL"), new pl_pl() },
{ new CultureInfo("fr-FR"), new fr_fr() },
};
private static readonly ResourceDictionary DefaultResource = new zh_cn();
private CultureInfo? _locale;
public CultureInfo? Locale public CultureInfo? Locale
{ {
get => _locale; get => _locale;
@@ -50,12 +48,26 @@ public class SemiTheme : Styles
if (TryGetLocaleResource(value, out var resource) && resource is not null) if (TryGetLocaleResource(value, out var resource) && resource is not null)
{ {
_locale = value; _locale = value;
foreach (var kv in resource) Resources[kv.Key] = kv.Value; if (Resources is ResourceDictionary rd)
{
rd.SetItems(resource);
}
else
{
foreach (var kv in resource) Resources[kv.Key] = kv.Value;
}
} }
else else
{ {
_locale = new CultureInfo("zh-CN"); _locale = new CultureInfo("zh-CN");
foreach (var kv in _defaultResource) Resources[kv.Key] = kv.Value; if (Resources is ResourceDictionary rd)
{
rd.SetItems(DefaultResource);
}
else
{
foreach (var kv in DefaultResource) Resources[kv.Key] = kv.Value;
}
} }
} }
catch catch
@@ -69,43 +81,52 @@ public class SemiTheme : Styles
{ {
if (Equals(locale, CultureInfo.InvariantCulture)) if (Equals(locale, CultureInfo.InvariantCulture))
{ {
resourceDictionary = _defaultResource; resourceDictionary = DefaultResource;
return true; return true;
} }
if (locale is null) if (locale is null)
{ {
resourceDictionary = _defaultResource; resourceDictionary = DefaultResource;
return false; return false;
} }
if (_localeToResource.TryGetValue(locale, out var resource)) if (LocaleToResource.TryGetValue(locale, out var resource))
{ {
resourceDictionary = resource; resourceDictionary = resource;
return true; return true;
} }
resourceDictionary = _defaultResource; resourceDictionary = DefaultResource;
return false; return false;
} }
public static void OverrideLocaleResources(Application application, CultureInfo? culture) public static void OverrideLocaleResources(Application application, CultureInfo? culture)
{ {
if (culture is null) return; if (culture is null) return;
if (!_localeToResource.TryGetValue(culture, out var resources)) return; if (!LocaleToResource.TryGetValue(culture, out var resources)) return;
foreach (var kv in resources)
if (application.Resources is ResourceDictionary rd)
{ {
application.Resources[kv.Key] = kv.Value; rd.SetItems(resources);
}
else
{
foreach (var kv in resources) application.Resources[kv.Key] = kv.Value;
} }
} }
public static void OverrideLocaleResources(StyledElement element, CultureInfo? culture) public static void OverrideLocaleResources(StyledElement element, CultureInfo? culture)
{ {
if (culture is null) return; if (culture is null) return;
if (!_localeToResource.TryGetValue(culture, out var resources)) return; if (!LocaleToResource.TryGetValue(culture, out var resources)) return;
foreach (var kv in resources) if (element.Resources is ResourceDictionary rd)
{ {
element.Resources[kv.Key] = kv.Value; rd.SetItems(resources);
}
else
{
foreach (var kv in resources) element.Resources[kv.Key] = kv.Value;
} }
} }
} }