Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
338c4d4
adding locales
fellyph Oct 26, 2025
a45baff
installing i18n package
fellyph Oct 26, 2025
9fea464
Adding the I18n provider
fellyph Oct 26, 2025
14fb6bc
Creatring internationalization provider
fellyph Oct 26, 2025
a39fbfb
Adding i18n config settings
fellyph Oct 26, 2025
3080a0d
adding localization to PR menu
fellyph Oct 26, 2025
5fd8a52
Adding localization for view logs
fellyph Oct 26, 2025
deb803d
adding localization for view error component
fellyph Oct 26, 2025
afdb1ef
adding localization for renaming site modal
fellyph Oct 26, 2025
41b221a
Adding localization for the import form component
fellyph Oct 26, 2025
5d08c03
Adding localization for missing site modal
fellyph Oct 26, 2025
3b79589
Adding Localization for offline notice
fellyph Oct 26, 2025
281c001
Adding localization for save-site-modal
fellyph Oct 26, 2025
664f069
adding localization for download as zip component
fellyph Oct 26, 2025
9811832
adding localization on restore zip
fellyph Oct 26, 2025
3a0cbea
adding localization Start error modal
fellyph Oct 26, 2025
583c1c3
adding localization for modal button
fellyph Oct 26, 2025
55bab3e
adding localization for impor and export github
fellyph Oct 26, 2025
be0feb5
adding localization for pr preview
fellyph Oct 26, 2025
5dbbfe7
adding portuguese translation
fellyph Oct 26, 2025
82a3a65
Adding localization on the settings panel
fellyph Oct 26, 2025
27d64cf
adding translations for brazilian portuguese
fellyph Oct 26, 2025
a2178cb
adding translations for spanish
fellyph Oct 26, 2025
1cfd690
adding support for the property language
fellyph Oct 26, 2025
a86ef61
adding localization for site manage components
fellyph Oct 26, 2025
39cc687
Adding missing translations
fellyph Oct 26, 2025
e307941
adding space to the text
fellyph Oct 26, 2025
0b5b569
adding localization to the address bar
fellyph Oct 26, 2025
7bff596
Adding localization to playground components
fellyph Oct 26, 2025
4e137ea
adding localization to site manager components
fellyph Oct 26, 2025
3dc2c16
adding localization to missing string
fellyph Oct 26, 2025
206c508
updating configuration
fellyph Oct 26, 2025
8cd55c3
Merge branch 'trunk' into add-site-internationalization
fellyph Oct 27, 2025
74be879
Merge branch 'trunk' into add-site-internationalization
fellyph Oct 27, 2025
6a80daa
fixing package lock
fellyph Oct 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,538 changes: 346 additions & 1,192 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@
"@wordpress/core-data": "7.4.0",
"@wordpress/data": "10.4.0",
"@wordpress/element": "6.4.0",
"@wordpress/i18n": "5.4.0",
"@wordpress/notices": "5.4.0",
"chalk": "5.2.0",
"clsx": "^1.2.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import React, { useCallback } from 'react';
import css from './style.module.css';
import { useI18n } from '../../lib/i18n';

