Localization
Text in a view is translated by key against the session's language — a property marked [Translatable]
holding a translation key renders as its translated text, both when the server renders it statically and when
it is patched live.
Translation sources
application.AddLocalizationSource(dictionary) registers an in-memory source: a dictionary keyed by
language, then by key, each value the translated text.
internal static class DemoTranslations
{
public static IReadOnlyDictionary<string, IReadOnlyDictionary<string, string>> Build()
=> new Dictionary<string, IReadOnlyDictionary<string, string>>
{
["en"] = new Dictionary<string, string>
{
["demo.home.header"] = "NE.Standard.UI",
["demo.home.description"] = "A server-driven UI framework...",
}
};
}
application.AddLocalizationSource(DemoTranslations.Build());
That overload wraps the dictionary in the built-in DictionaryTranslationSource. AddLocalizationSource(ITranslationSource source) registers any other source — implement ITranslationSource (Languages, TryTranslate(language, key, out value)) for one backed by a database, a .resx set, or a translation service, and register it the same way, or as an
ordinary DI service (ITranslationSource is resolved from the container too). Sources are consulted most-recently-added
first, so a later AddLocalizationSource call can override a key an earlier one set.
UILocalizationOptions
application.ConfigureLocalization(o => o.DefaultLanguage = "en");
DefaultLanguage (default "en") is the fallback language used when a translation is missing for the
session's requested language, and the language a brand-new session starts in.
The session's language
UserSessionState.Language is the session's current language, read by every translation the session's
requests make. Change it through Context.UpdateSessionAsync, the same way any other session field changes:
[UICommand]
public ValueTask SetLanguage(string language)
=> Context.UpdateSessionAsync(session => session with { Language = language });
[Translatable]
[Translatable] marks a component or item-model property whose value is a translation key rather than
literal text — TextComponent.Title, TextBaseItem.Title/Icon, BadgeItem's text properties, and most
other text-bearing properties on the built-in components and models carry it. A value on such a property is
translated at render time; a plain literal that happens not to be a registered key renders unchanged (a
lookup miss falls back to the key itself — see below), which is what makes writing "Add one" directly, with
no translation source configured, work exactly as shown in getting started.
A static item's [Translatable] fields are translated on the static-rendering path too, not only through
a live binding — an author-declared MenuItem or TabItem whose Title holds a translation key renders
translated even though it was never bound to the controller. This is what makes a static navigation menu, or
any other author-declared item collection, fully localizable.
Context.Translate
A controller translates a key directly with Context.Translate(key), using the current session's language —
useful for text going into a ShowNotificationEffect or any other place text is built in code rather than
carried by a [Translatable] property:
[UICommand]
public UICommandResult Save()
=> UICommandResult.Ok([new ShowNotificationEffect(Context.Translate("demo.save.done"), UIColorStyle.Success)]);
The framework's own words
UIStrings is the vocabulary the framework's own chrome uses — a date picker's "Today", a tab strip's "More
tabs", a file input's "Uploading… %" — each a translation key (UIStrings.PickerToday,
UIStrings.TabsMore, …) with English text in UIStrings.English. Override one the same way you translate
your own text: register the same key in your own ITranslationSource.
application.AddLocalizationSource(new Dictionary<string, IReadOnlyDictionary<string, string>>
{
["en"] = new Dictionary<string, string> { [UIStrings.TabsMore] = "More tabs…" },
["fr"] = new Dictionary<string, string> { [UIStrings.TabsMore] = "Plus d'onglets" }
});
Fallback order
A lookup tries, in order: the requested language in the application's own sources, then the application's
DefaultLanguage in those same sources, then UIStrings' built-in English (which answers for any
requested language, so a framework word the application has not translated still reads instead of showing its
key), and finally the key itself if nothing answered. An application's own text in its default language always
outranks the framework's built-in English — the framework's words are a base to override, not a ceiling.