feat: 完成国际化支持库
This commit is contained in:
19
JackCraft.I18N/Converters/I18NConverter.cs
Normal file
19
JackCraft.I18N/Converters/I18NConverter.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Globalization;
|
||||
using Avalonia.Data.Converters;
|
||||
|
||||
namespace JackCraft.I18N.Converters;
|
||||
|
||||
internal class I18NConverter(I18NBinding binding, object[] bindingValues) : IMultiValueConverter
|
||||
{
|
||||
public object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
if (values.Count < 2 || values[0] is not CultureInfo)
|
||||
return null;
|
||||
if (binding.KeyConverter.Convert(values[1], null!, null, culture) is not string key)
|
||||
return values[1];
|
||||
var value = I18NConfig.Manager.Get<object>(key, values[0] as CultureInfo);
|
||||
if (value is string str && bindingValues.Length > 0)
|
||||
value = string.Format(str, bindingValues);
|
||||
return binding.ValueConverter.Convert(value, null!, null, culture);
|
||||
}
|
||||
}
|
22
JackCraft.I18N/Converters/I18NKeyConverter.cs
Normal file
22
JackCraft.I18N/Converters/I18NKeyConverter.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System.Globalization;
|
||||
using Avalonia.Data.Converters;
|
||||
|
||||
namespace JackCraft.I18N.Converters;
|
||||
|
||||
internal class I18NKeyConverter : IValueConverter
|
||||
{
|
||||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
return value switch
|
||||
{
|
||||
Enum e => value.GetType().Name + "." + e,
|
||||
string str => str,
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
17
JackCraft.I18N/Converters/I18NValueConverter.cs
Normal file
17
JackCraft.I18N/Converters/I18NValueConverter.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Globalization;
|
||||
using Avalonia.Data.Converters;
|
||||
|
||||
namespace JackCraft.I18N.Converters;
|
||||
|
||||
internal class I18NValueConverter : IValueConverter
|
||||
{
|
||||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
23
JackCraft.I18N/I18NBinding.cs
Normal file
23
JackCraft.I18N/I18NBinding.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Data.Converters;
|
||||
using JackCraft.I18N.Converters;
|
||||
|
||||
namespace JackCraft.I18N;
|
||||
|
||||
internal class I18NBinding : MultiBinding
|
||||
{
|
||||
public readonly IValueConverter KeyConverter;
|
||||
public readonly IValueConverter ValueConverter;
|
||||
|
||||
public I18NBinding(string key, params dynamic[] values)
|
||||
{
|
||||
Mode = BindingMode.OneWay;
|
||||
TargetNullValue = key;
|
||||
FallbackValue = key;
|
||||
Converter = new I18NConverter(this, values);
|
||||
KeyConverter = new I18NKeyConverter();
|
||||
ValueConverter = new I18NValueConverter();
|
||||
Bindings.Add(new Binding { Source = I18NConfig.Manager, Path = nameof(I18NConfig.Manager.Culture) });
|
||||
Bindings.Add(new Binding { Source = key });
|
||||
}
|
||||
}
|
12
JackCraft.I18N/I18NConfig.cs
Normal file
12
JackCraft.I18N/I18NConfig.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
|
||||
namespace JackCraft.I18N;
|
||||
|
||||
internal static class I18NConfig
|
||||
{
|
||||
public static I18NManager Manager { get; set; } = null!;
|
||||
public static string BaseName { get; set; } = string.Empty;
|
||||
public static Assembly Assembly { get; set; } = typeof(I18NConfig).Assembly;
|
||||
public static CultureInfo Culture { get; set; } = CultureInfo.InvariantCulture;
|
||||
}
|
15
JackCraft.I18N/I18NExtension.cs
Normal file
15
JackCraft.I18N/I18NExtension.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace JackCraft.I18N;
|
||||
|
||||
public class I18NExtension(string key, params object[] values) : MarkupExtension
|
||||
{
|
||||
public I18NExtension(string key) : this(key, [])
|
||||
{
|
||||
}
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
return new I18NBinding(key, values);
|
||||
}
|
||||
}
|
48
JackCraft.I18N/I18NManager.cs
Normal file
48
JackCraft.I18N/I18NManager.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace JackCraft.I18N;
|
||||
|
||||
public sealed class I18NManager : INotifyPropertyChanged
|
||||
{
|
||||
public I18NManager(string baseName, Assembly assembly)
|
||||
{
|
||||
I18NConfig.BaseName = baseName;
|
||||
I18NConfig.Assembly = assembly;
|
||||
I18NConfig.Manager = this;
|
||||
}
|
||||
|
||||
public CultureInfo Culture
|
||||
{
|
||||
get => I18NConfig.Culture;
|
||||
set
|
||||
{
|
||||
if (Equals(value, I18NConfig.Culture)) return;
|
||||
I18NConfig.Culture = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public static string BaseName => I18NConfig.BaseName;
|
||||
public static Assembly Assembly => I18NConfig.Assembly;
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
private void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
public T? Get<T>(string key, CultureInfo? culture = null, params object?[] values)
|
||||
{
|
||||
culture ??= Culture;
|
||||
var resourceManager = new ResourceManager(BaseName, Assembly);
|
||||
var resourceSet = resourceManager.GetResourceSet(culture, true, true);
|
||||
var obj = resourceSet?.GetObject(key);
|
||||
if (obj is string str && values.Length > 0) return (dynamic)string.Format(str, values);
|
||||
if (obj != null) return (dynamic)obj;
|
||||
return default;
|
||||
}
|
||||
}
|
@@ -7,4 +7,8 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="11.2.3"/>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
Reference in New Issue
Block a user