libraryPackage manifestv3.0.4

lib.translation-runtime

Framework-independent ContractSpec translation runtime

@lssm-tech/lib.translation-runtime
Source, release and verification context

Source snapshot bcc79fcc · Declared package version 3.0.4. This page combines the checked-in package guide and manifest; commands and runtime behavior were not executed in this review.

Package source ↗ Manifest ↗
servernode
EXPLORE THE PACKAGE

See where this package fits.

Follow a declared connection, inspect an import, then open the source guide when you need the detail.

THIS PACKAGElib.translation-runtimeplatform

Arrows point from a package to its direct dependency. Each count is derived from the captured manifests.

3 déclarationsSELECT TO INSPECT

@lssm-tech/lib.translation-runtime

Framework-independent runtime for ContractSpec translation contracts.

Static catalog diagnostics, translation validation (including ICU, readability, keyword density and locale validation), and tenant override declarations are available from ./contracts/diagnostics, ./contracts/validation, and ./contracts/tenant. Historical ContractSpec imports forward to the same implementations. Static diagnostics retain their distinct contract namespace; the existing runtime ./diagnostics API is unchanged. Private source partitions preserve validation ordering, issue codes, defaults and the nominal TranslationRegistry and TranslationValidationError identities.

@lssm-tech/lib.contracts-spec-core/translations/spec remains the canonical source of truth for TranslationSpec contracts, metadata, ownership, versions, locale variants, validation, fallback declarations, and override policy. This package consumes those specs at runtime to resolve, format, cache, load, diagnose, and serialize translations across server code, React, React Native, CLIs, and tests.

Boundaries

  • Spec layer: @lssm-tech/lib.contracts-spec-core/translations/spec
  • Runtime layer: this package
  • Formatter engine: MessageFormatter, with createIntlMessageFormatter() backed by FormatJS/intl-messageformat
  • Adapters: React/design-system/i18next integrations consume this runtime and are optional downstream layers

Example

Resolve messages through the createI18nFactory stack, with one factory per stable TranslationSpec.meta.key:

ts
import { createI18nFactory } from "@lssm-tech/lib.translation-runtime/contracts/i18n-factory";
import { cartEn, cartFr } from "./catalogs";

const cartI18n = createI18nFactory({
  specKey: "cart.messages",
  catalogs: [cartEn, cartFr],
  supportedLocales: ["en", "fr"],
  defaultLocale: "en",
});

cartI18n.create("fr-FR").t("cart.greeting", { name: "Alice" });

create() resolves the requested locale within supportedLocales ("fr-FR" falls back to "fr", then to defaultLocale), so keep that list aligned with the locale of each catalog. A missing message falls back to the catalog's declared fallback locale, then to the key itself. Root catalogs declare no fallback; only variants point at their parent locale.

t() interpolates {placeholder} values only. Format ICU messages (plural, select, selectordinal, number, date) with the formatter engine:

ts
import { createIntlMessageFormatter } from "@lssm-tech/lib.translation-runtime/formatters/intl-messageformat";

const formatter = createIntlMessageFormatter();
formatter
  .compile({
    id: "cart.itemCount",
    locale: "en",
    message: "{count, plural, one {# item} other {# items}}",
  })
  .format({ count: 3 }); // "3 items"

Removed in 1.0.0. The createTranslationRuntime engine, its ./runtime, ./registry and ./runtime-helpers subpaths, and the preference override-layer builders (createTranslationRuntimeFromPreferences and related helpers) no longer exist. Migrate render paths to createI18nFactory. resolveTranslationPreferenceContext (./preferences) still resolves app, workspace, team, user and request locale precedence.

SSR and hydration

The factory stack produces a versioned, framework-neutral I18nFactoryHydrationPayload that never aliases live catalog references:

ts
import {
  createI18nFactory,
  createI18nFactoryFromHydrationPayload,
} from "@lssm-tech/lib.translation-runtime/contracts/i18n-factory";

// Server (RSC / route handler)
const factory = createI18nFactory({
  specKey: "cart.messages",
  catalogs: [cartEn, cartFr, cartEs],
  supportedLocales: ["en", "fr", "es"],
  defaultLocale: "en",
});
const payload = factory.hydrationPayload(requestLocale);
// Transfer payload to the client (inline script, RSC stream, etc.)

// Client: rehydrate without refetching or renegotiating locale
const hydrated = createI18nFactoryFromHydrationPayload(payload);
hydrated.create(payload.snapshot.locale).t("cart.greeting", { name: "Alice" });

