Skip to content

feat: i18n per-component message groups (#325) - #333

Merged
mvilacad merged 3 commits into
mainfrom
feat/325-i18n-the-whole-message-catalog-ships
Oct 17, 2026
Merged

mvilacad merged 3 commits into
mainfrom
feat/325-i18n-the-whole-message-catalog-ships

Conversation

@mvilacad

@mvilacad mvilacad commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Closes #325

Design

  • The catalog is split per group: i18n/groups/<name>.ts, each defineGroup("name", { en, "pt-BR" }) (50 groups). pt-BR stays typed against en (missing key = type error).
  • Components import only the groups they read and call useMessages(group, …) instead of useT(); t().group.key call sites are unchanged. Built-in locales travel inside each group, so SSR stays synchronous and a component pays for its own en + pt-BR strings only.
  • catalog.ts (rune-free) holds defineGroup, getGroup(group, locale, override?) and the registerLocale registry; resolution order, deep-merge overrides, region fallback (es-MX → es → en) and "registered locale replaces built-in" are unchanged. registerLocale invalidates the caches.
  • all.ts lists every group and backs Messages, public getMessages() and useT() (full catalog, bundled only if imported). I18nProvider, setLocale, registerLocale, useLocale unchanged.
  • scripts/size-lib.ts: bundling helpers extracted from size-limit.ts so tests reuse them.
  • AGENTS.md i18n section and the i18n docs page updated (new authoring rule); changeset: minor.

Size (gzip, esbuild min, Svelte runtime included)

entry before after limit before → after
floor: Divider only 17.57 kB 17.57 kB 18.42 → 18.42 kB
root: Button only 27.89 kB 23.91 kB (-3.98) 27.93 → 25.11 kB
root: AppShellLayout 39.88 kB 36.07 kB (-3.81) 39.94 → 37.88 kB
./seo 30.01 kB 30.01 kB unchanged
styles/*.css unchanged unchanged unchanged

Before: dist/i18n/pt-BR.js + en.js were 13.1 kB minified (uncompressed) of Button's bundle.

Test-first (tests/i18n-split.test.ts)

Before the change:

(fail) Button-only bundle contains none of the other components' strings
- [] + ["Command palette","Paleta de comandos","Search failed","Selected values","Valores selecionados","Module navigation","Resize navigation panel","Replay","On this page","Could not copy"]
(fail) a component brings its own group, not its neighbours'   (Expected not to contain "Module navigation")
 1 pass / 2 fail

After: 10 pass 0 fail (i18n-split + i18n + i18n-register).

Verification

  • bun run test:browser: 154 files, 1555 tests pass
  • bun run test:unit: 824 pass; test:ssr: 3 pass
  • bun run validate: ok (build, themes, token lint, biome, types package+site, unit, size)

@mvilacad mvilacad changed the title feat: i18n: the whole message catalog ships with every root import (Button budget grows with every new component string) feat(i18n): split the message catalog per group Oct 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Site preview: https://pr-333.codeatlas-ui.pages.dev

@mvilacad
mvilacad force-pushed the feat/325-i18n-the-whole-message-catalog-ships branch from 9e363b5 to b164aa7 Compare October 17, 2026 15:12
@mvilacad mvilacad changed the title feat(i18n): split the message catalog per group feat: i18n per-component message groups (#325) Oct 17, 2026
@mvilacad
mvilacad force-pushed the feat/325-i18n-the-whole-message-catalog-ships branch from b164aa7 to ec43cba Compare October 17, 2026 15:17
@mvilacad
mvilacad marked this pull request as ready for review October 17, 2026 15:17
@mvilacad
mvilacad merged commit c23cff4 into main Oct 17, 2026
@mvilacad
mvilacad deleted the feat/325-i18n-the-whole-message-catalog-ships branch October 17, 2026 15:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

i18n: the whole message catalog ships with every root import (Button budget grows with every new component string)

1 participant