feat: Add Urdu (ur) language localization#1683
feat: Add Urdu (ur) language localization#1683iamahsanmehmood wants to merge 5 commits intoHumanizr:mainfrom
Conversation
- Resources.ur.resx: 45 Urdu translations for DateHumanize and TimeSpanHumanize - UrduNumberToWordsConverter: South Asian numbering (lakh/crore/arab) - Unique Urdu words for numbers 1-99 with ordinal support - Registered in NumberToWordsConverterRegistry and FormatterRegistry
- DateHumanizeTests: 10 test methods covering all time units (past/future) - TimeSpanHumanizeTests: 9 test methods + NoTime + NoTimeToWords - NumberToWordsTests: 10 test methods covering 0-99, hundreds, thousands, lakhs, crores, arabs, negatives, ordinals
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: db30674307
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
|
||
| if (number < 0) | ||
| { | ||
| return $"منفی {Convert(-number)}"; |
There was a problem hiding this comment.
Guard long.MinValue before negating number
Negating a negative long here is unsafe for long.MinValue: in unchecked arithmetic -long.MinValue stays long.MinValue, so Convert(-number) recurses indefinitely and eventually stack-overflows. Any call like long.MinValue.ToWords() in Urdu will hard-crash instead of returning text.
Useful? React with 👍 / 👎.
src/Humanizer/Localisation/NumberToWords/UrduNumberToWordsConverter.cs
Outdated
Show resolved
Hide resolved
- P1: Guard long.MinValue before negation to prevent infinite recursion - P2: Use recursive Convert() instead of ConvertUpTo99() for group values, preventing IndexOutOfRangeException on very large numbers
There was a problem hiding this comment.
Pull request overview
Adds initial Urdu (ur) localisation support to Humanizer, including resource strings for date/timespan humanization and an Urdu number-to-words converter, with corresponding localisation tests.
Changes:
- Added Urdu localisation resources for
DateHumanizeandTimeSpanHumanize. - Implemented and registered an Urdu
NumberToWordsconverter (ur) and enabled the default formatter forur. - Added Urdu localisation test coverage for dates, timespans, and number/ordinal-to-words.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Humanizer.Tests/Localisation/ur/TimeSpanHumanizeTests.cs | Adds Urdu assertions for TimeSpan.Humanize output. |
| tests/Humanizer.Tests/Localisation/ur/NumberToWordsTests.cs | Adds Urdu assertions for cardinal and ordinal number-to-words. |
| tests/Humanizer.Tests/Localisation/ur/DateHumanizeTests.cs | Adds Urdu assertions for DateHumanize past/future phrasing. |
| src/Humanizer/Properties/Resources.ur.resx | Introduces Urdu resource strings for date/timespan humanization. |
| src/Humanizer/Localisation/NumberToWords/UrduNumberToWordsConverter.cs | Adds Urdu number-to-words implementation (cardinal + ordinal). |
| src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs | Registers the Urdu number-to-words converter for locale ur. |
| src/Humanizer/Configuration/FormatterRegistry.cs | Enables default formatter registration for locale ur. |
| if (number >= 100) | ||
| { | ||
| parts.Add(HundredsMap[number / 100]); | ||
| number %= 100; | ||
| } | ||
|
|
||
| if (number > 0) | ||
| { | ||
| parts.Add(UnitsMap[number]); | ||
| } |
There was a problem hiding this comment.
This won’t compile as written: array indexes must be int, but number / 100 and number are long here (e.g., HundredsMap[number / 100], UnitsMap[number]). Consider converting the remainder to an int after you’ve bounded it (e.g., after number %= 100) or explicitly casting to int where safe, so the converter builds on all target frameworks.
| static string ConvertUpTo99(long number) | ||
| { | ||
| if (number < 100) | ||
| { | ||
| return UnitsMap[number]; | ||
| } | ||
|
|
||
| var result = HundredsMap[number / 100]; | ||
| number %= 100; | ||
|
|
||
| if (number > 0) | ||
| { | ||
| result += " " + UnitsMap[number]; | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
There was a problem hiding this comment.
ConvertUpTo99 is currently unused within this type. If it’s not intentionally kept for future work, consider removing it to reduce dead code and maintenance surface (or refactor Convert to use it if that was the intent).
| static string ConvertUpTo99(long number) | |
| { | |
| if (number < 100) | |
| { | |
| return UnitsMap[number]; | |
| } | |
| var result = HundredsMap[number / 100]; | |
| number %= 100; | |
| if (number > 0) | |
| { | |
| result += " " + UnitsMap[number]; | |
| } | |
| return result; | |
| } |
clairernovotny
left a comment
There was a problem hiding this comment.
Please address the potential unchecked arithmetic overflow
…ove dead code - Cast number to int for HundredsMap and UnitsMap array indexing (safe: value bounded to 0-99/0-9) - Remove unused ConvertUpTo99 method (replaced by recursive Convert in prior commit)
|
Hi @clairernovotny 👋 I've addressed all the review feedback:
Please let me know if anything else is needed — happy to make further adjustments! |
Summary
Adds complete Urdu (ur) language support to Humanizer. Urdu is spoken by 230+ million people worldwide (primarily Pakistan and India) and was not previously supported.
What's included
Source files (4):
Resources.ur.resxDateTime.Humanize()andTimeSpan.Humanize()UrduNumberToWordsConverter.csToWords()andToOrdinalWords()implementation with South Asian numberingNumberToWordsConverterRegistry.csurlocaleFormatterRegistry.csurlocale withDefaultFormatterTest files (3):
DateHumanizeTests.csTimeSpanHumanizeTests.csNoTime+NoTimeToWordsNumberToWordsTests.csDesign decisions
South Asian numbering system — Urdu uses لاکھ (lakh = 100,000), کروڑ (crore = 10,000,000), ارب (arab = 1,000,000,000) instead of Western million/billion. This is how numbers are actually spoken in Pakistan and India.
Unique words for 1–99 — Unlike most languages that have patterns (e.g., twenty-one, twenty-two), Urdu has a completely unique word for every number from 1 to 99. All 100 words are included.
GenderlessNumberToWordsConverter— Urdu cardinal numbers don't change based on grammatical gender (unlike Arabic), so the simpler base class is used, following the same pattern as Farsi.DefaultFormatter— Urdu pluralization doesn't require special dual/plural forms like Arabic, so the default formatter is sufficient.Examples
PR Checklist
mainbranchbuild.cmdorbuild.ps1— Requires .NET 10 preview SDK; CI pipeline should validate