RepoPilotOpen in app →

Humanizr/Humanizer

Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities

Mixed

Mixed signals — read the receipts

worst of 4 axes
Use as dependencyConcerns

non-standard license (Other)

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 5d ago
  • 13 active contributors
  • Other licensed
Show 4 more →
  • CI configured
  • Tests present
  • Concentrated ownership — top contributor handles 65% of recent commits
  • Non-standard license (Other) — review terms
What would change the summary?
  • Use as dependency ConcernsMixed if: clarify license terms

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/humanizr/humanizer?axis=fork)](https://repopilot.app/r/humanizr/humanizer)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/humanizr/humanizer on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: Humanizr/Humanizer

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/Humanizr/Humanizer shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Mixed signals — read the receipts

  • Last commit 5d ago
  • 13 active contributors
  • Other licensed
  • CI configured
  • Tests present
  • ⚠ Concentrated ownership — top contributor handles 65% of recent commits
  • ⚠ Non-standard license (Other) — review terms

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live Humanizr/Humanizer repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/Humanizr/Humanizer.

What it runs against: a local clone of Humanizr/Humanizer — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in Humanizr/Humanizer | Confirms the artifact applies here, not a fork | | 2 | License is still Other | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | Last commit ≤ 35 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>Humanizr/Humanizer</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of Humanizr/Humanizer. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/Humanizr/Humanizer.git
#   cd Humanizer
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of Humanizr/Humanizer and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "Humanizr/Humanizer(\\.git)?\\b" \\
  && ok "origin remote is Humanizr/Humanizer" \\
  || miss "origin remote is not Humanizr/Humanizer (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Other)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Other\"" package.json 2>/dev/null) \\
  && ok "license is Other" \\
  || miss "license drift — was Other at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 35 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~5d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/Humanizr/Humanizer"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Humanizer is a .NET library that transforms programmatic data (strings, enums, dates, timespans, numbers) into human-readable formats with locale-aware internationalization. It solves the problem of display formatting across 50+ languages via YAML-driven locale definitions compiled by a source generator into runtime tables—eliminating the need for separate satellite assemblies or English-only core packages. Monorepo structure: src/Humanizer/ contains the main library with YAML locale definitions under src/Humanizer/Locales/, a source generator (inferred from locale data description) transforms YAML→C# runtime tables, test suites target net10.0/net8.0/net48. .agents/skills/add-locale/ provides structured workflow for locale contributors. .codex/ and .flow/ directories manage AI-assisted engineering and epic checkpoints—not core to runtime.

👥Who it's for

.NET developers building applications that require culture-aware display of dates (e.g., '2 hours ago' in 20+ languages), number formatting, ordinal suffixes, timespan humanization, and string manipulation without writing custom locale-specific logic for each target region.

🌱Maturity & risk

Production-ready. The project has significant .NET ecosystem adoption (visible via NuGet downloads badge and active Azure Pipelines CI), supports modern frameworks (net10.0, net8.0, net48), recently underwent a major v3 refactor (documented in migration guide), and maintains active development evidenced by .flow epic checkpoints through late feature work on calendar systems and NET 11 support.

Low risk for core features but moderate complexity in locale parity: the .flow checkpoints reveal ongoing struggles with NET48 test suite blockers and locale test coverage gaps (45 failing tests in fn-6 checkpoint). Single-language locale additions require coordination across 8 canonical surfaces (list, formatter, phrases, number, ordinal, clock, compass, calendar) per docs/localization.md, creating maintenance burden if contributor discipline lapses. No visible 'DEPRECATED' marker, but migration guide suggests v2→v3 involved breaking changes.

Active areas of work

Active work on locale parity and non-Gregorian calendar support (fn-12 epic), NET 11 framework audit (fn-13), Windows NLS backend addition (fn-14), and performance optimization of string transformation hot paths (fn-15, fn-16). Recent focus on fixing NET48 test suite blockers and code coverage gaps toward 95% line coverage (fn-9 checkpoint completed). Urdu locale was recently added with full language support (fn-8, fn-11 checkpoints).

