feat: implement locale switch.

This commit is contained in:
rabbitism
2024-01-28 00:12:35 +08:00
parent e18534d9b2
commit f0c8d5dba5
9 changed files with 113 additions and 34 deletions

View File

@@ -1,9 +1,10 @@
<Application <Application
x:Class="Ursa.Demo.App" x:Class="Ursa.Demo.App"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:u-semi="https://irihi.tech/ursa/themes/semi">
<Application.Styles> <Application.Styles>
<StyleInclude Source="avares://Semi.Avalonia/Themes/Index.axaml" /> <StyleInclude Source="avares://Semi.Avalonia/Themes/Index.axaml" />
<StyleInclude Source="avares://Ursa.Themes.Semi/Index.axaml" /> <u-semi:SemiTheme Locale="en-US"/>
</Application.Styles> </Application.Styles>
</Application> </Application>

View File

@@ -115,7 +115,7 @@ public class MessageBoxDemoViewModel: ObservableObject
private async Task OnOkCancelAsync() private async Task OnOkCancelAsync()
{ {
await Show(MessageBoxButton.OK); await Show(MessageBoxButton.OKCancel);
} }
private async Task Show(MessageBoxButton button) private async Task Show(MessageBoxButton button)

View File

@@ -0,0 +1,4 @@
using Avalonia.Metadata;
[assembly:XmlnsPrefix("https://irihi.tech/ursa/themes/semi", "u-semi")]
[assembly:XmlnsDefinition("https://irihi.tech/ursa/themes/semi", "Ursa.Themes.Semi")]

View File

