Release v0.8.0
[0.8.0] — 2026-07-06
Readable keys + lazy catalogs. Opt-in readable message ids (t.id, <Trans id> extraction) and lazy catalog loading in the core runtime — both born from dogfooding. Ready to publish. No breaking changes.
Added
- Readable keys, opt-in (
@verbaly/compiler+verbaly): hashed keys stay the zero-config default; explicit ids are per-message opt-in. Dotted ids (inbox.title) are the namespace convention — catalogs stay flat JSON.t.id('inbox.title')`Hello ${name}`→ extracted under the explicit key, rewritten tot("inbox.title", { name })(member receivers preserved:i18n.t.id(…)→i18n.t(…)). Dynamic ids (t.id(someVar)) are left untouched.<Trans id="inbox.title">Hello {user.name}</Trans>(id + children, no other props) → extracted under the explicit id with the same write-in-place machinery (values/components, JSX whitespace semantics, safe bails → falls back to used-key).<Trans id>without children stays runtime-first, unchanged.- Runtime
t.id(key)returns a template tag that formats the inline source — identical tot`…`pre-compile, so code runs before extraction. - Duplicate explicit ids with different texts surface through the existing key-collision warning.
- Lazy catalog loaders (
verbalycore):createVerbaly({ loaders: { es: () => import('./locales/es.json') } }).loadLocale(locale)— BCP-47 narrowing (es-MX→es), in-flight dedupe, unwraps moduledefault, idempotent; rejects propagate and retry is possible.setLocaleauto-loads a pending catalog (fire-and-forget: UI shows fallback, re-renders when the catalog lands; warn-once on load failure). Flash-free switch:await v.loadLocale('es'); v.setLocale('es').localesgetter now returns loaded ∪ loadable locales — switchers can list languages before any catalog loads.
Changed
- Virtual module (
@verbaly/vitecodegen): per-localeimport()s now flow through coreloaders; generatedsetLocale=await v.loadLocale(l); v.setLocale(l)(same behavior, less generated code). Generatedverbaly.d.tstypest.id.
Notes
- New public API:
VerbalyOptions.loaders(+ exportedLocaleLoadertype),Verbaly.loadLocale,TFunction.id.localesgetter behavior extended (loaded ∪ loadable) — additive, not breaking. @verbaly/vite0.8.0 requiresverbaly0.8.0 (peerworkspace:^rewrites to^0.8.0on publish).- Dogfooding origin:
verbaly-webhand-rolled lazy catalogs (ensure()+ loadedSetinscripts/i18n.ts) — that pattern is now core, like 0.4.0's rich text. - 187 tests (core 88 · compiler 65 · vue 10 · svelte 9 · react 8 · vite 7). Bench re-run: lookup 38×, interpolation 10.6×, plural 4.7×, currency 4.9× vs i18next.