Skip to content

fix: i18n locale resolution (spurious es/fr 404s; short locales served English)#31

Merged
kilbot merged 2 commits into
mainfrom
fix/i18n-locale-resolution
Jun 15, 2026
Merged

fix: i18n locale resolution (spurious es/fr 404s; short locales served English)#31
kilbot merged 2 commits into
mainfrom
fix/i18n-locale-resolution

Conversation

@kilbot

@kilbot kilbot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

What & why

Reported from production console: GET …/src/translations/es/wp-admin-landing-shared.json 404 (and fr, etc.).

Two bugs in the i18n config, confirmed by reproducing the actual network requests per locale:

  1. Spurious 404 every load. i18next's default load: 'all' requested both the full locale es_ES (exists → 200) and the base language es (no such dir → 404). Page worked, but logged a 404 each load.
  2. Short-locale users served English. A site whose WP locale is a language-only code (es, fr) requested only that → 404 → silent English fallback instead of the user's language.

Fix

  • load: 'currentOnly' — request only the exact locale (our locale files are key-complete per lint-translations, so no region→base fallback layer is needed).
  • loadPath is now a function that maps the requested code to an available directory via resolveLocaleDir (short eses_ES, ptpt_BR, zhzh_CN; unknown → passthrough → 404 → bundled English).
  • Extracted to a pure, unit-tested src/shared/locale-resolve.mjs (tests/locale-resolve.test.mjs).

Verified

Reproduced before/after with a headless harness — every locale now makes exactly one request to the correct dir; short codes resolve to their region; the es/fr 404s are gone.

Please review before merge — I'm not self-merging these.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Improved locale resolution to correctly handle exact language codes, hyphenated forms, and region variants with consistent directory selection.
  • Performance
    • Optimized translation loading to request only the currently active locale, reducing extra companion requests.
  • Tests
    • Added automated coverage for locale/region resolution behavior, including edge cases and unknown locale pass-through.

…erved English)

i18next's default load:'all' requested both the full locale (es_ES → 200) and
its base language (es → 404, no such dir), logging a 404 each load; and a site
whose WP locale is a short code (es, fr) requested only that → 404 → silently
fell back to English instead of its language.

Fix: load:'currentOnly' (request only the exact locale, no redundant base) plus
a loadPath function that maps the requested code to an available directory via
resolveLocaleDir (short es → es_ES, etc.). Extracted to a pure, unit-tested
src/shared/locale-resolve.mjs. Verified: every locale now makes exactly one
request to the correct dir; short codes resolve to their region.
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: wcpos/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c9dbb82d-6b1d-4cca-898d-3c35cc9bb58a

📥 Commits

Reviewing files that changed from the base of the PR and between 71363e5 and 0d61057.

📒 Files selected for processing (3)
  • assets/js/welcome.js
  • src/shared/locale-resolve.mjs
  • tests/locale-resolve.test.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/shared/locale-resolve.mjs

📝 Walkthrough

Walkthrough

Adds src/shared/locale-resolve.mjs exporting a LOCALE_DIRS allowlist and a resolveLocaleDir function that maps i18next locale codes to existing translation directory names. Updates i18n.ts to import and use this resolver as the HTTP backend loadPath function and sets load: 'currentOnly'. Adds a corresponding test file covering all resolution cases.

Changes

Locale resolver and i18n CDN path integration

Layer / File(s) Summary
LOCALE_DIRS allowlist and resolveLocaleDir implementation
src/shared/locale-resolve.mjs, tests/locale-resolve.test.mjs
New module exports LOCALE_DIRS (supported translation directory names) and resolveLocaleDir(lng) with exact-match, base-language, and passthrough logic. Tests cover full locale pass-through, short-code mapping, hyphenated inputs, region-variant preservation, unknown-locale passthrough, and an invariant that LOCALE_DIRS contains no short-code entries that would shadow region codes.
i18n backend wired to resolveLocaleDir
src/shared/i18n.ts
Imports resolveLocaleDir, adds load: 'currentOnly' to suppress companion base-language loads, and replaces the Handlebars loadPath template with a function that calls resolveLocaleDir(lngs[0]) to compute the CDN URL for the correct locale directory.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🌐 A resolver steps in, tidy and bright,
No more guessing which folder's right.
es finds es_ES on the shelf,
Unknown codes just handle themselves.
CDN paths served without a fight! 🗂️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title precisely summarizes the two primary bugs being fixed: spurious 404 errors on base language codes and short-locale users receiving English instead of their intended language.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/i18n-locale-resolution

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 71363e543b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/shared/locale-resolve.mjs Outdated
@kilbot

kilbot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

Fix triage

# Source File Class Category Decision Outcome
1 Codex locale-resolve.mjs:31 Logic P2 / Major Fix Hyphenated region codes (zh-TW, es-MX, pt-PT) resolved to the first region of the base language instead of the exact match. Normalizing -_ and checking for an exact supported dir before the base fallback; adding the multi-region hyphen cases to the test (which would have caught it).
2 CodeRabbit Skip "No actionable comments 🎉"

Working through #1 now; will reply in-thread and push.

)

BCP-47 hyphen forms (zh-TW, es-MX, pt-PT) collapsed to the base language's first
region (zh_CN, es_ES, pt_BR) because the lookup split on '-'/'_' and fell straight
to the base. Normalize '-'→'_' and match an exact supported dir first. Added the
multi-region hyphen cases to the test (the prior fr-FR case passed only because
fr has a single region).
@kilbot

kilbot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

✅ Fix round complete.

# Source Decision Outcome
1 Codex locale-resolve.mjs:31 Fixed 0d61057 — normalize -_, match exact region before base fallback (zh-TWzh_TW). Regression test added. Thread resolved.
2 CodeRabbit Skip No actionable comments.

CI green, all review threads resolved. Ready for review/merge — not self-merging.

@kilbot kilbot merged commit d18e1a1 into main Jun 15, 2026
8 checks passed
@kilbot kilbot deleted the fix/i18n-locale-resolution branch June 15, 2026 11:14
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