Suprnova v1.1.0
Added
-
Per-locale fallback chains.
LocalizationConfiggainsparents
(APP_LOCALE_PARENTS, comma-separatedchild=parentpairs, or the
chainable.parent(child, parent)builder): a locale can inherit from a
configured sibling before falling further back to the global
fallback_locale—pt-PTfrompt-BR,en-AUfromen-GB, and so
on, transitively.Lang::get/try_get/get_with/try_get_with/has
all walk the chain, current locale first, so this works for any
Translatordriver, not just the bundled one. A malformed pair, an
invalid locale, a child named twice, or a cycle (including a locale
naming itself as its own parent) fails loudly at config load rather
than degrading at request time.Served catalogs stay chain-flattened ahead of time:
FluentTranslator
now builds each locale's/_suprnova/lang/<locale>.ftlcatalog as a
fold — the embedded framework catalog at the bottom foren/en-*
locales, then the locale's configured parent chain, then its own
*.ftlfiles — so a chained locale is still one self-contained file
the browser fetches once, with no client-side chain awareness needed.
Flattening covers configured parents only; the terminal
fallback_localeis still aLang-facade-level fallback, not baked
into the served bytes.This makes delta-style catalogs practical: a
lang/pt-PT/directory
can hold only the handful of strings that actually differ from
lang/pt-BR/, rather than a full duplicate catalog. The merge that
makes it possible works at the Fluent AST level — a child's value
replaces the parent's, attributes merge by name (an override that
doesn't mention an attribute no longer loses it), select expressions
replace whole (CLDR plural categories are locale-dependent, so
variant-by-variant merging isn't coherent), and child-only entries
append. Seemanual/localization.md's new "Fallback chains" section
for the full contract.
Changed
LocalizationConfiggained theparentsfield.from_env()and
the builder are unaffected; a literal struct constructor (tests
building aLocalizationConfigby hand) needs one more field.- Served catalog text is now serializer-normalized for every locale,
and intra-locale multi-file merging (several.ftlfiles in one
locale directory) now goes through the same AST-level merge as parent
chains rather than simple bundle-overriding. Resolved translations are
unchanged except for the two strict improvements below; the
underlying bytes rotate regardless —ETag/?v=<hash>rotates once
on upgrade. The improvements: an override no longer silently drops
the attributes it doesn't mention, and an attributes-only override no
longer strips the message's own value (previously an error or a
fallback resolution; it now resolves to the earlier override's
value).