🚀Get running

git clone https://github.com/Humanizr/Humanizer.git
cd Humanizer
dotnet restore
dotnet build
dotnet test

Daily commands: For development: dotnet build src/Humanizer/Humanizer.csproj then dotnet test src/Humanizer.Tests/. The library is consumed as a NuGet package in downstream projects; no dev server needed—this is a class library, not a web service.

🗺️Map of the codebase

  • src/Humanizer/Locales: Contains all 50+ locale YAML definitions (one subdirectory per language code) that source generators compile into runtime internationalization tables; core to locale-aware output.
  • docs/localization.md: Defines the 8 canonical localization surfaces (list, formatter, phrases, number, ordinal, clock, compass, calendar) and nested-member inventory—essential spec for adding or modifying locale support.
  • .agents/skills/add-locale/SKILL.md: Structured workflow and checklist for contributors adding new locales; references parity-checklist.md and urdu-epic-learnings.md to avoid rework.
  • .flow/epics: Historical record of major work items (locale parity, NET48 fixes, calendar refactor, performance); epics like fn-6 (45 failing tests) and fn-9 (coverage gaps) show current pain points.
  • docs/migration-v3.md: Documents breaking changes from v2→v3 and patch-line fixes; mandatory reading for contributors touching public APIs or upgrading dependent code.
  • src/Humanizer/Humanizer.csproj: Multi-target framework configuration (net10.0, net8.0, net48, netstandard2.0) and source generator references; any framework-specific logic or build changes happen here.

🛠️How to make changes

Add a new locale: Use .agents/skills/add-locale/SKILL.md and the parity-checklist.md as your template; add YAML files under src/Humanizer/Locales/{language-code}/, ensure all 8 canonical surfaces are covered. Fix a locale bug: Edit the corresponding YAML under src/Humanizer/Locales/, then run locale-specific tests. Optimize a feature: Focus on src/Humanizer/{Core,Extensions,Transformers}/ for the main string/date/number logic; see fn-15 epic for current hot-path targets. Framework compatibility: Updates to csproj multi-targeting or runtime behavior go in src/Humanizer/Humanizer.csproj.

🪤Traps & gotchas

  1. Locale surface completeness: Adding a locale requires satisfying 8 separate surfaces (not just one translation file); incomplete coverage is silently ignored until runtime or tests catch it—use parity-checklist.md. 2. NET48 test instability: .flow checkpoints show recurring NET48 blockers (fn-4, fn-6); if tests fail inconsistently across frameworks, isolate NET48 runs first. 3. Source generator rebuild: Modifying YAML under src/Humanizer/Locales/ only takes effect if the source generator runs; dotnet clean && dotnet build may be needed. 4. variantOf inheritance resolution: Language variants (e.g., pt-BR variant of pt) must chain correctly via variantOf; circular or broken references are hard to debug. 5. SourceLink symbol indexing: Published NuGet includes SourceLink; if you modify source and publish locally without re-running SourceLink generation, debugging symbols will be stale.

