尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Humanizer 数字本地化转换器契约:INumberToWordsConverter 接口深度解析与自定义实现指南

Humanizer 数字本地化转换器契约:INumberToWordsConverter 接口深度解析与自定义实现指南 开发工具【免费下载链接】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点击查看免费下载INumberToWordsConverter 是 Humanizer 中负责把数字转换为本地化文字基数词与序数词的核心接口所有ToWords()与ToOrdinalWords()扩展方法最终都会委托给它的实现。本文以 2.10.1 版 API 文档中该接口的完整定义为主体结合当前仓库源码逐一拆解接口成员的签名、参数语义与返回约定并说明转换器如何通过注册表按区域性解析、内置实现如何组织以及如何编写并注册自定义转换器让读者既能看懂契约也能落地实现。INumberToWordsConverterToWords 与 ToOrdinalWords 背后的本地化扩展点Humanizer 官方对该接口的定义非常直白An interface you should implement to localise ToWords and ToOrdinalWords methods——即它是面向扩展开放的语言化组件开发者通过实现它把数字 → 人类可读文字的规则按语言/区域插入 Humanizer 体系。接口的声明位于 INumberToWordsConverter.cs命名空间为Humanizer是公开接口public interface INumberToWordsConverter在 2.10.1 版 API 文档中该接口只包含 5 个核心方法3 个基数词转换 2 个序数词转换而从当前仓库源码看接口已在此基础上扩展出支持WordForm词形、ConvertToTuple元组命名的重载当前版本共 11 个方法。无论版本如何演进这 5 个核心方法始终是契约主干也是所有实现必须回答的最小问题集。完整调用链从扩展方法到具体实现INumberToWordsConverter并不直接面向使用者它是通过 NumberToWordsExtension.cs 中的扩展方法间接驱动的。例如public static string ToWords(this long number, CultureInfo? culture null, bool addAnd true) Configurator.GetNumberToWordsConverter(culture).Convert(number, addAnd);见 NumberToWordsExtension.cs。调用链可概括为用户调用number.ToWords(...)/number.ToOrdinalWords(...)扩展方法扩展方法经 Configurator.GetNumberToWordsConverter(culture) 解析出与当前区域性匹配的INumberToWordsConverter转换器执行Convert/ConvertToOrdinal并返回本地化文字。因此INumberToWordsConverter的语义直接决定了ToWords()系列 API 的输出质量——它是整条数字本地化管线的最后一公里。核心成员逐一解析源自 2.10.1 API 文档以下 5 个方法完整继承自关联文档签名、参数与返回值语义均以原文为准。1. Convert(long number)按区域设置的默认语法性别将数字转换为字符串string Convert(long number);项说明number[System.Int64]待转换的数字返回值[System.String]本地化后的数字文字默认语法性别指语言本身约定的默认词形。对无性别区分的语言如英语结果与性别无关对有性别区分的语言则使用转换器内置的默认性别详见下文语法性别小节。2. Convert(long number, bool addAnd)按区域设置的默认语法性别转换数字并可选择是否加入连词 Andstring Convert(long number, bool addAnd);项说明number[System.Int64]待转换的数字addAnd[System.Boolean]指定是否加入连词 And返回值[System.String]本地化后的数字文字典型差异可用英语验证见 NumberToWordsTests.cs3501L.ToWords(addAnd: true) // three thousand five hundred and one 3501L.ToWords(addAnd: false) // three thousand five hundred one注意addAnd的语义是语言相关连词的开关并非所有语言都使用 And 这个词本身具体连词由各区域性转换器内部决定。3. Convert(long number, GrammaticalGender gender, bool addAnd true)按显式提供的语法性别转换数字string Convert(long number, Humanizer.GrammaticalGender gender, bool addAndtrue);项说明number[System.Int64]待转换的数字genderGrammaticalGender期望的语法性别addAnd[System.Boolean]是否加入连词默认true返回值[System.String]本地化后的数字文字这是对有性别的语言俄语、希伯来语、西班牙语、意大利语等最关键的入口。例如俄语中数字 1 的阳性与阴性词形不同见 NumberToWordsExtension.cs 的文档注释1.ToWords(GrammaticalGender.Masculine) - один 1.ToWords(GrammaticalGender.Feminine) - одна4. ConvertToOrdinal(int number)按区域设置的默认语法性别将数字转换为序数词字符串string ConvertToOrdinal(int number);项说明number[System.Int32]待转换的数字返回值[System.String]本地化后的序数词文字注意序数词入口的数字类型是int32 位与基数词的long不同。英语示例测试见 NumberToWordsTests.cs1.ToOrdinalWords() // first 21.ToOrdinalWords() // twenty-first5. ConvertToOrdinal(int number, GrammaticalGender gender)按显式提供的语法性别将数字转换为序数词string ConvertToOrdinal(int number, Humanizer.GrammaticalGender gender);项说明number[System.Int32]待转换的数字genderGrammaticalGender期望的语法性别返回值[System.String]本地化后的序数词文字典型场景如巴西葡萄牙语1.ToOrdinalWords(GrammaticalGender.Masculine)得到 primeiro而1.ToOrdinalWords(GrammaticalGender.Feminine)得到 primeira见 NumberToWordsExtension.cs 的注释示例。理解 addAnd 与语法性别两个关键参数的实现语义语法性别枚举GrammaticalGendergender参数的类型是 GrammaticalGender.cs 定义的公开枚举仅有三个取值public enum GrammaticalGender { Masculine, // 阳性 Feminine, // 阴性 Neuter // 中性 }它在接口中的作用是输出语言要求当目标语言区分词形时转换器据此选择正确的词干与后缀当语言不区分时如英语、中文该参数会被忽略。两类基类无性别与有性别的默认路由从当前仓库源码结构看INumberToWordsConverter的全部内置实现都通过两个内部抽象基类组织它们承担了重载转发overload fan-out的职责GenderlessNumberToWordsConverter源码面向不区分性别的语言。核心是Convert(long)与ConvertToOrdinal(int)两个抽象方法其余所有重载含addAnd、gender、WordForm组合默认都转发到核心方法。例如Convert(long, bool addAnd)在基类中的默认实现会忽略addAnd因为连词行为由具体转换器固化见 GenderlessNumberToWordsConverter.cs。GenderedNumberToWordsConverter源码面向区分性别的语言构造函数接收defaultGender默认GrammaticalGender.Masculine。Convert(long)被实现为Convert(number, defaultGender)把无性别重载全部路由到Convert(long, GrammaticalGender, bool addAnd)与ConvertToOrdinal(int, GrammaticalGender)两个抽象方法见 GenderedNumberToWordsConverter.cs。这意味着对于使用者而言不传gender与传gender的差异本质上是使用语言默认词形与强制指定词形的差异对于实现者而言只需按语言特性选择继承恰当的基类覆盖最核心的抽象方法即可其余重载由基类自动补齐。addAnd 的实际落地以 TriadScale 转换器为例英语等三位一节triad语言的内置转换器 TriadScaleNumberToWordsConverter.cs 展示了Convert的完整流程见 TriadScaleNumberToWordsConverter.cs取绝对值为 0 时直接返回区域的ZeroWord当指定阴性且数值恰为 1 时返回FeminineOneWord依次按降序的Scales如千、百万、十亿分解数值对每个量级调用ConvertScalePart剩余部分百、十、个位走ConvertTriad负数统一以MinusWord 结果前缀。连词如英语的 and正是通过 profile 中的CountToScaleJoiner等字段嵌入各级拼接的因此addAnd的开关最终体现为语言特定的连接词行为而不是简单的字符串替换。转换器如何被解析注册表与区域性回退链理解接口之后下一个问题是给定一个区域性Humanizer 如何找到对应的INumberToWordsConverter答案在配置层。Configurator 与 NumberToWordsConverterRegistryConfigurator.cs 暴露了公开属性public static LocaliserRegistryINumberToWordsConverter NumberToWordsConverters { get; } new NumberToWordsConverterRegistry();而 NumberToWordsConverterRegistry.cs 把默认回退转换器绑定为英语class NumberToWordsConverterRegistry : LocaliserRegistryINumberToWordsConverter { public NumberToWordsConverterRegistry() : base(_ NumberToWordsProfileCatalog.Resolve(en, CultureInfo.InvariantCulture)) NumberToWordsConverterRegistryRegistrations.Register(this); }即当某个区域性没有专门的转换器时回退到英语同时注册表在构造时通过Register(this)批量注入各语言实现。LocaliserRegistry 的解析策略泛型注册表 LocaliserRegistry.cs 的解析逻辑见 LocaliserRegistry.cs值得关注精确匹配优先用culture.Name精确查找例如pt-BR父文化链回退精确匹配失败后沿culture.Parent逐级向上pt-BR→pt→ 中性文化直到找到注册项最终回退链上都没有时使用构造时传入的默认转换器英语性能优化注册表在首次使用后冻结字典ToFrozenDictionary并对每个CultureInfo实例做缓存ConditionalWeakTable避免重复解析注册时机约束正因为先冻结、后只读Register 方法在冻结后再次调用会抛出InvalidOperationExceptionCannot register localisers after the registry has been used.。自定义转换器必须在使用任何ToWords/ToOrdinalWords之前完成注册如应用启动阶段。从接口到实现Humanizer 内置转换器的三种形态形态一最小回退实现 DefaultNumberToWordsConverterDefaultNumberToWordsConverter.cs 是最简实现当某语言没有专门的字词渲染规则时它直接委托 .NET 框架的区域性数字格式化器输出public override string Convert(long number) number.ToString(culture); public override string ConvertToOrdinal(int number) number.ToString(culture);见 DefaultNumberToWordsConverter.cs。它保证任何区域性都能返回一个合理结果是契约完整性的兜底。形态二族化组合器以 TriadScale 为例在src/Humanizer/Localisation/NumberToWords/目录下共有 40 余个转换器实现如 ConjunctionalScaleNumberToWordsConverter.cs、EastSlavicNumberToWordsConverter.cs、IndianGroupingNumberToWordsConverter.cs 等按语言的数词组合结构划分为三进制triad连词量级印度分组东斯拉夫变格等族。这些实现以不可变的Profile记录词表 规则驱动例如TriadScaleNumberToWordsConverter的 Profile 包含零词、负号词、十的词干、序数后缀、百/十/个位映射与降序量级表见 TriadScaleNumberToWordsConverter.cs。其序数转换逻辑TriadScaleNumberToWordsConverter.cs也很有代表性个位数直接查OrdinalUnderTen表并附加性别后缀末两位为 10 时把词尾替换为TenOrdinalStem否则剥去最后一个字符、做词干元音恢复、应用精确量级序数变换最后追加CommonOrdinalStem与性别后缀——可见序数词并非简单地在基数词后拼 th而是随语言形态变化的词干改写过程。形态三数据驱动生成从仓库结构可以推断各语言的词表与规则数据存放于 src/Humanizer/Locales/ 下的*.yml如 en.yml、ru.yml而 Humanizer.SourceGenerators 项目在编译期把这些数据生成注册代码NumberToWordsProfileCatalog及...RegistryRegistrations。这意味着多数语言无需手写转换器类修改 yml 数据并经源生成器重新编译即可接入新语言INumberToWordsConverter的族化组合器则负责把数据翻译为实际输出。如何自定义 INumberToWordsConverter 并接入 Humanizer若目标语言不在内置支持列表中或需要覆盖某语言的特殊规则可按以下步骤接入第一步实现接口注意两个内部基类GenderlessNumberToWordsConverter、GenderedNumberToWordsConverter均为internal外部使用者不能直接继承因此需要直接实现公开接口。以 2.10.1 的 5 方法契约为最小集示例骨架如下public sealed class MyNumberToWordsConverter : INumberToWordsConverter { public string Convert(long number) Convert(number, GrammaticalGender.Masculine); public string Convert(long number, bool addAnd) Convert(number, GrammaticalGender.Masculine, addAnd); public string Convert(long number, GrammaticalGender gender, bool addAnd true) { // 在这里实现目标语言的基数词规则 // 拆分量级 - 查词表 - 按 addAnd 决定是否插入连词 - 处理负数前缀 return /* 目标语言文字 */; } public string ConvertToOrdinal(int number) ConvertToOrdinal(number, GrammaticalGender.Masculine); public string ConvertToOrdinal(int number, GrammaticalGender gender) { // 实现序数词规则词干改写 性别后缀 return /* 目标语言序数词文字 */; } }若针对当前版本源码还需补齐WordForm相关重载与ConvertToTuple无特殊需要时委托给核心方法即可可参考 GenderlessNumberToWordsConverter.cs 的默认转发模式。第二步注册到 Configurator在应用启动阶段任何ToWords调用之前执行Configurator.NumberToWordsConverters.Register(my-LC, new MyNumberToWordsConverter());Register接受区域性代码字符串见 LocaliserRegistry.cs。注册后my-LC及其未单独注册的子文化都会通过父文化链命中该实现。第三步用测试验证行为Humanizer 的测试体系如 NumberToWordsTests.cs以[Theory]/[InlineData]驱动覆盖基数词、序数词、连词开关与多语言输出。自定义转换器同样建议用这类数据驱动测试锁定输出例如参照 ToWordsLong 与 ToWordsWithoutAnd 的写法验证addAnd两种开关路径。测试与验证行为契约的可信依据接口的语义最终由测试固化。在 NumberToWordsTests.cs 中可找到直接支撑上文各结论的用例英语序数词0→zeroth、21→twenty-first、112→hundred and twelfth、1000000→millionthL4-L49英语基数词-1→minus one、122→one hundred and twenty-two、1234567890→one billion two hundred and thirty-four million five hundred and sixty-seven thousand eight hundred and ninetyL188-L221long 大数1111111111111111111L→one quintillion one hundred and eleven quadrillion …L223-L245多语言显式区域性阿拉伯语22→اثنان و عشرون、俄语40→сорок、克罗地亚语1021→tisuću dvadeset jedan、泰米尔语555→ஐந்நூற்று ஐம்பத்து ஐந்துL124-L133序数词多语言阿拉伯语21→الحادي و العشرون、俄语1112→одна тысяча сто двенадцатыйL51-L56。这些用例直接验证了Convert与ConvertToOrdinal在真实语言上的输出也是实现自定义转换器时最值得对照的行为基准。小结INumberToWordsConverter是 Humanizer 数字本地化能力的核心扩展点它用 5 个核心方法当前版本已扩展至 11 个定义了数字 → 本地化基数词/序数词的完整契约通过Configurator.NumberToWordsConverters注册表按区域性解析并遵循精确匹配 → 父文化回退 → 默认英语的解析链内置实现则以无性别/有性别两个内部基类组织重载转发以数据驱动的族化组合器承载具体语言规则。理解这份契约既有助于精准使用ToWords()/ToOrdinalWords()的重载参数addAnd、GrammaticalGender也为接入自定义语言提供了清晰的实现与注册路径。赞分享开发工具【免费下载链接】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点击查看免费下载相关推荐Humanizer IStringTransformer 接口全解析字符串转换契约、内置实现与自定义管线Humanizer IStringTransformer 接口全解析字符串转换契约、内置实现与自定义管线 IStringTransformer 是 Human开发工具Humanizer 的 INumberToWordsConverter深入解析数字转单词的多语言转换接口Humanizer 的 INumberToWordsConverter深入解析数字转单词的多语言转换接口 导读 INumberToWordsConverter开发工具memU bridging 任务跑过却没有产生记忆如何按 prepare、jobs、commit 顺序检查memU bridging 任务跑过却没有产生记忆如何按 prepare、jobs、commit 顺序检查 memU 的 Codex 适配器通过一个计划任务开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表