From e25d4639de5824b610ec7ccfca491df5fec34a67 Mon Sep 17 00:00:00 2001 From: Jack <3486688394@qq.com> Date: Mon, 19 Jan 2026 03:21:26 +0800 Subject: [PATCH] =?UTF-8?q?feat(i18n):=20=E6=94=AF=E6=8C=81=E7=BB=91?= =?UTF-8?q?=E5=AE=9A=E8=A1=A8=E8=BE=BE=E5=BC=8F=E4=BD=9C=E4=B8=BA=E5=9B=BD?= =?UTF-8?q?=E9=99=85=E5=8C=96=E9=94=AE=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 I18NBinding 构造函数的 key 参数从 string 类型改为 object 类型 - 添加对 BindingBase 类型键值的支持,允许动态绑定国际化键 - 为 I18NExtension 添加多个构造函数重载以支持 BindingBase 键值 - 更新资源文件添加新的测试键值对 - 修改视图模型属性访问修饰符并添加测试属性 - 在主窗口视图中添加绑定表达式的国际化使用示例 --- JackCraft.I18N/I18NBinding.cs | 23 +++++++--- JackCraft.I18N/I18NExtension.cs | 49 +++++++++++++++++++++- TestMvvm/Assets/Resources.resx | 6 ++- TestMvvm/Assets/Resources.zh-hans.resx | 3 ++ TestMvvm/ViewModels/MainWindowViewModel.cs | 3 +- TestMvvm/Views/MainWindow.axaml | 1 + 6 files changed, 76 insertions(+), 9 deletions(-) diff --git a/JackCraft.I18N/I18NBinding.cs b/JackCraft.I18N/I18NBinding.cs index 1adaad0..61a8dc6 100644 --- a/JackCraft.I18N/I18NBinding.cs +++ b/JackCraft.I18N/I18NBinding.cs @@ -9,7 +9,7 @@ internal class I18NBinding : MultiBinding public readonly IValueConverter KeyConverter; public readonly IValueConverter ValueConverter; - public I18NBinding(string key, params dynamic[] values) + public I18NBinding(object key, params dynamic[] values) { Mode = BindingMode.OneWay; TargetNullValue = key; @@ -18,13 +18,26 @@ internal class I18NBinding : MultiBinding KeyConverter = new I18NKeyConverter(); ValueConverter = new I18NValueConverter(); Bindings.Add(new Binding { Source = I18NConfig.Manager, Path = nameof(I18NConfig.Manager.Culture) }); - Bindings.Add(new Binding { Source = key }); - foreach (var value in values) + + switch (key) { - if (value is BindingBase binding) + // 处理 key 参数,可能是字符串或 BindingBase + case string keyStr: + Bindings.Add(new Binding { Source = keyStr }); + break; + case BindingBase binding: Bindings.Add(binding); + break; + // 其他情况,作为普通对象处理 + default: + Bindings.Add(new Binding { Source = key }); + break; + } + + foreach (var value in values) + if (value is BindingBase valueBinding) + Bindings.Add(valueBinding); else Bindings.Add(new Binding { Source = value }); - } } } \ No newline at end of file diff --git a/JackCraft.I18N/I18NExtension.cs b/JackCraft.I18N/I18NExtension.cs index 5a4a8be..862e9f9 100644 --- a/JackCraft.I18N/I18NExtension.cs +++ b/JackCraft.I18N/I18NExtension.cs @@ -1,9 +1,19 @@ +using Avalonia.Data; using Avalonia.Markup.Xaml; namespace JackCraft.I18N; -public class I18NExtension(string key, params dynamic[] values) : MarkupExtension +public class I18NExtension : MarkupExtension { + private readonly object _key; + private readonly dynamic[] _values; + + public I18NExtension(string key, params dynamic[] values) + { + _key = key; + _values = values; + } + public I18NExtension(string key) : this(key, []) { } @@ -31,8 +41,43 @@ public class I18NExtension(string key, params dynamic[] values) : MarkupExtensio { } + // 支持 BindingBase 作为 key + public I18NExtension(BindingBase key, params dynamic[] values) + { + _key = key; + _values = values; + } + + public I18NExtension(BindingBase key) : this(key, []) + { + } + + public I18NExtension(BindingBase key, dynamic value1) : this(key, [value1]) + { + } + + public I18NExtension(BindingBase key, dynamic value1, dynamic value2) : this(key, [value1, value2]) + { + } + + public I18NExtension(BindingBase key, dynamic value1, dynamic value2, dynamic value3) : this(key, + [value1, value2, value3]) + { + } + + public I18NExtension(BindingBase key, dynamic value1, dynamic value2, dynamic value3, dynamic value4) : this(key, + [value1, value2, value3, value4]) + { + } + + public I18NExtension(BindingBase key, dynamic value1, dynamic value2, dynamic value3, dynamic value4, + dynamic value5) : + this(key, [value1, value2, value3, value4, value5]) + { + } + public override object ProvideValue(IServiceProvider serviceProvider) { - return new I18NBinding(key, values); + return new I18NBinding(_key, _values); } } \ No newline at end of file diff --git a/TestMvvm/Assets/Resources.resx b/TestMvvm/Assets/Resources.resx index 53651eb..ee65c91 100644 --- a/TestMvvm/Assets/Resources.resx +++ b/TestMvvm/Assets/Resources.resx @@ -1,7 +1,8 @@ - @@ -26,4 +27,7 @@ Test1: {0} + + Test2Test2 + \ No newline at end of file diff --git a/TestMvvm/Assets/Resources.zh-hans.resx b/TestMvvm/Assets/Resources.zh-hans.resx index bbdc8f4..ee63f84 100644 --- a/TestMvvm/Assets/Resources.zh-hans.resx +++ b/TestMvvm/Assets/Resources.zh-hans.resx @@ -18,4 +18,7 @@ 测试1: {0} + + 测试2测试2 + \ No newline at end of file diff --git a/TestMvvm/ViewModels/MainWindowViewModel.cs b/TestMvvm/ViewModels/MainWindowViewModel.cs index 082a5f9..4efc7ab 100644 --- a/TestMvvm/ViewModels/MainWindowViewModel.cs +++ b/TestMvvm/ViewModels/MainWindowViewModel.cs @@ -7,7 +7,8 @@ namespace TestMvvm.ViewModels; public partial class MainWindowViewModel : ViewModelBase { - [ObservableProperty] public string? test = Path.GetRandomFileName(); + [ObservableProperty] private string? _test = Path.GetRandomFileName(); + [ObservableProperty] private string _test2 = "Test2"; [RelayCommand] public void RandomText() diff --git a/TestMvvm/Views/MainWindow.axaml b/TestMvvm/Views/MainWindow.axaml index c249cbb..7bb8d9e 100644 --- a/TestMvvm/Views/MainWindow.axaml +++ b/TestMvvm/Views/MainWindow.axaml @@ -19,6 +19,7 @@ +