Studio: Translate "About Studio" modal - #228
Conversation
| <p class="studio-name" id="studio-by-wpcom">Studio by WordPress.com</p> | ||
| <p class="version"><span id="version-text">Version</span> <span id="version"></span></p> | ||
| <p class="links"> | ||
| <a href="https://github.com/Automattic/studio" target="_blank">GitHub</a> |
There was a problem hiding this comment.
I did not add translation for GitHub since it is a proper name. Happy to add it if it is considered necessary.
sejas
left a comment
There was a problem hiding this comment.
I've followed the testing instructions and it works as expected.
I wanted to recommend using esc_attr__ , but it's not part of @wordpress/i18n.
I suggest adding Sentry or sanitizing the strings with a custom function. My concern is that some translation would include a single quote: ' , which would break the string replacements.
| document.getElementById('local-sites').innerText = '${ __( 'Local sites powered by' ) }';` | ||
| ) | ||
| .catch( ( err ) => { | ||
| console.error( 'Error executing JavaScript:', err ); |
There was a problem hiding this comment.
Should we capture the error in sentry?
| `document.getElementById('version').innerText = '${ packageJson }'; | ||
| document.getElementById('studio-by-wpcom').innerText = '${ __( 'Studio by WordPress.com' ) }'; | ||
| document.getElementById('version-text').innerText = '${ __( 'Version' ) }'; |
There was a problem hiding this comment.
Let's unify the word Version and the actual number. Something like sprintf( __( 'Version %s' ), packageJson )
| <p class="studio-name">Studio by WordPress.com</p> | ||
| <p class="version">Version <span id="version"></span></p> | ||
| <p class="studio-name" id="studio-by-wpcom">Studio by WordPress.com</p> | ||
| <p class="version"><span id="version-text">Version</span> <span id="version"></span></p> |
There was a problem hiding this comment.
Let's use only one string here, so RTL languages will work better.
| <p class="version"><span id="version-text">Version</span> <span id="version"></span></p> | |
| <p class="version"><span id="version-text">Version x.y.z</span></p> |
Yeah I think you are right, I tried to break it and it did break. Let me conjure something for this. I will re-request review once I am ready |
|
@sejas I added something simple in 6c1f64f to handle the I also found that we have something like https://www.npmjs.com/package/@wordpress/escape-html that we already have available and installed but a single quote breaks when I try to use |
| function escapeSingleQuotes( str: string ) { | ||
| return str.replace( /'/g, "\\'" ); | ||
| } |
There was a problem hiding this comment.
wojtekn
left a comment
There was a problem hiding this comment.
I explored refactoring the HTML file into a React component and then rendering it into this custom window but the solution required modifying the app setup in multiple places. I opted for a more straightforward approach considering that that window is fairly static
Thanks for sharing the details explaining the approach you took. It seems reasonable to do so.
| </div> | ||
| <div class="info"> | ||
| <p>Local sites powered by<br><a href="https://wordpress.org/playground/" target="_blank">WordPress Playground ↗</a></p> | ||
| <p><span id="local-sites">Local sites powered by</span><br><a href="https://wordpress.org/playground/" target="_blank">WordPress Playground ↗</a></p> |
There was a problem hiding this comment.
Do we need those phrases in two places: here in the template and in the file that replaces those with translations?
There was a problem hiding this comment.
Do you mean why the translation is divided in two "divs"?
<p><span id="local-sites">Local sites powered by</span><br><a href="https://wordpress.org/playground/" target="_blank">WordPress Playground ↗</a></p> instead of <p id="local-sites">Local sites powered by<br><a href="https://wordpress.org/playground/" target="_blank">WordPress Playground ↗</a></p>
When reviewing I thought it could produce errors in RTL languages but the fact that we display one on top of the other solves any issue.
There was a problem hiding this comment.
No, I meant that tests, e.g., Local sites powered by, are now placed in two places.
There was a problem hiding this comment.
I am guessing that your question is if it could be removed from https://github.com/Automattic/studio/blob/c2c9c20219ea884493bd3ba8ffbc64f2bc5cc1ce/src/about-menu/about-menu.html#L90 since we are inserting it anyway so that it would be something like:
<p><span id="demo-sites"></span><br><a href="https://wordpress.com/hosting/?utm_source=studio&utm_medium=referral&utm_campaign=about_screen" target="_blank">WordPress.com hosting ↗</a></p>
(so just the id and no text)
Is that right?
There was a problem hiding this comment.
Yes, this is correct. I was wondering if, with the current implementation, there is a reason to keep it in the file template, too. Does it work as a fallback, so if the translation couldn't be loaded, we would display the English version included in the template? Or could such a situation not occur?
My point is that keeping the source text in two places comes with a risk that someone updates it in one place, skipping the latter.
There was a problem hiding this comment.
Yes, that's right. The strings in the HTML file serve as fallback content. This ensures that if the JavaScript fails to inject the translations or if there is any issue with the translation strings, the user will still see the default text that is added in the HTML file.
However, you bring up an important point - it might not be obvious that the code needs to be handled in two places. I will create a PR to add clarifying comments to this code.
There was a problem hiding this comment.
I created a PR here to add some clarifying comments:
There was a problem hiding this comment.
Thanks for following up on this and adding those comments. It will be helpful for future us!
## Related issues Closes ~35 open Dependabot security alerts on the repository. ## How AI was used in this PR Claude identified which Dependabot alerts were fixable via `npm update` (stale lockfile entries within existing semver ranges) vs. those requiring direct dep bumps or overrides, then applied all the easy wins in one shot. ## Proposed Changes Updates transitive and direct dependencies to their patched versions to close the majority of open Dependabot security alerts. All updates are within the existing declared semver ranges of their parent packages — no breaking changes expected. | Package | From | To | Alerts closed | |---------|------|----|---------------| | `fast-uri` | 3.1.0 | 3.1.2 | [#210](https://github.com/Automattic/studio/security/dependabot/210), [#207](https://github.com/Automattic/studio/security/dependabot/207) | | `@xmldom/xmldom` | 0.8.11 | 0.8.13 | [#192](https://github.com/Automattic/studio/security/dependabot/192), [#191](https://github.com/Automattic/studio/security/dependabot/191), [#190](https://github.com/Automattic/studio/security/dependabot/190), [#170](https://github.com/Automattic/studio/security/dependabot/170) | | `brace-expansion` | 1.1.12 | 1.1.15 | [#168](https://github.com/Automattic/studio/security/dependabot/168) | | `qs` | 6.14.0 | 6.15.2 | [#228](https://github.com/Automattic/studio/security/dependabot/228), [#89](https://github.com/Automattic/studio/security/dependabot/89), [#110](https://github.com/Automattic/studio/security/dependabot/110) | | `ip-address` | 10.1.0 | 10.1.1 | [#199](https://github.com/Automattic/studio/security/dependabot/199) | | `basic-ftp` | 5.3.0 | 5.3.1 | [#202](https://github.com/Automattic/studio/security/dependabot/202) | | `ws` | 8.18.0 | 8.21.0 | [#224](https://github.com/Automattic/studio/security/dependabot/224) | | `protobufjs` | 7.5.5 | 7.6.2 | [#221](https://github.com/Automattic/studio/security/dependabot/221), [#220](https://github.com/Automattic/studio/security/dependabot/220), [#217](https://github.com/Automattic/studio/security/dependabot/217), [#216](https://github.com/Automattic/studio/security/dependabot/216), [#219](https://github.com/Automattic/studio/security/dependabot/219), [#218](https://github.com/Automattic/studio/security/dependabot/218), [#215](https://github.com/Automattic/studio/security/dependabot/215), [#225](https://github.com/Automattic/studio/security/dependabot/225) | | `hono` | 4.12.7 | 4.12.23 | [#211](https://github.com/Automattic/studio/security/dependabot/211), [#208](https://github.com/Automattic/studio/security/dependabot/208), [#204](https://github.com/Automattic/studio/security/dependabot/204), [#203](https://github.com/Automattic/studio/security/dependabot/203), [#188](https://github.com/Automattic/studio/security/dependabot/188), [#185](https://github.com/Automattic/studio/security/dependabot/185), [#184](https://github.com/Automattic/studio/security/dependabot/184), [#183](https://github.com/Automattic/studio/security/dependabot/183), [#182](https://github.com/Automattic/studio/security/dependabot/182), [#181](https://github.com/Automattic/studio/security/dependabot/181), [#209](https://github.com/Automattic/studio/security/dependabot/209) | | `@hono/node-server` | 1.19.11 | 1.19.14 | [#180](https://github.com/Automattic/studio/security/dependabot/180) | | `lodash` | 4.17.23 | 4.18.1 | [#172](https://github.com/Automattic/studio/security/dependabot/172), [#171](https://github.com/Automattic/studio/security/dependabot/171) | | `@babel/plugin-transform-modules-systemjs` | 7.27.1 | 7.29.7 | [#212](https://github.com/Automattic/studio/security/dependabot/212) | | `@anthropic-ai/sdk` | ^0.90.0 | ^0.91.1 | [#197](https://github.com/Automattic/studio/security/dependabot/197), [#196](https://github.com/Automattic/studio/security/dependabot/196) | **Remaining open alerts** are blocked by exact-pinned third-party packages (`@php-wasm/*`, `@mariozechner/pi-*`, `electron2appx`) or have no upstream fix (`showdown`). Those require upstream releases to resolve. ## Testing Instructions - [ ] `npm run typecheck` passes - [ ] `npm test` passes - [ ] App starts and sites load normally ## Pre-merge Checklist - [x] No direct dependency version constraints changed (all updates are lockfile-only except `@anthropic-ai/sdk` range bump) - [x] `@wp-playground/*` and `@php-wasm/*` pins untouched

Closes https://github.com/Automattic/dotcom-forge/issues/7522
Proposed Changes
This PR makes the strings in the "About Studio" window translatable.
Testing Instructions
locale.tsingetPreferredSystemLanguagesto return French:src/translations/studio-fr.jed.jsonnvm use && npm install && npm startNotes:
Pre-merge Checklist