💡Concepts to learn

  • Source Generators — Humanizer's locale YAML is transformed into compiled C# tables at build-time via a source generator, eliminating runtime reflection and separate satellite assemblies—you need to understand generator activation and file generation to modify locale compilation.
  • Locale Data Inheritance (variantOf) — Humanizer uses a variantOf chain to inherit locale data across language variants (e.g., pt-BR inherits from pt); understanding the fallback chain is crucial to avoid duplication and spot inheritance bugs.
  • Culture-Aware String Formatting — The library relies on .NET's CultureInfo and RegionInfo to adapt humanized output to locale conventions (e.g., date ordering, number separators); you must test against multiple cultures to avoid Western-centric assumptions.
  • Multi-Targeting (.NET TFM) — Humanizer targets net10.0, net8.0, net48, and netstandard2.0 simultaneously; tests must run against all frameworks, and code paths may differ per target—understanding TFM-specific behavior is essential to avoid NET48 regressions.
  • Gregorian vs. Non-Gregorian Calendar Systems — fn-12 epic references generalizing non-Gregorian calendars; Humanizer must handle Islamic, Hebrew, Hindu, and other calendar systems for date humanization in regions using them—this requires mapping between calendar epochs.
  • SourceLink Debugging — Humanizer ships SourceLink symbols in the NuGet package so downstream developers can step through source code; if you modify the build pipeline or commit history, you must ensure SourceLink metadata remains valid.
  • Fluent Extension Methods — Humanizer's API is built on C# extension methods (e.g., string.Humanize(), DateTime.Humanize()); the pattern enables natural, chained humanization without wrapper classes—you'll extend these for new features.
  • dotnet/coreclr — Provides the native globalization and locale APIs that Humanizer wraps for culture-aware formatting; understanding CultureInfo and CompareOptions is foundational.
  • dotnet/sourcelink — Humanizer uses SourceLink for symbol indexing in NuGet packages; relevant if you modify build configuration or publish pipeline.
  • NodaTime/nodatime — Alternative .NET date/time library with strong internationalization; Humanizer users often compare the two for date humanization features.
  • Humanizr/Humanizer.js — JavaScript port of Humanizer; if you add a locale to C#, the JS ecosystem may want parity—occasionally synced by contributors.
  • xliff/xliff — Standard for localization interchange; Humanizer's YAML→C# pipeline could theoretically consume XLIFF if contributors propose it as an alternative format.

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Implement comprehensive locale parity test suite for NET48

The .flow/checkpoints and epics reveal ongoing struggles with NET48 locale test failures (fn-4, fn-6, fn-10). There are 45+ failing NET48 locale tests and unresolved byte parity issues between runtime environments. A new contributor could add a dedicated test fixture that validates locale data consistency across all supported .NET target frameworks (net48, net6.0, net7.0, etc.) to prevent regression and document platform-specific locale behavior.

  • [ ] Review existing test failures in .flow/epics/fn-6-fix-45-failing-net48-locale-tests.json and fn-10-verify-net48-runtime-byte-parity-for.md
  • [ ] Create src/Humanizer.Tests/Localization/LocaleParity.NET48Tests.cs with parameterized tests for each supported locale
  • [ ] Add test cases validating NumberToWords, Ordinalize, and PluralizeVerb across NET48 vs modern .NET for at least 10 locales
  • [ ] Document known platform differences in .flow/memory/pitfalls.md

Add missing locale documentation index in docs/locales/

The .agents/skills/add-locale/references/parity-checklist.md and urdu-epic-learnings.md suggest a complex locale addition workflow exists, but there's no discoverable documentation listing all supported locales, their implementation status (complete/partial/needs-review), and per-locale known issues. New contributors adding locales need this reference.

  • [ ] Create docs/locales/SUPPORTED_LOCALES.md listing all locales with columns: locale code, language, implementation status, test coverage %, known issues
  • [ ] Reference .agents/skills/add-locale/references/parity-checklist.md to extract locale validation requirements
  • [ ] Add locale-specific subdirectories under docs/locales/ for complex cases (e.g., docs/locales/ur-PK/ for Urdu learnings from fn-8)
  • [ ] Link to this index from main docs/index.md

Create reusable non-Gregorian calendar abstraction layer (fn-12 groundwork)

The epic fn-12-generalize-non-gregorian-calendar.json indicates plans to support non-Gregorian calendars (relevant for locales like Urdu, Arabic, Persian). Currently each locale likely implements calendar logic independently. A new contributor could extract a shared ICalendarProvider interface and implement it for at least Gregorian and Hijri/Islamic calendars, reducing code duplication.

  • [ ] Review .flow/epics/fn-12-generalize-non-gregorian-calendar.md to understand scope and existing code references
  • [ ] Create src/Humanizer/Localisation/Calendars/ICalendarProvider.cs interface with methods for GetDaysInMonth, IsLeapYear, ConvertToGregorian
  • [ ] Implement GregorianCalendarProvider and IslamicHijriCalendarProvider in separate files
  • [ ] Refactor at least one existing locale (e.g., Urdu from fn-8) to use the new provider, demonstrating 20%+ code reduction
  • [ ] Add unit tests in src/Humanizer.Tests/Localisation/Calendars/

