Interface ILocalizer

Namespace
RentADeveloper.ResXLocalization
Assembly
ResXLocalization.Core.dll

Resolves localized strings from one or more ResourceManager instances for a runtime-selectable culture, and raises change notifications so bindings update live when the culture changes - without reloading views.

public interface ILocalizer : INotifyPropertyChanged
Inherited Members
Extension Methods

Remarks

Lookups. Every Get overload and the indexer resolve the key in CurrentCulture, with .NET's own parent and neutral fallback, and pass the resolved value to MessageFormatter together with the lookup's arguments - empty arguments when the lookup has none. The default formatter (StringFormatMessageFormatter) returns a value without arguments unchanged and formats one with arguments with Format(IFormatProvider, string, params object[]). A null or empty key returns Empty without calling the formatter and without raising an event.

The failure text. When no resource file contains the key, or the formatter throws, a lookup raises LookupFailed and then returns the failure text produced by LookupFailureTextBuilder, by default !key!. The failure text never passes through the formatter.

Exceptions. A lookup catches every exception the formatter throws. Exceptions from the resource lookup itself, from event handlers and from LookupFailureTextBuilder propagate unchanged; an event handler that throws prevents the failure text from being built.

Threading. Implementations are intended for UI-thread use: register resource managers at startup and switch CurrentCulture from the UI thread, so change notifications reach bindings on the thread WPF and Avalonia expect.

Properties

CurrentCulture

Gets or sets the culture used to resolve resources. Setting a different value raises PropertyChanged, advances RefreshTriggeringRevision and raises CultureChanged.

CultureInfo CurrentCulture { get; set; }

Property Value

CultureInfo

The active culture. Defaults to CurrentUICulture.

Remarks

Setting this property changes only how this localizer resolves translations; it deliberately does not touch CurrentUICulture or DefaultThreadCurrentUICulture. ResXLocalization is a translation engine, not a formatting engine - if number, date, or currency formatting should follow the selected language too, set those thread cultures yourself when handling CultureChanged.

Exceptions

ArgumentNullException

The supplied value is null.

EnumKeyBuilder

Gets or sets the function that builds the resource key of an enum lookup from the enumeration value and an optional key prefix.

Func<Enum, string?, string> EnumKeyBuilder { get; set; }

Property Value

Func<Enum, string, string>

The enum key function. Defaults to the Enum_{EnumTypeName}_{Value} convention.

Remarks

The function receives, in order:

  1. The enumeration value of the lookup (Enum); never null.
  2. The key prefix the lookup passed (keyPrefix, KeyPrefix; string?), or null when it passed none. null means "use your own default"; a non-null value is an explicit override.

It returns the resource key, never null or empty. The default builds {keyPrefix ?? "Enum_"}{EnumTypeName}_{Value}, for example Enum_FileSortOrder_Ascending. A custom convention might look like this: Localizer.Current.EnumKeyBuilder = (value, keyPrefix) => (keyPrefix ?? "Text_") + value.GetType().Name + "." + value;

The builder applies to every enum lookup: Get(Enum, …), {l:LocalizeEnum} and LocalizeEnumConverter. It must not throw or return null or an empty string: an exception it throws propagates out of the lookup, and a null or empty result makes the lookup throw InvalidOperationException.

Assigning a different delegate instance advances RefreshTriggeringRevision, so bound text re-resolves; assigning the current instance again does nothing.

Exceptions

ArgumentNullException

The supplied value is null.

this[string]

Gets the localized string for the specified key by searching every registered ResourceManager in registration order.

string this[string key] { get; }

Parameters

key string

The resource key to resolve.

Property Value

string

The localized string, Empty for a null or empty key, or the failure text (see ILocalizer).

LookupFailureTextBuilder

Gets or sets the function that produces the failure text: the text a lookup returns instead of a translation when no resource file contains the key or its value cannot be formatted.

Func<LookupFailure, string> LookupFailureTextBuilder { get; set; }

Property Value

Func<LookupFailure, string>

The failure-text function. Defaults to failure => $"!{failure.Key}!".

Remarks

The function receives a LookupFailure describing the failed lookup; Reason tells the two cases apart. It returns the text shown instead of the translation; an empty string shows nothing.

Examples:

  • failure => $"[{failure.Key}]"
  • failure => failure.Key[(failure.Key.LastIndexOf('.') + 1)..]
  • failure => failure.Culture.TwoLetterISOLanguageName == "de" ? $"[fehlt: {failure.Key}]" : $"[missing: {failure.Key}]"
  • failure => failure.Reason == LookupFailureReason.TranslationNotFound ? $"[missing: {failure.Key}]" : $"[broken: {failure.Key}]"

