Skip to content

Provider Chain

The ILocalizationFormatter resolves localized strings through a chain of providers, stopping at the first one that returns a result.

Resolution Order

  1. Self-provider — If the type implements ILocalizationProvider, its Localize(culture) method is called directly

  2. DI provider — If an ILocalizationProvider<T> for the specific type is registered in the DI container, it is used

  3. Registry template — The ILocalizationRegistry is queried using the type’s FullName as key

  4. Default formatTypeName(Prop1=val1, Prop2=val2) — a diagnostic representation

Self-Provider

The highest priority. Implement ILocalizationProvider directly on your type:

public class SpecialError : ILocalizable, ILocalizationProvider
{
public string Localize(CultureInfo culture) => "Special error message";
}

DI Provider

Register a provider for a specific type in the DI container:

public class OrderErrorProvider : ILocalizationProvider<OrderError>
{
public string? Localize(OrderError instance, CultureInfo culture)
{
// Custom localization logic
return $"Order {instance.OrderId} failed: {instance.Reason}";
}
}
// Registration
services.AddSingleton<ILocalizationProvider<OrderError>, OrderErrorProvider>();

Registry Template

The standard approach. Templates are loaded from JSON files into the ILocalizationRegistry:

{
"MyApp.Errors.OrderError": "Order #{OrderId} failed: {Reason}"
}

Default Format

When no other provider returns a result, the formatter produces a diagnostic string:

OrderError(OrderId=12345, Reason=Payment declined)

This ensures that the formatter always returns a meaningful string, even without configured templates.

Recursive Resolution

When a template placeholder or fallback property resolves to an ILocalizable value, the entire chain is applied recursively. The culture is propagated through all nesting levels. See the Nested Localization guide for details and examples.