开发工具【免费下载链接】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 是一个面向 .NET 的字符串、枚举、日期、时间、数字与数量处理库其中“数字转本地化文字”是最常用也最具跨语言差异性的能力之一。本文以Humanizer.Localisation.NumberToWords命名空间及核心契约 INumberToWordsConverter 为主线完整梳理该接口的全部方法签名、参数语义、默认实现、注册与解析机制并结合仓库内数十个语种转换器与测试用例说明如何为自定义语言实现一个可用的数字转文字转换器。接口定位本地化 ToWords 与 ToOrdinalWords 的唯一扩展点在 Humanizer 中把数字123输出为英文 one hundred and twenty-three、把1输出为序数 first或者把3输出为 third都经由NumberToWordsExtension提供的ToWords()、ToOrdinalWords()、ToTuple()等扩展方法完成。这些扩展方法本身并不直接实现转换逻辑而是委托给一个按文化culture解析出来的转换器对象public static string ToWords(this long number, CultureInfo? culture null, bool addAnd true) Configurator.GetNumberToWordsConverter(culture).Convert(number, addAnd);这段代码位于 src/Humanizer/NumberToWordsExtension.cs。而Configurator.GetNumberToWordsConverter内部从 Configurator.NumberToWordsConverters 注册表中按文化解析转换器internal static INumberToWordsConverter GetNumberToWordsConverter(CultureInfo? culture) NumberToWordsConverters.ResolveForCulture(culture);见 src/Humanizer/Configuration/Configurator.cs。因此INumberToWordsConverter就是整个“数字转文字”子系统对外的唯一契约也是接入新语言的唯一扩展点只要实现该接口并通过注册表绑定到对应 locale即可让ToWords()等扩展方法自动使用你的实现。接口契约全景八个方法、三类能力INumberToWordsConverter定义于 src/Humanizer/Localisation/NumberToWords/INumberToWordsConverter.cs语义上分为三大类能力1. 基数词转换Convert(long) 系列方法签名语义关键参数string Convert(long number)使用该 locale 的默认语法性别grammatical gender输出基数词number要转换的整数string Convert(long number, bool addAnd)使用默认性别并按开关决定是否在复合数中插入本地化连接词如英文的 andaddAnd是否插入连接词string Convert(long number, GrammaticalGender gender, bool addAnd true)使用调用方指定的语法性别输出并控制连接词genderGrammaticalGender 枚举Masculine / Feminine / NeuteraddAnd默认值为true原始 API 文档明确描述了这三个重载的行为第一个重载“使用 locale 默认语法性别”第二个“按是否加 And 输出”第三个“使用提供的语法性别”其中addAnd的默认值为true。从当前仓库接口定义看INumberToWordsConverter.cs现代版本还在此基础上扩展了WordForm与bool/WordForm组合重载用于处理同一数字在不同句式中的形态变化见下文“词形与性别”一节但文档所记载的三个核心重载始终保留且addAnd默认true的语义不变。2. 序数词转换ConvertToOrdinal(int) 系列方法签名语义string ConvertToOrdinal(int number)使用 locale 默认语法性别输出序数词如英文 1 → firststring ConvertToOrdinal(int number, GrammaticalGender gender)使用指定语法性别输出序数词注意序数重载的入参类型是int而非long这是 Humanizer 有意为之的设计序数词在日常生活中通常只涉及较小的整数范围且多数语言对较大序数的表达并不自然。3. 元组名词转换ConvertToTuple(int)ConvertToTuple(int number)将整数转换为 locale 化的具名元组词例如英文中 1 → single、2 → double、3 → triple、100 → centuple、1000 → milluple。该能力对应扩展方法 ToTuple()测试覆盖见 tests/Humanizer.Tests/NumberToWordsTests.cs。当 locale 未定义元组名词时接口文档说明其会回退到数值形式。参数语义速查numberlong/int待转换的整数基数词支持long范围序数与元组限定int。genderGrammaticalGender取值Masculine、Feminine、Neuter定义见 src/Humanizer/GrammaticalGender.cs。仅对区分性别的语言生效无性别概念的语言可忽略。addAndbool默认 true控制复合数中是否插入 locale 特有连接词。英文典型输出为 one hundred and twenty-threetrue与 one hundred twenty-threefalse之别。深入扩展点WordForm 与 GrammaticalGender 如何影响输出词形WordForm解决“同一个数字在不同句式中的拼写差异”WordForm枚举定义于 src/Humanizer/WordForm.cs包含三个值Normal单词的常规形式Abbreviation单词的缩写形式Eifeler遵循 Eifeler 规则的形式卢森堡语特有拼写规则。典型场景是西班牙语中“以 1 结尾的数字”在修饰名词与独立使用时拼写不同。扩展方法注释中给出的示例src/Humanizer/NumberToWordsExtension.cs21.ToWords(WordForm.Normal) // - veintiuno 如 Mi número favorito es el veintiuno 21.ToWords(WordForm.Abbreviation) // - veintiún 如 En total, conté veintiún coches序数同理西班牙语中 tercer/tercera 因性别与词形而变src/Humanizer/NumberToWordsExtension.cs3.ToOrdinalWords(GrammaticalGender.Masculine, WordForm.Normal) // - tercero 3.ToOrdinalWords(GrammaticalGender.Masculine, WordForm.Abbreviation) // - tercer 3.ToOrdinalWords(GrammaticalGender.Feminine, WordForm.Normal) // - tercera语法性别GrammaticalGender俄语、希伯来语的阴阳性差异GrammaticalGender定义于 src/Humanizer/GrammaticalGender.cs为Masculine、Feminine、Neuter三值枚举。对俄语与希伯来语等区分阴阳性的语言同一个数字 1 在不同性别下拼写不同示例同样记录在扩展方法注释中// 俄语 1.ToWords(GrammaticalGender.Masculine) // - один 1.ToWords(GrammaticalGender.Feminine) // - одна // 希伯来语 1.ToWords(GrammaticalGender.Masculine) // - אחד 1.ToWords(GrammaticalGender.Feminine) // - אחת注册与解析机制Configurator 与 LocaliserRegistry 如何工作注册表按 locale 检索转换器Configurator.NumberToWordsConverters是一个LocaliserRegistryINumberToWordsConverter类型的公开静态属性src/Humanizer/Configuration/Configurator.cs其默认实例为 NumberToWordsConverterRegistry。该类将默认转换器指定为英文en并在构造时通过源码生成器生成的注册方法批量注册各语种转换器class NumberToWordsConverterRegistry : LocaliserRegistryINumberToWordsConverter { public NumberToWordsConverterRegistry() : base(_ NumberToWordsProfileCatalog.Resolve(en, CultureInfo.InvariantCulture)) NumberToWordsConverterRegistryRegistrations.Register(this); }解析流程精确匹配 → 父文化回退 → 默认值LocaliserRegistryTLocaliser的解析逻辑位于 src/Humanizer/Configuration/LocaliserRegistry.cs核心流程为若指定了 culture则使用该 culture否则使用当前线程的CultureInfo.CurrentCulture从fr-CH这类完整 locale 名称开始先尝试精确匹配注册项若未命中沿文化层级逐级向父文化回退如fr-CH→fr全部未命中则返回注册表默认值英文转换器。测试用例对上述行为做了系统验证tests/Humanizer.Tests/Localisation/LocaliserRegistryTests.cs精确 locale 优先于父 localeResolveForCulturePrefersExactLocaleOverParentLocale、无匹配时回退默认ResolveForCultureFallsBackToDefaultWhenNoLocaleMatches。此外注册表在首次被解析后会被冻结冻结后再调用Register会抛出InvalidOperationExceptionRegisterInstanceThrowsAfterRegistryHasBeenUsed因此自定义注册必须发生在首次调用任何ToWords()之前例如应用启动阶段或ModuleInitializer中。文化感知的默认实现对未注册专门转换器的 locale注册表默认使用 DefaultNumberToWordsConverter。该实现刻意保持最小Convert与ConvertToOrdinal都直接委托给框架的文化感知数字格式化器number.ToString(culture)即输出12345而非 twelve thousand three hundred forty-five。这保证了任何文化下扩展方法都不会抛异常只是退化为数字字符串。从基类到语种实现仓库中的转换器谱系NumberToWords目录src/Humanizer/Localisation/NumberToWords下共有约 40 个转换器文件其中多数是针对特定语言的专门实现。它们的公共祖先与架构可以归纳为两条主线无性别语言GenderlessNumberToWordsConverter对不存在语法性别概念的语言如英语、汉语以 GenderlessNumberToWordsConverter 为基类。它把Convert(long, GrammaticalGender, bool)与ConvertToOrdinal(int, GrammaticalGender)等性别感知方法直接降级为忽略性别的简单重载派生类只需实现最少的纯数字逻辑。有性别语言GenderedNumberToWordsConverter对俄语、西班牙语、希伯来语等区分性别的语言以 GenderedNumberToWordsConverter 为基类。其关键设计是构造时接收默认性别参数默认Masculine所有不带性别参数的重载如Convert(long)都路由到带默认性别的重载派生类只需覆写真正随性别变化的两个抽象成员Convert(long, GrammaticalGender, bool)与ConvertToOrdinal(int, GrammaticalGender)词形WordForm与元组Tuple方法提供 virtual 默认实现未覆写时自动回退到性别感知的基数/序数转换。public string Convert(long number) Convert(number, defaultGender); public abstract string Convert(long number, GrammaticalGender gender, bool addAnd true); public abstract string ConvertToOrdinal(int number, GrammaticalGender gender);见 src/Humanizer/Localisation/NumberToWords/GenderedNumberToWordsConverter.cs。这一“默认性别下沉 最小抽象面”的设计使一个 40 文件的目录得以覆盖 120 语言区域多数语言仅需实现几个关键方法其余重载自动获得一致行为。实战如何为自定义语言实现 INumberToWordsConverter综合接口契约、基类设计与注册机制接入一门新语言的完整步骤如下第 1 步继承基类实现核心方法优先选择与目标语言语法匹配的基类// 无语法性别的语言 public sealed class MyLanguageNumberToWordsConverter : GenderlessNumberToWordsConverter { public override string Convert(long number) { /* 实现基数词 */ } public override string ConvertToOrdinal(int number) { /* 实现序数词 */ } } // 有语法性别的语言 public sealed class MyLanguageNumberToWordsConverter : GenderedNumberToWordsConverter { public MyLanguageNumberToWordsConverter() : base(GrammaticalGender.Masculine) { } public override string Convert(long number, GrammaticalGender gender, bool addAnd true) { /* ... */ } public override string ConvertToOrdinal(int number, GrammaticalGender gender) { /* ... */ } }也可以直接实现 INumberToWordsConverter 接口本身此时需要按前文表格补齐全部八个方法。第 2 步通过 Configurator 注册到对应 localeConfigurator.NumberToWordsConverters.Register(my-LC, new MyLanguageNumberToWordsConverter());也可注册工厂委托以便按具体 culture 生成实例Configurator.NumberToWordsConverters.Register(my-LC, culture new MyLanguageNumberToWordsConverter(culture));注册表 API 定义见 src/Humanizer/Configuration/LocaliserRegistry.cs。第 3 步在应用启动早期完成注册由于注册表在首次解析后即被冻结注册动作必须发生在任何ToWords()/ToOrdinalWords()/ToTuple()调用之前推荐放在Main入口或[ModuleInitializer]中。第 4 步验证与测试注册完成后即可通过扩展方法直接调用Console.WriteLine(1234.ToWords(new CultureInfo(my-LC))); // 基数词 Console.WriteLine(21.ToOrdinalWords(new CultureInfo(my-LC))); // 序数词 Console.WriteLine(3.ToTuple(new CultureInfo(my-LC))); // 元组词参考仓库的测试模式tests/Humanizer.Tests/NumberToWordsTests.cs用[Theory][InlineData]批量断言各数字与预期字符串覆盖个位、复合数、addAnd开关、性别与词形等分支例如俄语序数测试1112.ToOrdinalWords(new CultureInfo(ru))应输出одна тысяча сто двенадцатый。设计要点回顾单一扩展点所有数字转文字功能收敛于INumberToWordsConverter扩展方法只做文化解析与参数透传职责清晰文化感知的参数集GrammaticalGender性别、WordForm词形、addAnd连接词三个维度共同刻画跨语言差异接口为每个维度提供独立重载渐进式实现成本通过GenderlessNumberToWordsConverter/GenderedNumberToWordsConverter两级基类把必须覆写的方法数压缩到最小新语言接入成本显著降低健壮的回退策略解析按“精确 locale → 父文化 → 默认英文/数字格式化”逐级回退未覆盖的语言也能获得可用输出延迟冻结注册表首次使用后冻结字典并缓存解析结果兼顾多线程安全与查询性能src/Humanizer/Configuration/LocaliserRegistry.cs。对于需要在多语言场景下输出数字文字、序数或元组名词的 .NET 应用而言理解INumberToWordsConverter的契约与注册机制就等于掌握了 Humanizer 本地化数字能力的全部钥匙无论是直接消费内置的 120 语言支持还是为小众语言定制转换器都只需围绕这一个接口展开。赞分享开发工具【免费下载链接】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点击查看免费下载相关推荐memU bridging 任务跑过却没有产生记忆如何按 prepare、jobs、commit 顺序检查memU bridging 任务跑过却没有产生记忆如何按 prepare、jobs、commit 顺序检查 memU 的 Codex 适配器通过一个计划任务开发工具Humanizer NumberToWordsExtension 详解用 ToWords 与 ToOrdinalWords 实现本地化数字转文字Humanizer NumberToWordsExtension 详解用 ToWords 与 ToOrdinalWords 实现本地化数字转文字 导读 Num开发工具Humanizer 数字转文字核心接口 INumberToWordsConverter 完全指南本地化基数词、序数词与元组名的统一抽象Humanizer 数字转文字核心接口 INumberToWordsConverter 完全指南本地化基数词、序数词与元组名的统一抽象 Humanizer 是开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
