news 2026/9/28 2:37:13

Humanizer IOrdinalizer 接口深度解析:本地化序数词生成的扩展点与实现原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Humanizer IOrdinalizer 接口深度解析:本地化序数词生成的扩展点与实现原理
  • 开发工具

【免费下载链接】Humanizer

Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities

项目地址:https://gitcode.com/gh_mirrors/hu/Humanizer
点击查看免费下载

IOrdinalizer是 Humanizer 中负责把数字转换为序数词(如1st、2nd、3rd)的本地化扩展点接口,也是Ordinalize()扩展方法背后真正的执行者。本篇指南以该接口的 API 契约为骨架,结合 接口定义、注册表 与 扩展方法入口 等源码,讲解四个重载的语义差异、GrammaticalGender与WordForm的作用,以及如何自定义或替换序数词实现,帮助你在多语言场景下精确控制序数词输出。

一、接口定位:Ordinalize 的本地化后端

Humanizer 的Ordinalize()扩展方法(定义于 OrdinalizeExtensions.cs)能把数字字符串或数值转换成序数词形式。默认情况下它输出英文规则(1st、2nd、3rd、4th),但在西班牙语、法语、意大利语、俄语等语言中,序数词还要受语法性别(grammatical gender)甚至缩写/全写词形(word form)的制约。

IOrdinalizer正是为了解决"不同语言如何生成序数词"这一本地化问题而设计的接口,其官方注释明确说明它的职责是"Localizes the ordinal form of a number"(本地化数字的序数形式)。接口本身不包含任何实现逻辑,只定义契约;真正按语言路由到具体实现的是配置层:

  • Configurator.cs 暴露静态属性Ordinalizers(类型为LocaliserRegistry<IOrdinalizer>),并在 L83 提供便捷访问器Ordinalizer(解析当前线程文化对应的实现);
  • OrdinalizerRegistry.cs 是注册表实现,构造时以DefaultOrdinalizer作为兜底,并调用OrdinalizerRegistryRegistrations.Register(this)批量注册各语言实现。

因此,IOrdinalizer是 Humanizer 序数词体系的"插件契约":内置实现全部实现该接口,自定义实现也可以注册到同一注册表。

二、接口契约:四个 Convert 重载

接口定义位于 IOrdinalizer.cs,共声明 4 个方法重载,签名如下:

public interface IOrdinalizer { // 使用默认语法形式将数字序数化 string Convert(int number, string numberString); // 使用区域特定的词形(缩写 / 全写)序数化 string Convert(int number, string numberString, WordForm wordForm); // 使用提供的语法性别序数化 string Convert(int number, string numberString, GrammaticalGender gender); // 同时使用语法性别与词形序数化 string Convert(int number, string numberString, GrammaticalGender gender, WordForm wordForm); }

2.1 参数含义

参数类型说明
numberSystem.Int32正在被序数化的数值
numberStringSystem.String该数字的基数(cardinal)文本表示,即转换前的原始数字字符串
genderHumanizer.GrammaticalGender语法性别,仅在语言要求时生效(如巴西葡萄牙语的1º/1ª)
wordFormHumanizer.WordForm词形,用于区分缩写与全写(如西班牙语1.ervs1.º)

返回值统一为System.String。接口注释特别指出:numberString是数字的基数表示,实现通常在其上追加后缀或做整体替换,而不是重新把number格式化——这样既能保留调用方传入的原始文本(如带千分位或本地化数字字符),又能拿到数值做规则判断。

2.2 四个重载的语义差异

  • Convert(int, string):最基础的重载,使用默认语法形式。例如英文下把"1"变成"1st"。
  • Convert(int, string, WordForm):按词形输出。Humanizer 的WordForm枚举区分Normal(正常词形)与Abbreviation(缩写词形)。以西班牙语为例(源码中的 XML 注释原例):"1".Ordinalize(WordForm.Abbreviation) -> 1.er(如 "Vivo en el 1.er piso"),而"1".Ordinalize(WordForm.Normal) -> 1.º(如 "Fui el 1º de mi promoción")。
  • Convert(int, string, GrammaticalGender):按语法性别输出。典型场景是巴西葡萄牙语:"1".Ordinalize(GrammaticalGender.Masculine) -> "1º","1".Ordinalize(GrammaticalGender.Feminine) -> "1ª"。
  • Convert(int, string, GrammaticalGender, WordForm):性别与词形组合的完整重载,允许西班牙语等语言同时区分 "1.er / 1.º / 1.ª"。

2.3 衍生接口 ILongOrdinalizer

除IOrdinalizer外,IOrdinalizer.cs 还定义了继承它的ILongOrdinalizer,为 64 位整型补充了 4 个对应的Convert(long, string, ...)重载。注释明确说明:注册自定义序数器时,若需要支持超出int范围的值,应实现ILongOrdinalizer;已有的IOrdinalizer实现仍可继续用于 32 位数值。

为什么需要单独扩展?因为 OrdinalizeExtensions.cs 中的ConvertOrdinalizer辅助方法采用运行时类型判断:若解析到的序数器是ILongOrdinalizer,则调用其 64 位重载;否则回退到 32 位重载,并在数值超出int范围时抛出NotSupportedException。测试 OrdinalizeTests.cs 验证了大数值行为,例如4294967297L.Ordinalize(new CultureInfo("fr-FR"))输出"4294967297ème",说明法语实现已通过ILongOrdinalizer支持 64 位输入。

三、扩展方法如何驱动接口:完整调用链

IOrdinalizer不会直接暴露给业务代码,而是由 OrdinalizeExtensions.cs 中的一系列Ordinalize重载代理。理解调用链有助于判断自定义实现何时生效:

  1. 调用方执行"1".Ordinalize(...)或1.Ordinalize(...);
  2. 扩展方法解析文化:culture ?? CultureInfo.CurrentCulture;
  3. 通过Configurator.Ordinalizers.ResolveForCulture(culture)按文化解析出IOrdinalizer实例;
  4. 调用对应重载的Convert(number, numberString, ...);
  5. 实现内部按语言规则追加/替换后缀,返回序数词。

细节上,OrdinalizeExtensions还做了两类预处理:

  • NormalizeOrdinalNumberString:剔除输入字符串中的 UnicodeFormat类字符(如零宽字符),避免干扰后缀判断;
  • FormatOrdinalNumberString:针对非不变文化(如使用本地化数字字符或特殊负号规则的语言)格式化数字字符串;内置实现还按文化名对OrdinalNumberFormatting做了缓存(OrdinalNumberFormattingCache)。

四、内置实现族:从空操作到模板规则

Localisation/Ordinalizers目录下共有 6 个实现文件,构成了从"什么都不做"到"模板化规则"的完整谱系:

4.1 DefaultOrdinalizer(默认实现)

DefaultOrdinalizer.cs 是注册表的兜底类型,实现ILongOrdinalizer并标记所有方法为virtual。它的核心行为是原样返回numberString(L29-L30),不做任何变换;带性别/词形的重载只是逐级向下委托到无参形式(如Convert(number, numberString, gender)委托给Convert(number, numberString))。它同时提供两个受保护的工具方法GetAbsoluteValue(求绝对值,正确处理long.MinValue的溢出)和TryGetInt32Value(安全的 int 范围检查),供派生类复用。

4.2 SuffixOrdinalizer 与 ModuloSuffixOrdinalizer(后缀规则)

  • SuffixOrdinalizer:最简单的后缀追加实现,把固定后缀拼到数字字符串后面;
  • ModuloSuffixOrdinalizer.cs:按取模规则选后缀,Options支持DefaultSuffix、按精确数字的ExactSuffixes、按最后两位的LastTwoDigitSuffixes、按最后一位的LastDigitSuffixes,以及可选的LastTwoDigitsRange(闭区间规则)与AbsoluteAtLeast/AbsoluteAtLeastSuffix(阈值规则)。其GetSuffix方法的规则优先级为:后两位区间 > 精确数字 > 阈值 > 后两位 > 后一位 > 默认后缀,典型用于英语11th/12th/13th这类特殊规则。

4.3 TemplateOrdinalizer 与 WordFormTemplateOrdinalizer(模板规则)

  • TemplateOrdinalizer.cs:面向需要前缀+后缀的语言。Options按GrammaticalGender提供三套Pattern(Masculine/Feminine/Neuter),每个Pattern含Prefix、DefaultSuffix、ExactReplacements(精确替换,直接覆盖输入文本)、ExactSuffixes与LastDigitSuffixes;还支持ZeroAsPlainNumber、MinValueAsPlainNumber(把0/int.MinValue当作纯数字输出)与NegativeNumberMode(负数处理策略,AbsoluteInvariant模式用不变文化重排绝对值)。
  • WordFormTemplateOrdinalizer:进一步把词形(WordForm)纳入模板维度,让同一性别下缩写与全写可走不同模板,支撑西班牙语1.er(缩写)与1.º(全写)的区分。

4.4 NumberWordSuffixOrdinalizer(词后缀)

对于序数词后缀附着在完整数字单词上的语言(如印地语hi-IN),使用该实现把序数词缀接到数字单词后面。测试 OrdinalizeTests.cs 的OrdinalizeLongNumberUsesNumberWordSuffixFallback即验证了此类回退行为。

五、自定义序数器:注册到 LocaliserRegistry

要替换或扩展序数词行为,核心入口是Configurator.Ordinalizers(Configurator.cs)。以注册表模式工作:

// 1. 实现 IOrdinalizer(或 ILongOrdinalizer) public sealed class CustomOrdinalizer : IOrdinalizer { public string Convert(int number, string numberString) => numberString + "º"; // 示例:统一追加后缀 public string Convert(int number, string numberString, WordForm wordForm) => Convert(number, numberString); public string Convert(int number, string numberString, GrammaticalGender gender) => Convert(number, numberString); public string Convert(int number, string numberString, GrammaticalGender gender, WordForm wordForm) => Convert(number, numberString); } // 2. 注册到注册表(并注册对应文化) Configurator.Ordinalizers.Register<CustomOrdinalizer>(new CultureInfo("xx-XX")); Configurator.Ordinalizers.RegisterDefault<CustomOrdinalizer>();

注册之后,所有调用"数字".Ordinalize()的代码都会经由 OrdinalizeExtensions.cs 解析到你的实现。需要注意:

  • 若只实现IOrdinalizer而注册表恰好返回ILongOrdinalizer类型的实例,ConvertOrdinalizer会优先调用 64 位重载;反之long输入超过int范围时,仅实现IOrdinalizer会抛NotSupportedException;
  • 若需要完全自定义每种语言的规则,可以参考TemplateOrdinalizer的Pattern/Options结构组织数据,避免把规则散落在switch分支中;
  • 注册表本身基于LocaliserRegistry<IOrdinalizer>,支持按文化解析与默认回退,具体见 OrdinalizerRegistry.cs。

六、与相邻 API 的关系

IOrdinalizer并非孤岛,它与 Humanizer 序数词体系中的两个类型紧密协作:

  • GrammaticalGender:枚举定义Masculine、Feminine、Neuter三个性别值,作为Convert重载的入参,仅在语言要求时被消费(如巴西葡萄牙语、西班牙语、俄语);
  • WordForm:枚举定义Normal与Abbreviation两种词形,用于区分全写与缩写输出,主要被西班牙语等场景使用。

同时,Ordinalize扩展方法还有无性别/词形的简洁版本,以及按文化显式指定的版本,完整重载清单见 OrdinalizeExtensions.cs,其行为覆盖由 OrdinalizeTests.cs 的OrdinalizeNumberGenderIsImmaterial、OrdinalizeStringWithSpecifiedCultureInsteadOfCurrentCulture等用例验证。

七、小结

IOrdinalizer是 Humanizer 序数词能力的本地化契约层:它用 4 个Convert重载覆盖"基础形式、词形、语法性别、性别+词形"四种输出维度,用ILongOrdinalizer扩展 64 位支持,并由OrdinalizerRegistry按文化路由到DefaultOrdinalizer、SuffixOrdinalizer、ModuloSuffixOrdinalizer、TemplateOrdinalizer等内置实现。理解这个接口,你就能:

  1. 解释1.Ordinalize(GrammaticalGender.Feminine)为何在葡萄牙语输出1ª;
  2. 判断为什么西班牙语WordForm.Abbreviation与Normal结果不同;
  3. 通过Configurator.Ordinalizers注册自定义实现,为私有语言/业务场景定制序数词规则;
  4. 在大数值场景下正确选择实现ILongOrdinalizer以避免NotSupportedException。

无论你是要深入理解 Humanizer 的本地化架构,还是要定制自己的序数词输出,IOrdinalizer都是最核心的起点。

  • 开发工具

【免费下载链接】Humanizer

Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities

项目地址:https://gitcode.com/gh_mirrors/hu/Humanizer
点击查看免费下载
上一篇:以"开发上下文"约束 Agent 编码行为:解读 ECC 的 Development Context 规范
下一篇:NativeScript-Vue 代码质量保障:ESLint、Prettier 与 Git Hooks 配置

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 2:36:54

大麦网自动抢票脚本 3 步上手:新手快速启动教程

大麦网自动抢票脚本 3 步上手&#xff1a;新手快速启动教程 【免费下载链接】Automatic_ticket_purchase 大麦网抢票脚本 项目地址: https://gitcode.com/GitHub_Trending/au/Automatic_ticket_purchase 开抢前 3 秒&#xff0c;你的手指悬在"立即购买"上——…

作者头像 李华
网站建设 2026/9/28 2:36:54

C# WinForm酒店管理系统源码解析:从数据库设计到前台实战

简介&#xff1a;面向C#初学者的酒店管理系统项目源码&#xff0c;基于WinForm界面框架实现&#xff0c;覆盖用户管理、房客管理、客房管理和出入管理四大核心模块&#xff0c;适合用于课程设计、毕业设计或入门企业级桌面应用开发。资源压缩包共54个文件&#xff0c;整体仅159…

作者头像 李华
网站建设 2026/9/28 2:33:56

BaiduPCS-Go 下载速度调优全解:3 种账号配置一次到位

BaiduPCS-Go 下载速度调优全解&#xff1a;3 种账号配置一次到位 【免费下载链接】BaiduPCS-Go iikira/BaiduPCS-Go原版基础上集成了分享链接/秒传链接转存功能 项目地址: https://gitcode.com/GitHub_Trending/ba/BaiduPCS-Go BaiduPCS-Go 是一款基于 iikira 原版开发的…

作者头像 李华
网站建设 2026/9/28 2:33:28

Qt+C++扫雷实战:从环境搭建到状态机设计

简介&#xff1a;本资源是一份面向C初学者与高校程序设计课程学习者的可视化扫雷小程序完整实现源码&#xff0c;适用于《C程序设计》大作业实践与图形界面编程入门训练。项目基于Qt框架开发&#xff0c;包含15个核心文件&#xff1a;4个.cpp源文件&#xff08;含主窗口、游戏逻…

作者头像 李华