@@ -52,7 +52,7 @@
<MenuItem <MenuItem
Command="{Binding $parent[u:DialogControl].UpdateLayer}" Command="{Binding $parent[u:DialogControl].UpdateLayer}"
CommandParameter="{x:Static u:DialogLayerChangeType.BringForward}" CommandParameter="{x:Static u:DialogLayerChangeType.BringForward}"
Header="Bring Forward"> Header="{DynamicResource STRING_MENU_BRING_FORWARD}">
<MenuItem.Icon> <MenuItem.Icon>
<PathIcon <PathIcon
Width="12" Width="12"
@@ -63,7 +63,7 @@
<MenuItem <MenuItem
Command="{Binding $parent[u:DialogControl].UpdateLayer}" Command="{Binding $parent[u:DialogControl].UpdateLayer}"
CommandParameter="{x:Static u:DialogLayerChangeType.BringToFront}" CommandParameter="{x:Static u:DialogLayerChangeType.BringToFront}"
Header="Bring To Front"> Header="{DynamicResource STRING_MENU_BRING_TO_FRONT}">
<MenuItem.Icon> <MenuItem.Icon>
<PathIcon <PathIcon
Width="12" Width="12"
@@ -74,7 +74,7 @@
<MenuItem <MenuItem
Command="{Binding $parent[u:DialogControl].UpdateLayer}" Command="{Binding $parent[u:DialogControl].UpdateLayer}"
CommandParameter="{x:Static u:DialogLayerChangeType.SendBackward}" CommandParameter="{x:Static u:DialogLayerChangeType.SendBackward}"
Header="Send Backward"> Header="{DynamicResource STRING_MENU_SEND_BACKWARD}">
<MenuItem.Icon> <MenuItem.Icon>
<PathIcon <PathIcon
Width="12" Width="12"
@@ -85,7 +85,7 @@
<MenuItem <MenuItem
Command="{Binding $parent[u:DialogControl].UpdateLayer}" Command="{Binding $parent[u:DialogControl].UpdateLayer}"
CommandParameter="{x:Static u:DialogLayerChangeType.SendToBack}" CommandParameter="{x:Static u:DialogLayerChangeType.SendToBack}"
Header="Send To Back"> Header="{DynamicResource STRING_MENU_SEND_TO_BACK}">
<MenuItem.Icon> <MenuItem.Icon>
<PathIcon <PathIcon
Width="12" Width="12"
@@ -161,24 +161,24 @@
Name="{x:Static u:DefaultDialogControl.PART_CancelButton}" Name="{x:Static u:DefaultDialogControl.PART_CancelButton}"
Margin="8,0,0,0" Margin="8,0,0,0"
Classes="Tertiary" Classes="Tertiary"
Content="取消" /> Content="{DynamicResource STRING_MENU_DIALOG_CANCEL}" />
<Button <Button
Name="{x:Static u:DefaultDialogControl.PART_NoButton}" Name="{x:Static u:DefaultDialogControl.PART_NoButton}"
Margin="8,0,0,0" Margin="8,0,0,0"
Classes="Danger" Classes="Danger"
Content="" Content="{DynamicResource STRING_MENU_DIALOG_NO}"
Theme="{DynamicResource SolidButton}" /> Theme="{DynamicResource SolidButton}" />
<Button <Button
Name="{x:Static u:DefaultDialogControl.PART_YesButton}" Name="{x:Static u:DefaultDialogControl.PART_YesButton}"
Margin="8,0,0,0" Margin="8,0,0,0"
Classes="Primary" Classes="Primary"
Content="" Content="{DynamicResource STRING_MENU_DIALOG_YES}"
Theme="{DynamicResource SolidButton}" /> Theme="{DynamicResource SolidButton}" />
<Button <Button
Name="{x:Static u:DefaultDialogControl.PART_OKButton}" Name="{x:Static u:DefaultDialogControl.PART_OKButton}"
Margin="8,0,0,0" Margin="8,0,0,0"
Classes="Primary" Classes="Primary"
Content="确认" Content="{DynamicResource STRING_MENU_DIALOG_OK}"
Theme="{DynamicResource SolidButton}" /> Theme="{DynamicResource SolidButton}" />
</StackPanel> </StackPanel>
</Grid> </Grid>
@@ -311,7 +311,7 @@
<MenuItem <MenuItem
Command="{Binding $parent[u:DialogControl].UpdateLayer}" Command="{Binding $parent[u:DialogControl].UpdateLayer}"
CommandParameter="{x:Static u:DialogLayerChangeType.BringForward}" CommandParameter="{x:Static u:DialogLayerChangeType.BringForward}"
Header="Bring Forward"> Header="{DynamicResource STRING_MENU_BRING_FORWARD}">
<MenuItem.Icon> <MenuItem.Icon>
<PathIcon <PathIcon
Width="12" Width="12"
@@ -322,7 +322,7 @@
<MenuItem <MenuItem
Command="{Binding $parent[u:DialogControl].UpdateLayer}" Command="{Binding $parent[u:DialogControl].UpdateLayer}"
CommandParameter="{x:Static u:DialogLayerChangeType.BringToFront}" CommandParameter="{x:Static u:DialogLayerChangeType.BringToFront}"
Header="Bring To Front"> Header="{DynamicResource STRING_MENU_BRING_TO_FRONT}">
<MenuItem.Icon> <MenuItem.Icon>
<PathIcon <PathIcon
Width="12" Width="12"
@@ -333,7 +333,7 @@
<MenuItem <MenuItem
Command="{Binding $parent[u:DialogControl].UpdateLayer}" Command="{Binding $parent[u:DialogControl].UpdateLayer}"
CommandParameter="{x:Static u:DialogLayerChangeType.SendBackward}" CommandParameter="{x:Static u:DialogLayerChangeType.SendBackward}"
Header="Send Backward"> Header="{DynamicResource STRING_MENU_SEND_BACKWARD}">
<MenuItem.Icon> <MenuItem.Icon>
<PathIcon <PathIcon
Width="12" Width="12"
@@ -344,7 +344,7 @@
<MenuItem <MenuItem
Command="{Binding $parent[u:DialogControl].UpdateLayer}" Command="{Binding $parent[u:DialogControl].UpdateLayer}"
CommandParameter="{x:Static u:DialogLayerChangeType.SendToBack}" CommandParameter="{x:Static u:DialogLayerChangeType.SendToBack}"
Header="Send To Back"> Header="{DynamicResource STRING_MENU_SEND_TO_BACK}">
<MenuItem.Icon> <MenuItem.Icon>
<PathIcon <PathIcon
Width="12" Width="12"
@@ -492,24 +492,24 @@
Name="{x:Static u:DefaultDialogControl.PART_CancelButton}" Name="{x:Static u:DefaultDialogControl.PART_CancelButton}"
Margin="8,0,0,0" Margin="8,0,0,0"
Classes="Tertiary" Classes="Tertiary"
Content="取消" /> Content="{DynamicResource STRING_MENU_DIALOG_CANCEL}" />
<Button <Button
Name="{x:Static u:DefaultDialogControl.PART_NoButton}" Name="{x:Static u:DefaultDialogControl.PART_NoButton}"
Margin="8,0,0,0" Margin="8,0,0,0"
Classes="Danger" Classes="Danger"
Content="" Content="{DynamicResource STRING_MENU_DIALOG_NO}"
Theme="{DynamicResource SolidButton}" /> Theme="{DynamicResource SolidButton}" />
<Button <Button
Name="{x:Static u:DefaultDialogControl.PART_YesButton}" Name="{x:Static u:DefaultDialogControl.PART_YesButton}"
Margin="8,0,0,0" Margin="8,0,0,0"
Classes="Primary" Classes="Primary"
Content="" Content="{DynamicResource STRING_MENU_DIALOG_YES}"
Theme="{DynamicResource SolidButton}" /> Theme="{DynamicResource SolidButton}" />
<Button <Button
Name="{x:Static u:DefaultDialogControl.PART_OKButton}" Name="{x:Static u:DefaultDialogControl.PART_OKButton}"
Margin="8,0,0,0" Margin="8,0,0,0"
Classes="Primary" Classes="Primary"
Content="确认" Content="{DynamicResource STRING_MENU_DIALOG_OK}"
Theme="{DynamicResource SolidButton}" /> Theme="{DynamicResource SolidButton}" />
</StackPanel> </StackPanel>
</Grid> </Grid>

