Concepts, value, and typical clone scenarios — less code.
Concepts, value, and typical clone scenarios — less code.
Preparing Ring content
Preparing Ring content
Preparing Ring content
Use Founder / Developer tabs in the docs sidebar to filter this page. Shared sections apply to both audiences.
Ring Platform uses env-driven locale configuration and next-intl with localePrefix: 'as-needed'. Translation JSON lives under locales/{locale}/. Request-time merge then layers an optional pack file and an optional clone overlay on top of the cached Layer1 corpus.
| Stage | When it runs | Who owns the strings |
|---|---|---|
| Layer1 locale files | Cached in buildCachedLocaleMessages ('use cache') | Community ring/web/locales/ |
locales/{locale}/pack.json | Per request, only if presets.pack is set | L2 pack overwrite at compose |
| Clone overlay | Per request, only if overlay.featureId is set | appendOverlayMessages via lib/overlay/registry.ts |
Later leaf keys win. Nested objects merge (mergeJsonRecords in lib/i18n.ts). A clone can override one string without replacing the whole pack namespace.
Source of truth: lib/locale-config.ts — imported by routing, SEO, preferences, and static generation. Fallback locale list when env is empty: en, uk, ru, es, de.
You do not paste vertical copy into Layer1 lib/i18n.ts. If the clone uses a vertical pack (presets.pack in ring-config.json), pack labels arrive from locales/{locale}/pack.json after compose. Brand-only tweaks stay in the clone overlay (registry plug), so platform upgrades keep shipping new Layer1 strings.
navigation.json?No. Merge is nested. Only keys present in pack.json overlay matching Layer1 paths. Missing keys stay on Layer1.
No. When presets.pack is unset, loadPackMessages returns {} and webpack still resolves the empty Layer1 file.
assembleMessages?No. That would put pack bytes inside 'use cache'. Keep pack load in buildMessages next to loadOverlayMessages.
pack.json?Layer1. Packs overwrite the file at compose; they must not be the only copy webpack can see on bare ring/web.
Same-workflow: locale env, routing helpers, and message scopes.
Depends-on: pack socket, overlay runtime, and named catalogs.
Next-step: nav labels and closed icon ids after copy merge.
See-also: proxy locale rewrite vs layout auth.
Use Founder / Developer tabs in the docs sidebar to filter this page. Shared sections apply to both audiences.
Ring Platform uses env-driven locale configuration and next-intl with localePrefix: 'as-needed'. Translation JSON lives under locales/{locale}/. Request-time merge then layers an optional pack file and an optional clone overlay on top of the cached Layer1 corpus.
| Stage | When it runs | Who owns the strings |
|---|---|---|
| Layer1 locale files | Cached in buildCachedLocaleMessages ('use cache') | Community ring/web/locales/ |
locales/{locale}/pack.json | Per request, only if presets.pack is set | L2 pack overwrite at compose |
| Clone overlay | Per request, only if overlay.featureId is set | appendOverlayMessages via lib/overlay/registry.ts |
Later leaf keys win. Nested objects merge (mergeJsonRecords in lib/i18n.ts). A clone can override one string without replacing the whole pack namespace.
Source of truth: lib/locale-config.ts — imported by routing, SEO, preferences, and static generation. Fallback locale list when env is empty: en, uk, ru, es, de.
You do not paste vertical copy into Layer1 lib/i18n.ts. If the clone uses a vertical pack (presets.pack in ring-config.json), pack labels arrive from locales/{locale}/pack.json after compose. Brand-only tweaks stay in the clone overlay (registry plug), so platform upgrades keep shipping new Layer1 strings.
navigation.json?No. Merge is nested. Only keys present in pack.json overlay matching Layer1 paths. Missing keys stay on Layer1.
No. When presets.pack is unset, loadPackMessages returns {} and webpack still resolves the empty Layer1 file.
assembleMessages?No. That would put pack bytes inside 'use cache'. Keep pack load in buildMessages next to loadOverlayMessages.
pack.json?Layer1. Packs overwrite the file at compose; they must not be the only copy webpack can see on bare ring/web.
Same-workflow: locale env, routing helpers, and message scopes.
Depends-on: pack socket, overlay runtime, and named catalogs.
Next-step: nav labels and closed icon ids after copy merge.
See-also: proxy locale rewrite vs layout auth.
Use Founder / Developer tabs in the docs sidebar to filter this page. Shared sections apply to both audiences.
Ring Platform uses env-driven locale configuration and next-intl with localePrefix: 'as-needed'. Translation JSON lives under locales/{locale}/. Request-time merge then layers an optional pack file and an optional clone overlay on top of the cached Layer1 corpus.
| Stage | When it runs | Who owns the strings |
|---|---|---|
| Layer1 locale files | Cached in buildCachedLocaleMessages ('use cache') | Community ring/web/locales/ |
locales/{locale}/pack.json | Per request, only if presets.pack is set | L2 pack overwrite at compose |
| Clone overlay | Per request, only if overlay.featureId is set | appendOverlayMessages via lib/overlay/registry.ts |
Later leaf keys win. Nested objects merge (mergeJsonRecords in lib/i18n.ts). A clone can override one string without replacing the whole pack namespace.
Source of truth: lib/locale-config.ts — imported by routing, SEO, preferences, and static generation. Fallback locale list when env is empty: en, uk, ru, es, de.
You do not paste vertical copy into Layer1 lib/i18n.ts. If the clone uses a vertical pack (presets.pack in ring-config.json), pack labels arrive from locales/{locale}/pack.json after compose. Brand-only tweaks stay in the clone overlay (registry plug), so platform upgrades keep shipping new Layer1 strings.
navigation.json?No. Merge is nested. Only keys present in pack.json overlay matching Layer1 paths. Missing keys stay on Layer1.
No. When presets.pack is unset, loadPackMessages returns {} and webpack still resolves the empty Layer1 file.
assembleMessages?No. That would put pack bytes inside 'use cache'. Keep pack load in buildMessages next to loadOverlayMessages.
pack.json?Layer1. Packs overwrite the file at compose; they must not be the only copy webpack can see on bare ring/web.
Same-workflow: locale env, routing helpers, and message scopes.
Depends-on: pack socket, overlay runtime, and named catalogs.
Next-step: nav labels and closed icon ids after copy merge.
See-also: proxy locale rewrite vs layout auth.
locales/{locale}/editor.json (scope must include editor) |
Do not add pack to LocaleFileId or assembleMessages. Pack JSON is merged after the cache, same as the overlay, so a pack or registry change is not frozen for hours.
loadPackMessages maps unknown locale codes to en. Known codes match the fallback list: uk, ru, es, de, else en.
In block comments, write locales/{locale}/pack.json. A glob locales/*/pack.json inside /* … */ terminates the comment at */.
Layer1 files are empty objects. A pack overwrites the file with nested namespaces (leaf-wins against L1 keys of the same path):
Clone overlay still wins the same leaf after that merge.
Link, useRouter, usePathname from @/i18n/routing only.persistRingLocalePreference() + replaceLocalePath() from lib/locale-pref.ts.components/seo/hreflang-links.tsxlib/seo-metadata.ts with pathnameWithoutLocale() for raw URLsAdd the BCP-47 short code to NEXT_PUBLIC_SUPPORTED_LOCALES (must match a folder under locales/).
Mirror the locales/{code}/ tree, including an empty pack.json if you extend the Layer1 fallback set so webpack still resolves the pack import.
Keep docs locale trees in ringdom-clones/ring-platform-org/web/docs/{locale}/ in sync with lib/locale-config.ts. There is no scripts/LOCALE-GAPS.md.
Prerequisite: clone overlay bans — do not patch lib/i18n.ts per brand.
# .env.local
NEXT_PUBLIC_SUPPORTED_LOCALES=en,uk,ru,es,de
NEXT_PUBLIC_DEFAULT_LOCALE=enlocales/{locale}/editor.json (scope must include editor) |
Do not add pack to LocaleFileId or assembleMessages. Pack JSON is merged after the cache, same as the overlay, so a pack or registry change is not frozen for hours.
loadPackMessages maps unknown locale codes to en. Known codes match the fallback list: uk, ru, es, de, else en.
In block comments, write locales/{locale}/pack.json. A glob locales/*/pack.json inside /* … */ terminates the comment at */.
Layer1 files are empty objects. A pack overwrites the file with nested namespaces (leaf-wins against L1 keys of the same path):
Clone overlay still wins the same leaf after that merge.
Link, useRouter, usePathname from @/i18n/routing only.persistRingLocalePreference() + replaceLocalePath() from lib/locale-pref.ts.components/seo/hreflang-links.tsxlib/seo-metadata.ts with pathnameWithoutLocale() for raw URLsAdd the BCP-47 short code to NEXT_PUBLIC_SUPPORTED_LOCALES (must match a folder under locales/).
Mirror the locales/{code}/ tree, including an empty pack.json if you extend the Layer1 fallback set so webpack still resolves the pack import.
Keep docs locale trees in ringdom-clones/ring-platform-org/web/docs/{locale}/ in sync with lib/locale-config.ts. There is no scripts/LOCALE-GAPS.md.
Prerequisite: clone overlay bans — do not patch lib/i18n.ts per brand.
# .env.local
NEXT_PUBLIC_SUPPORTED_LOCALES=en,uk,ru,es,de
NEXT_PUBLIC_DEFAULT_LOCALE=enlocales/{locale}/editor.json (scope must include editor) |
Do not add pack to LocaleFileId or assembleMessages. Pack JSON is merged after the cache, same as the overlay, so a pack or registry change is not frozen for hours.
loadPackMessages maps unknown locale codes to en. Known codes match the fallback list: uk, ru, es, de, else en.
In block comments, write locales/{locale}/pack.json. A glob locales/*/pack.json inside /* … */ terminates the comment at */.
Layer1 files are empty objects. A pack overwrites the file with nested namespaces (leaf-wins against L1 keys of the same path):
Clone overlay still wins the same leaf after that merge.
Link, useRouter, usePathname from @/i18n/routing only.persistRingLocalePreference() + replaceLocalePath() from lib/locale-pref.ts.components/seo/hreflang-links.tsxlib/seo-metadata.ts with pathnameWithoutLocale() for raw URLsAdd the BCP-47 short code to NEXT_PUBLIC_SUPPORTED_LOCALES (must match a folder under locales/).
Mirror the locales/{code}/ tree, including an empty pack.json if you extend the Layer1 fallback set so webpack still resolves the pack import.
Keep docs locale trees in ringdom-clones/ring-platform-org/web/docs/{locale}/ in sync with lib/locale-config.ts. There is no scripts/LOCALE-GAPS.md.
Prerequisite: clone overlay bans — do not patch lib/i18n.ts per brand.
# .env.local
NEXT_PUBLIC_SUPPORTED_LOCALES=en,uk,ru,es,de
NEXT_PUBLIC_DEFAULT_LOCALE=en