The function is called on every failed lookup, so it should be cheap. It must not throw or return null: an exception it throws propagates out of the lookup, and a null result makes the lookup throw InvalidOperationException.

Assigning a different delegate instance advances RefreshTriggeringRevision; assigning the current instance again does nothing.

Exceptions

ArgumentNullException

The supplied value is null.

MessageFormatter

Gets or sets the formatter that turns each resolved resource value and the arguments of its lookup into the final string.

IMessageFormatter MessageFormatter { get; set; }

Property Value

IMessageFormatter

The formatter. Defaults to Instance.

Remarks

Every lookup that resolves a value calls the formatter, also a lookup without arguments, so it is the one hook for all translated texts (see ILocalizer).

Localizer.Current.UseMessageFormat() from the ResXLocalization.MessageFormat package installs an ICU MessageFormat formatter here (plural, select). That formatter parses every resolved value as an ICU message, including the values of lookups without arguments.

Assigning a different instance advances RefreshTriggeringRevision; assigning the current instance again does nothing. Exceptions thrown by PropertyChanged handlers propagate from the assignment.

Exceptions

ArgumentNullException

The supplied value is null.

RefreshTriggeringRevision

Gets a value that changes whenever something changes that can change the result of a lookup - the culture, the formatter, the lookup-failure text builder, the enum key builder or the registered resource managers. Bind to it to re-resolve localized text; only whether the value differs is meaningful.

int RefreshTriggeringRevision { get; }

Property Value

int

Remarks

The value advances after each real change of CurrentCulture, MessageFormatter, LookupFailureTextBuilder or EnumKeyBuilder, and after RegisterResourceManager(ResourceManager), UnregisterResourceManager(ResourceManager) and ClearResourceManagers() when they change the registered set. Each advance raises PropertyChanged for this property and then for the indexer (Item[]). Strings previously returned by Get are not updated.

Make these changes on the UI thread once views exist. In XAML, the trigger is <Binding Path="RefreshTriggeringRevision" Source="{x:Static core:Localizer.Current}" />.

Methods

ClearResourceManagers()

Removes every registered ResourceManager from the search-all set. Typed and scoped lookups are unaffected - they never consult the registration set. When at least one manager was registered, advances RefreshTriggeringRevision.

void ClearResourceManagers()

Get(ResourceKey, MessageArguments?)

Resolves the localized string for a typed ResourceKey, which carries both the key name and the owning ResourceManager, and passes it to MessageFormatter with the supplied arguments.

string Get(ResourceKey key, MessageArguments? arguments = null)

Parameters

key ResourceKey

The typed key identifying the resource and its resource manager.

arguments MessageArguments

The arguments of the lookup, built with MessageArguments; null or empty for none.

Returns

string

The localized (or formatted) string, or the failure text (see ILocalizer).

Remarks

Every resolved value passes through MessageFormatter; a formatting failure returns the failure text and raises LookupFailed (see ILocalizer).

Exceptions

ArgumentNullException

key is a default or otherwise uninitialized ResourceKey, whose Manager is null.

Get(Enum, MessageArguments?, ResourceManager?, string?)

Resolves the localized string for an enumeration value: EnumKeyBuilder builds the resource key from the value, which is then resolved like a string key and passed to MessageFormatter with the supplied arguments.

string Get(Enum value, MessageArguments? arguments = null, ResourceManager? resourceManager = null, string? keyPrefix = null)

Parameters

value Enum

The enumeration value to resolve.

arguments MessageArguments

The arguments of the lookup, built with MessageArguments, for example MessageArguments.FromValues(count); null or empty for none.

resourceManager ResourceManager

The single resource manager to read the key from, or null (the default) to search every registered resource manager in registration order.

keyPrefix string

A key prefix passed to EnumKeyBuilder, overriding only its default prefix (by default Enum_); null (the default) lets the builder decide. Pass it by name: Get(sortOrder, keyPrefix: "Display_").

Returns

string

The localized (or formatted) string, or the failure text (see ILocalizer).

Remarks

Every resolved value passes through MessageFormatter; a formatting failure returns the failure text and raises LookupFailed (see ILocalizer).

Exceptions

ArgumentNullException

value is null.

InvalidOperationException

EnumKeyBuilder returned null or an empty string.

Get(string, MessageArguments?, ResourceManager?)

Resolves the localized string for the specified key - searching every registered ResourceManager in registration order, or reading a single, explicit one - and passes it to MessageFormatter with the supplied arguments.

string Get(string key, MessageArguments? arguments = null, ResourceManager? resourceManager = null)

Parameters

key string

The resource key to resolve.

arguments MessageArguments

The arguments of the lookup, built with MessageArguments, for example MessageArguments.FromValues(3, 10); null or empty for none.

resourceManager ResourceManager

