Skip to content

fix(i18n/build/ci): ICU-escape 381 message values, externalize tiktoken, add blocking UI-ICU gate - #12564

Open
chirag127 wants to merge 3 commits into
diegosouzapw:release/v3.8.51from
chirag127:fix/i18n-icu-sweep-and-gate
Open

fix(i18n/build/ci): ICU-escape 381 message values, externalize tiktoken, add blocking UI-ICU gate#12564
chirag127 wants to merge 3 commits into
diegosouzapw:release/v3.8.51from
chirag127:fix/i18n-icu-sweep-and-gate

Conversation

@chirag127

Copy link
Copy Markdown
Contributor

Summary

Three tightly-related fixes, verified live on the latest release/v3.8.51:

  1. fix(i18n) — ICU-escape 381 message values containing raw <tag> / literal {...} across all 42 locale catalogs (src/i18n/messages/*.json).
  2. fix(build) — externalize tiktoken in next.config.mjs so tiktoken_bg.wasm resolves at runtime.
  3. chore(ci) — add a blocking check:ui-icu gate that compiles every message value with IntlMessageFormat (next-intl's parser), so this defect class can never ship again.

Background

A message value containing a raw <tag> or literal {...} fails to compile under IntlMessageFormat. At runtime the component silently breaks — the RSC/Flight path throws INVALID_MESSAGE and the UI falls back to showing the raw i18n key. This exact class shipped repeatedly:

The fix (commit 1)

Every literal is wrapped in ICU single quotes so it renders verbatim — required here because the values are copy-paste content (file paths, JSON, regex), where real </>/{ characters must render. HTML entities would corrupt the pasted content. Every single change was asserted render-identical (new IntlMessageFormat(fixed).format() === original) by scripts/ad-hoc/fix-invalid-icu.mjs; the only deliberate wording change is the nl <emdeze typo correction.

The duplicate 'in' locale was retired upstream in #12496, so the sweep covers the current 42 catalogs.

The gate (commit 3)

npm run check:ui-icuscripts/i18n/check-ui-icu.mjs compiles all 545,817 messages across 42 catalogs. Legitimate t.rich rich-text ("<b>bold</b>") and normal ICU ({count, plural, ...}) compile fine — no false positives, pinned by tests/unit/i18n-ui-icu.test.ts (10 tests). Wired into the blocking i18n-ui-coverage job in .github/workflows/ci.yml.

The tiktoken fix (commit 2)

tiktoken resolves tiktoken_bg.wasm at runtime via fs.readFileSync relative to __dirname; bundled by Turbopack that lookup fails ("Missing tiktoken_bg.wasm") and 500s every route touching codex-chatgpt-web token estimation (e.g. GET /api/providers). Externalizing it (like sqlite-vec / better-sqlite3) keeps the require at runtime.

Verification

  • check:ui-icuPASS — all 545,817 messages in 42 catalogs compile
  • tests/unit/i18n-ui-icu.test.ts10/10 pass
  • check-ui-value-drift (against base) → PASS
  • check-ui-keys-coveragePASS

Note: intl-messageformat is currently a transitive dep of next-intl (^11.1.0) — the gate requires it, so if that dependency is ever dropped it should be promoted to a direct dependency.

chirag127 and others added 3 commits September 3, 2026 11:29
…s all catalogs

Messages containing raw `<tag>` or `{...}` literals fail to compile under
IntlMessageFormat (the parser next-intl uses) and silently break pages:
the component throws INVALID_MESSAGE and the UI falls back to showing the
raw key. Same class as diegosouzapw#12302 (ccOnboardingKeyPlaceholder), diegosouzapw#12505
(OMNIROUTE_AUTO_SYNC_CLAUDE_PROFILES.description) and diegosouzapw#12559
(featureFlagExposeFunctionalGatewayMirrorsDescription), all of which
shipped with these values.

Wrap every literal in ICU single quotes so it renders verbatim: file
paths, copy-paste JSON/regex hints, service-account JSON placeholders and
two `{" "}` status-label artifacts (phi/sv). The one deliberate wording
fix is a broken `<emdeze` rich-text tag in nl. Every change is asserted
render-identical (`format(fixed) === original`) by
scripts/ad-hoc/fix-invalid-icu.mjs.

381 message values changed across the 42 catalogs (the duplicate 'in'
locale was retired upstream by diegosouzapw#12496).

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
When tiktoken is bundled by Turbopack, its runtime fs.readFileSync lookup
for tiktoken_bg.wasm (relative to __dirname) fails with "Missing
tiktoken_bg.wasm", 500ing every route that touches codex-chatgpt-web token
estimation (e.g. /api/providers). Externalize it like sqlite-vec /
better-sqlite3 so the require stays at runtime.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
check:ui-icu compiles EVERY message value in every catalog
(src/i18n/messages/*.json) with IntlMessageFormat — the exact parser
next-intl uses. Any message that fails to compile (raw <tag>, literal
{...}) would silently break its page at runtime (the RSC path throws
INVALID_MESSAGE and the UI shows the raw key), so fail the PR instead.

The diegosouzapw#12302/diegosouzapw#12505/diegosouzapw#12559 defect class shipped 381 such values across the
catalogs; commit f85fc11 fixed them all. This gate runs in the blocking
i18n-ui-coverage job and pins the pure core (findInvalidMessages /
flattenLeaves) with unit tests (tests/unit/i18n-ui-icu.test.ts).

Legitimate t.rich rich-text messages (<b>bold</b>) and normal ICU
({count, plural, ...}) compile fine — no false positives.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
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