Compare commits

...

2 Commits

Author SHA1 Message Date
e25d4639de feat(i18n): 支持绑定表达式作为国际化键值
- 将 I18NBinding 构造函数的 key 参数从 string 类型改为 object 类型
- 添加对 BindingBase 类型键值的支持,允许动态绑定国际化键
- 为 I18NExtension 添加多个构造函数重载以支持 BindingBase 键值
- 更新资源文件添加新的测试键值对
- 修改视图模型属性访问修饰符并添加测试属性
- 在主窗口视图中添加绑定表达式的国际化使用示例
2026-01-19 03:21:26 +08:00
416cbc9224 style(build): 格式化项目文件中的包引用
- 移除 JackCraft.I18N.csproj 中 PackageReference 的多余空格
- 统一 solution 文件中项目路径的 XML 格式
- 移除 Test 项目中所有 PackageReference 的多余空格
- 移除 TestMvvm 项目中所有 PackageReference 的多余空格
2026-01-19 03:21:03 +08:00
10 changed files with 93 additions and 26 deletions

View File

@@ -1,9 +1,9 @@
<Solution>
<Folder Name="/Solution Folder/">
<File Path="LICENSE" />
<File Path="Readme.MD" />
</Folder>
<Project Path="JackCraft.I18N/JackCraft.I18N.csproj" />
<Project Path="Test/Test.csproj" />
<Project Path="TestMvvm/TestMvvm.csproj" />
<Folder Name="/Solution Folder/">
<File Path="LICENSE"/>
<File Path="Readme.MD"/>
</Folder>
<Project Path="JackCraft.I18N/JackCraft.I18N.csproj"/>
<Project Path="Test/Test.csproj"/>
<Project Path="TestMvvm/TestMvvm.csproj"/>
</Solution>

View File

@@ -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 });
}
}
}

View File

@@ -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);
}
}

View File

@@ -12,7 +12,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.3.11" />
<PackageReference Include="Avalonia" Version="11.3.11"/>
</ItemGroup>
</Project>

View File

@@ -9,10 +9,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.3.11" />
<PackageReference Include="Avalonia.Desktop" Version="11.3.11" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.11" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.11" />
<PackageReference Include="Avalonia" Version="11.3.11"/>
<PackageReference Include="Avalonia.Desktop" Version="11.3.11"/>
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.11"/>
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.11"/>
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Include="Avalonia.Diagnostics" Version="11.3.11">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>

View File

@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root"
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
id="root"
xmlns="">
<xsd:element name="root" msdata:IsDataSet="true">
@@ -26,4 +27,7 @@
<data name="Test1" xml:space="preserve">
<value>Test1: {0}</value>
</data>
<data name="Test2" xml:space="preserve">
<value>Test2Test2</value>
</data>
</root>

View File

@@ -18,4 +18,7 @@
<data name="Test1" xml:space="preserve">
<value>测试1: {0}</value>
</data>
<data name="Test2" xml:space="preserve">
<value>测试2测试2</value>
</data>
</root>

View File

@@ -14,16 +14,16 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.3.11" />
<PackageReference Include="Avalonia.Desktop" Version="11.3.11" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.11" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.11" />
<PackageReference Include="Avalonia" Version="11.3.11"/>
<PackageReference Include="Avalonia.Desktop" Version="11.3.11"/>
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.11"/>
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.11"/>
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Include="Avalonia.Diagnostics" Version="11.3.11">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0"/>
</ItemGroup>
<ItemGroup>

View File

@@ -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()

View File

@@ -19,6 +19,7 @@
<StackPanel>
<TextBlock Text="{Binding Test}" HorizontalAlignment="Center" VerticalAlignment="Center" />
<TextBlock Text="{i18N:I18N Test1, {Binding Test}}" HorizontalAlignment="Center" VerticalAlignment="Center" />
<TextBlock Text="{i18N:I18N {Binding Test2}}" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Button Content="随机文本"
Command="{Binding RandomTextCommand}" />
<Button Content="切换中文"