The payload carries only the catalogs for the resolved locale and its declared fallback chain. createI18nFactoryFromHydrationPayload rebuilds the factory with the default en/fr/es locale set and en default, so create the client instance with payload.snapshot.locale and keep catalog locales within that set when you rehydrate.

validateI18nFactorySnapshot(snapshot) and validateI18nFactoryHydrationPayload(payload) return human-readable error strings for partial or unknown payloads before hydration.

The ./snapshot helpers (createTranslationHydrationPayload, createTranslationSnapshotStreamChunk, validateTranslationHydrationPayload) serialize a host-assembled TranslationRuntimeSnapshot, which the i18next adapter can consume. createTranslationSnapshotStreamChunk(snapshot) returns a cloned payload that is safe to enqueue before later async catalog loads; validateTranslationHydrationPayload(payload) returns invalid_snapshot diagnostics for unsupported payloads.

Shard-scoped catalog loading

src/loader.ts accepts an optional specKeys? array on TranslationBundleLoadRequest to load a subset of catalogs per route. Use loadShardDelta to fetch only the incremental shards needed on navigation:

ts
import {
  computeShardDelta,
  createStaticBundleLoader,
  loadShardDelta,
} from "@lssm-tech/lib.translation-runtime/loader";

const delta = computeShardDelta(alreadyLoadedSpecKeys, requiredSpecKeys);
// delta = requiredSpecKeys not yet loaded

const bundleLoader = createStaticBundleLoader(allCatalogs);
const newCatalogs = await loadShardDelta(bundleLoader, {
  loaded: alreadyLoadedSpecKeys,
  required: requiredSpecKeys,
  locales: [locale],
});

Absent specKeys ⇒ all keys pass (existing {specKey, locales} semantics unchanged).

Optimization surfaces (Model A — per-request inline payload)

Scope: per-request inline HTML reduction. Catalogs remain bundled and cached in the JS bundle (shipped once per deploy). These optimizations reduce the per-request inline <script> hydration payload — NOT total transferred bytes. The ~90% total-bytes win requires Model B (catalog code-splitting + load-bearing inline payload). See .omc/plans/ralplan-translation-catalog-sharding-ssr.md § "Optimization Wave — ARCHITECTURE DECISION: Model A".

O2/O3 — Slim inline payload + value-pool dedup

Enable slim mode on your scoped hydration builder to strip spec metadata from each shard before serialization. The value-pool dedup step folds message values appearing ≥2× into a values[] pool; expansion is automatic on rehydration.

Realized: / en 96.6 KB → 37.8 KB (−61%); /companyos/founder en 93.9 KB → 35.6 KB (−62%); fr routes ~−60%. No-flash (AC1) re-proven through slim+dedup path. CI budget gates: single-locale ≤ 64 KB, with-fallback ≤ 128 KB.

O3 adds only ~2% over O2 (five lanes have disjoint key namespaces; ~53 pooled value strings). The projected ~41 KB en-fallback win requires a shared-base architecture follow-up.

O4 — Precompiled ICU AST fast-path (./precompile subpath)

At bundle build time, call buildPrecompiledIcuCatalogFromSpecs(specs) from @lssm-tech/lib.translation-runtime/precompile over your TranslationSpec[] set. This produces a PrecompiledIcuCatalog with FormatJS IR AST entries for every message. Pass createPrecompiledIcuLookup(catalog) as the precompiled option to createIntlMessageFormatter to activate the parse-skip fast-path:

ts
// build step (runs once at bundle time, e.g. in your bundler plugin)
import {
  buildPrecompiledIcuCatalogFromSpecs,
  createPrecompiledIcuLookup,
  serializePrecompiledIcuCatalog,
} from "@lssm-tech/lib.translation-runtime/precompile";

const catalog = buildPrecompiledIcuCatalogFromSpecs([enMessages, frMessages]);
// optionally serialize and ship as a build asset
const serialized = serializePrecompiledIcuCatalog(catalog);

// runtime (wire the formatter with the precompiled lookup)
import { parsePrecompiledIcuCatalog, createPrecompiledIcuLookup } from "@lssm-tech/lib.translation-runtime/precompile";
import { createIntlMessageFormatter } from "@lssm-tech/lib.translation-runtime/formatters/intl-messageformat";

const precompiled = createPrecompiledIcuLookup(parsePrecompiledIcuCatalog(serialized));
const formatter = createIntlMessageFormatter({ precompiled });
// formatter skips ICU re-parsing for any message with a precompiled entry