interface AddressBarProps {
url?: string;
onUpdate?: (url: string) => void;
}
export default function AddressBar({ url, onUpdate }: AddressBarProps) {
const { __ } = useI18n();
const input = React.useRef<HTMLInputElement>(null);
const [value, setValue] = React.useState(url || '');
const [isFocused, setIsFocused] = React.useState(false);
Expand Down Expand Up @@ -38,7 +40,9 @@ export default function AddressBar({ url, onUpdate }: AddressBarProps) {
onBlur={() => setIsFocused(false)}
name="url"
type="text"
aria-label='URL to visit in the WordPress site, like"/wp-admin"'
aria-label={__(
'URL to visit in the WordPress site, like"/wp-admin"'
)}
autoComplete="off"
/>
</div>
Expand Down
39 changes: 27 additions & 12 deletions packages/playground/website/src/components/browser-chrome/index.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
/**
* External dependencies
*/
import React from 'react';
import css from './style.module.css';
import AddressBar from '../address-bar';
import classNames from 'classnames';

/**
* WordPress dependencies
*/
import { useMediaQuery } from '@wordpress/compose';
import { Dropdown, Icon } from '@wordpress/components';
import { cog } from '@wordpress/icons';
import { SiteManagerIcon } from '@wp-playground/components';

/**
* Internal dependencies
*/
import css from './style.module.css';
import AddressBar from '../address-bar';
import {
useAppSelector,
getActiveClientInfo,
useActiveSite,
useAppDispatch,
} from '../../lib/state/redux/store';
import { SyncLocalFilesButton } from '../sync-local-files-button';
import { Dropdown, Icon } from '@wordpress/components';
import { Modal } from '../../components/modal';
import { cog } from '@wordpress/icons';
import Button from '../button';
import { ActiveSiteSettingsForm } from '../site-manager/site-settings-form';
import { setSiteManagerOpen } from '../../lib/state/redux/slice-ui';
import { SiteManagerIcon } from '@wp-playground/components';
import { useI18n } from '../../lib/i18n';

interface BrowserChromeProps {
children?: React.ReactNode;
Expand All @@ -27,6 +39,7 @@ export default function BrowserChrome({
children,
className,
}: BrowserChromeProps) {
const { __ } = useI18n();
const clientInfo = useAppSelector(getActiveClientInfo);
const activeSite = useActiveSite();
const showAddressBar = !!clientInfo;
Expand Down Expand Up @@ -55,7 +68,7 @@ export default function BrowserChrome({
className={classNames(css.toolbar, {
[css.withSidebarOpen]: siteManagerIsOpen,
})}
aria-label="Playground toolbar"
aria-label={__('Playground toolbar')}
>
<div className={addressBarClass}>
<AddressBar
Expand All @@ -71,8 +84,8 @@ export default function BrowserChrome({
variant="browser-chrome"
aria-label={
siteManagerIsOpen
? 'Close Site Manager'
: 'Open Site Manager'
? __('Close Site Manager')
: __('Open Site Manager')
}
aria-pressed={siteManagerIsOpen}
className={classNames(css.openSiteManagerButton, {
Expand All @@ -94,7 +107,7 @@ export default function BrowserChrome({
<>
<Button
variant="browser-chrome"
aria-label="Edit Playground settings"
aria-label={__('Edit Playground settings')}
onClick={onToggle}
aria-expanded={isModalOpen}
style={{
Expand All @@ -108,7 +121,7 @@ export default function BrowserChrome({
{isModalOpen && (
<Modal
isFullScreen={true}
title="Playground settings"
title={__('Playground settings')}
onRequestClose={closeModal}
>
<ActiveSiteSettingsForm
Expand All @@ -125,7 +138,9 @@ export default function BrowserChrome({
renderToggle={({ isOpen, onToggle }) => (
<Button
variant="browser-chrome"
aria-label="Edit Playground settings"
aria-label={__(
'Edit Playground settings'
)}
onClick={onToggle}
aria-expanded={isOpen}
style={{
Expand All @@ -147,7 +162,7 @@ export default function BrowserChrome({
>
<div className={css.headerSection}>
<h2 style={{ margin: 0 }}>
Playground settings
{__('Playground settings')}
</h2>
</div>
<ActiveSiteSettingsForm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { modalSlugs } from '../layout';
import { setActiveModal } from '../../lib/state/redux/slice-ui';
import { selectClientBySiteSlug } from '../../lib/state/redux/slice-clients';
import { randomSiteName } from '../../lib/state/redux/random-site-name';
import { useI18n } from '../../lib/i18n';

/**
* Ensures the redux store always has an activeSite value.
Expand All @@ -34,6 +35,7 @@ export function EnsurePlaygroundSiteIsSelected({
}: {
children: React.ReactNode;
}) {
const { __ } = useI18n();
const siteListingStatus = useAppSelector(
(state) => state.sites.opfsSitesLoadingState
);
Expand All @@ -58,14 +60,14 @@ export function EnsurePlaygroundSiteIsSelected({

useEffect(() => {
if (!opfsSiteStorage) {
logger.error('Error loading sites: OPFS not available');
logger.error(__('Error loading sites: OPFS not available'));
dispatch(OPFSSitesLoaded([]));
return;
}
opfsSiteStorage.list().then(
(sites) => dispatch(OPFSSitesLoaded(sites)),
(error) => {
logger.error('Error loading sites:', error);
logger.error(__('Error loading sites:'), error);
dispatch(OPFSSitesLoaded([]));
}
);
Expand All @@ -87,7 +89,9 @@ export function EnsurePlaygroundSiteIsSelected({
if (!requestedSiteObject) {
if (promptIfSiteMissing) {
logger.log(
'The requested site was not found. Creating a new temporary site.'
__(
'The requested site was not found. Creating a new temporary site.'
)
);

await createNewTemporarySite(
Expand All @@ -99,7 +103,9 @@ export function EnsurePlaygroundSiteIsSelected({
} else {
// @TODO: Notification: 'The requested site was not found. Redirecting to a new temporary site.'
logger.log(
'The requested site was not found. Redirecting to a new temporary site.'
__(
'The requested site was not found. Redirecting to a new temporary site.'
)
);
const currentUrl = new URL(window.location.href);
currentUrl.searchParams.delete('site-slug');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import { useAppSelector } from '../../lib/state/redux/store';
import { setActiveModal } from '../../lib/state/redux/slice-ui';
import { Modal } from '../../components/modal';
import ModalButtons from '../modal/modal-buttons';
import { useI18n } from '../../lib/i18n';

export function ErrorReportModal(props: { blueprint: BlueprintV1Declaration }) {
const { __ } = useI18n();
const activeModal = useAppSelector(
(state: PlaygroundReduxState) => state.ui.activeModal
);
Expand Down Expand Up @@ -97,48 +99,50 @@ export function ErrorReportModal(props: { blueprint: BlueprintV1Declaration }) {

function getTitle() {
if (!submitted) {
return 'Report error';
return __('Report error');
} else if (submitError) {
return 'Failed to report the error';
return __('Failed to report the error');
} else {
return 'Thank you for reporting the error';
return __('Thank you for reporting the error');
}
}

function getContent() {
if (!submitted) {
return (
<>
Playground crashed because of an error. You can help resolve
the issue by sharing the error details with us.
{__(
'Playground crashed because of an error. You can help resolve the issue by sharing the error details with us.'
)}
</>
);
} else if (submitError) {
return (
<>
We were unable to submit the error report. Please try again
or open an{' '}
{__(
'We were unable to submit the error report. Please try again or open an '
)}
<a
href="https://github.com/WordPress/wordpress-playground/issues/"
target="_blank"
rel="noopener noreferrer"
>
issue on GitHub.
{__('issue on GitHub.')}
</a>
</>
);
} else {
return (
<>
Your report has been submitted to the{' '}
{__('Your report has been submitted to the ')}
<a
href="https://wordpress.slack.com/archives/C06Q5DCKZ3L"
target="_blank"
rel="noopener noreferrer"
>
Making WordPress #playground-logs Slack channel
</a>{' '}
and will be reviewed by the team.
{__('Making WordPress #playground-logs Slack channel')}
</a>
{__(' and will be reviewed by the team.')}
</>
);
}
Expand All @@ -160,19 +164,25 @@ export function ErrorReportModal(props: { blueprint: BlueprintV1Declaration }) {
{showForm() && (
<>
<TextareaControl
label="How can we recreate this error?"
help="Describe what caused the error and how can we recreate it."
label={__('How can we recreate this error?')}
help={__(
'Describe what caused the error and how can we recreate it.'
)}
value={text}
onChange={setText}
required={true}
/>
<TextareaControl
label="Logs"
label={__('Logs')}
value={logs}
onChange={setLogs}
/>

<TextControl label="Url" value={url} onChange={setUrl} />
<TextControl
label={__('Url')}
value={url}
onChange={setUrl}
/>

<ModalButtons
areBusy={loading}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import ImportForm from '../import-form/index';
import { Modal } from '../../components/modal';
import { setActiveModal } from '../../lib/state/redux/slice-ui';
import type { PlaygroundDispatch } from '../../lib/state/redux/store';
import { useI18n } from '../../lib/i18n';

export const ImportFormModal = () => {
const { __ } = useI18n();
const playground = usePlaygroundClient();
const dispatch: PlaygroundDispatch = useDispatch();

Expand All @@ -16,19 +18,20 @@ export const ImportFormModal = () => {
function handleImported() {
// eslint-disable-next-line no-alert
alert(
'File imported! This Playground instance has been updated. Refreshing now.'
__(
'File imported! This Playground instance has been updated. Refreshing now.'
)
);
closeModal();
playground!.goTo('/');
}

return (
<Modal
title="Import Playground"
contentLabel='This is a dialog window which overlays the main content of the
page. The modal begins with a heading 2 called "Import
Playground". Pressing the Close Import Window will close
the modal and bring you back to where you were on the page.'
title={__('Import Playground')}
contentLabel={__(
'This is a dialog window which overlays the main content of the page. The modal begins with a heading 2 called "Import Playground". Pressing the Close Import Window will close the modal and bring you back to where you were on the page.'
)}
onRequestClose={closeModal}
>
<ImportForm
Expand Down
13 changes: 9 additions & 4 deletions packages/playground/website/src/components/import-form/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { importWordPressFiles } from '@wp-playground/client';
import forms from '../../forms.module.css';
import { logger } from '@php-wasm/logger';
import ModalButtons from '../modal/modal-buttons';
import { useI18n } from '../../lib/i18n';

interface ImportFormProps {
playground: PlaygroundClient;
Expand All @@ -17,6 +18,7 @@ export default function ImportForm({
onImported,
onClose,
}: ImportFormProps) {
const { __ } = useI18n();
const fileInputRef = useRef<any>();
const [file, setFile] = useState<File | null>(null);
const [error, setError] = useState<string>('');
Expand All @@ -35,7 +37,9 @@ export default function ImportForm({
} catch (error) {
logger.error(error);
setError(
'Unable to import file. Is it a valid WordPress Playground export?'
__(
'Unable to import file. Is it a valid WordPress Playground export?'
)
);
return;
}
Expand All @@ -46,8 +50,9 @@ export default function ImportForm({
return (
<>
<p>
You may replace the current WordPress Playground site with a
previously exported one.
{__(
'You may replace the current WordPress Playground site with a previously exported one.'
)}
</p>
<div className={`${forms.formGroup} ${forms.formGroupLast}`}>
{error ? <div className={forms.error}>{error}</div> : null}
Expand All @@ -64,7 +69,7 @@ export default function ImportForm({
areDisabled={!file}
onCancel={onClose}
onSubmit={handleSubmit}
submitText="Import"
submitText={__('Import')}
/>
</>
);
Expand Down
Loading
Loading