From fca38086574f97105c2e3b6590bd6da5e838ccf0 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Sat, 21 Mar 2026 15:01:47 +0800 Subject: [PATCH] =?UTF-8?q?fix(localization):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E7=B4=A7=E5=87=91=E6=95=B0=E5=AD=97=E6=A0=BC=E5=BC=8F=E5=8C=96?= =?UTF-8?q?=E5=99=A8=E5=A4=84=E7=90=86=E6=9C=AA=E7=9F=A5=E9=80=89=E9=A1=B9?= =?UTF-8?q?=E7=9A=84=E8=A1=8C=E4=B8=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 CompactNumberLocalizationFormatter 中 TryApplyOption 方法的返回逻辑 - 当键名未知时现在返回 true 而不是 false,允许忽略未知选项 - 更新 NumericDisplayFormatter 使用 ResolveRule 方法来确定格式化规则 - 添加对不同数值显示风格的支持和验证 - 在集成测试中添加未知选项的测试用例以验证正确行为 - 改进 NumericSuffixFormatRule 的文档注释以更清楚地描述功能 --- .../LocalizationIntegrationTests.cs | 12 +++++++++ .../CompactNumberLocalizationFormatter.cs | 4 +-- .../Numeric/NumericDisplayFormatter.cs | 18 ++++++++++++- .../Numeric/NumericSuffixFormatRule.cs | 25 ++++++++++++------- 4 files changed, 47 insertions(+), 12 deletions(-) diff --git a/GFramework.Core.Tests/Localization/LocalizationIntegrationTests.cs b/GFramework.Core.Tests/Localization/LocalizationIntegrationTests.cs index 5086867..e37c1be 100644 --- a/GFramework.Core.Tests/Localization/LocalizationIntegrationTests.cs +++ b/GFramework.Core.Tests/Localization/LocalizationIntegrationTests.cs @@ -52,6 +52,7 @@ public class LocalizationIntegrationTests "status.health": "Health: {current}/{max}", "status.gold": "Gold: {gold:compact}", "status.damage": "Damage: {damage:compact:maxDecimals=2}", + "status.unknownCompact": "Gold: {gold:compact:maxDecimalss=2}", "status.invalidCompact": "Gold: {gold:compact:maxDecimals=abc}" } """); @@ -63,6 +64,7 @@ public class LocalizationIntegrationTests "status.health": "生命值: {current}/{max}", "status.gold": "金币: {gold:compact}", "status.damage": "伤害: {damage:compact:maxDecimals=2}", + "status.unknownCompact": "金币: {gold:compact:maxDecimalss=2}", "status.invalidCompact": "金币: {gold:compact:maxDecimals=abc}" } """); @@ -134,6 +136,16 @@ public class LocalizationIntegrationTests Assert.That(damage, Is.EqualTo("Damage: 1.23K")); } + [Test] + public void GetString_WithUnknownCompactFormatterArgs_ShouldIgnoreUnknownOptions() + { + var gold = _manager!.GetString("common", "status.unknownCompact") + .WithVariable("gold", 1_250) + .Format(); + + Assert.That(gold, Is.EqualTo("Gold: 1.3K")); + } + [Test] public void GetString_WithInvalidCompactFormatterArgs_ShouldFallbackToDefaultFormatting() { diff --git a/GFramework.Core/Localization/Formatters/CompactNumberLocalizationFormatter.cs b/GFramework.Core/Localization/Formatters/CompactNumberLocalizationFormatter.cs index 7630842..b37d892 100644 --- a/GFramework.Core/Localization/Formatters/CompactNumberLocalizationFormatter.cs +++ b/GFramework.Core/Localization/Formatters/CompactNumberLocalizationFormatter.cs @@ -146,7 +146,7 @@ public sealed class CompactNumberLocalizationFormatter : ILocalizationFormatter /// 最小小数位数的引用参数 /// 是否去除尾随零的引用参数 /// 是否在阈值以下使用分组的引用参数 - /// 如果键名有效且值成功解析则返回true;如果键名无效或值解析失败则返回false + /// 如果值成功解析或键名未知则返回true;如果键名已知但值解析失败则返回false private static bool TryApplyOption( string key, string value, @@ -161,7 +161,7 @@ public sealed class CompactNumberLocalizationFormatter : ILocalizationFormatter "minDecimals" => int.TryParse(value, out minDecimalPlaces), "trimZeros" => bool.TryParse(value, out trimTrailingZeros), "grouping" => bool.TryParse(value, out useGroupingBelowThreshold), - _ => false + _ => true }; } } \ No newline at end of file diff --git a/GFramework.Core/Utility/Numeric/NumericDisplayFormatter.cs b/GFramework.Core/Utility/Numeric/NumericDisplayFormatter.cs index e9afc87..372d30b 100644 --- a/GFramework.Core/Utility/Numeric/NumericDisplayFormatter.cs +++ b/GFramework.Core/Utility/Numeric/NumericDisplayFormatter.cs @@ -37,7 +37,7 @@ public sealed class NumericDisplayFormatter : INumericDisplayFormatter } var resolvedOptions = NormalizeOptions(options); - var rule = resolvedOptions.Rule ?? _defaultRule; + var rule = ResolveRule(resolvedOptions); if (rule.TryFormat(value, resolvedOptions, out var result)) { @@ -113,6 +113,22 @@ public sealed class NumericDisplayFormatter : INumericDisplayFormatter return resolved; } + private INumericFormatRule ResolveRule(NumericFormatOptions options) + { + ArgumentNullException.ThrowIfNull(options); + + if (options.Rule is not null) + { + return options.Rule; + } + + return options.Style switch + { + NumericDisplayStyle.Compact => _defaultRule, + _ => throw new ArgumentOutOfRangeException(nameof(options), options.Style, "不支持的数值显示风格。") + }; + } + private static string FormatFallback(object value, IFormatProvider? provider) { return value switch diff --git a/GFramework.Core/Utility/Numeric/NumericSuffixFormatRule.cs b/GFramework.Core/Utility/Numeric/NumericSuffixFormatRule.cs index 3e1f706..60a90f3 100644 --- a/GFramework.Core/Utility/Numeric/NumericSuffixFormatRule.cs +++ b/GFramework.Core/Utility/Numeric/NumericSuffixFormatRule.cs @@ -33,7 +33,7 @@ public sealed class NumericSuffixFormatRule : INumericFormatRule } /// - /// 默认国际缩写规则。 + /// 默认国际缩写规则,使用标准的K、M、B、T后缀表示千、百万、十亿、万亿。 /// public static NumericSuffixFormatRule InternationalCompact { get; } = new( "compact", @@ -44,10 +44,19 @@ public sealed class NumericSuffixFormatRule : INumericFormatRule new NumericSuffixThreshold(1_000_000_000_000m, "T") ]); - /// + /// + /// 获取此格式化规则的名称。 + /// public string Name { get; } - /// + /// + /// 尝试将指定的数值按照当前规则进行格式化。 + /// + /// 数值的类型 + /// 要格式化的数值 + /// 格式化选项,包含小数位数、舍入模式等设置 + /// 格式化后的字符串结果 + /// 如果格式化成功则返回true;如果输入无效或格式化失败则返回false public bool TryFormat(T value, NumericFormatOptions options, out string result) { ArgumentNullException.ThrowIfNull(options); @@ -164,15 +173,13 @@ public sealed class NumericSuffixFormatRule : INumericFormatRule } catch (OverflowException) { - try + var doubleValue = (double)value; + if (TryFormatSpecialFloatingPoint(doubleValue, options.FormatProvider, out result)) { - return TryFormatDouble((double)value, options, out result); - } - catch (OverflowException) - { - result = value.ToString(options.FormatProvider ?? CultureInfo.CurrentCulture); return true; } + + return TryFormatDouble(doubleValue, options, out result); } }