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