Additive opt-in — messages without a precompiled entry fall back to the standard parser transparently. Scope: formatter-path latency win only. Factory proof routes use {placeholder} interpolation (no ICU); O4 benefits apply to ICU-heavy catalogs (plural/select/date/number).

O5b (#17) — Scoped-hydration intersection (wired, currently no-op)

App-layer wiring — not a translation-runtime export. intersectScopedI18nHydration and isEffectiveReachabilityMap are implemented in web-application-monolith's scoped hydration path (packages/apps/web-application-monolith/src/i18n/scoped-hydration.reachability.ts and reachability-map.loader.ts). They compose with the loader's loadShardDelta but are not themselves library APIs. Do not import them from @lssm-tech/lib.translation-runtime.

Wired into getRequestI18n and fail-safe (pruned keys resolve via the bundled combined runtime — no flash). Currently no-op (77/129 t() call sites use dynamic dispatch; scanner emits retain-all map). Auto-activates if a precise reachability map ships. Zero regression.

O5 (#14) — Dead-key audit tool (@lssm-tech/tool.i18n-prune)

@lssm-tech/tool.i18n-prune in packages/tools/ walks t('key') call sites against a RouteShardManifest and reports dead keys per route. Use it in CI to surface dead-key drift. It does not drive the runtime inline payload under Model A.

Optional i18next adapter

i18next is an optional downstream adapter, not the canonical ContractSpec model. Import it through the dedicated subpath so core runtime consumers do not load i18next:

ts
import { createInstance } from "i18next";
import {
  createI18nextInitOptions,
  exportContractSpecToI18next,
} from "@lssm-tech/lib.translation-runtime/i18next";

const exported = exportContractSpecToI18next([cartEn, cartFr], {
  defaultLocale: "en",
  lng: requestLocale,
  assumeIcuFormatter: true,
});
const { options, diagnostics } = createI18nextInitOptions(exported);
const i18next = createInstance();

await i18next.init(options);

The adapter exports resources as { [locale]: { [namespace]: { [messageKey]: string } } }. TranslationSpec.locale becomes the i18next language, while the namespace defaults to the stable TranslationSpec.meta.key. Flat ContractSpec keys such as "cart.items" remain flat because generated init options set keySeparator: false.

ContractSpec ICU messages are exported intact. i18next does not use ICU as its default JSON format, so apps that call i18next.t() for ICU plural/select/selectordinal messages must install and configure an ICU-capable i18next format plugin such as i18next-icu. The adapter reports i18next_icu_plugin_required unless you explicitly acknowledge that formatting layer.

Utiliser exportTranslationSnapshotToI18next(snapshot) when the host already assembles a TranslationRuntimeSnapshot (./snapshot); it carries the snapshot locale, default locale and fallback chain into the init options. For SSR, export from the same catalogs and locale used by the server render and reuse those resources/options on the client. Do not let client-only language detection renegotiate the first hydrated render. For React Native, pass the host-selected locale explicitly; the adapter does not use DOM APIs or browser storage.

React Native

The core runtime uses no DOM APIs. Locale detection is host-owned; pass the device or user locale to factory.create(locale), or negotiate it first with negotiateLocale({ requestedLocales, supportedLocales, defaultLocale }) from ./locale. Ensure the host JS engine provides the required Intl APIs or install platform polyfills before using the default formatter.

Compatible factory and registry ownership

The registry and BCP 47 contract helpers live in this package under ./contracts/registry and ./contracts/locale. The pure package i18n factory and its hydration snapshot are owned by Core (@lssm-tech/lib.contracts-spec-core/translations/i18n-factory and ./translations/i18n-factory-snapshot), so domain specs can use them; ./contracts/i18n-factory and ./contracts/i18n-factory-snapshot here forward those same implementations, with unchanged resolution. Historical ContractSpec translation imports forward these same implementations. The existing runtime root and locale exports retain their names and behavior; use the explicit contract subpaths for the factory stack. Translation declarations come from @lssm-tech/lib.contracts-spec-core/translations/spec.

Translation catalog model ownership

The unchanged Locale, MessageKey, TranslationEntry, TranslationCatalogMeta, PlatformTranslationCatalog and BlueprintTranslationCatalog declarations are canonical at @lssm-tech/lib.translation-runtime/contracts/catalog. Historical @lssm-tech/lib.contracts-spec/translations/catalog imports forward these same declarations. The model move adds no loading, formatting or runtime initialization behavior; Core continues to own TranslationSpec.

Declared capabilities.

Lib Translation Runtime

Framework-independent ContractSpec translation runtime

Use it to

  • Adopt framework-independent contractspec translation runtime

Requires

  • TypeScript

Choose another boundary when

  • The @lssm-tech/lib.translation-runtime package constraints do not match the target runtime or platform.

@lssm-tech/lib.translation-runtime

@lssm-tech/lib.translation-runtime/diagnostics

@lssm-tech/lib.translation-runtime/direction

@lssm-tech/lib.translation-runtime/fallback

@lssm-tech/lib.translation-runtime/formatter

@lssm-tech/lib.translation-runtime/formatters/intl-messageformat

@lssm-tech/lib.translation-runtime/i18next

@lssm-tech/lib.translation-runtime/loader

@lssm-tech/lib.translation-runtime/locale

@lssm-tech/lib.translation-runtime/overrides

@lssm-tech/lib.translation-runtime/precompile

@lssm-tech/lib.translation-runtime/preferences

@lssm-tech/lib.translation-runtime/contracts/catalogLocale, MessageKey, TranslationEntry, TranslationCatalogMeta, PlatformTranslationCatalog, BlueprintTranslationCatalog

Imports and export paths.

21 entries

These are package-manifest entry points. Named symbols listed above come from the capability catalogue; this is not an exhaustive TypeScript symbol reference.

21 imports

Dependencies and related packages.

Runtime dependencies 3
@formatjs/icu-messageformat-parser
catalog:i18n
intl-messageformat
catalog:i18n
Development dependencies 4
i18next
catalog:i18n
typescript
catalog:

Package scripts.

Commands declared by this package. Review its setup requirements before running them; no command here was executed by this review.

publish:pkgbun publish --tolerate-republish --ignore-scripts --verbose
publish:pkg:canarybun publish:pkg --tag canary
buildcontractspec-bun-build build
build:bundlecontractspec-bun-build transpile
build:typescontractspec-bun-build types
cleanrm -rf dist
devcontractspec-bun-build dev
lintbun run lint:fix
lint:fixnode ../../../../scripts/biome.cjs check --write --unsafe --only=nursery/useSortedClasses . && node ../../../../scripts/biome.cjs check --write .
lint:checknode ../../../../scripts/biome.cjs check .
prebuildcontractspec-bun-build prebuild
testbun test
typechecktsgo --noEmit
Votre vue

Make room for your context.

Shape the presentation around this moment. You can change it whenever you need.

Votre contexte

The different parts of you

Choose a starting point

Un mélange utile de contexte, de visuels et de guidage discret.

Tune each dimension
Each dimension can change independently. Product permissions and available actions stay unchanged.

Support the way you begin and return

Tune your support

Confort de lecture

Choisir votre langue

La langue de l’interface change uniquement le texte. Les marchés, les prix et les parcours conservent leurs propres paramètres.

Couverture des traductions

Une partie du contenu est affichée en anglais.

Navigation151
Graphe616
Catégories378
Portfolio833
Exemples2 035
Aperçu de la source1 542

D’autres traductions seront ajoutées à mesure que le contenu sera relu.

Cette préférence est enregistrée dans ce navigateur.

Rechercher sur le site

Des points de départ utiles

Aucun résultat. Essayez une expression plus courte, un nom d’opération ou un autre périmètre de recherche.

UN PEU DE PLACE POUR EXPLORER

Trouvez quelque chose à explorer.

Ouvrez un aperçu détaillé sur cette page, essayez une autre perspective ou suivez le détail vers sa propre page.

Fonctionnement des aperçus et des commandes
01

Regarder avant de partir

Survolez un lien ou sélectionnez-le avec Tab pour voir un aperçu. Cliquer sur le lien d’origine ou appuyer sur Entrée ouvre toujours sa destination.

02

Rester dans le contexte

Entrez dans l’aperçu pour explorer ses sections. Depuis un lien sélectionné, utilisez Alt + ↓ pour y entrer au clavier. Échap le ferme.

03

Ouvrir les possibilités

Les lignes dépliables, les choix de perspective et les commandes mises en évidence révèlent davantage. Votre vue adapte le confort de lecture et le contexte exploré.

Un bouton séparé pour voir de plus près

Affichez de petits boutons d’aperçu à côté des liens quand l’espace le permet. Touchez l’œil pour examiner ou le lien pour y aller directement. Ce choix reste dans cet onglet.

Aucun historique de navigation n’est collecté. La réduction des animations suit votre appareil et Votre vue.