easyi18n library

easyi18n - runtime SDK.

Wrap your MaterialApp with Easyi18nScope and translate with context.tr('Welcome {name}', args: {'name': n}). Strings resolve from an offline floor (baked assets) and hot-update from the delivery manifest with no extra code. See the README for setup.

Classes

BundleStore
Persistence for delivered bundles + delivery state. Bundles are content-addressed (locale + bundleHash), so a write is idempotent and a stale hash never collides with a fresh one. Implementations must make saveBundle atomic (no torn reads).
CdnClient
Thin HTTP client for the delivery origin (CDN or backend-origin - the SDK is agnostic, it only follows the URLs the manifest hands it). Injectable http.Client so tests run against a MockClient.
DeliveryService
Orchestrates offline-first delivery: load the last-good persisted bundles at startup, then conditionally refresh against the manifest and download only the bundles whose content address changed. Throws nothing on a network/parse failure during refresh except a DeliveryException the caller swallows - hot-update is best-effort, the floor always serves.
DeliveryState
What the SDK persists between launches so it can serve the last-good translations offline before the network answers: the manifest validator (ETag) and the current {locale → bundleHash} pointer for a channel.
Easyi18nController
The runtime brain: owns the per-locale BundleStacks and resolves tr(). It is a ChangeNotifier so the Flutter layer rebuilds on a hot-swap.
Easyi18nScope
Wrap your app's MaterialApp with this to enable context.tr(...). Identify the project either by its opaque projectId, or by the human-readable workspace handle + project slug pair (F1 — mirrors the dashboard's /@handle/project URL, so a shipped app bakes stable identifiers). Exactly one of the two forms must be provided. Everything else has a sensible default: the production origin, the production channel, an en floor, and baked assets at assets/easyi18n/{locale}.json.
FileBundleStore
Filesystem-backed BundleStore for IO platforms (desktop/mobile). Layout under dir:
InMemoryBundleStore
In-memory store: the always-available fallback (used on platforms without a filesystem, and in tests). Persists nothing across launches - the baked asset floor covers cold starts there.
LazyBundleStore
Wraps a store that is still being created (e.g. path_provider is async) so the rest of the SDK can be wired synchronously. Each call awaits the future once; resolution is cheap thereafter.
RefreshResult
The outcome of a DeliveryService.refresh: the bundles that changed (to swap into the hot layer) and the full set of locales the manifest advertises (so the runtime can discover languages it wasn't told about up front).

Constants

kDefaultBaseUrl → const String
Default delivery origin (overridable via Easyi18nScope.baseUrl).

Functions

localeFromTag(String tag) → Locale
A delivery locale tag (en, pt-br, zh-hant, es-419, sr_Latn_RS) as a Locale with Flutter's subtag casing, so it compares equal to the platform's own. A part outside language-region ends the parse.

Typedefs

BakedLoader = Future<Bundle?> Function(String locale)
Loads the offline-floor bundle for a locale (e.g. a shipped asset). Returns null when none is baked for that locale.

Exceptions / Errors

DeliveryException
Raised when a delivery fetch fails in a way the caller should treat as "no update available" (network error, bad status, or a content-integrity violation). Hot-update is best-effort: the offline floor still serves.