The single resource manager to read the key from, or null (the default) to search every registered resource manager in registration order. Pass it by name: Get("Key", resourceManager: rm).

Returns

string

The localized (or formatted) string, Empty for a null or empty key, or the failure text (see ILocalizer) in case the lookup failed.

Remarks

This is the lookup every other Get overload, the indexer and the XAML markup extensions go through. Every resolved value passes through MessageFormatter; a formatting failure returns the failure text and raises LookupFailed (see ILocalizer).

GetAvailableCultures()

Discovers the cultures for which any registered ResourceManager ships its own resources - the natural source for a language picker.

IReadOnlyList<CultureInfo> GetAvailableCultures()

Returns

IReadOnlyList<CultureInfo>

The union of the available cultures across every registered resource manager, sorted by culture name, with InvariantCulture (the neutral resources) first when present. Empty when nothing is registered.

Remarks

The neutral (fallback) resources embedded in the main assembly are reported as InvariantCulture, because a ResourceManager does not expose which language they are written in. Map it to the language you declared in <NeutralLanguage> when building a picker.

Discovery probes every known culture for a satellite assembly, which is I/O-bound: call it once at startup and cache the result rather than per lookup or per binding.

GetAvailableCultures(ResourceManager)

Discovers the cultures for which a single ResourceManager ships its own resources. See GetAvailableCultures() for how neutral resources are reported and why the result should be cached.

IReadOnlyList<CultureInfo> GetAvailableCultures(ResourceManager resourceManager)

Parameters

resourceManager ResourceManager

The resource manager to probe.

Returns

IReadOnlyList<CultureInfo>

The available cultures, sorted by culture name, with InvariantCulture (the neutral resources) first when present.

Exceptions

ArgumentNullException

resourceManager is null.

RegisterResourceManager(ResourceManager)

Registers a ResourceManager to be searched by search-all lookups. Managers are searched in registration order, and the first match wins; registering the same instance more than once has no effect. Adding a manager advances RefreshTriggeringRevision.

void RegisterResourceManager(ResourceManager resourceManager)

Parameters

resourceManager ResourceManager

The resource manager to add to the search set.

Remarks

Registration is needed only for search-all lookups - lookups without a resource manager: {l:Localize Key} and {l:LocalizeEnum} without ResourceManager in the UI packages, ILocalizer.Get("Key") and ILocalizer.Get(enumValue). Typed and scoped lookups need none.

Register the generated <Name>Keys.ResourceManager, the instance the typed keys use. Registering the designer's <Name>.ResourceManager works too, but it is a second instance of the same file with its own cache, and UnregisterResourceManager(ResourceManager) finds only the instance that was registered.

Register at application startup - in BuildAvaloniaApp in Avalonia, in App.OnStartup in WPF - or in a [ModuleInitializer] when search-all lookups must work in the WPF designer, which runs no startup code. See Registering resource files.

Localizer rejects a manager of exactly the type ResourceManager for which no resources exist under its base name, with an ArgumentException; a custom implementation need not follow that rule.

Exceptions

ArgumentNullException

resourceManager is null.

UnregisterResourceManager(ResourceManager)

Removes a previously registered ResourceManager from the search-all set, for example when the plugin or module that owns its strings is unloaded. Typed and scoped lookups are unaffected - they never consult the registration set. Removing a manager advances RefreshTriggeringRevision.

bool UnregisterResourceManager(ResourceManager resourceManager)

Parameters

resourceManager ResourceManager

The resource manager to remove from the search set.

Returns

bool

true when the manager was registered and has been removed; false when it was not registered.

Remarks

Managers are compared by reference: pass the instance that was registered, normally the generated <Name>Keys.ResourceManager. Another instance of the same file, such as the designer's <Name>.ResourceManager, is not found.

Exceptions

ArgumentNullException

resourceManager is null.

Events

CultureChanged

Occurs after CurrentCulture changes, carrying the previous and current culture. Subscribe to refresh values that are not resolved through a binding.

event EventHandler<CultureChangedEventArgs> CultureChanged

Event Type

EventHandler<CultureChangedEventArgs>

LookupFailed

Occurs when a lookup fails, before it returns the failure text: no resource file contains the key, or MessageFormatter threw while formatting its value. Reason tells the two apart. Subscribe to log missing or broken translations.

event EventHandler<LookupFailedEventArgs> LookupFailed

Event Type

EventHandler<LookupFailedEventArgs>

Remarks

Normal .NET resource fallback runs first, so a key that resolves from a parent or the neutral resources is not reported. A formatting failure is not specific to ICU MessageFormat: the default StringFormatMessageFormatter reports one for Broken {0, or for File {0} of {1} with one argument.

Handlers must not throw (see ILocalizer).