View File

@@ -88,24 +88,24 @@
Name="{x:Static u:MessageBoxWindow.PART_CancelButton}" Name="{x:Static u:MessageBoxWindow.PART_CancelButton}"
Margin="8,0,0,0" Margin="8,0,0,0"
Classes="Tertiary" Classes="Tertiary"
Content="Cancel" /> Content="{DynamicResource STRING_MENU_DIALOG_CANCEL}" />
<Button <Button
Name="{x:Static u:MessageBoxWindow.PART_NoButton}" Name="{x:Static u:MessageBoxWindow.PART_NoButton}"
Margin="8,0,0,0" Margin="8,0,0,0"
Classes="Danger" Classes="Danger"
Content="No" Content="{DynamicResource STRING_MENU_DIALOG_NO}"
Theme="{DynamicResource SolidButton}" /> Theme="{DynamicResource SolidButton}" />
<Button <Button
Name="{x:Static u:MessageBoxWindow.PART_YesButton}" Name="{x:Static u:MessageBoxWindow.PART_YesButton}"
Margin="8,0,0,0" Margin="8,0,0,0"
Classes="Primary" Classes="Primary"
Content="Yes" Content="{DynamicResource STRING_MENU_DIALOG_YES}"
Theme="{DynamicResource SolidButton}" /> Theme="{DynamicResource SolidButton}" />
<Button <Button
Name="{x:Static u:MessageBoxWindow.PART_OKButton}" Name="{x:Static u:MessageBoxWindow.PART_OKButton}"
Margin="8,0,0,0" Margin="8,0,0,0"
Classes="Primary" Classes="Primary"
Content="OK" Content="{DynamicResource STRING_MENU_DIALOG_OK}"
Theme="{DynamicResource SolidButton}" /> Theme="{DynamicResource SolidButton}" />
</StackPanel> </StackPanel>
</Grid> </Grid>
@@ -219,24 +219,24 @@
Name="{x:Static u:MessageBoxControl.PART_CancelButton}" Name="{x:Static u:MessageBoxControl.PART_CancelButton}"
Margin="8,0,0,0" Margin="8,0,0,0"
Classes="Tertiary" Classes="Tertiary"
Content="Cancel" /> Content="{DynamicResource STRING_MENU_DIALOG_CANCEL}" />
<Button <Button
Name="{x:Static u:MessageBoxControl.PART_NoButton}" Name="{x:Static u:MessageBoxControl.PART_NoButton}"
Margin="8,0,0,0" Margin="8,0,0,0"
Classes="Danger" Classes="Danger"
Content="No" Content="{DynamicResource STRING_MENU_DIALOG_NO}"
Theme="{DynamicResource SolidButton}" /> Theme="{DynamicResource SolidButton}" />
<Button <Button
Name="{x:Static u:MessageBoxControl.PART_YesButton}" Name="{x:Static u:MessageBoxControl.PART_YesButton}"
Margin="8,0,0,0" Margin="8,0,0,0"
Classes="Primary" Classes="Primary"
Content="Yes" Content="{DynamicResource STRING_MENU_DIALOG_YES}"
Theme="{DynamicResource SolidButton}" /> Theme="{DynamicResource SolidButton}" />
<Button <Button
Name="{x:Static u:MessageBoxControl.PART_OKButton}" Name="{x:Static u:MessageBoxControl.PART_OKButton}"
Margin="8,0,0,0" Margin="8,0,0,0"
Classes="Primary" Classes="Primary"
Content="OK" Content="{DynamicResource STRING_MENU_DIALOG_OK}"
Theme="{DynamicResource SolidButton}" /> Theme="{DynamicResource SolidButton}" />
</StackPanel> </StackPanel>
</Grid> </Grid>

