Skip to content

feat(i18n): consume central translations from @escalated-dev/locale#53

Merged
mpge merged 5 commits intomainfrom
feat/central-locale
May 2, 2026
Merged

feat(i18n): consume central translations from @escalated-dev/locale#53
mpge merged 5 commits intomainfrom
feat/central-locale

Conversation

@mpge
Copy link
Copy Markdown
Member

@mpge mpge commented May 2, 2026

Summary

Wires this frontend to read translations from the central source (escalated-dev/escalated-locale) with override fallback.

Blocked on escalated-dev/escalated-locale v0.1.0 publish. CI will fail until then (npm install cannot resolve @escalated-dev/locale@^0.1.0).

After v0.1.0 publishes, mark this PR ready and CI should go green.

Pattern

useI18n().t(key, replacements) (and the $t shim used in templates) now resolves a key through this layered chain:

  1. Host-app customMessages for the current locale (mergeMessages(locale, msgs) from a host app — top priority).
  2. Local plugin overrides for the current locale (src/locales/<lang>.json — this repo's existing JSON files, retained AS overrides so any string this plugin phrases differently still wins over central).
  3. Central source for the current locale (@escalated-dev/locale — the canonical base layer).
  4. Same three layers again as English fallback (when current locale is not en).
  5. Raw key.

The public composable API is unchanged — every component that calls useI18n() keeps working without edits. No translation strings are modified by this PR.

Why retain src/locales/*.json as overrides?

Per the rollout plan, Codex will populate @escalated-dev/locale with canonical strings sourced from THIS repo (it is the authoritative origin). Until that consolidation lands, keeping the local JSON files in place means the layered chain still finds every key — there is no UI regression while the central package is empty / partial. After Codex finishes, the local files can be trimmed (or deleted) so the central source becomes the sole source for any key not specifically overridden by this plugin.

Files changed

  • package.json — add @escalated-dev/locale ^0.1.0 to dependencies
  • src/composables/useI18n.js — three-tier lookup (host customMessages → local overrides → central) with English fallback in the same order
  • src/locales/README.md — new, documents the override layering
  • CHANGELOG.md — Unreleased entry

Test plan

  • Wait for @escalated-dev/locale v0.1.0 to publish on npm
  • Mark PR ready for review; verify CI npm install resolves
  • Verify Storybook renders English UI unchanged (local overrides should still win for every existing key)
  • Verify locale switching to a non-en locale (e.g., de) still produces translated strings
  • Verify a host-app mergeMessages('en', {...}) call still wins over both layers
  • Verify a key present ONLY in central (and not in local overrides) is found

Expected CI failure

npm ci / npm install will fail with 404 Not Found - GET https://registry.npmjs.org/@escalated-dev%2flocale - Not found (or equivalent) until the central package publishes v0.1.0. This PR is intentionally a draft for that reason.

mpge added 4 commits May 1, 2026 22:08
Adds the central locale package as a runtime dependency. The next
commit wires it into the i18n loader as the BASE source, with local
src/locales/ files retained as overrides until the central source is
populated.
Wires useI18n() to consume @escalated-dev/locale as the canonical BASE
translation source, with src/locales/*.json now treated as local
plugin overrides that win over central. Lookup order:

  1. host-app customMessages (current locale)
  2. local override (src/locales/<lang>.json)
  3. central source (@escalated-dev/locale)
  4. host-app customMessages (en fallback)
  5. local override (en fallback)
  6. central source (en fallback)
  7. raw key

Public API is unchanged: components still call useI18n().t(key, repl)
and $t works identically. No translation strings are modified by this
commit — Codex will populate the central package separately, after
which the local override files can be trimmed.

Blocked on @escalated-dev/locale v0.1.0 publish; CI npm install will
fail until then.
Clarifies that the JSON files in src/locales/ are now local overrides
that win over the central @escalated-dev/locale source, and explains
the resolution order used by useI18n().t().
@mpge
Copy link
Copy Markdown
Member Author

mpge commented May 2, 2026

Blocked on npm publish

This PR is intentionally staying as draft until @escalated-dev/locale is published to the npm registry.

Why we can't consume from GitHub directly

npm supports git-source dependencies (e.g. github:escalated-dev/escalated-locale#v0.1.1 or git+https://...#v0.1.1), but it expects the package's package.json to live at the repository root. The central locale repo intentionally keeps its npm artifact under packages/npm/ (alongside packages/pypi/, packages/rubygems/, packages/go/, etc.):

escalated-locale/
  packages/
    npm/
      package.json   <-- the real npm manifest
      index.js
      index.d.ts
      locales/
    pypi/
    rubygems/
    go/
    ...

npm has no first-class way to point a git-source dep at a subdirectory (no ?path= fragment, no subdirectory qualifier like pip's #subdirectory=). Workarounds (gitpkg, custom postinstall, duplicating the manifest at the repo root) are all worse than just publishing to the registry.

What needs to happen to unblock

Per the registry checklist at C:\Users\work\REGISTRIES_TO_PUBLISH.txt:

npm (escalated, escalated-nestjs, escalated-adonis)
publish later to npmjs.com:
cd packages/npm && npm publish --access public
(needs NPM_TOKEN secret in escalated-dev/escalated-locale settings;
the publish.yml workflow does this on tag push automatically)

Once NPM_TOKEN is added as a secret on escalated-dev/escalated-locale and the publish.yml workflow is re-run on the v0.1.1 tag (or a fresh tag is pushed), @escalated-dev/locale@0.1.1 will be available on the public registry. At that point this PR's existing dependency line — "@escalated-dev/locale": "^0.1.0" — will resolve cleanly and the PR can be marked ready for review and merged.

Note on other ecosystems

Most other host plugins (Composer/Packagist via vcs repositories, RubyGems via git: + glob:, PyPI via git+...#subdirectory=, Go modules natively) can consume the central locale from GitHub today, so their plugin PRs are landing on the git-source path. npm is the odd one out here because of the subdirectory limitation.

Leaving as draft. No code changes required on this branch — flipping to "Ready for review" after publish should be sufficient.

The central package's root package.json shim landed at v0.1.2 in
escalated-dev/escalated-locale, making github tarball deps resolve
cleanly. This unblocks the central-locale PR; once @escalated-dev/locale
publishes to the npm registry this can revert to a semver range.
@mpge mpge marked this pull request as ready for review May 2, 2026 19:36
@mpge mpge merged commit 97d1480 into main May 2, 2026
7 checks passed
@mpge mpge deleted the feat/central-locale branch May 2, 2026 19:40
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.

1 participant