feat(portal-shell): ci gate — fail prod build on missing translations #98

Merged
julien merged 1 commits from feat/portal-shell/i18n-ci-gate-missing-translations into main 2026-05-12 00:30:28 +02:00
Owner

Summary

Set "i18nMissingTranslation": "error" on the production build configuration in apps/portal-shell/project.json. The Angular CLI checks every <source> extracted from i18n markers and $localize calls against the loaded translation file (messages.fr.xlf); with the flag on error, the build now fails when a target is missing instead of silently falling back to the source text in the FR bundle.

Closes the loop on ADR-0019 §"Confirmation" — the final piece of the i18n track that does not depend on the BFF route + cookie work (deferred to the auth-flow chantier).

Gate mechanics

  • pnpm ci:check runs nx affected -t ... build, which uses the production configuration by default. A PR that adds an i18n marker without updating messages.fr.xlf fails its build job → merge blocked.
  • The default build configuration is unchanged (production), so no other CI plumbing is needed.

Verification

Locally, temporarily inserting an unmarked-in-fr string:

<span i18n="@@sanity.test.missingTranslation">A string with no FR translation</span>

then running pnpm exec nx build portal-shell --configuration=production produces:

ERROR: No translation found for "sanity.test.missingTranslation"
       ("A string with no FR translation").
Application bundle generation failed.
NX   Running target build for project portal-shell failed

…with a non-zero exit code. The patch was reverted before commit.

Test plan

  • pnpm exec nx run-many -t lint test build --projects=portal-shell — green (40 / 40 specs, build still passes on the current state).
  • Sanity-check that the gate actually fires when a translation is missing (above).
  • CI: the next PR that adds an i18n marker without updating messages.fr.xlf should fail at the build step with the explicit error.

What this PR explicitly does NOT do

  • Catch unmarked source strings (e.g. a developer who forgets to add i18n="@@..." to a new template line). That would need a custom ESLint rule against the Angular template AST — a separate, smaller scope mentioned in ADR-0019 as a future refinement.
  • Localise editorial / CMS content. Editorial copy comes from the BFF already localised; this gate covers only the developer-owned UI strings baked at build time.
  • Add a similar gate to the i18n extraction (we could fail the build if nx extract-i18n produces diffs against the committed messages.xlf, but we don't commit messages.xlf today).
## Summary Set `"i18nMissingTranslation": "error"` on the production build configuration in [`apps/portal-shell/project.json`](apps/portal-shell/project.json). The Angular CLI checks every `<source>` extracted from `i18n` markers and `$localize` calls against the loaded translation file (`messages.fr.xlf`); with the flag on `error`, the build now **fails** when a target is missing instead of silently falling back to the source text in the FR bundle. Closes the loop on ADR-0019 §"Confirmation" — the final piece of the i18n track that does not depend on the BFF route + cookie work (deferred to the auth-flow chantier). ## Gate mechanics - `pnpm ci:check` runs `nx affected -t ... build`, which uses the production configuration by default. A PR that adds an `i18n` marker without updating `messages.fr.xlf` fails its build job → merge blocked. - The default build configuration is unchanged (`production`), so no other CI plumbing is needed. ## Verification Locally, temporarily inserting an unmarked-in-fr string: ```html <span i18n="@@sanity.test.missingTranslation">A string with no FR translation</span> ``` then running `pnpm exec nx build portal-shell --configuration=production` produces: ``` ERROR: No translation found for "sanity.test.missingTranslation" ("A string with no FR translation"). Application bundle generation failed. NX Running target build for project portal-shell failed ``` …with a non-zero exit code. The patch was reverted before commit. ## Test plan - [x] `pnpm exec nx run-many -t lint test build --projects=portal-shell` — green (40 / 40 specs, build still passes on the current state). - [x] Sanity-check that the gate actually fires when a translation is missing (above). - [ ] CI: the next PR that adds an `i18n` marker without updating `messages.fr.xlf` should fail at the `build` step with the explicit error. ## What this PR explicitly does NOT do - Catch **unmarked** source strings (e.g. a developer who forgets to add `i18n="@@..."` to a new template line). That would need a custom ESLint rule against the Angular template AST — a separate, smaller scope mentioned in ADR-0019 as a future refinement. - Localise editorial / CMS content. Editorial copy comes from the BFF already localised; this gate covers only the developer-owned UI strings baked at build time. - Add a similar gate to the i18n extraction (we could fail the build if `nx extract-i18n` produces diffs against the committed `messages.xlf`, but we don't commit `messages.xlf` today).
julien added 1 commit 2026-05-12 00:28:33 +02:00
feat(portal-shell): ci gate — fail prod build on missing translations
CI / commits (pull_request) Successful in 2m17s
CI / scan (pull_request) Successful in 2m26s
CI / check (pull_request) Successful in 2m35s
CI / a11y (pull_request) Successful in 2m35s
CI / perf (pull_request) Successful in 5m40s
0c0a88a02e
Set `i18nMissingTranslation: "error"` on the production build
configuration. The Angular CLI checks every `<source>` extracted
from `i18n` markers and `$localize` calls against the loaded
translation file (`messages.fr.xlf`), and now fails the build if a
target is missing instead of silently falling back to the source
text in the FR bundle.

Gates automatically through CI: `pnpm ci:check` runs `nx affected -t
... build`, which uses the production configuration by default. A PR
that adds an `i18n` marker without updating `messages.fr.xlf` fails
its build job and blocks the merge.

Verified locally by temporarily inserting an unmarked-in-fr string,
running the prod build, observing the explicit error message:

  ERROR: No translation found for "sanity.test.missingTranslation"
         ("A string with no FR translation").

Closes the loop on ADR-0019 §"Confirmation" — the final piece of
the i18n track before the BFF route + cookie work (deferred to the
auth-flow chantier).
julien merged commit 99522540a5 into main 2026-05-12 00:30:28 +02:00
julien deleted branch feat/portal-shell/i18n-ci-gate-missing-translations 2026-05-12 00:30:31 +02:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: julien/apf_portal#98