View File

@@ -1,9 +1,4 @@
<Styles xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Styles x:Class="Ursa.Themes.Semi.SemiTheme" xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Design.PreviewWith>
<Border Padding="20">
<!-- Add Controls for Previewer Here -->
</Border>
</Design.PreviewWith>
<Styles.Resources> <Styles.Resources>
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.ThemeDictionaries> <ResourceDictionary.ThemeDictionaries>
@@ -13,11 +8,11 @@
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
<ResourceInclude Source="../Controls/_index.axaml" /> <ResourceInclude Source="../Controls/_index.axaml" />
<ResourceInclude Source="Themes/Shared/_index.axaml" /> <ResourceInclude Source="Themes/Shared/_index.axaml" />
<ResourceInclude Source="Locale/zh-cn.axaml" />
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>
</Styles.Resources> </Styles.Resources>
<StyleInclude Source="../Styles/_index.axaml" /> <StyleInclude Source="../Styles/_index.axaml" />
<!-- Add Styles Here --> <!-- Add Styles Here -->
</Styles> </Styles>

View File

@@ -0,0 +1,55 @@
using System.Globalization;
using System.Runtime.CompilerServices;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.Styling;
using Avalonia.Platform;
using Avalonia.Styling;
namespace Ursa.Themes.Semi;
public class SemiTheme: Styles
{
private static readonly Dictionary<CultureInfo, string> _localeToResource = new()
{
{ new CultureInfo("zh-CN"), "avares://Ursa.Themes.Semi/Locale/zh-CN.axaml" },
{ new CultureInfo("en-US"), "avares://Ursa.Themes.Semi/Locale/en-US.axaml" },
};
private readonly IServiceProvider? sp;
public SemiTheme(IServiceProvider? provider = null)
{
AvaloniaXamlLoader.Load(provider, this);
}
private CultureInfo? _locale;
public CultureInfo? Locale
{
get => _locale;
set
{
_locale = value;
var resource = TryGetLocaleResource(value);
var d = AvaloniaXamlLoader.Load(sp, new Uri(resource)) as ResourceDictionary;
foreach (var kv in d)
{
this.Resources.Add(kv);
}
}
}
private string TryGetLocaleResource(CultureInfo? locale)
{
if (locale is null)
{
return _localeToResource[new CultureInfo("zh-CN")];
}
if (_localeToResource.TryGetValue(locale, out var resource))
{
return resource;
}
return _localeToResource[new CultureInfo("zh-CN")];
}
}

View File

@@ -0,0 +1,12 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Add Resources Here -->
<x:String x:Key="STRING_MENU_BRING_TO_FRONT">Bring to Front</x:String>
<x:String x:Key="STRING_MENU_BRING_FORWARD">Bring Forward</x:String>
<x:String x:Key="STRING_MENU_SEND_BACKWARD">Send Backward</x:String>
<x:String x:Key="STRING_MENU_SEND_TO_BACK">Send to Back</x:String>
<x:String x:Key="STRING_MENU_DIALOG_OK">OK</x:String>
<x:String x:Key="STRING_MENU_DIALOG_CANCEL">Cancel</x:String>
<x:String x:Key="STRING_MENU_DIALOG_YES">Yes</x:String>
<x:String x:Key="STRING_MENU_DIALOG_NO">No</x:String>
</ResourceDictionary>

View File

@@ -0,0 +1,12 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Add Resources Here -->
<x:String x:Key="STRING_MENU_BRING_TO_FRONT">置于顶层</x:String>
<x:String x:Key="STRING_MENU_BRING_FORWARD">上移一层</x:String>
<x:String x:Key="STRING_MENU_SEND_BACKWARD">下移一层</x:String>
<x:String x:Key="STRING_MENU_SEND_TO_BACK">置于底层</x:String>
<x:String x:Key="STRING_MENU_DIALOG_OK">确认</x:String>
<x:String x:Key="STRING_MENU_DIALOG_CANCEL">取消</x:String>
<x:String x:Key="STRING_MENU_DIALOG_YES">是</x:String>
<x:String x:Key="STRING_MENU_DIALOG_NO">否</x:String>
</ResourceDictionary>