Repository navigation
Add a language setting, applied at the next launch - #639
Merged
Merged
Conversation
The second of the settings (#559). The General tab offers the languages the build ships a catalog for, each named in its own language, with the system's language as the default; main reads the one set before the OS list, as it does the --lang switch, which still wins over both. A change shows after a relaunch, since main applies the catalog as it starts, and the dialog says so and offers the relaunch, a quit and a start, so that the quit sweep ends what the app started. The entries of the control are made from the language the window began in rather than the one set: an entry taken away under the control while it is choosing is reported as a second choice, of none. A language the window began in that the build has no catalog for is listed, so that the control shows what is set, and is refused if chosen again. A journey can now launch without --lang, as the app launches for a contributor, and does: the pseudo-locale set in the store is the one the app starts in, and the one kept is the one it restarts in. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ly, and relaunch without the launch's link From the review. A chosen language goes before the OS's languages and not in their place, so one whose catalog a release has dropped falls back to the OS's language and not to English. The store is read before there is a window, and one that cannot be read is logged and counts as no choice, where it would have stopped the window from opening. The relaunch hands the new instance this one's arguments less a wpct:// address a cold start was given, which is not a second request for its ticket, and a --lang switch, which would outrank the language just chosen. Also: the system's entry is kept as no choice through one tested function; a relaunch that fails is said where it was asked for; a comment in the store module and one in a journey said what is no longer so, and the catalogs' README counted entries that are not offered. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nch from the AppImage on Linux From the second review. The catalogs' README said the chosen language is used instead of the OS's, where it is tried before them. On Linux the app is an AppImage, mounted while it runs and gone once it quits, so the new instance is started from the image itself. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
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:
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 |
zaerl
added a commit
that referenced
this pull request
Oct 6, 2026
…he next server start (#640) ## Why Third part of #559, on the dialog of #638. Every site's development server ran on the PHP the bundled Playground chooses and with WordPress's debug constants fixed on; a contributor whose ticket is about PHP 7.4, or about what a site does with `WP_DEBUG` off, had no way to see it. This adds the PHP version and the two debug constants that can be turned off to the settings, and shows what a server will start with in the open site's details. ## What changes **A Sites tab: Development server.** The PHP version, one of the seven the bundled Playground has (7.4 to 8.5), 8.3 unless another is chosen; and two switches, **Report notices and deprecations (WP_DEBUG)** and **Use unminified scripts (SCRIPT_DEBUG)**. The rest of the constants a server is booted with (the log, the display, the disabled fatal handler and updater) stay as they were and are not anyone's to change. **Applied at the next start.** Main reads the three at every server start and hands them to the runner in its config; a server that is running keeps what it started with until it is stopped and started, and the tab says so. A version a release has taken out of the bundle is passed over for 8.3, with a line in the app log, and the control shows 8.3 as chosen with a note saying why. **The details say what a server will start with**, as the prototype has them: "WordPress Core · PHP 8.3" on the Checkout row, and a Debugging row with the constants that are on, or "Off". **What WP_DEBUG off does, said for what it is.** It takes away notices and deprecations. Warnings and errors still reach `debug.log` and the browser, and `error_log()` calls still reach `debug.log`, because Playground's own PHP keeps logging and display on whatever WP_DEBUG says. The switch, the guide and the constants' module say so. **The guide's pictures are retaken.** The details changed here, and the footer's cog from #638 had never been retaken. The three pictures of a site's page are taken in a window 900 high, so the details' Build watch section is whole. **Not in this pull request:** - The PHP version a *running* server is on, in the Server section, where the details show the version the next start is given. Follow-up. - Per-site values: these are global, like the other settings. A per-site override can go in `siteMeta` if one is ever wanted. - The remaining constants (`WP_DEBUG_LOG`, `WP_DEBUG_DISPLAY`, `WP_DISABLE_FATAL_ERROR_HANDLER`, `AUTOMATIC_UPDATER_DISABLED`), on purpose: `src/wp-debug-constants.js` says why each is on. - The rest of #559: what starts when a site opens and what happens on quit; the theme (#560). ## How to test this Platforms: any for the dialog and the details; macOS for the real server, below. The journeys drive the dialog and the details on macOS and Windows. From the repository root, after `npm ci` and `npm run build:once`: ``` npx playwright test --project=journeys settings.spec site-header.spec i18n.spec ``` - `settings.spec.js`, the Sites journey: the fallbacks (8.3, both constants on); 8.4 chosen is kept, WP_DEBUG off is kept and SCRIPT_DEBUG left as it was; the open site's details then say "WordPress Core · PHP 8.4" and "SCRIPT_DEBUG"; restarted, the tab shows what was kept. - `site-header.spec.js`: the details name the project with the PHP a server starts on and which constants are on. - `i18n.spec.js`: the tab in the pseudo-locale. I broke two claims one at a time (main not reading the settings at a start; the switch not writing) and each was caught, the first by `ipc-wiring.test.cjs`, the second by the journey. `tests/unit/runner-wiring.test.cjs` proves the runner hands Playground the version and turns the two constants off in the blueprint; `wp-debug-constants.test.cjs` that nothing else in the set moves; `settings.test.cjs` and `settings-view.test.cjs` what is accepted and what the control shows. **The real server, run by me on this Mac (Apple Silicon, the current head), as TESTING.md asks for a change to `src/server-runner.js`.** The app was driven through Playwright with a throwaway profile listing a built `wordpress-develop` checkout; **Start development server** was pressed; the served WordPress was logged in to with the app's own credentials and asked, on Site Health's Info tab, which PHP it runs on: - PHP version set to **8.4**: the server came up, Site Health reported **PHP 8.4.25**, wp-admin served, Stop ended it. - PHP version left at the fallback, **8.3**: Site Health reported **PHP 8.3.33**. **Worth a look by hand** (any platform, the current head): Settings → Sites, choose 7.4, close: the details say "PHP 7.4". Start the server: wp-admin → Tools → Site Health → Info → Server says PHP 7.4. Turn WP_DEBUG off, stop and start the server: a page with a deprecated call shows nothing for it, and a page that calls a missing function still shows the fatal. **What must not have happened:** a running server changing PHP or constants under the contributor; a change applied to a site other than the next start; `WP_DEBUG_LOG` or the fatal handler's constant moving with the switches; the details saying a version the server will not start on. **What I could not test:** Windows, and a real server with WP_DEBUG off (I checked what the code sends, not a page's output). ## Risks and limitations - Review: 2 passes, 8 findings fixed here, 1 follow-up taken here (the real boot), 2 left. Details below. - **The details show the PHP of the next start, not of a server already running.** Change the version while a server runs and "PHP 8.4" sits above "Server running" on 8.3. Follow-up: the Server section should name the running server's PHP. - **Main requires `@php-wasm/universal`** for the list of versions. It is not a declared dependency; it is `@wp-playground/cli`'s, at whatever version that pins, and the comment says so. Declaring it pinned is a `package.json` decision I have left to the maintainer. - **The Electron unit suite failed one test once** in a run of 2004 and passed on three runs after; I could not see which test it was the first time. - A `WP_DEBUG` switch that is off still leaves `WP_DEBUG_LOG` on, by design, so the debug.log tab keeps showing warnings and errors. ## Related Part of #559, which is part of #542. Follows #639. --- <details> <summary>Design decisions and alternatives considered</summary> - **Global, applied at the next start, and read by main at each start.** The prototype's "New sites" tab suggests values copied into a site at creation. Here the version and the constants are what the server is booted with, so reading them at each start is simpler and also reaches existing sites. - **An explicit fallback, always passed.** The CLI's own default is 8.3 today; passing it ourselves keeps the behaviour stable across a Playground bump, and a stored version the bump took out falls back to it rather than to whatever the CLI then chooses. - **The list from the bundle, not written down.** `SupportedPHPVersions` from `@php-wasm/universal` is what the runner can serve; a list of our own would drift. - **Only two constants have a switch.** The others exist to make a fatal show as itself, the log exist for the tab and the updater stay out of a checkout; a switch for each would be one more thing to get wrong at a Contributor Day. - **One decision for which version is shown and used**, `phpVersionChoice` in `settings-view.cjs`: the dialog, the details and the start handler all agree on the fallback. </details> <details> <summary>Review outcome (required — see AGENTS.md)</summary> **Pass 1: 3 [fix here] · 3 [follow-up]. Pass 2 (on the fix-up and the details): 5 [fix here] · 1 [follow-up]. All 8 fixed, the real-boot follow-up taken here, 2 left.** - **Review:** completed — a separate agent context, read-only; head `9131ed7` / base `77751a1`; the runner's options checked against the CLI's `runCLI` signature and its persistent `start` command, WordPress's `wp_debug_mode()` and Playground's php.ini and mu-plugin read for what WP_DEBUG off does, the design system's switch and toggle props confirmed; ESLint and the unit files run; 3 [fix here], 3 [follow-up]. - Fixed: WP_DEBUG off was said to empty the log and the browser of errors, where it takes away notices and deprecations; which versions the control offers was decided in the component; the real boot TESTING.md asks for was not recorded. - Follow-ups: the undeclared require (a comment, left to the maintainer to declare); a stored version the bundle no longer has was shown as chosen but not used (taken here); the journey pins 8.4 (left). - **Review:** completed — a second separate agent context, read-only; head `ca84255` / base `77751a1`; the four rewordings checked against WordPress and Playground again, the details' new rows and their journeys, the retaken pictures opened against their alt texts; ESLint and the unit files run; 5 [fix here], 1 [follow-up]. - Fixed: the details showed the version set where the dialog and the start used the fallback; `error_log()` was said to reach the browser; three pictures cut the details' Build watch section off under the footer; the require had no comment on whose dependency it rides; a failed read of the versions left an enabled, empty control. - Follow-up left: the Server section naming the PHP a running server is on. - **Since review:** `ca84255 → ba66103` is those five fixes and two style notes, not reviewed again. The commit after it changes one journey: `site-header.spec.js`'s stickiness test failed on both runners, since the Debugging row left the details too tall to fit over the tray at its smallest on their screens; its seeded site now has no creation date and no trunk date, two rows fewer, and the journey was run at windows 700, 680 and 640 high and is red at 640 with the app's rule broken. On the head: `npm run lint`, `npm test` (2002), `npm run test:electron` (2003), all 119 journeys, the packaged smoke and the docs build pass. The twelve pictures were taken four times before the last change and two of them moved by 12 and 30 pixels on a corner between takes, the known noise; the three retaken after it were taken once. </details> <details> <summary>Implementation notes</summary> - `src/settings.cjs`: `phpVersion`, `wpDebug`, `scriptDebug`, `acceptSwitch`. `src/wp-debug-constants.js`: `debugConstants(debug)`. `src/server-runner.js`: `php` and the constants from the config. - `src/main.js`: `phpVersions()`, `playground:php-versions`, `playground:start` reads the store at each start. `src/preload.js`: `listPhpVersions`. - `src/renderer/settings-view.cjs`: `phpVersionChoice`. `src/renderer/hooks/use-settings.jsx`: `php`. `src/renderer/components/settings-dialog.jsx`: `SitesTab`. `src/renderer/site-details.cjs`: `phpVersion` and `debug` in the rows. - `scripts/screenshots/shots.cjs`: the three site views at 1200×900. </details> <details> <summary>Screenshots or recording</summary> The retaken images are in the diff: `docs/public/screenshots/` shows the details before and after. </details> 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Second part of #559, on the dialog of #638. The app is translatable (#540) and picks its language from the operating system's; a contributor on a machine set to a language they do not read, or at a shared laptop, had no way to choose. This adds the language to the settings.
What changes
Language, on the General tab. Your system's language, which is the default, or English, or any language the build ships a catalog for, each named in its own language ("Deutsch", "Português (Brasil)") so that someone looking for theirs finds it whatever the app is showing. The list is what
src/languages/holds, so it grows as releases ship catalogs; today that is English.Where it is read. Main puts the chosen language in front of the OS's languages and loads the first one with a catalog, as it walked the OS's before. In front, not in their place: a chosen language whose catalog a later release dropped falls back to the OS's language, not to English. The
--langswitch still replaces the whole list; it is how the journeys pick a locale, and a flag typed at launch is a decision.A change applies after a relaunch, since main applies the catalog as it starts, for its own strings and the window's. The dialog says so once what is set is no longer what the window started in, and offers Relaunch now: a quit and a start, so the quit sweep ends every child the app started, as it does on any quit. The new instance gets this one's arguments less a
wpct://address a cold start was given, which is not a second request for its ticket, and a--lang, which would outrank the language just chosen; on Linux it is started from the AppImage, since the mounted copy is gone once this one quits.The first read of the store is now before the window exists. One that cannot be read is logged and counts as no choice, so the window still opens; every later read then fails as it did before.
Beside it: the catalogs' README and CONTRIBUTING.md say where the language comes from now; a journey can launch without
--lang, as the app launches for a contributor.Not in this pull request:
pirate,art-xemoji), which are not offered, as they could not be picked from the OS list either.How to test this
Platforms: any. The journeys drive this on macOS and Windows. From the repository root, after
npm ciandnpm run build:once:settings.spec.js, the language journey: the pseudo-locale set in the store, with no--lang, is the language the app starts in; the control shows it though the build has no catalog for it; English chosen is kept at once and the dialog offers the relaunch, which asks main; the system's language chosen is kept as none and the offer stays; the pseudo-locale chosen again is refused, since the build has no catalog for it; started again with English kept, the app is in English and the control says so with no offer.i18n.spec.js: the dialog with the control, in the pseudo-locale.I broke two of the journey's claims one at a time (main not reading the chosen language; the relaunch button asking nothing of main) and each turned it red.
tests/unit/i18n.test.cjsholds the list,settings.test.cjswhat is accepted,settings-view.test.cjsthe control's entries and when the relaunch is offered, andipc-wiring.test.cjsthe order the languages are tried in, the store that cannot be read, and what the relaunch is given.Worth a look by hand (any platform, the current head): Settings → General → Language: with no catalog shipped the list is your system's language and English. Choose English, press Relaunch now: the app quits and comes back, the control says English and offers nothing. Choose your system's language, press the cog's relaunch again: as before. With
npm run i18n:download -- --locales=derun first (it needs the network), "Deutsch" is in the list, and chosen and relaunched, the app is in German where it is translated.What must not have happened: a running server or build left behind by the relaunch (the quit sweep ends them, as on any quit); a
wpct://ticket opened again after a relaunch of an app that was started from a link (Windows and Linux); the app failing to open a window whensettings.jsonis not JSON.What I could not test: Linux, where the relaunch is started from the AppImage; the unit test pins what Electron is told, not that the image starts. And a real catalog in the dialog: the repository ships none, and I did not run the download.
Risks and limitations
Related
Part of #559, which is part of #542. Follows #638. Translations: #540.
Design decisions and alternatives considered
app.exit. The relaunch goes throughapp.quit()so every child the app started is ended first.Review outcome (required — see AGENTS.md)
Pass 1: 3 [fix here] · 0 [follow-up] · 4 style notes. Pass 2 (on the fix-up): 1 [fix here] · 1 [follow-up] · 1 style note. All 4 fixed, the follow-up taken here, every style note applied.
82aac18/ basefe02e6b; the store read traced fromwhenReady, the relaunch against Electron's quit events and the single-instance lock, the language names checked on ICU for lowercase tags and Valencian, the select's value handling read in the design system's source, the journey read against the standard; ESLint, the unit files and the pot extraction run; 3 [fix here].wpct://address and a--langincluded.7eab0b6/ basefe02e6b; the fallback order followed throughresolveCatalogfor each case, the relaunch arguments against Electron's documented default and a dev launch, the three changed wiring tests confirmed red on the first commit; ESLint and the unit files run; 1 [fix here], 1 [follow-up].7eab0b6 → b68f7c2is that finding, the follow-up and the rewrap, not reviewed again. On the head:npm run lint,npm test,npm run test:electron, the settings, i18n and create-site journeys and the packaged smoke pass; all 118 journeys passed on82aac18.Implementation notes
src/i18n.cjs:languageChoices(names).src/settings.cjs:locale.src/main.js:localeReplyreads the store,languages(),i18n:languages,app:relaunch,relaunchArgs.src/preload.js:listLanguages,relaunch.src/renderer/settings-view.cjs:languageItems,languageValue,languageChanged,SYSTEM_LANGUAGE.src/renderer/components/settings-dialog.jsx:LanguageControl.src/renderer/hooks/use-settings.jsx:loaded.tests/e2e/helpers/app.cjs:lang: falsedrops the--langswitch.Screenshots or recording
Not attached: I have no way to upload images from the command line. The language journey drives everything that changed.
🤖 Generated with Claude Code