[Perf/i18n] Deliver Concept Reference overlays per active locale (not all-languages-baked) #304

Open
opened 2026-07-01 15:28:47 +00:00 by spikerj · 0 comments
Owner

Problem

Each language playground bakes its Concept Reference dictionary and every locale overlay into its lazy route chunk. The English source + each locale overlay are provided unconditionally via useValue, so every user downloads every locale's overlay for a playground regardless of the language they're using.

Today that's only es (~1.5× overhead on an already-lazy chunk), so the cost is small. But it grows as O(all UI languages): add fr/de/pt and each playground chunk carries all overlays for all users.

Current state (measured)

Provided in each runner (e.g. libraries/features/dev-tools-cpp-runner/src/lib/cpp-runner.ts):

{ provide: LANGUAGE_CONCEPT_REGISTRY, useValue: CPP_CONCEPTS },
{ provide: LANGUAGE_CONCEPT_TRANSLATIONS, useValue: { es: CPP_CONCEPTS_ES } },

Sizes (data + es overlay, baked into the lazy chunk):

  • cpp: 72,113 + 49,290 bytes (73 concepts)
  • c: 65,361 + 46,261 bytes (67 concepts)
  • csharp: 44,305 + 19,479 bytes (80 concepts)
  • python: 28,865 + 16,238 bytes (44 concepts)

Consumer: libraries/platform/clang-runtime/src/lib/language-concept-pane.component.ts injects LANGUAGE_CONCEPT_TRANSLATIONS with { optional: true } and picks the active locale from TranslocoService. The token is already optional + locale-keyed.

Proposal

Deliver only the active locale's overlay instead of baking all locales:

  • Option A (simplest): provide a loader that dynamic-import()s the locale overlay for the current Transloco lang (e.g. import('./cpp-concepts.es')), so English users never download es and vice-versa. Overlays become their own split chunks.
  • Option B: move overlays to fetched JSON assets (mirrors the Transloco scope model in #303) behind a tiny cache.

The registry service builds an O(1) index at construction, so overlays only need to be present before the pane renders — an async load with a graceful "English until loaded" fallback is acceptable.

Why this is non-breaking

  • The consumer already treats translations as { optional: true } and falls back to English prose when an overlay is missing — an async/absent overlay degrades to English, never errors.
  • English concept data (*_CONCEPTS) stays exactly as-is; only the overlay delivery changes.

Acceptance criteria

  • Opening a playground in English does not download that playground's non-English concept overlays.
  • Switching UI language loads the matching overlay (or falls back to English if absent) with no pane error.
  • Existing concept-pane + registry specs still pass.

Priority

Deferred / low now. With only es today the payoff is marginal. Trigger: schedule this the moment a 3rd UI language is added (or if playground chunk size becomes a concern). Filed now so the O(languages) trap is tracked rather than rediscovered later. Related: #213 (concept pane), #303 (same per-locale delivery idea for Transloco).

(Local-hosting only — no CDN.)

## Problem Each language playground bakes its Concept Reference dictionary **and every locale overlay** into its lazy route chunk. The English source + each locale overlay are provided unconditionally via `useValue`, so **every user downloads every locale's overlay** for a playground regardless of the language they're using. Today that's only `es` (~1.5× overhead on an already-lazy chunk), so the cost is small. But it grows as **O(all UI languages)**: add `fr`/`de`/`pt` and each playground chunk carries all overlays for all users. ## Current state (measured) Provided in each runner (e.g. `libraries/features/dev-tools-cpp-runner/src/lib/cpp-runner.ts`): ```ts { provide: LANGUAGE_CONCEPT_REGISTRY, useValue: CPP_CONCEPTS }, { provide: LANGUAGE_CONCEPT_TRANSLATIONS, useValue: { es: CPP_CONCEPTS_ES } }, ``` Sizes (data + es overlay, baked into the lazy chunk): - cpp: `72,113` + `49,290` bytes (73 concepts) - c: `65,361` + `46,261` bytes (67 concepts) - csharp: `44,305` + `19,479` bytes (80 concepts) - python: `28,865` + `16,238` bytes (44 concepts) Consumer: `libraries/platform/clang-runtime/src/lib/language-concept-pane.component.ts` injects `LANGUAGE_CONCEPT_TRANSLATIONS` with `{ optional: true }` and picks the active locale from `TranslocoService`. The token is already optional + locale-keyed. ## Proposal Deliver only the **active locale's** overlay instead of baking all locales: - Option A (simplest): provide a loader that dynamic-`import()`s the locale overlay for the current Transloco lang (e.g. `import('./cpp-concepts.es')`), so English users never download `es` and vice-versa. Overlays become their own split chunks. - Option B: move overlays to fetched JSON assets (mirrors the Transloco scope model in #303) behind a tiny cache. The registry service builds an O(1) index at construction, so overlays only need to be present before the pane renders — an async load with a graceful "English until loaded" fallback is acceptable. ## Why this is non-breaking - The consumer already treats translations as `{ optional: true }` and falls back to English prose when an overlay is missing — an async/absent overlay degrades to English, never errors. - English concept data (`*_CONCEPTS`) stays exactly as-is; only the overlay delivery changes. ## Acceptance criteria - [ ] Opening a playground in English does **not** download that playground's non-English concept overlays. - [ ] Switching UI language loads the matching overlay (or falls back to English if absent) with no pane error. - [ ] Existing concept-pane + registry specs still pass. ## Priority **Deferred / low now.** With only `es` today the payoff is marginal. **Trigger: schedule this the moment a 3rd UI language is added** (or if playground chunk size becomes a concern). Filed now so the O(languages) trap is tracked rather than rediscovered later. Related: #213 (concept pane), #303 (same per-locale delivery idea for Transloco). _(Local-hosting only — no CDN.)_
spikerj added the enhancement label 2026-07-01 15:28:47 +00:00
Sign in to join this conversation.