化(Ordinalize)擴(kuò)展方法完全指南:從 1st/2nd/3rd 到多語言本地化)
開發(fā)工具【免費(fèi)下載鏈接】HumanizerHumanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities項(xiàng)目地址https://gitcode.com/gh_mirrors/hu/Humanizer點(diǎn)擊查看免費(fèi)下載本篇技術(shù)指南以 Humanizer 庫 OrdinalizeExtensions 的 API 參考文檔為主體系統(tǒng)講解如何將數(shù)字轉(zhuǎn)換為序數(shù)形式如1st、2nd、3rd深入剖析其在當(dāng)前倉(cāng)庫中的源碼實(shí)現(xiàn)、語法性別GrammaticalGender支持、區(qū)域性CultureInfo本地化機(jī)制以及 64 位整數(shù)擴(kuò)展。讀完本文你將掌握Ordinalize全系列重載的用法、底層IOrdinalizer插件化架構(gòu)以及如何利用它輸出符合巴西葡萄牙語、西班牙語等語言習(xí)慣的序數(shù)文本。什么是序數(shù)化Ordinalize序數(shù)ordinal number用于表示在有序序列中的位置例如英文中的1st、2nd、3rd、4th。Humanizer 的OrdinalizeExtensions靜態(tài)類為int、long和string類型提供了同名的擴(kuò)展方法Ordinalize用于把一個(gè)數(shù)字變成序數(shù)字符串。它是 Humanizer 眾多人性化字符串功能Humanize、Dehumanize、ToQuantity等中的一員位于 src/Humanizer/OrdinalizeExtensions.cs。public static class OrdinalizeExtensions { public static string Ordinalize(this int number); public static string Ordinalize(this string numberString); // ... 更多重載 }根據(jù) src/Humanizer/OrdinalizeExtensions.cs 中的類注釋序數(shù)化只接受整數(shù)值如果調(diào)用方持有小數(shù)必須先自行選擇并執(zhí)行顯式的取整與類型轉(zhuǎn)換策略再調(diào)用Ordinalize?;A(chǔ)用法int 與 string 兩個(gè)入口原 API 文檔列出兩類接收者receiver的Ordinalize重載int與string。兩者在語義上等價(jià)——將數(shù)字轉(zhuǎn)為序數(shù)文本區(qū)別僅在于輸入類型。方法簽名參數(shù)說明返回string Ordinalize(this int number)number要被序數(shù)化的整數(shù)stringstring Ordinalize(this string numberString)numberString以字符串形式表示的數(shù)字string從源碼看int重載的默認(rèn)實(shí)現(xiàn)OrdinalizeExtensions.cs會(huì)委托給帶CultureInfo的重載public static string Ordinalize(this int number) number.Ordinalize(CultureInfo.CurrentCulture);而string重載OrdinalizeExtensions.cs則直接調(diào)用全局默認(rèn)序數(shù)化器public static string Ordinalize(this string numberString) Configurator.Ordinalizer.Convert(int.Parse(numberString), NormalizeOrdinalNumberString(numberString));即先通過int.Parse把字符串解析為整數(shù)再交給配置好的IOrdinalizer完成轉(zhuǎn)換。在英文環(huán)境下實(shí)際輸出由英語序數(shù)化器基于ModuloSuffixOrdinalizer的取模后綴規(guī)則決定1.Ordinalize(); // 1st 2.Ordinalize(); // 2nd 3.Ordinalize(); // 3rd 4.Ordinalize(); // 4th 11.Ordinalize(); // 11th —— 注意不是 11st 21.Ordinalize(); // 21st 101.Ordinalize(); // 101st這些結(jié)果與測(cè)試用例 tests/Humanizer.Tests/OrdinalizeTests.cs 中的[InlineData]斷言完全一致例如1 → 1st、11 → 11th、21 → 21st、101 → 101st。語法性別GrammaticalGender參數(shù)原文檔明確指出Ordinalize的多個(gè)重載接受Humanizer.GrammaticalGender參數(shù)并特別強(qiáng)調(diào)其用于**巴西葡萄牙語Brazilian Portuguese**區(qū)域1.Ordinalize(GrammaticalGender.Masculine) - 1o 1.Ordinalize(GrammaticalGender.Feminine) - 1aGrammaticalGender是一個(gè)三值枚舉src/Humanizer/GrammaticalGender.csMasculine陽性Feminine陰性Neuter中性// 巴西葡萄牙語 1.Ordinalize(GrammaticalGender.Masculine); // 1o 1.Ordinalize(GrammaticalGender.Feminine); // 1a 1.Ordinalize(GrammaticalGender.Masculine); // 1o 1.Ordinalize(GrammaticalGender.Feminine); // 1a源碼中性別相關(guān)的重載OrdinalizeExtensions.cs會(huì)將參數(shù)透?jìng)鹘oIOrdinalizer.Convert(int, string, GrammaticalGender)而巴西葡萄牙語的序數(shù)化器正是基于 SuffixOrdinalizer 實(shí)現(xiàn)——該類接收三個(gè)性別后綴并在Convert中按性別選擇后綴SuffixOrdinalizer.csreturn numberString gender switch { GrammaticalGender.Feminine feminineSuffix, // a GrammaticalGender.Neuter neuterSuffix, _ masculineSuffix // o };CultureInfo 參數(shù)與本地化機(jī)制原文檔中多個(gè)重載接受System.Globalization.CultureInfo culture參數(shù)其語義為指定用于序數(shù)化的區(qū)域性若傳入null則使用當(dāng)前線程的 UI 文化current threads UI culture。從實(shí)現(xiàn)看culture為null時(shí)實(shí)際回落邏輯OrdinalizeExtensions.cs為var resolvedCulture culture ?? CultureInfo.CurrentCulture; return Configurator.Ordinalizers.ResolveForCulture(culture) .Convert(ParseOrdinalNumber(numberString, resolvedCulture), ...);這里的關(guān)鍵是Configurator.Ordinalizers—— 一個(gè)LocaliserRegistryIOrdinalizer類型的注冊(cè)表src/Humanizer/Configuration/Configurator.cs。它由 OrdinalizerRegistry 構(gòu)建默認(rèn)回退到DefaultOrdinalizer原樣返回輸入文本隨后通過源代碼生成器Source Generator按 locale 注冊(cè)各語言的專用序數(shù)化器。DefaultOrdinalizersrc/Humanizer/Localisation/Ordinalizers/DefaultOrdinalizer.cs本身是一個(gè)什么都不做的基類public virtual string Convert(long number, string numberString) numberString;各區(qū)域語言通過繼承它來覆蓋行為。從 OrdinalizerProfileCatalogInput.cs 可見源生成器支持三種序數(shù)化器類型suffix固定性別后綴如巴西葡萄牙語的o/a對(duì)應(yīng)SuffixOrdinalizermodulo-suffix按數(shù)字取模規(guī)則選擇后綴如英語的st/nd/rd/th對(duì)應(yīng) ModuloSuffixOrdinalizernumber-word-suffix基于數(shù)字單詞的后綴形式。以英語為例ModuloSuffixOrdinalizer的后綴選擇遵循嚴(yán)格優(yōu)先級(jí)ModuloSuffixOrdinalizer.cs先檢查最后兩位數(shù)區(qū)間規(guī)則再查精確數(shù)值映射然后查后兩位后綴表最后回退到末位數(shù)字后綴表與默認(rèn)后綴。這正是11th、12th、13th不同于1st、2nd、3rd的底層原因11-13的末位1、2、3被精確映射覆蓋為th。顯式指定文化的示例// 指定文化與當(dāng)前線程文化無關(guān) 1.Ordinalize(new System.Globalization.CultureInfo(pt-BR), Humanizer.GrammaticalGender.Feminine); // 1a 1.Ordinalize(new System.Globalization.CultureInfo(en-US)); // 1st文化相關(guān)的數(shù)字格式化細(xì)節(jié)Ordinalize在內(nèi)部還會(huì)根據(jù)文化格式化數(shù)字本身OrdinalizeExtensions.cs對(duì)正數(shù)若該文化的NumberFormat.NativeDigits是標(biāo)準(zhǔn) ASCII 數(shù)字UsesInvariantDigits為true則用不變文化格式化否則使用該文化自身的數(shù)字格式例如某些語言的原生數(shù)字字符。負(fù)數(shù)則額外比對(duì)文化的負(fù)號(hào)與NumberNegativePattern以決定是否直接用不變文化輸出。這些數(shù)字格式化配置按文化名緩存在ConcurrentDictionarystring, OrdinalNumberFormatting中OrdinalizeExtensions.cs避免每次調(diào)用重復(fù)構(gòu)建。全系列重載一覽綜合原 API 文檔與 src/Humanizer/OrdinalizeExtensions.csOrdinalize的完整重載矩陣如下均返回string接收者參數(shù)組合int number()/(WordForm)/(CultureInfo?)/(CultureInfo?, WordForm)/(GrammaticalGender)/(GrammaticalGender, WordForm)/(GrammaticalGender, CultureInfo?)/(GrammaticalGender, CultureInfo?, WordForm)string numberString同上 8 種組合long number同上 8 種組合其中WordForm用于區(qū)分縮寫與完整詞形。例如西班牙語源碼注釋中的示例OrdinalizeExtensions.cs1.Ordinalize(WordForm.Abbreviation) - 1.er // 如 Vivo en el 1.er piso我住在一樓 1.Ordinalize(WordForm.Normal) - 1.o // 如 Fui el 1o de mi promoción我是班里第一名 1.Ordinalize(GrammaticalGender.Feminine, WordForm.Normal) - 1.a注意原 API 文檔生成的版本中string接收者僅收錄了int/string兩類long重載在源碼中同樣完整存在OrdinalizeExtensions.cs并通過ILongOrdinalizer接口提供原生 64 位支持詳見下文。底層架構(gòu)IOrdinalizer 與 64 位支持Ordinalize之所以能做到多語言、多形式輸出是因?yàn)樗耆薪o可插拔的序數(shù)化器接口src/Humanizer/Localisation/Ordinalizers/IOrdinalizer.cspublic 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); } public interface ILongOrdinalizer : IOrdinalizer { string Convert(long number, string numberString); // ... 對(duì)應(yīng)的 WordForm / gender 重載 }ILongOrdinalizer用于支持超出int范圍的 64 位值。在long重載的ConvertOrdinalizer輔助方法中OrdinalizeExtensions.cs如果注冊(cè)的序數(shù)化器實(shí)現(xiàn)了ILongOrdinalizer則直接傳入long否則嘗試把值安全收縮到int若超出范圍則拋出NotSupportedException: The registered ordinalizer {type} does not support 64-bit values.這意味著在默認(rèn)的英語環(huán)境下long.MaxValue.Ordinalize()可以正常工作DefaultOrdinalizer及其派生類實(shí)現(xiàn)了ILongOrdinalizer但若你通過 Configurator 注冊(cè)了一個(gè)僅實(shí)現(xiàn)IOrdinalizer的自定義序數(shù)化器超大long值會(huì)拋出上述異?!@是擴(kuò)展自定義序數(shù)化器時(shí)需要注意的邊界。另外string重載在解析與歸一化上做了兩層處理OrdinalizeExtensions.csParseOrdinalNumber按指定文化解析int.Parse(numberString, culture)NormalizeOrdinalNumberString剔除字符串中的 Unicode格式類字符UnicodeCategory.Format如不可見的控制/格式符保證傳入IOrdinalizer的字符串干凈一致。測(cè)試驗(yàn)證與可靠性倉(cāng)庫提供了詳盡的測(cè)試用例來鎖定Ordinalize行為。tests/Humanizer.Tests/OrdinalizeTests.cs 通過[Theory][InlineData]覆蓋了大量輸入-輸出對(duì)例如int系列0→0th、1→1st、2→2nd、3→3rd、4→4th、11→11th、21→21st、101→101st等以及string系列的同構(gòu)斷言。運(yùn)行測(cè)試即可驗(yàn)證dotnet test tests/Humanizer.Tests/Humanizer.Tests.csproj --filter FullyQualifiedName~Ordinalize實(shí)用注意事項(xiàng)小結(jié)只接受整數(shù)Ordinalize的語義限定于整數(shù)值類注釋明確說明見 OrdinalizeExtensions.cs小數(shù)需自行取整后再調(diào)用。culture為null時(shí)按源碼實(shí)現(xiàn)而非原文檔措辭實(shí)際使用CultureInfo.CurrentCulture當(dāng)前線程文化作為回落值。默認(rèn)文化行為int/long的無參數(shù)重載均委托給CultureInfo.CurrentCulture版本因此輸出隨線程當(dāng)前文化變化。性別只對(duì)特定語言生效GrammaticalGender主要影響巴西葡萄牙語1o/1a等區(qū)分性別的語言對(duì)英語等無性別后綴的語言性別參數(shù)通常被忽略SuffixOrdinalizer按性別選擇而英語的ModuloSuffixOrdinalizer不感知性別。自定義序數(shù)化器可通過Configurator.Ordinalizers注冊(cè)新的IOrdinalizer/ILongOrdinalizer實(shí)現(xiàn)來擴(kuò)展若注冊(cè)項(xiàng)僅實(shí)現(xiàn) 32 位接口注意 64 位大數(shù)會(huì)拋NotSupportedException。借助這套 API你可以在極少的代碼量下輸出符合多種語言習(xí)慣的序數(shù)文本——從英文的1st/2nd/3rd/4th到巴西葡萄牙語的1o/1a再到西班牙語的1.er/1.o無需手寫任何規(guī)則分支。贊分享開發(fā)工具【免費(fèi)下載鏈接】HumanizerHumanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities項(xiàng)目地址https://gitcode.com/gh_mirrors/hu/Humanizer點(diǎn)擊查看免費(fèi)下載相關(guān)推薦Humanizer 序數(shù)化擴(kuò)展OrdinalizeExtensions完全指南從 1st/2nd/3rd 到多語言序數(shù)輸出Humanizer 序數(shù)化擴(kuò)展OrdinalizeExtensions完全指南從 1st/2nd/3rd 到多語言序數(shù)輸出 OrdinalizeExten開發(fā)工具Humanizer 序數(shù)化擴(kuò)展OrdinalizeExtensions完全指南從 1st/2nd/3rd 到多語言、多性別的序數(shù)格式化Humanizer 序數(shù)化擴(kuò)展OrdinalizeExtensions完全指南從 1st/2nd/3rd 到多語言、多性別的序數(shù)格式化 Ordinaliz開發(fā)工具Humanizer OrdinalizeExtensions 序數(shù)化完全指南從 1st 到多語言序數(shù)輸出Humanizer OrdinalizeExtensions 序數(shù)化完全指南從 1st 到多語言序數(shù)輸出 導(dǎo)讀 本文以 Humanizer 項(xiàng)目中的 Ordi開發(fā)工具創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考