开发工具【免费下载链接】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 3.x 版本 API 文档中的IFormatter接口原文档为主体结合仓库内src/Humanizer的源码实现系统讲解该接口的完整方法契约、参数语义、默认实现原理以及如何通过Configurator与LocaliserRegistry注册自定义格式化器。读完本文你将掌握 Humanizer 本地化格式化体系的内部结构并能独立为缺少内置支持的语种编写、注册与测试IFormatter实现。为什么需要 IFormatter复数与语法规则差异的抽象Humanizer 负责把数字、日期、时间跨度、数据单位等值转换为人类可读的字符串。不同语言处理“数量 单位”的方式差异巨大远不止加不加s这么简单罗马尼亚语中 “5 days” 是 “5 zile”而 “24 days” 是 “24 de zile”需要根据数值决定是否插入介词de阿拉伯语中 “2 days” 是双数形式يومين而不是2 يوم俄语、波兰语、斯洛文尼亚语等语言还存在 paucal少数、dual双数、many多数等额外的语法数范畴。IFormatter正是为此设计的抽象层。接口的定义位于 src/Humanizer/Localisation/Formatters/IFormatter.cs其职责注释明确写着Localizes Humanizers number, date, duration, and unit formatting.它把“如何用某种语言表达某个时间单位/数据单位”的规则全部封装为一个契约使上层扩展方法如Humanize、TimeSpanHumanize、ToSymbol不关心具体语言的语法细节只面向接口编程。接口的派生类型为DefaultFormatter完整实现见 src/Humanizer/Localisation/Formatters/DefaultFormatter.cs它是所有语言格式化器的基类下面逐一拆解其成员。接口成员全解IFormatter共声明 8 个方法覆盖四类场景相对日期、时间跨度时长、数据单位、时间单位符号。接口定义如下public interface IFormatter { string DateHumanize_Now(); string DateHumanize_Never(); string DateHumanize(TimeUnit timeUnit, Tense timeUnitTense, int unit); string TimeSpanHumanize_Zero(); string TimeSpanHumanize(TimeUnit timeUnit, int unit, bool toWords false); string TimeSpanHumanize_Age(); string DataUnitHumanize(DataUnit dataUnit, double count, bool toSymbol true); string TimeUnitHumanize(TimeUnit timeUnit); }所有方法返回string即某种语言下的最终可读文本。方法命名中的_Now、_Never、_Zero、_Age等后缀用于区分类似但语义不同的短语如“现在”与“从未”、“0 秒”与“年龄后缀”避免与带参数的DateHumanize/TimeSpanHumanize重载冲突。相对日期短语DateHumanize 家族方法签名语义DateHumanize_Nowstring DateHumanize_Now()返回“此刻/现在”的本地化文本如英文nowDateHumanize_Neverstring DateHumanize_Never()返回“从未发生”的本地化文本如英文neverDateHumanizestring DateHumanize(TimeUnit timeUnit, Tense timeUnitTense, int unit)返回指定时间单位、时态与数量的相对日期短语其中DateHumanize的三个参数含义如下timeUnitTimeUnit枚举src/Humanizer/Localisation/TimeUnit.cs取值包括Millisecond、Second、Minute、Hour、Day、Week、Month、YeartimeUnitTenseTense枚举src/Humanizer/Localisation/Tense.csFuture表示“in 2 days”这类未来表达Past表示“2 days ago”这类过去表达unit单位数量用于驱动单数/双数/复数等语法形态的选择。从源码看DateHumanize_Never被空值日期的Humanize扩展直接调用。在 src/Humanizer/DateHumanizeExtensions.cs 中DateTime?为null时通过Configurator.GetFormatter(culture).DateHumanize_Never()返回never或对应语言的等价文本。DateHumanize的默认实现会先在短语表中查“count 0 即 now”的情况再处理single数量为 1、two模板阿拉伯语“前天/后天”类特殊双数表达与multiple其余数量分支详见 DefaultFormatter.cs。时间跨度短语TimeSpanHumanize 家族方法签名语义TimeSpanHumanize_Zerostring TimeSpanHumanize_Zero()返回零时长文本如英文0 secondsTimeSpanHumanizestring TimeSpanHumanize(TimeUnit timeUnit, int unit, bool toWords false)返回时长短语toWords为true时数字转英文单词TimeSpanHumanize_Agestring TimeSpanHumanize_Age()返回“年龄后缀”格式字符串英文为{0} oldTimeSpanHumanize的参数中toWords控制数字的呈现形式。默认实现中toWords为真时会优先选择SingleWordsVariant/MultipleWordsVariant词形变体并把计数交给NumberToWords(unit, number, Culture)转成单词DefaultFormatter.cs。TimeSpanHumanize_Age的设计很巧妙它返回一个带占位符的格式模板而不是完整句子。英文返回{0} old于是 “40 years” 可以被拼装成 “40 years old”。源码实现为phraseTable.TimeSpanAge ?? {0}DefaultFormatter.cs默认回退为原样输出。数据单位DataUnitHumanizestring DataUnitHumanize(Humanizer.DataUnit dataUnit, double count, bool toSymbol true);dataUnitDataUnit枚举src/Humanizer/Localisation/DataUnit.cs涵盖Bit、Byte、Kilobyte…Exabyte等十进制单位Pebibyte、Kibibyte…Tebibyte等二进制 IEC 单位以及DecimalKilobyte…DecimalExabyte、BinaryKibibyte…BinaryPebibyte等显式单位系统取值count单位数量用于调整单复数形态toSymboltrue时返回符号如KB、MiBfalse时返回完整单词如kilobyte。该方法是数据大小格式化ByteSize系列多语言化的关键入口。默认实现会优先查短语表当目标语言缺少Petabyte、Exabyte及各种二进制单位短语时会回退到内置英文DefaultFormatterDefaultFormatter.cs。时间单位符号TimeUnitHumanizestring TimeUnitHumanize(Humanizer.TimeUnit timeUnit);返回给定时间单位的本地化符号如英文的ms、s、min、h、d、w、M、y。它是TimeSpanHumanize中toSymbols场景秒的符号化表达的底层支撑同时被TimeUnitToSymbolExtensions使用。默认实现剖析DefaultFormatter 与短语表机制DefaultFormatter是IFormatter的唯一直接派生类型Formatters 目录。它的构造器接受CultureInfo或 localeCode 字符串并解析生成好的LocalePhraseTableDefaultFormatter.cspublic DefaultFormatter(CultureInfo culture) { Culture culture; phraseTable LocalePhraseTableCatalog.Resolve(culture) ?? throw new InvalidOperationException(The generated locale phrase tables are missing the required English fallback.); } public DefaultFormatter(string localeCode) : this(new CultureInfo(localeCode)) { }关键点短语表由源码生成器生成各语言短语来自src/Humanizer/Locales/*.yml如 ar.yml、en.yml经Humanizer.SourceGenerators编译为LocalePhraseTable运行时“分支少、无需解析”每个短语含多种形态single、dual、paucal、plural、default等LocalizedPhraseForms字段以及countPlacement数字放在单位前/后/不出现、beforeCountText/afterCountText、template如阿拉伯语“two”模板等结构兜底英文即使某个语种缺短语也会回退英文EnglishFallback见 DefaultFormatter.cs。以阿拉伯语为例ar.yml 中relativeDate.past.second定义了second: single: منذ ثانية واحدة multiple: countPlacement: none forms: default: منذ {count} ثانية singular: منذ ثانيتين dual: منذ ثانيتين paucal: منذ ثانيتين plural: منذ {count} ثوان可见阿拉伯语的“2 秒”直接使用双数短语منذ ثانيتين而非拼接数字这正是IFormatter要抽象出的语言差异。ProfiledFormatter声明式规则内核仓库中还存在一个DefaultFormatter的变体ProfiledFormattersrc/Humanizer/Localisation/Formatters/ProfiledFormatter.cs它从 YAML 中的formatter段读取声明式规则支持多种复数检测器FormatterNumberDetectorKind枚举定义了SingularPlural、ArabicLike、ArabicCardinal、Between2And4Paucal、Polish、SouthSlavic、Slovenian、Russian、Lithuanian等形态检测算法ProfiledFormatter.cs精确数字覆盖规则FormatterDateFormRule/FormatterTimeSpanFormRule允许为特定数字指定形态如俄语21, 31…单数、2-4, 22-24…paucal语言特殊处理罗马尼亚语de介词插入ShouldUseRomanianPreposition当numeral % 100为 0 或大于 19 时插入、卢森堡语 Eifeler 规则后缀n、拉脱维亚语回退变形等单位性别UnitGenders使数字转单词时带上语法性别。YAML 中的 formatter 配置形如ar.ymlformatter: engine: profiled dataUnitFallbackTransform: trim-trailing-s pluralRule: arabic-like casePluralRule: arabic-cardinal由此可推断ProfiledFormatter是DefaultFormatter针对“可由声明式规则表达”的语言提供的统一实现新增语种通常只需在 YAML 中补充短语与规则无需手写 C# 类。注册与解析机制Configurator LocaliserRegistryIFormatter的实例由Configurator.Formatters注册表统一管理src/Humanizer/Configuration/Configurator.cspublic static LocaliserRegistryIFormatter Formatters { get; } new FormatterRegistry();FormatterRegistrysrc/Humanizer/Configuration/FormatterRegistry.cs以DefaultFormatter为默认工厂然后通过源码生成器批量注册各语种的实现class FormatterRegistry : LocaliserRegistryIFormatter { public FormatterRegistry() : base(c new DefaultFormatter(c)) FormatterRegistryRegistrations.Register(this); }LocaliserRegistryTLocalisersrc/Humanizer/Configuration/LocaliserRegistry.cs提供了解析与注册能力ResolveForCulture(CultureInfo? culture)按当前线程文化或指定文化解析格式化器首次使用时将注册表“冻结”为FrozenDictionary以获得更好的读性能并用ConditionalWeakTable做按文化的实例缓存LocaliserRegistry.csRegister(localeCode, localiser)/Register(localeCode, factory)注册自定义格式化器。注意注册表被使用冻结后不能再注册会抛出InvalidOperationExceptionLocaliserRegistry.cs解析时按culture → culture.Parent链向上回退最后落到默认格式化器LocaliserRegistry.cs。上层扩展方法通过Configurator.GetFormatter(culture)获取当前文化的IFormatterConfigurator.csculture为null时使用当前线程文化。DateHumanizeExtensions中的调用链即为典型示例// DateHumanizeExtensions.cs return Configurator .GetFormatter(culture) .DateHumanize_Never();自定义 IFormatter 实战指南当目标语言无法用 YAML 声明式规则表达或需要完全自控输出时可自行实现IFormatter1. 定义实现类继承DefaultFormatter推荐可复用短语表机制与英文回退或直接实现IFormatter全部 8 个方法。若希望支持语法格grammatical case感知的时长短语还应实现可选接口IGrammaticalCaseTimeSpanFormattersrc/Humanizer/Localisation/Formatters/IGrammaticalCaseTimeSpanFormatter.cs它额外声明string TimeSpanHumanize(TimeUnit timeUnit, int unit, GrammaticalCase grammaticalCase);从DefaultFormatter的显式实现可以看出自定义类型若要启用语法格时长必须显式实现该接口否则会抛出NotSupportedExceptionDefaultFormatter.cs。2. 在应用启动时注册由于注册表一旦使用即被冻结注册必须发生在任何 Humanizer 调用之前应用启动阶段或ModuleInitializer中Configurator.Formatters.Register(xx-YY, new MyFormatter(new CultureInfo(xx-YY)));3. 验证解析通过Configurator.Formatters.ResolveForCulture(new CultureInfo(xx-YY))确认返回的是自定义实例未注册的文化会沿父文化链回退到DefaultFormatter。测试与验证仓库测试目录 tests/Humanizer.Tests 中与IFormatter直接相关的验证包括FormatterExactOutputTests.cs针对各语种格式化输出做精确断言Localisation子目录下每个语种文件夹的测试类如ar/、ru/逐一验证该语言DateHumanize、TimeSpanHumanize等方法的输出LocaliserRegistryTests.cs验证注册表解析、回退与注册机制。编写自定义IFormatter时可参照这些测试的模式用UseCulture特性tests/Humanizer.Tests/UseCultureAttribute.cs切换线程文化后断言输出文本。小结IFormatter是 Humanizer 本地化体系的枢纽契约它以 8 个方法覆盖相对日期、时长、年龄后缀、数据单位与时间单位符号五类输出DefaultFormatter提供了基于生成短语表的默认实现ProfiledFormatter进一步以声明式规则表达各语言的复数、介词、性别等特殊语法而Configurator.Formatters注册表则负责按文化解析与自定义扩展。理解这一契约即可把 Humanizer 的本地化能力延伸到任意语言场景。赞分享开发工具【免费下载链接】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 本地化格式化核心IFormatter 接口与 DefaultFormatter 实现深度解析Humanizer 本地化格式化核心IFormatter 接口与 DefaultFormatter 实现深度解析 本指南围绕 Humanizer 的 Huma开发工具Humanizer 本地化格式化核心接口 IFormatter 完全解析多语言日期、时长与数据单位的可扩展格式化契约Humanizer 本地化格式化核心接口 IFormatter 完全解析多语言日期、时长与数据单位的可扩展格式化契约 IFormatter 是 Humaniz开发工具Humanizer IFormatter 接口深度解析多语言日期、时间跨度与数据单位的本地化格式化Humanizer IFormatter 接口深度解析多语言日期、时间跨度与数据单位的本地化格式化 IFormatter 是 Humanizer 本地化体系中开发工具上一篇vit_large_patch16_384.augreg_in21k_ft_in1k源码解析从论文到PyTorch实现的完整解读下一篇Pinpoint 的 Reactor Netty 插件Netty 响应式 HTTP 服务端与客户端全链路追踪实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考