🌿Good first issues

  • Add missing nested-member coverage to an existing locale: Pick a language in src/Humanizer/Locales/ with incomplete nested coverage (e.g., missing number.formatting.currency) identified in a parity-checklist.md, add the YAML structure, and verify with a unit test asserting the humanized output.: Medium: Teaches locale system mechanics without requiring new language fluency; checklist-driven so success criteria are clear.
  • Port a locale variant using variantOf inheritance: Create src/Humanizer/Locales/{lang}-{REGION}/variant.yaml that inherits from a base language locale using variantOf, covering regional differences (e.g., pt-BR vs pt-PT). Add a test in the test suite asserting variant humanization works.: Medium: Low risk since inheritance model handles fallback; unblocks locale coverage for 20+ language variants without duplicating YAML.
  • Fix a NET48-specific test failure from .flow checkpoints fn-4 or fn-6: Examine the 45 failing NET48 tests, pick one, debug why it fails only on net48 (not net8.0), apply a target-framework-specific workaround in the test or implementation, and document the trap in a comment.: Hard: Unblocks CI stability and teaches deep framework compatibility; .flow epics show this is a known blocker, so your fix has immediate production value.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 43b0e65 — correct compass direction names (#1734) (sigmade)
  • 4214280 — Improve ordinal and clock notation hot paths (#1732) (clairernovotny)
  • 19527a5 — ci: update benchmark workflow for net11 (#1731) (clairernovotny)
  • 944e589 — test: cover branch coverage gaps (#1730) (clairernovotny)
  • 4468f52 — test: cover canonical locale authoring gaps (clairernovotny)
  • e501513 — test: raise Humanizer coverage above 99 percent (clairernovotny)
  • 30d00a7 — Update .NET SDK version from 10 to 11 (clairernovotny)
  • 40bb6d0 — Add .NET 11 support (net11.0 TFM, preview SDK, analyzer refactor) (#1725) (clairernovotny)
  • 8b8a5dd — Fix typo in README: change 'month' to 'months' (#1705) (mavonx)
  • f3d30ee — Add Urdu locale (#1720) (clairernovotny)

🔒Security observations

The Humanizer repository shows a generally secure structure with no critical vulnerabilities identified based on the provided analysis scope. The codebase is a legitimate .NET string/date manipulation library with no obvious hardcoded secrets, SQL injection risks, or XSS vulnerabilities visible in the file structure. However, security assessment is limited by missing dependency information. The presence of workflow and configuration directories (.flow/, .codex/, .agents/) warrants review to ensure no sensitive data is exposed. Recommendations include: (1) Performing complete dependency vulnerability scanning, (2) Implementing automated security scanning in CI/CD pipeline, and (3) Maintaining security practices for open-source .NET library development including code review processes and security policy documentation.

  • Low · Workflow and Configuration Files in Repository Root — .flow/, .codex/, .agents/. The repository contains multiple workflow and configuration files (.flow/, .codex/, .agents/) in the root directory. While these appear to be agent/workflow configuration files rather than sensitive data, storing extensive metadata and checkpoints in version control could potentially expose implementation details or workflow logic. Fix: Review whether these directories should be version controlled. Consider moving sensitive workflow configurations to a separate configuration management system or ensuring they don't contain any sensitive information. Document the purpose of these files clearly.
  • Low · Missing Dependency Information — Project manifest files (*.csproj, packages.config, or similar). The dependency/package file content section is empty, preventing assessment of vulnerable dependencies. A .NET project like Humanizer should have a project file (*.csproj) or packages.config that can be analyzed for known vulnerabilities. Fix: Provide package dependency information for security scanning. Implement regular dependency scanning using tools like NuGet Auditor, OWASP Dependency-Check, or GitHub's dependabot to identify and patch known vulnerabilities in dependencies.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · Humanizr/Humanizer — RepoPilot