Zamburak uses injection-first localization. The host application owns locale negotiation and loader lifecycle; Zamburak never reads process locale environment variables or maintains mutable global state.
Host-owned loader setup
Create a FluentLanguageLoader in the host application and pass it through a
FluentLocalizerAdapter that implements the Localizer trait:
use zamburak_core::i18n::{FluentLocalizerAdapter, Localizer};
use i18n_embed::fluent::FluentLanguageLoader;
let loader: FluentLanguageLoader = /* host-configured loader */;
let localizer: Box<dyn Localizer> = Box::new(
FluentLocalizerAdapter::new(loader),
);
When no localization backend is configured, use the deterministic fallback:
use zamburak_core::i18n::NoOpLocalizer;
let localizer = NoOpLocalizer;
Loading Zamburak embedded assets
Zamburak publishes embedded .ftl translation assets via Localizations. Load
them into the host-owned loader so Zamburak messages are available:
use zamburak_core::i18n::Localizations;
loader.load_assets(&Localizations, &requested_locales);
Resolution order is:
- host application catalogue entries,
- Zamburak bundled entries for the requested locale,
- Zamburak bundled
en-USentries, - caller-provided fallback text.
Rendering localized diagnostics
Zamburak diagnostics expose a render_localized method that accepts an injected
&dyn Localizer plus caller fallback copy:
let message = diagnostic.render_localized(&localizer, "fallback text");
Formatting failures and missing translations fall through the resolution chain
and always produce deterministic output. See
adr-002-localization-and-internationalization-with-fluent.md for the full
design rationale.