Repository navigation
Load translations for the OS language, not only the languages Chromium ships - #632
Conversation
…m ships app.getLocale() is Chromium's UI language, folded into the 55 locales Chromium ships, so es-mx.json and gl.json were shipped and never loaded. The i18n:locale handler now walks app.getPreferredSystemLanguages() and loads the first language with a catalog, falling back to getLocale(). A --lang switch replaces the OS list, unfolded. Slugs are matched to OS tags through Intl.getCanonicalLocales, which maps the 32 three-letter slugs and Filipino; Valencian is the one entry kept by hand. ELECTRON_LOCALES and its test go away, and the download script's note now lists only the slugs no OS reports. Fixes #584.
Simplified Chinese in the US is zh-Hans-US, and translate.wordpress.org has no bare zh, so the walk fell through to English where trunk loaded zh-cn. A tag with a script now tries its script's usual region before the bare language. The bal/bcc tie test now runs on a fixed list of names in both orders, since readdir's order depends on the file system.
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (8)
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughLocale resolution now checks operating-system language preferences in order and loads the first matching catalog. Catalog lookup supports canonical locale tags and fallback candidates. The
Priority: ➖ Normal Severity of issue fixed: Medium Merge Risk: ⚪ Minimal · up to The change makes the app pick translations from the OS language list in order, with Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to More bundled translations become reachable, but catalog reads remain owned by the main process and the renderer gains no new selection or filesystem authority. No introduced security-boundary bypass was identified. Catalogs supplied with a later release were not assessed. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
🚥 Pre-merge checks | ✅ 1✅ Passed checks (1 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
…og titles (#634) ## Why Several modules build sentences in main and send them to the window, and main has its own menu and native dialogs. Main had no catalog, so a translated window would still show those in English. This is the first batch of #622, and #625, #627, #628 and #629 need it. ## What changes - Main resolves the locale once (`localeReply()` in `src/main.js`) and applies it with the same `applyLocale()` the renderer uses, before it builds the menu and the window. The `i18n:locale` handler returns that same reply, so main and the window cannot disagree, and the en-XA pseudo-locale now covers main too. - Wrapped: "Open App Log" and "Show Logs Folder" in the Help menu, and the titles and filter names of the save-patch, choose-patch and choose-application dialogs. 10 strings. - Electron's role menus (File, Edit, View, Window) are deliberately left alone, as the issue says. ## How to test this Covered by a journey, red without this change: from the repository root, `npx playwright test --project=journeys tests/e2e/journeys/i18n.spec.js -g "Help menu"`. It reads the Help menu labels and the title and filters the patch file dialog was opened with, under `--lang=en-XA`. What the journey cannot reach is the real OS dialog. Platform: Windows for the dialogs (macOS does not show an open or save panel's title), either for the menu. Build: the current head. **Starting state:** the app launched from the repository root with `npx electron . --lang=en-XA`, with one site that has an edited file. 1. Open the **Help** menu. Expected: both "Open App Log" and "Show Logs Folder" are accented and in brackets. "Toggle Developer Tools" stays in English (a role menu). 2. Click **Review & submit changes**, then **Save**. Expected: the save dialog's title ("Save Diff File") and its "Patch Files" filter are accented and in brackets. 3. Cancel. In the **Apply a patch or PR** card, open the **Diff** tab and click **Choose a .diff or .patch file…**. Expected: the dialog title and both filters are accented and in brackets. 4. Cancel. Open **Site actions → Open in → Other application…**. Expected: the title and the "Programs" filter are accented and in brackets. **What must not have happened:** launching with no `--lang` shows every one of these in English, and the app opens one window, not two, when started from a `wpct://ticket/…` link. ## Risks and limitations - Main now awaits the locale before it creates the window, so startup gains one catalog read (the same one the window already waited for). A `wpct://` link that arrives in that gap opens the window itself; startup then creates a window only if none exists. - Not tested by a journey: the save dialog and the choose-application dialog. Only the patch file dialog is checked. - "Dev server stopped unexpectedly (see Help → Open App Log for details)" still names the menu entry in English. It belongs in #627, where it should take the label as `%s`. ## Related Fixes #623. Part of #622. Follows #632 (#584). --- <details> <summary>Design decisions and alternatives considered</summary> The reply is memoised rather than computed twice so the window and main read the catalog once and always agree. `applyLocale()` was reused as is: it has no DOM dependency, and with main's `setLocaleData` and `addFilter` it installs the pseudo-locale filters for main too. Main's CommonJS `@wordpress/i18n` builds its default instance on `@wordpress/hooks`' `defaultHooks`, and there is one copy of `@wordpress/hooks`, so the filters apply to `menu.js` as well. </details> <details> <summary>Review outcome (required, see AGENTS.md)</summary> - **Review:** completed. Reviewer: a separate agent context (Claude Code, read-only) against `.github/instructions/code-review.instructions.md`; head `08d29ef` / base `eb3f70f`. `npm run lint` clean, `npm test` 1955 pass / 0 fail, full journey suite 114 pass. Outcome: 1 [fix here] · 1 [follow-up], both 🔵 low. - Architecture, `src/main.js` ready path: if the locale load rejected, startup would stop before the menu and the window. **Not changed:** the reviewer found no path that rejects (`resolveCatalog` catches its own read and parse errors), and AGENTS.md asks for no defensive branches without a realistic path. - Tests, `tests/unit/ipc-wiring.test.cjs`: the `ready` path runs after the harness removes its require hook, so a lazy `require` added there would load real modules. **Fixed** with a note beside the option. - **Since review:** `08d29ef → 4c34787` checked; the only change is that comment. Then rebased onto `trunk` after #632's squash merge: head `a6fb7da` / base `8dbed36`. The diff against the new base is line for line the reviewed one plus that comment; lint clean, `npm test` 1955 pass / 0 fail, journeys 114 pass on the new head. </details> <details> <summary>Implementation notes</summary> - `tests/unit/ipc-wiring.test.cjs` gains a `ready` option so one test can run the ready path. It checks that main applies the locale before any menu or window exists, that the handler returns the same reply object, and that the catalog is read once. - `tests/unit/menu.test.cjs` checks the labels are translated when the template is built, not at require time. </details> <details> <summary>Screenshots or recording</summary> Nothing changes in English. In the pseudo-locale the change is the Help menu labels and the native dialog titles, which the journey asserts. </details> 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Why
The app picked its language from
app.getLocale(), which is Chromium's UI language, folded into the 55 locales Chromium ships. So a Mac set to Spanish (Mexico) reportedes-419and never loadedes-mx.json, and Galician, Basque or Welsh never asked for a catalog at all. 53 of translate.wordpress.org's 202 locales were reachable. #584 has the details.What changes
i18n:localehandler walksapp.getPreferredSystemLanguages()in order and loads the first language that has a catalog.app.getLocale()is the last fallback. A--langswitch replaces the OS list and is used as given, so--lang=es-MXis not folded either.zh-Hans-US, and there is no barezhcatalog.Intl.getCanonicalLocales, which covers the 32 three-letter slugs (belisbe) and Filipino (tlisfil). Valencian (ca-val) is the one entry kept by hand.ELECTRON_LOCALES, its test andGLOTPRESS_SLUGSare gone.pirateandart-xemoji.Not in this PR: a language picker (out of scope in #584), and the catalogs themselves, which ship with the version-bump PR.
How to test this
Platforms: macOS or Windows, from source on the current head. A Buildkite artifact won't show anything, because trunk has no catalogs committed in
src/languages/.Starting state: a checkout of this branch with dependencies installed. From the repository root, run
npm run i18n:downloadto fetch the catalogs.esandes-mxboth translate the create-site button as Crear sitio, but they word the dialog differently, so the dialog shows which catalog loaded.npm run start -- --lang=es-MX. Click Crear sitio. The dialog reads Aún no se ha seleccionado una carpeta. (fromes-mx). Only about 15 strings are translated so far, so the rest stays English.npm run start -- --lang=gl. Click Crear sitio. The dialog reads Aínda non se seleccionou ningún cartafol. On trunk this is all English, because Chromium has no Galician and reportsen-US.npm run start -- --lang=de. The button reads Website erstellen.npm run startwith no--lang. Click Crear sitio. The dialog reads Aún no se ha seleccionado una carpeta.npm run start. The button reads Create site.What must not have happened:
escatalog, which is what trunk loads, because Chromium foldses-MXtoes-419.tests/unit/ipc-wiring.test.cjs"i18n:locale asks i18n.cjs for the catalog of the OS languages…" and thees-MX,zh-Hans-USand Valencian cases intests/unit/i18n.test.cjsfail on trunk's code.Risks and limitations
en-AU,en-NZ,en-IE) now get US English. Chromium used to fold them intoen-GB, so they loadeden-gb.json. This only matters onceen-gbpasses the 80% cut-off (it's at 6%); they get their own catalogs when those ship.en-CAthere.Related
Fixes #584. Part of #540. Unblocks #623.
Design decisions and alternatives considered
be-BYtobel.jsonneeds the slugs, so the lookup reads the directory and maps each file to its tag. File names come only fromreaddir, so no OS or--langinput reaches a path.Intl.DisplayNames, but Electron's ICU has no names for many real languages (kab,fur,oci), so it can't tell a real language frompirate.bccandbalboth canonicalize tobal. It's the only collision among the 202 slugs. The slug that is its own tag wins.Review outcome (required, see AGENTS.md)
2 [fix here] · 1 [follow-up]. Both fixed in eb3f70f; the follow-up is the en-AU note under Risks.
🟡
src/i18n.cjscatalogCandidates:zh-Hans-USnever reachedzh-cn, and English second then stopped the walk. That's a regression from trunk, where Chromium folds it tozh-CN. Fixed by trying the script's usual region (Intl.Locale(…).maximize()), with tests forzh-Hans-USandzh-Hant-US.🔵
tests/unit/i18n.test.cjs: thebal/bcctie test depended onreaddirorder. It now runs oncatalogsFromNameswith both orders. Also added a test for the unreadable-directory log.🔵 [follow-up] English variants without a catalog now get US English. Left as is; see Risks.
Review: completed. Separate agent context, fresh. Reviewed head b9df719, base d1616d2. Lint clean,
npm test1951/1951, Electron unit run clean. Checked: Intl on Electron 43 (Node 24.20, ICU 78.2), odd and empty OS lists, path safety, reading fromapp.asar, removed exports, e2e locale pinning.Since review: b9df719 → eb3f70f (the two fixes, plus the README sentence). The author session checked it, not a fresh context. Lint clean,
npm test1953/1953, Electron 1954 passed.CodeRabbit: not requested yet.
Implementation notes
resolveCatalog(locales, dir, log)now takes a list and returns{ locale, messages }or null. The handler returns{ locale, data }as before, andlocaleis the OS tag that matched, which ends up in<html lang>.tlandca-val). Onlypirateandart-xemojican't be selected.Screenshots or recording
Nothing new on screen: the same strings load for more languages.
🤖 Generated with Claude Code