Humanizer PluralizationForms 完全指南:基于 CLDR 基数复数规则的多语言复数形式建模

发布时间:2026/9/25 5:45:58
Humanizer PluralizationForms 完全指南:基于 CLDR 基数复数规则的多语言复数形式建模 开发工具【免费下载链接】HumanizerHumanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities项目地址https://gitcode.com/gh_mirrors/hu/Humanizer点击查看免费下载导读PluralizationForms是 Humanizer 中用于承载一个名词的作者化单复数形态集合的公开类型你为名词显式提供单数形态与 CLDRUnicode Common Locale Data Repository各基数复数类别对应的形态Humanizer 依据所选文化的基数复数规则自动挑选正确形态。本文完整讲解该类的构造函数、7 个属性与 3 个方法并深入源码剖析其背后的 CLDR 48.2 规则引擎、decimal小数位visible-fraction operands语义与 NFC 规范化匹配机制帮助你在多语言场景下准确、可控地处理数量词复数。一、为什么需要 PluralizationForms英语的复数规则很简单1 item/2 items。但阿拉伯语有zero、one、two、few、many、other六种类别俄语、波兰语等斯拉夫语言对few和many有严格的分段规则法语连0都算复数。通用复数引擎可以覆盖常见语言但总有些名词需要作者化authored的精确控制——比如品牌名、外来词、固定短语。PluralizationForms就是为这种需求设计的纯数据容器它不自己计算复数只保存你显式写下的各形态真正决定当前数量该用哪个形态的是文化对应的 CLDR 基数复数规则。正如其类注释所强调的两条契约见 src/Humanizer/PluralizationForms.csHumanizer 应用受支持文化的基数复数规则来挑选已声明的形态缺失的形态不会被推断Missing selected forms are not inferred。二、类型定义与整体设计public sealed class PluralizationForms类声明在命名空间Humanizer中继承自System.Object且是sealed的——它只负责保存形态数据不开放继承扩展。完整实现见 src/Humanizer/PluralizationForms.cs。类的核心成员一览构造函数PluralizationForms(string singular, string other, string? zero, string? one, string? two, string? few, string? many)属性Singular、Other、Zero、One、Two、Few、Many方法Invariant(string)静态工厂、TryPluralize(decimal, CultureInfo, out string?)、TrySingularize(string, out string?)其中 6 个属性对应 CLDR 的 6 种基数复数类别这些类别由内部枚举CardinalPluralCategory定义见 src/Humanizer/CardinalPluralCategory.cs。需要注意这些类别名是语法类别而非数值区间——one并不总是等于数量 1具体含义由所选文化的 CLDR 规则决定。例如葡萄牙语pt与欧洲葡萄牙语pt-PT的规则就不同测试用例 tests/Humanizer.Tests/LocalizedInflectionTests.cs 验证了这一点。三、构造函数为名词声明完整形态集合public PluralizationForms( string singular, string other, string? zero null, string? one null, string? two null, string? few null, string? many null);3.1 参数详解参数类型必填含义singularstring是名词的单数形态otherstring是CLDRother类别对应的形态所有语言都必须有的兜底类别zerostring?否CLDRzero类别形态不可用时传nullonestring?否CLDRone类别形态不可用时传nulltwostring?否CLDRtwo类别形态不可用时传nullfewstring?否CLDRfew类别形态不可用时传nullmanystring?否CLDRmany类别形态不可用时传null只有singular和other是必填的其余 5 个都是可选参数支持命名参数调用。这在英语场景下非常简洁——英语的 CLDR 规则只有one和other两类其余类别永远不会被选中所以只需var forms new PluralizationForms(item, items, one: item);3.2 验证规则与异常从源码实现src/Humanizer/PluralizationForms.cs可以看到构造函数内部调用RequireForm和ValidateOptionalForm完成校验singular或other为null→ 抛出System.ArgumentNullExceptionsingular或other为空字符串或纯空白 → 抛出System.ArgumentException任意可选形态zero/one/two/few/many非null但为空或纯空白 → 同样抛出System.ArgumentException。也就是说可选参数要么不传保持null要么就必须传一个非空有效值。对应的测试见 tests/Humanizer.Tests/LocalizedInflectionTests.csAssert.ThrowsArgumentNullException(() new PluralizationForms(null!, items)); Assert.ThrowsArgumentException(() new PluralizationForms(item, )); Assert.ThrowsArgumentException(() new PluralizationForms(item, items, one: ));3.3 实战示例阿拉伯语名词阿拉伯语拥有全部 6 个非 singular 类别适合展示完整构造。下面参考测试用例 tests/Humanizer.Tests/LocalizedInflectionTests.cs 的写法形态取自仓库中 src/Humanizer/Locales/ar.yml 所体现的复数类别体系var forms new PluralizationForms( ملي ثانية, // singular ملي ثانية, // other zero: ملي ثانية, one: ملي ثانية, two: ملي ثانية, few: ملي ثانية, many: ملي ثانية);如果一个名词在所有类别下形态完全相同可以直接使用下面的静态工厂方法。四、属性读取已声明的形态7 个属性均为只读{ get; }在构造时被赋值后不可修改属性类型说明Singularstring名词的单数形态必填OtherstringCLDRother类别形态必填Zerostring?CLDRzero类别形态未声明时为nullOnestring?CLDRone类别形态未声明时为nullTwostring?CLDRtwo类别形态未声明时为nullFewstring?CLDRfew类别形态未声明时为nullManystring?CLDRmany类别形态未声明时为null可空属性是否返回null直接决定了TryPluralize在选中该类别时能否成功——这正是缺失形态不被推断的具体体现。五、静态工厂Invariant(string)对于任何类别下形态都不变的名词如品牌名token、缩写、专有名词Invariant工厂方法把同一个词填充到所有 7 个形态位public static PluralizationForms Invariant(string word);源码实现非常直白src/Humanizer/PluralizationForms.cspublic static PluralizationForms Invariant(string word) new(word, word, word, word, word, word, word);参数与异常word为null→System.ArgumentNullExceptionword为空或纯空白 →System.ArgumentException。该工厂的典型用途是测试与占位测试代码 tests/Humanizer.Tests/LocalizedInflectionTests.cs 用它构造token对每一种已发布 locale执行TryPluralize(1.0m, ...)验证任何受支持文化下都能成功返回token。六、TryPluralize按数量与文化挑选形态这是类的核心方法签名如下public bool TryPluralize( decimal quantity, System.Globalization.CultureInfo culture, [NotNullWhen(true)] out string? result);6.1 行为契约quantity数量值。其编码的十进制小数位decimal scale提供 CLDR 的 visible-fraction operands见下文原理分析culture应用其基数复数规则的受支持文化为null时抛出System.ArgumentNullExceptionresult被选中的作者化形态当选中类别未声明对应形态时为null返回值选中形态可用返回true否则返回false。6.2 实现原理与调用链源码实现src/Humanizer/PluralizationForms.cs分两步调用LocalizedInflectionCatalog.TrySelectCategory(culture, quantity, out var category)算出数量在该文化下属于哪个 CLDR 类别调用内部方法TryGetForm(category, out result)在已声明的形态中查找——找不到对应属性为null就返回false。TryGetForm本质是一个switch表达式src/Humanizer/PluralizationForms.cs将CardinalPluralCategory枚举映射到对应属性遇到未知枚举值抛出System.ArgumentOutOfRangeException测试见 tests/Humanizer.Tests/LocalizedInflectionTests.cs。TrySelectCategory位于 src/Humanizer/Inflections/LocalizedInflectionCatalog.cs其逻辑是先解析该文化命中的 CLDR 规则集CardinalPluralRuleKind支持按 locale 归并到 LocaleProfileOwner再交给CardinalPluralRules.Select(rule, quantity)计算类别解析不到规则时返回false。6.3 CLDR 48.2 规则与小数位visible fraction语义规则集与选择器定义在 src/Humanizer/Localisation/GrammaticalNumber/CardinalPluralRules.cs共实现了AmharicLike、EnglishLike、Arabic、Slovenian、CzechSlovak、Polish、RussianUkrainian、French、Portuguese等约 30 套 CLDR 48.2 基数规则。CLDR 规则的一个关键点是小数是否可见会影响类别判定。例如英语规则中整数1属于one而带可见小数位的1.0属于other。测试 tests/Humanizer.Tests/LocalizedInflectionTests.cs 精确验证了这一语义var forms new PluralizationForms(item, other, one: one); var culture new CultureInfo(en); Assert.True(forms.TryPluralize(1m, culture, out var integer)); Assert.True(forms.TryPluralize(1.0m, culture, out var visibleFraction)); Assert.Equal(one, integer); // 1 → one Assert.Equal(other, visibleFraction); // 1.0 → other其中quantity的十进制小数位由 src/Humanizer/Localisation/GrammaticalNumber/CardinalPluralOperands.cs 精确提取通过decimal.GetBits读取编码的 96 位整数与 scaleV再计算整数部分、小数部分、去尾零小数部分W等 CLDR 操作数对double则采用 Ryu 最短往返算法还原十进制表示该文件声明改编自 Ulf Adams 的 Ryu版权与许可见 THIRD-PARTY-NOTICES.txt。测试 tests/Humanizer.Tests/LocalizedInflectionTests.cs 展示了操作数提取的精确性例如1.230m得到小数位数V3、去尾零后W2。6.4 缺失形态返回 false因为缺失形态不被推断所以当规则选中few而你未声明few形态时即使other已声明也不会被拿来兜底。测试用例 tests/Humanizer.Tests/LocalizedInflectionTests.cs 用new PluralizationForms(item, items)未声明zero/one等在en与ar上验证en下1、ar下0、2、3、11均返回false且result为null。6.5 不受支持的文化不降级两个值得注意的行为边界均有测试佐证见 tests/Humanizer.Tests/LocalizedInflectionTests.cs传入不受支持的文化如世界语eo时TryPluralize返回false不会静默降级为英语规则CultureInfo.InvariantCulture同样不受支持返回false。七、TrySingularize从形态反查单数public bool TrySingularize(string form, out string? result);form一个精确的作者化形态null时抛出System.ArgumentNullExceptionresult匹配成功时返回该形态集合的单数形态Singular否则为null返回值form与任一已声明形态匹配返回true否则false。7.1 匹配规则NFC 规范化 序号比较 区分大小写源码实现src/Humanizer/PluralizationForms.cs先将输入与每个候选形态做Normalize若未处于 NFC 规范化形式则调用value.Normalize(NormalizationForm.FormC)再通过string.Equals(normalized, candidate, StringComparison.Ordinal)做序号ordinal且区分大小写的比较。这意味着café的 NFD 写法cafe\u0301s也能匹配上cafés合成字符被 NFC 归一但CAFÉS大小写不同与coffee不属于任何已声明形态都匹配失败。对应测试 tests/Humanizer.Tests/LocalizedInflectionTests.csvar forms new PluralizationForms(café, cafés); Assert.True(forms.TrySingularize(cafe\u0301s, out var singular)); Assert.Equal(café, singular); Assert.False(forms.TrySingularize(CAFÉS, out singular)); Assert.Null(singular);7.2 多类别形态集合的反查示例测试 tests/Humanizer.Tests/LocalizedInflectionTests.cs 展示了完整 7 形态名词的反查无论传入child、children、zero children、one child、two children、few children还是many children只要它精确命中某个已声明形态TrySingularize都返回统一的单数child。八、完整实战示例把前面所有知识点串起来一个覆盖多语言场景的完整示例using System.Globalization; using Humanizer; // 1. 英语只需 one other var english new PluralizationForms(item, items, one: item); english.TryPluralize(1m, CultureInfo.GetCultureInfo(en), out var enOne); // item english.TryPluralize(2m, CultureInfo.GetCultureInfo(en), out var enTwo); // items english.TryPluralize(1.0m, CultureInfo.GetCultureInfo(en), out var enFrac); // items可见小数位 → other // 2. 阿拉伯语六类别齐全才完整 var arabic new PluralizationForms( عنصر, // singular عناصر, // other zero: عنصر, one: عنصر, two: عنصرين, few: عناصر, many: عنصر); arabic.TryPluralize(0m, CultureInfo.GetCultureInfo(ar), out var arZero); // zero → عنصر arabic.TryPluralize(2m, CultureInfo.GetCultureInfo(ar), out var arTwo); // two → عنصرين arabic.TryPluralize(11m, CultureInfo.GetCultureInfo(ar), out var arMany); // many → عنصر // 3. 不变名词Invariant 工厂 var brand PluralizationForms.Invariant(token); brand.TryPluralize(1m, CultureInfo.GetCultureInfo(en), out var brandForm); // token brand.TrySingularize(token, out var singular); // token // 4. 缺失形态不推断只声明 two 别的类别命中 two 之外就失败 var partial new PluralizationForms(item, items, two: 一对); partial.TryPluralize(2m, CultureInfo.GetCultureInfo(ar), out var pair); // true → 一对 partial.TryPluralize(3m, CultureInfo.GetCultureInfo(ar), out var missing); // false, missing null九、使用建议与边界总结先查规则再声明形态TryPluralize的成功与否取决于该文化的规则是否选中了已声明的类别。英语只需oneother阿拉伯语、俄语、波兰语等需要按需补齐zero/two/few/many。仓库中各语言的 src/Humanizer/Locales YAML 数据展示了真实语言中各类别形态的形态差异可作为参考。不要依赖兜底other只是规则层面最普遍的类别规则选中few而few未声明时不会回退到other务必用返回值判断是否成功。注意可见小数位1与1.0在不同文化下可能属于不同类别这是 CLDR 规则的预期行为并非缺陷。不受支持的文化返回false且不降级到英语调用方需要自行处理降级策略。反查是精确匹配TrySingularize只接受恰好等于某个已声明形态的输入且比较区分大小写、做 NFC 归一化它不做词法分析无法推断未声明的变体。配合既有复数 APIPluralizationForms属于 Humanizer 本地化词形变化Inflection体系的显式作者化路径与此前基于规则的Pluralize()/Singularize()/ToQuantity()等扩展方法如 InflectorExtensions.cs并存互补——前者精确可控后者通用便捷测试 tests/Humanizer.Tests/LocalizedInflectionTests.cs 也验证了旧契约在新引擎下保持行为不变。赞分享开发工具【免费下载链接】HumanizerHumanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities项目地址https://gitcode.com/gh_mirrors/hu/Humanizer点击查看免费下载相关推荐PHPStan 错误标识符 parameter.notOptional 完全解析子类重写把可选参数变成必选参数PHPStan 错误标识符 parameter.notOptional 完全解析子类重写把可选参数变成必选参数 parameter.notOptional 是开发工具代码质量静态分析深入解析 go-playground/localesGo 语言基于 Unicode CLDR 的本地化与复数规则引擎深入解析 go playground/localesGo 语言基于 Unicode CLDR 的本地化与复数规则引擎 导读 go playground/loc网络安全Cloud-Probe常见问题解答新手必知的10个关键知识点Cloud Probe常见问题解答新手必知的10个关键知识点 Cloud Probe是一款专为云环境和虚拟化场景设计的网络数据包捕获与转发工具能够解决在缺乏网络可观测性上一篇为什么你的朋友圈回忆需要备份3个关键原因与解决方案下一篇Monstercat Visualizer 音频可视化终极上手指南三分钟让你的桌面跟着音乐跳动创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询