Humanizer .NET Library

repository·main·Indexed 27 days ago

https://github.com/humanizr/humanizer

A .NET library for manipulating and displaying strings, enums, dates, times, timespans, numbers, and quantities in a human-readable format. It provides tools for casing control, pluralization, ordinalization, relative time descriptions, and fluent date syntax. Supports .NET 10.0, 8.0, 4.8, and .NET Standard 2.0.

Tokens
30.8K
Snippets
60
Records
161
Agent score
94%

What's inside Humanizer

  1. Check supported frameworks for Humanizer

    main

    Humanizer officially supports the following frameworks:

    • net10.0
    • net8.0
    • net48
    • netstandard2.0 (specifically for Roslyn Analyzers and MSBuild tasks)

    Note on unsupported versions: While .NET Framework versions net4.6.1 through net4.7.2 can technically consume netstandard2.0 libraries, they are not officially supported and may exhibit incorrect behavior. Use one of the supported frameworks listed above for stability.

  2. Core features of Humanizer

    main

    Humanizer provides a wide range of capabilities across several domains:

    String Manipulation

    • String Humanization: Transform computerized strings (like snake_case) to human-readable text.
    • String Dehumanization: Convert human-readable text back to formats like PascalCase.
    • String Transformations: Apply custom transformations using the IStringTransformer interface.
    • String Truncation: Use intelligent truncation strategies for text.

    Enumerations

    • Enum Humanization: Make enum values readable.
    • Enum Dehumanization: Parse strings back into enum values.

    Date and Time

    • DateTime Humanization: Generate relative time strings (e.g., "2 hours ago", "tomorrow").
    • TimeSpan Humanization: Convert durations into human-readable formats.
    • Fluent Date API: Construct and manipulate dates/times using a readable fluent interface.
    • DateTime to Ordinal Words: Convert dates to formats like "1st of January 2020".
    • TimeOnly to Clock Notation: Convert time to clock notation (e.g., "half past two") (requires .NET 6+).

    Numbers

    • Number to Words: Convert numbers to text (e.g., "123" → "one hundred twenty-three").
    • Number to Ordinal Words: Convert numbers to ordinal text (e.g., "1" → "first").
    • Words to Number: Convert text numbers back to numeric values (e.g., "forty-two" → 42).
    • Ordinalization: Convert numbers to ordinal strings (e.g., "1" → "1st").
    • Roman Numerals: Convert between integers and Roman numerals.
    • Metric Numerals: Convert numbers to metric notation (e.g., "1230" → "1.23k").
    • Number to Numbers: Use a fluent API for handling large numbers.
    • Tupleize: Convert numbers to their tuple representation (e.g., "2" → "double").

    Collections

    • Collection Humanization: Format lists into readable strings (e.g., "item1, item2, and item3").
    • ToQuantity: Handle pluralization for quantities (e.g., "5 cases", "1 man", "2 men").

    Word Manipulation

    • Pluralization/Singularization: Handle singular and plural forms of words.
    • Inflector Methods: Apply casing transformations like Pascalize, Camelize, Underscore, and Kebaberize.

    Specialized Features

    • ByteSize: Convert bytes into human-readable sizes.
    • Heading: Convert headings into text.
    • Time Unit Symbols: Use symbols like "ms", "s", "min", etc.
  3. Understand the Locale YAML Generator Pipeline

    main

    The following internal components are responsible for transforming locale YAML files into runtime behavior:

    • LocaleYamlCatalog.cs: Reads YAML, resolves locale inheritance, merges child mappings with parent mappings, and normalizes references like self.
    • EngineContractCatalog.cs: Defines the typed generator-side structural contracts for shared engines.
    • ProfileCatalogs/*.cs: Emits typed profile catalogs for supported surfaces.
    • LocaleRegistryInput.cs: Emits the locale-to-implementation registry wiring.
    • src/Humanizer/Localisation/*: Contains the shared runtime kernels.
  4. Advanced configuration and extensibility

    main

    For complex use cases, Humanizer offers advanced customization options:

    • Localization: Support multiple languages using YAML locale data and inheritance.
    • Custom Vocabularies: Add your own custom pluralization rules.
    • Extensibility: Implement custom IStringTransformer or truncation logic.
    • Configuration: Customize the global or local behavior of Humanizer.
  5. Related Humanizer projects and ports

    main

    Humanizer has several community-driven ports and extensions for different environments:

    • Humanizer ReSharper Annotations: Available via the Humanizer.Annotations package for ReSharper users.
    • PowerShell Humanizer: A PowerShell module wrapping Humanizer.
    • Humanizer JVM: A Kotlin adaptation for the JVM.
    • Humanizer.node: A TypeScript port of the framework.
  6. Understand the Humanizer library architecture

    main

    Humanizer is a multi-targeted .NET library designed for culture-aware string and data humanization. It uses a build-time pipeline where YAML locale definitions are transformed into high-performance C# lookup tables via Roslyn source generators. This ensures that locale data is available in-memory at runtime with no I/O overhead.

    Key Components:

    • Extension Methods: The primary public API (e.g., StringHumanizeExtensions, DateHumanizeExtensions).
    • Formatters: Culture-specific logic managed by the FormatterRegistry.
    • Converters: Implementations for number-to-words, ordinalization, and other locale-specific conversions.
    • Configuration: Global settings and strategy selection via the Configurator class.
  7. Understand the Locale YAML Mental Model

    main

    Locale YAML files are used to define locale-owned data that the generator compiles into runtime code.

    Key Boundaries:

    • Locale YAML: Owns words, phrases, tokens, scale rows, and strategy choices.
    • Shared Runtime Kernels: Own reusable algorithms.
    • Generator C#: Handles the structural mapping from YAML to runtime constructors.
    • Runtime: Never parses YAML or JSON directly.

    If a value describes generator plumbing or constructor shapes, it does not belong in the locale YAML.

  8. Author locale YAML files

    main

    Locale YAML files (located in src/Humanizer/Locales/*.yml) are the single authoring surface for locale-owned generated behavior. These files are consumed at build time by the source generator and are not parsed at runtime.

    File Naming and Structure

    • Naming: Use the locale code as the filename (e.g., en.yml, en-US.yml, pt-BR.yml).
    • Top-level properties: Only locale, variantOf, and surfaces are permitted.
    • Required fields: Non-variant locales must include a surfaces block. Variant locales may omit it if there are no overrides.

    Supported Surface Names

    The following canonical names are allowed under the surfaces key:

    • list
    • formatter
    • phrases
    • number
    • ordinal
    • clock
    • compass
    • calendar
    locale: 'en-IN'
    variantOf: 'en'
    
    surfaces:
      number:
        words:
          engine: 'conjunctional-scale'
          tensUnitsSeparator: ' '
          scales:
            - value: 10000000
              name: 'crore'
              ordinalName: 'crore'
            - value: 100000
              name: 'lakh'
              ordinalName: 'lakh'
            - value: 1000
              name: 'thousand'
              ordinalName: 'thousand'
  9. Add a new engine contract

    main

    Add a new engine contract only when the behavior is structural, reusable, applies to at least two locales, and the runtime kernel can remain generic.

    When adding a new engine contract, you must update:

    1. src/Humanizer.SourceGenerators/Common/EngineContractCatalog.cs
    2. The relevant profile catalog generator in src/Humanizer.SourceGenerators/Generators/ProfileCatalogs
    3. A shared runtime kernel under src/Humanizer/Localisation
    4. Source-generator tests
    5. Runtime tests
    6. Benchmark coverage (if the runtime path is hot)
  10. Determine if a new Locale File is required

    main

    Before creating a new locale file, evaluate the following:

    1. Check Fallback: Ensure runtime culture fallback isn't masking missing behavior. Fallback is not a substitute for parity.
    2. Check Variants: If it is a regional variant of an existing neutral locale, use variantOf to create a child file and override only the differences.
    3. Check Engines: Reuse existing shared engines if possible. Only create a new shared structural engine if the behavior is truly reusable.
    4. Check Stability: If the locale requires specific month names, decimal separators, negative signs, or group separators that differ from CultureInfo.DateTimeFormat / NumberFormatInfo, author them in calendar: or number.formatting: to ensure stable output across different operating systems and .NET globalization modes.
  11. Dehumanize strings to PascalCase

    main

    Use the .Dehumanize() extension method to convert human-friendly strings (like sentences or space-separated words) back into PascalCase format. This is useful for converting user input or display text back into code-friendly identifiers.

    The process follows these steps:

    1. Splits the input on spaces.
    2. Humanizes each word to handle edge cases.
    3. Pascalizes each word (capitalizing the first letter).
    4. Removes all spaces.

    If the input string is already in PascalCase (contains no spaces), it is returned unchanged.

    "Pascal case input string is turned into sentence".Dehumanize() 
        // => "PascalCaseInputStringIsTurnedIntoSentence"
    
    "some string".Dehumanize() 
        // => "SomeString"
    
    "Some String".Dehumanize() 
        // => "SomeString"
    
    "SomeStringAndAnotherString".Dehumanize() 
        // => "SomeStringAndAnotherString" (unchanged)