Skip to content
Bogoware logo

Bogoware.Localization

Type-safe localization where each message is a class

Define a class, and you’ve defined a message. The type name is the key, the properties are the placeholders — rename either and the compiler catches it.

NuGetDownloads.NET versionsChangelog

Why?

String-based localization keys are fragile. You pick "errors.required_field" by convention, match {0} placeholders by position, and maintain separate resource files that drift out of sync with every refactor.

Bogoware.Localization takes a different approach. The fully-qualified type name becomes the lookup key. Properties become template placeholders. Rename either and the compiler catches it — no conventions to memorize, no resource files to keep aligned by hand. It’s a well-established idea — types as messages — applied to localization.

The library handles the rest: three-tier culture fallback, a four-step provider resolution chain, recursive nested formatting, and seamless ASP.NET Core integration — including automatic JSON response localization and ProblemDetails support.

Key Features

Class-Based Modeling

The type name is the key, properties are the placeholders. Rename either and the compiler catches it.

Culture Fallback

Three-tier resolution: exact culture, parent culture, then invariant culture.

Provider Resolution Chain

Self-provider, DI provider, registry template, then fallback format — in that order, always.

Nested Localization

ILocalizable properties are formatted recursively through the full resolution chain.

JSON Templates

Load templates from embedded resources, files, or raw JSON strings. JSONC supported.

JSON Serialization

Localize properties during System.Text.Json serialization automatically.

DI Integration

AddLocalization() extension methods with additive, assembly-scanning registration.

ASP.NET Core

Per-request culture resolution, JSON response localization, and ProblemDetails support.

Quick Start

  1. Install from NuGet

    Terminal window
    dotnet add package Bogoware.Localization
  2. Define a localizable type

    using Bogoware.Localization;
    public class RequiredFieldError(string fieldName) : ILocalizable
    {
    public string FieldName { get; } = fieldName;
    }
  3. Create JSON templates (embedded resources)

    localized-messages.en-US.json
    { "MyApp.Errors.RequiredFieldError": "'{FieldName}' is required" }
    // localized-messages.it-IT.json
    { "MyApp.Errors.RequiredFieldError": "'{FieldName}' è obbligatorio" }
  4. Register and format

    services.AddLocalization(typeof(RequiredFieldError).Assembly);
    var formatter = serviceProvider.GetRequiredService<ILocalizationFormatter>();
    var message = formatter.Format(new RequiredFieldError("Email"));
    // → "'Email' is required" (en-US)
    // → "'Email' è obbligatorio" (it-IT)

Library Overview

TypePurposeKey Operations
ILocalizableMarker interface for localizable typesImplement on any class to make it localizable
ILocalizationFormatterFormat localizable objects to stringsFormat(ILocalizable) with culture support
ILocalizationRegistryStore and retrieve templatesTryGetTemplate(type, culture) with fallback
ILocalizationProvider<T>DI-based per-type providersRegister via AddLocalization()
JsonLocalizationRegistryJSON-backed template storageLoad from embedded resources, files, or strings

Next Steps