Minimal Viable Navigation Menu (#1510)

* Minimal Viable Navigation Menu
Translation with new namespace
I18Next configuration leaning on default separator and namespace

Broom: i18n + debug:false

* Minimal Viable Navigation Menu
Test entry for Toolbar.test.jsx

* Translation.json : Changes in translation for new namespace
About : broom About lines 17-26
Nav component : changes in keys
KeyboardShortcutModal.jsx: Key now in Common

* Voice Over Labels in Preferences:index
Labels included in translations.json

* Voice Over Labels in Preferences:index
Labels included in translations.json

* Voice Over Labels in Preferences:index
Labels included in translations.json

* Voice Over Labels in Preferences:index
Labels included in translations.json
Snapshot updated npm run test -- -u

* translations.json ARIA labels adjacent to respective label
Updated names to call the labels
Common namespace without currently used entries

* Update Nav.jsx

Missing Common.p5logoARIA key

* Update Toolbar.test.jsx

Deleting commented line 78

* Update in keys

Co-authored-by: Andrew Nicolaou <me@andrewnicolaou.co.uk>
This commit is contained in:
ov 2020-07-31 14:20:42 +01:00 committed by GitHub
parent db18ff4a28
commit 05e43c70b7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 444 additions and 323 deletions

View file

@ -100,11 +100,11 @@ class Nav extends React.PureComponent {
const { unsavedChanges, warnIfUnsavedChanges } = this.props; const { unsavedChanges, warnIfUnsavedChanges } = this.props;
if (!unsavedChanges) { if (!unsavedChanges) {
this.props.showToast(1500); this.props.showToast(1500);
this.props.setToastText('Opened new sketch.'); this.props.setToastText('Toast.OpenedNewSketch');
this.props.newProject(); this.props.newProject();
} else if (warnIfUnsavedChanges && warnIfUnsavedChanges()) { } else if (warnIfUnsavedChanges && warnIfUnsavedChanges()) {
this.props.showToast(1500); this.props.showToast(1500);
this.props.setToastText('Opened new sketch.'); this.props.setToastText('Toast.OpenedNewSketch');
this.props.newProject(); this.props.newProject();
} }
this.setDropdown('none'); this.setDropdown('none');
@ -172,7 +172,7 @@ class Nav extends React.PureComponent {
handleLangSelection(event) { handleLangSelection(event) {
i18next.changeLanguage(event.target.value); i18next.changeLanguage(event.target.value);
this.props.showToast(1500); this.props.showToast(1500);
this.props.setToastText('LangChange'); this.props.setToastText('Toast.LangChange');
this.setDropdown('none'); this.setDropdown('none');
} }
@ -240,13 +240,13 @@ class Nav extends React.PureComponent {
return ( return (
<ul className="nav__items-left"> <ul className="nav__items-left">
<li className="nav__item-logo"> <li className="nav__item-logo">
<LogoIcon role="img" aria-label="p5.js Logo" focusable="false" className="svg__logo" /> <LogoIcon role="img" aria-label={this.props.t('Common.p5logoARIA')} focusable="false" className="svg__logo" />
</li> </li>
<li className="nav__item nav__item--no-icon"> <li className="nav__item nav__item--no-icon">
<Link to="/" className="nav__back-link"> <Link to="/" className="nav__back-link">
<CaretLeftIcon className="nav__back-icon" focusable="false" aria-hidden="true" /> <CaretLeftIcon className="nav__back-icon" focusable="false" aria-hidden="true" />
<span className="nav__item-header"> <span className="nav__item-header">
{this.props.t('BackEditor')} {this.props.t('Nav.BackEditor')}
</span> </span>
</Link> </Link>
</li> </li>
@ -258,7 +258,7 @@ class Nav extends React.PureComponent {
return ( return (
<ul className="nav__items-left"> <ul className="nav__items-left">
<li className="nav__item-logo"> <li className="nav__item-logo">
<LogoIcon role="img" aria-label="p5.js Logo" focusable="false" className="svg__logo" /> <LogoIcon role="img" aria-label={this.props.t('Common.p5logoARIA')} focusable="false" className="svg__logo" />
</li> </li>
<li className={navDropdownState.file}> <li className={navDropdownState.file}>
<button <button
@ -271,7 +271,7 @@ class Nav extends React.PureComponent {
} }
}} }}
> >
<span className="nav__item-header">{this.props.t('File')}</span> <span className="nav__item-header">{this.props.t('Nav.File.Title')}</span>
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" /> <TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
</button> </button>
<ul className="nav__dropdown"> <ul className="nav__dropdown">
@ -281,7 +281,7 @@ class Nav extends React.PureComponent {
onFocus={this.handleFocusForFile} onFocus={this.handleFocusForFile}
onBlur={this.handleBlur} onBlur={this.handleBlur}
> >
{this.props.t('New')} {this.props.t('Nav.File.New')}
</button> </button>
</li> </li>
{ getConfig('LOGIN_ENABLED') && (!this.props.project.owner || this.isUserOwner()) && { getConfig('LOGIN_ENABLED') && (!this.props.project.owner || this.isUserOwner()) &&
@ -291,7 +291,7 @@ class Nav extends React.PureComponent {
onFocus={this.handleFocusForFile} onFocus={this.handleFocusForFile}
onBlur={this.handleBlur} onBlur={this.handleBlur}
> >
{this.props.t('Save')} {this.props.t('Common.Save')}
<span className="nav__keyboard-shortcut">{metaKeyName}+S</span> <span className="nav__keyboard-shortcut">{metaKeyName}+S</span>
</button> </button>
</li> } </li> }
@ -302,7 +302,7 @@ class Nav extends React.PureComponent {
onFocus={this.handleFocusForFile} onFocus={this.handleFocusForFile}
onBlur={this.handleBlur} onBlur={this.handleBlur}
> >
{this.props.t('Duplicate')} {this.props.t('Nav.File.Duplicate')}
</button> </button>
</li> } </li> }
{ this.props.project.id && { this.props.project.id &&
@ -312,7 +312,7 @@ class Nav extends React.PureComponent {
onFocus={this.handleFocusForFile} onFocus={this.handleFocusForFile}
onBlur={this.handleBlur} onBlur={this.handleBlur}
> >
{this.props.t('Share')} {this.props.t('Nav.File.Share')}
</button> </button>
</li> } </li> }
{ this.props.project.id && { this.props.project.id &&
@ -322,7 +322,7 @@ class Nav extends React.PureComponent {
onFocus={this.handleFocusForFile} onFocus={this.handleFocusForFile}
onBlur={this.handleBlur} onBlur={this.handleBlur}
> >
{this.props.t('Download')} {this.props.t('Nav.File.Download')}
</button> </button>
</li> } </li> }
{ this.props.user.authenticated && { this.props.user.authenticated &&
@ -333,7 +333,7 @@ class Nav extends React.PureComponent {
onBlur={this.handleBlur} onBlur={this.handleBlur}
onClick={this.setDropdownForNone} onClick={this.setDropdownForNone}
> >
{this.props.t('Open')} {this.props.t('Nav.File.Open')}
</Link> </Link>
</li> } </li> }
{getConfig('UI_COLLECTIONS_ENABLED') && {getConfig('UI_COLLECTIONS_ENABLED') &&
@ -346,7 +346,7 @@ class Nav extends React.PureComponent {
onBlur={this.handleBlur} onBlur={this.handleBlur}
onClick={this.setDropdownForNone} onClick={this.setDropdownForNone}
> >
{this.props.t('AddToCollection')} {this.props.t('Nav.File.AddToCollection')}
</Link> </Link>
</li>} </li>}
{ getConfig('EXAMPLES_ENABLED') && { getConfig('EXAMPLES_ENABLED') &&
@ -357,7 +357,7 @@ class Nav extends React.PureComponent {
onBlur={this.handleBlur} onBlur={this.handleBlur}
onClick={this.setDropdownForNone} onClick={this.setDropdownForNone}
> >
{this.props.t('Examples')} {this.props.t('Nav.File.Examples')}
</Link> </Link>
</li> } </li> }
</ul> </ul>
@ -373,7 +373,7 @@ class Nav extends React.PureComponent {
} }
}} }}
> >
<span className="nav__item-header">{this.props.t('Edit')}</span> <span className="nav__item-header">{this.props.t('Nav.Edit.Title')}</span>
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" /> <TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
</button> </button>
<ul className="nav__dropdown" > <ul className="nav__dropdown" >
@ -386,7 +386,7 @@ class Nav extends React.PureComponent {
onFocus={this.handleFocusForEdit} onFocus={this.handleFocusForEdit}
onBlur={this.handleBlur} onBlur={this.handleBlur}
> >
{this.props.t('TidyCode')} {this.props.t('Nav.Edit.TidyCode')}
<span className="nav__keyboard-shortcut">{'\u21E7'}+Tab</span> <span className="nav__keyboard-shortcut">{'\u21E7'}+Tab</span>
</button> </button>
</li> </li>
@ -396,7 +396,7 @@ class Nav extends React.PureComponent {
onFocus={this.handleFocusForEdit} onFocus={this.handleFocusForEdit}
onBlur={this.handleBlur} onBlur={this.handleBlur}
> >
{this.props.t('Find')} {this.props.t('Nav.Edit.Find')}
<span className="nav__keyboard-shortcut">{metaKeyName}+F</span> <span className="nav__keyboard-shortcut">{metaKeyName}+F</span>
</button> </button>
</li> </li>
@ -406,7 +406,7 @@ class Nav extends React.PureComponent {
onFocus={this.handleFocusForEdit} onFocus={this.handleFocusForEdit}
onBlur={this.handleBlur} onBlur={this.handleBlur}
> >
{this.props.t('FindNext')} {this.props.t('Nav.Edit.FindNext')}
<span className="nav__keyboard-shortcut">{metaKeyName}+G</span> <span className="nav__keyboard-shortcut">{metaKeyName}+G</span>
</button> </button>
</li> </li>
@ -416,7 +416,7 @@ class Nav extends React.PureComponent {
onFocus={this.handleFocusForEdit} onFocus={this.handleFocusForEdit}
onBlur={this.handleBlur} onBlur={this.handleBlur}
> >
{this.props.t('FindPrevious')} {this.props.t('Nav.Edit.FindPrevious')}
<span className="nav__keyboard-shortcut">{'\u21E7'}+{metaKeyName}+G</span> <span className="nav__keyboard-shortcut">{'\u21E7'}+{metaKeyName}+G</span>
</button> </button>
</li> </li>
@ -433,7 +433,7 @@ class Nav extends React.PureComponent {
} }
}} }}
> >
<span className="nav__item-header">{this.props.t('Sketch')}</span> <span className="nav__item-header">{this.props.t('Nav.Sketch.Title')}</span>
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" /> <TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
</button> </button>
<ul className="nav__dropdown"> <ul className="nav__dropdown">
@ -443,7 +443,7 @@ class Nav extends React.PureComponent {
onFocus={this.handleFocusForSketch} onFocus={this.handleFocusForSketch}
onBlur={this.handleBlur} onBlur={this.handleBlur}
> >
{this.props.t('AddFile')} {this.props.t('Nav.Sketch.AddFile')}
</button> </button>
</li> </li>
<li className="nav__dropdown-item"> <li className="nav__dropdown-item">
@ -452,7 +452,7 @@ class Nav extends React.PureComponent {
onFocus={this.handleFocusForSketch} onFocus={this.handleFocusForSketch}
onBlur={this.handleBlur} onBlur={this.handleBlur}
> >
{this.props.t('AddFolder')} {this.props.t('Nav.Sketch.AddFolder')}
</button> </button>
</li> </li>
<li className="nav__dropdown-item"> <li className="nav__dropdown-item">
@ -461,7 +461,7 @@ class Nav extends React.PureComponent {
onFocus={this.handleFocusForSketch} onFocus={this.handleFocusForSketch}
onBlur={this.handleBlur} onBlur={this.handleBlur}
> >
{this.props.t('Run')} {this.props.t('Nav.Sketch.Run')}
<span className="nav__keyboard-shortcut">{metaKeyName}+Enter</span> <span className="nav__keyboard-shortcut">{metaKeyName}+Enter</span>
</button> </button>
</li> </li>
@ -471,7 +471,7 @@ class Nav extends React.PureComponent {
onFocus={this.handleFocusForSketch} onFocus={this.handleFocusForSketch}
onBlur={this.handleBlur} onBlur={this.handleBlur}
> >
{this.props.t('Stop')} {this.props.t('Nav.Sketch.Stop')}
<span className="nav__keyboard-shortcut">{'\u21E7'}+{metaKeyName}+Enter</span> <span className="nav__keyboard-shortcut">{'\u21E7'}+{metaKeyName}+Enter</span>
</button> </button>
</li> </li>
@ -508,7 +508,7 @@ class Nav extends React.PureComponent {
} }
}} }}
> >
<span className="nav__item-header">{this.props.t('Help')}</span> <span className="nav__item-header">{this.props.t('Nav.Help.Title')}</span>
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" /> <TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
</button> </button>
<ul className="nav__dropdown"> <ul className="nav__dropdown">
@ -518,7 +518,7 @@ class Nav extends React.PureComponent {
onBlur={this.handleBlur} onBlur={this.handleBlur}
onClick={this.handleKeyboardShortcuts} onClick={this.handleKeyboardShortcuts}
> >
{this.props.t('KeyboardShortcuts')} {this.props.t('Nav.Help.KeyboardShortcuts')}
</button> </button>
</li> </li>
<li className="nav__dropdown-item"> <li className="nav__dropdown-item">
@ -529,7 +529,7 @@ class Nav extends React.PureComponent {
onFocus={this.handleFocusForHelp} onFocus={this.handleFocusForHelp}
onBlur={this.handleBlur} onBlur={this.handleBlur}
onClick={this.setDropdownForNone} onClick={this.setDropdownForNone}
>{this.props.t('Reference')} >{this.props.t('Nav.Help.Reference')}
</a> </a>
</li> </li>
<li className="nav__dropdown-item"> <li className="nav__dropdown-item">
@ -539,7 +539,7 @@ class Nav extends React.PureComponent {
onBlur={this.handleBlur} onBlur={this.handleBlur}
onClick={this.setDropdownForNone} onClick={this.setDropdownForNone}
> >
{this.props.t('About')} {this.props.t('Nav.Help.About')}
</Link> </Link>
</li> </li>
</ul> </ul>
@ -562,7 +562,7 @@ class Nav extends React.PureComponent {
} }
}} }}
> >
<span className="nav__item-header"> {this.props.t('Lang')}</span> <span className="nav__item-header"> {this.props.t('Nav.Lang')}</span>
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" /> <TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
</button> </button>
<ul className="nav__dropdown"> <ul className="nav__dropdown">
@ -608,13 +608,13 @@ class Nav extends React.PureComponent {
<ul className="nav__items-right" title="user-menu"> <ul className="nav__items-right" title="user-menu">
<li className="nav__item"> <li className="nav__item">
<Link to="/login" className="nav__auth-button"> <Link to="/login" className="nav__auth-button">
<span className="nav__item-header">{this.props.t('Login')}</span> <span className="nav__item-header">{this.props.t('Nav.Login.Login')}</span>
</Link> </Link>
</li> </li>
<span className="nav__item-or">{this.props.t('LoginOr')}</span> <span className="nav__item-or">{this.props.t('Nav.Login.LoginOr')}</span>
<li className="nav__item"> <li className="nav__item">
<Link to="/signup" className="nav__auth-button"> <Link to="/signup" className="nav__auth-button">
<span className="nav__item-header">{this.props.t('SignUp')}</span> <span className="nav__item-header">{this.props.t('Nav.Login.SignUp')}</span>
</Link> </Link>
</li> </li>
</ul> </ul>
@ -625,7 +625,7 @@ class Nav extends React.PureComponent {
return ( return (
<ul className="nav__items-right" title="user-menu"> <ul className="nav__items-right" title="user-menu">
<li className="nav__item"> <li className="nav__item">
<span>{this.props.t('Hello')}, {this.props.user.username}!</span> <span>{this.props.t('Nav.Auth.Hello')}, {this.props.user.username}!</span>
</li> </li>
<span className="nav__item-spacer">|</span> <span className="nav__item-spacer">|</span>
<li className={navDropdownState.account}> <li className={navDropdownState.account}>
@ -640,7 +640,7 @@ class Nav extends React.PureComponent {
} }
}} }}
> >
{this.props.t('MyAccount')} {this.props.t('Nav.Auth.MyAccount')}
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" /> <TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
</button> </button>
<ul className="nav__dropdown"> <ul className="nav__dropdown">
@ -651,7 +651,7 @@ class Nav extends React.PureComponent {
onBlur={this.handleBlur} onBlur={this.handleBlur}
onClick={this.setDropdownForNone} onClick={this.setDropdownForNone}
> >
{this.props.t('MySketches')} {this.props.t('Nav.Auth.MySketches')}
</Link> </Link>
</li> </li>
{getConfig('UI_COLLECTIONS_ENABLED') && {getConfig('UI_COLLECTIONS_ENABLED') &&
@ -662,7 +662,7 @@ class Nav extends React.PureComponent {
onBlur={this.handleBlur} onBlur={this.handleBlur}
onClick={this.setDropdownForNone} onClick={this.setDropdownForNone}
> >
{this.props.t('MyCollections')} {this.props.t('Nav.Auth.MyCollections')}
</Link> </Link>
</li> </li>
} }
@ -673,7 +673,7 @@ class Nav extends React.PureComponent {
onBlur={this.handleBlur} onBlur={this.handleBlur}
onClick={this.setDropdownForNone} onClick={this.setDropdownForNone}
> >
{this.props.t('MyAssets')} {this.props.t('Nav.Auth.MyAssets')}
</Link> </Link>
</li> </li>
<li className="nav__dropdown-item"> <li className="nav__dropdown-item">
@ -683,7 +683,7 @@ class Nav extends React.PureComponent {
onBlur={this.handleBlur} onBlur={this.handleBlur}
onClick={this.setDropdownForNone} onClick={this.setDropdownForNone}
> >
{this.props.t('Settings')} {this.props.t('Preferences.Settings')}
</Link> </Link>
</li> </li>
<li className="nav__dropdown-item"> <li className="nav__dropdown-item">
@ -692,7 +692,7 @@ class Nav extends React.PureComponent {
onFocus={this.handleFocusForAccount} onFocus={this.handleFocusForAccount}
onBlur={this.handleBlur} onBlur={this.handleBlur}
> >
{this.props.t('LogOut')} {this.props.t('Nav.Auth.LogOut')}
</button> </button>
</li> </li>
</ul> </ul>
@ -842,5 +842,5 @@ const mapDispatchToProps = {
setAllAccessibleOutput setAllAccessibleOutput
}; };
export default withTranslation('WebEditor')(withRouter(connect(mapStateToProps, mapDispatchToProps)(Nav))); export default withTranslation()(withRouter(connect(mapStateToProps, mapDispatchToProps)(Nav)));
export { Nav as NavComponent }; export { Nav as NavComponent };

View file

@ -14,7 +14,6 @@ exports[`Nav renders correctly 1`] = `
class="nav__item-logo" class="nav__item-logo"
> >
<test-file-stub <test-file-stub
aria-label="p5.js Logo"
classname="svg__logo" classname="svg__logo"
focusable="false" focusable="false"
role="img" role="img"

View file

@ -16,11 +16,10 @@ const options = {
i18n i18n
.use(initReactI18next) // pass the i18n instance to react-i18next. .use(initReactI18next) // pass the i18n instance to react-i18next.
.use(LanguageDetector)// to detect the language from currentBrowser // .use(LanguageDetector)// to detect the language from currentBrowser
.use(Backend) // to fetch the data from server .use(Backend) // to fetch the data from server
.init({ .init({
lng: 'en-US', lng: 'en-US',
defaultNS: 'WebEditor',
fallbackLng, // if user computer language is not on the list of available languages, than we will be using the fallback language specified earlier fallbackLng, // if user computer language is not on the list of available languages, than we will be using the fallback language specified earlier
debug: false, debug: false,
backend: options, backend: options,

View file

@ -157,19 +157,19 @@ export function saveProject(selectedFile = null, autosave = false) {
if (!autosave) { if (!autosave) {
if (state.ide.justOpenedProject && state.preferences.autosave) { if (state.ide.justOpenedProject && state.preferences.autosave) {
dispatch(showToast(5500)); dispatch(showToast(5500));
dispatch(setToastText('Sketch saved.')); dispatch(setToastText('Toast.SketchSaved'));
setTimeout(() => dispatch(setToastText('Autosave enabled.')), 1500); setTimeout(() => dispatch(setToastText('Toast.AutosaveEnabled')), 1500);
dispatch(resetJustOpenedProject()); dispatch(resetJustOpenedProject());
} else { } else {
dispatch(showToast(1500)); dispatch(showToast(1500));
dispatch(setToastText('Sketch saved.')); dispatch(setToastText('Toast.SketchSaved'));
} }
} }
}) })
.catch((error) => { .catch((error) => {
const { response } = error; const { response } = error;
dispatch(endSavingProject()); dispatch(endSavingProject());
dispatch(setToastText('Failed to save sketch.')); dispatch(setToastText('Toast.SketchFailedSave'));
dispatch(showToast(1500)); dispatch(showToast(1500));
if (response.status === 403) { if (response.status === 403) {
dispatch(showErrorModal('staleSession')); dispatch(showErrorModal('staleSession'));
@ -199,19 +199,19 @@ export function saveProject(selectedFile = null, autosave = false) {
if (!autosave) { if (!autosave) {
if (state.preferences.autosave) { if (state.preferences.autosave) {
dispatch(showToast(5500)); dispatch(showToast(5500));
dispatch(setToastText('Sketch saved.')); dispatch(setToastText('Toast.SketchSaved'));
setTimeout(() => dispatch(setToastText('Autosave enabled.')), 1500); setTimeout(() => dispatch(setToastText('Toast.AutosaveEnabled')), 1500);
dispatch(resetJustOpenedProject()); dispatch(resetJustOpenedProject());
} else { } else {
dispatch(showToast(1500)); dispatch(showToast(1500));
dispatch(setToastText('Sketch saved.')); dispatch(setToastText('Toast.SketchSaved'));
} }
} }
}) })
.catch((error) => { .catch((error) => {
const { response } = error; const { response } = error;
dispatch(endSavingProject()); dispatch(endSavingProject());
dispatch(setToastText('Failed to save sketch.')); dispatch(setToastText('Toast.SketchFailedSave'));
dispatch(showToast(1500)); dispatch(showToast(1500));
if (response.status === 403) { if (response.status === 403) {
dispatch(showErrorModal('staleSession')); dispatch(showErrorModal('staleSession'));

View file

@ -10,23 +10,13 @@ function About(props) {
return ( return (
<div className="about__content"> <div className="about__content">
<Helmet> <Helmet>
<title>p5.js Web Editor | About </title> <title> {t('About.TitleHelmet')} </title>
</Helmet> </Helmet>
<div className="about__content-column"> <div className="about__content-column">
<SquareLogoIcon className="about__logo" role="img" aria-label="p5.js Logo" focusable="false" /> <SquareLogoIcon className="about__logo" role="img" aria-label={t('Common.p5logoARIA')} focusable="false" />
{/* Video button to hello p5 video page */}
{/* <p className="about__play-video">
<a
href="http://hello.p5js.org/"
target="_blank"
rel="noopener noreferrer"
>
<PlayIcon className="about__play-video-button" title="Play Hello Video" />
Play hello! video</a>
</p> */}
</div> </div>
<div className="about__content-column"> <div className="about__content-column">
<h3 className="about__content-column-title">{t('NewP5')}</h3> <h3 className="about__content-column-title">{t('About.NewP5')}</h3>
<p className="about__content-column-list"> <p className="about__content-column-list">
<a <a
href="https://p5js.org/examples/" href="https://p5js.org/examples/"
@ -34,7 +24,7 @@ function About(props) {
rel="noopener noreferrer" rel="noopener noreferrer"
> >
<AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" /> <AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" />
{t('Examples')} {t('About.Examples')}
</a> </a>
</p> </p>
<p className="about__content-column-list"> <p className="about__content-column-list">
@ -44,12 +34,12 @@ function About(props) {
rel="noopener noreferrer" rel="noopener noreferrer"
> >
<AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" /> <AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" />
{t('Learn')} {t('About.Learn')}
</a> </a>
</p> </p>
</div> </div>
<div className="about__content-column"> <div className="about__content-column">
<h3 className="about__content-column-title">{t('Resources')}</h3> <h3 className="about__content-column-title">{t('About.Resources')}</h3>
<p className="about__content-column-list"> <p className="about__content-column-list">
<a <a
href="https://p5js.org/libraries/" href="https://p5js.org/libraries/"
@ -57,7 +47,7 @@ function About(props) {
rel="noopener noreferrer" rel="noopener noreferrer"
> >
<AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" /> <AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" />
{t('Libraries')} {t('About.Libraries')}
</a> </a>
</p> </p>
<p className="about__content-column-list"> <p className="about__content-column-list">
@ -67,7 +57,7 @@ function About(props) {
rel="noopener noreferrer" rel="noopener noreferrer"
> >
<AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" /> <AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" />
{t('Reference')} {t('Nav.Help.Reference')}
</a> </a>
</p> </p>
<p className="about__content-column-list"> <p className="about__content-column-list">
@ -77,7 +67,7 @@ function About(props) {
rel="noopener noreferrer" rel="noopener noreferrer"
> >
<AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" /> <AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" />
{t('Forum')} {t('About.Forum')}
</a> </a>
</p> </p>
</div> </div>
@ -87,7 +77,7 @@ function About(props) {
href="https://github.com/processing/p5.js-web-editor" href="https://github.com/processing/p5.js-web-editor"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
>{t('Contribute')} >{t('About.Contribute')}
</a> </a>
</p> </p>
<p className="about__footer-list"> <p className="about__footer-list">
@ -95,7 +85,7 @@ function About(props) {
href="https://github.com/processing/p5.js-web-editor/issues/new" href="https://github.com/processing/p5.js-web-editor/issues/new"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
>{t('Report')} >{t('About.Report')}
</a> </a>
</p> </p>
<p className="about__footer-list"> <p className="about__footer-list">

View file

@ -6,50 +6,50 @@ function KeyboardShortcutModal() {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div className="keyboard-shortcuts"> <div className="keyboard-shortcuts">
<h3 className="keyboard-shortcuts__title">{t('CodeEditing')}</h3> <h3 className="keyboard-shortcuts__title">{t('KeyboardShortcuts.CodeEditing.CodeEditing')}</h3>
<p className="keyboard-shortcuts__description"> <p className="keyboard-shortcuts__description">
{t('Code editing keyboard shortcuts follow')} <a href="https://shortcuts.design/toolspage-sublimetext.html" target="_blank" rel="noopener noreferrer">{t('Sublime Text shortcuts')}</a>. {t('KeyboardShortcuts.ShortcutsFollow')} <a href="https://shortcuts.design/toolspage-sublimetext.html" target="_blank" rel="noopener noreferrer">{t('KeyboardShortcuts.SublimeText')}</a>.
</p> </p>
<ul className="keyboard-shortcuts__list"> <ul className="keyboard-shortcuts__list">
<li className="keyboard-shortcut-item"> <li className="keyboard-shortcut-item">
<span className="keyboard-shortcut__command">{'\u21E7'} + Tab</span> <span className="keyboard-shortcut__command">{'\u21E7'} + Tab</span>
<span>{t('Tidy')}</span> <span>{t('KeyboardShortcuts.CodeEditing.Tidy')}</span>
</li> </li>
<li className="keyboard-shortcut-item"> <li className="keyboard-shortcut-item">
<span className="keyboard-shortcut__command"> <span className="keyboard-shortcut__command">
{metaKeyName} + F {metaKeyName} + F
</span> </span>
<span>{t('FindText')}</span> <span>{t('KeyboardShortcuts.CodeEditing.FindText')}</span>
</li> </li>
<li className="keyboard-shortcut-item"> <li className="keyboard-shortcut-item">
<span className="keyboard-shortcut__command"> <span className="keyboard-shortcut__command">
{metaKeyName} + G {metaKeyName} + G
</span> </span>
<span>{t('FindNextTextMatch')}</span> <span>{t('KeyboardShortcuts.CodeEditing.FindNextTextMatch')}</span>
</li> </li>
<li className="keyboard-shortcut-item"> <li className="keyboard-shortcut-item">
<span className="keyboard-shortcut__command"> <span className="keyboard-shortcut__command">
{metaKeyName} + {'\u21E7'} + G {metaKeyName} + {'\u21E7'} + G
</span> </span>
<span>{t('FindPreviousTextMatch')}</span> <span>{t('KeyboardShortcuts.CodeEditing.FindPreviousTextMatch')}</span>
</li> </li>
<li className="keyboard-shortcut-item"> <li className="keyboard-shortcut-item">
<span className="keyboard-shortcut__command"> <span className="keyboard-shortcut__command">
{metaKeyName} + [ {metaKeyName} + [
</span> </span>
<span>{t('IndentCodeLeft')}</span> <span>{t('KeyboardShortcuts.CodeEditing.IndentCodeLeft')}</span>
</li> </li>
<li className="keyboard-shortcut-item"> <li className="keyboard-shortcut-item">
<span className="keyboard-shortcut__command"> <span className="keyboard-shortcut__command">
{metaKeyName} + ] {metaKeyName} + ]
</span> </span>
<span>{t('IndentCodeRight')}</span> <span>{t('KeyboardShortcuts.CodeEditing.IndentCodeRight')}</span>
</li> </li>
<li className="keyboard-shortcut-item"> <li className="keyboard-shortcut-item">
<span className="keyboard-shortcut__command"> <span className="keyboard-shortcut__command">
{metaKeyName} + / {metaKeyName} + /
</span> </span>
<span>{t('CommentLine')}</span> <span>{t('KeyboardShortcuts.CodeEditing.CommentLine')}</span>
</li> </li>
</ul> </ul>
<h3 className="keyboard-shortcuts__title">General</h3> <h3 className="keyboard-shortcuts__title">General</h3>
@ -58,31 +58,31 @@ function KeyboardShortcutModal() {
<span className="keyboard-shortcut__command"> <span className="keyboard-shortcut__command">
{metaKeyName} + S {metaKeyName} + S
</span> </span>
<span>{t('Save')}</span> <span>{t('Common.Save')}</span>
</li> </li>
<li className="keyboard-shortcut-item"> <li className="keyboard-shortcut-item">
<span className="keyboard-shortcut__command"> <span className="keyboard-shortcut__command">
{metaKeyName} + Enter {metaKeyName} + Enter
</span> </span>
<span>{t('StartSketch')}</span> <span>{t('KeyboardShortcuts.General.StartSketch')}</span>
</li> </li>
<li className="keyboard-shortcut-item"> <li className="keyboard-shortcut-item">
<span className="keyboard-shortcut__command"> <span className="keyboard-shortcut__command">
{metaKeyName} + {'\u21E7'} + Enter {metaKeyName} + {'\u21E7'} + Enter
</span> </span>
<span>{t('StopSketch')}</span> <span>{t('KeyboardShortcuts.General.StopSketch')}</span>
</li> </li>
<li className="keyboard-shortcut-item"> <li className="keyboard-shortcut-item">
<span className="keyboard-shortcut__command"> <span className="keyboard-shortcut__command">
{metaKeyName} + {'\u21E7'} + 1 {metaKeyName} + {'\u21E7'} + 1
</span> </span>
<span>{t('TurnOnAccessibleOutput')}</span> <span>{t('KeyboardShortcuts.General.TurnOnAccessibleOutput')}</span>
</li> </li>
<li className="keyboard-shortcut-item"> <li className="keyboard-shortcut-item">
<span className="keyboard-shortcut__command"> <span className="keyboard-shortcut__command">
{metaKeyName} + {'\u21E7'} + 2 {metaKeyName} + {'\u21E7'} + 2
</span> </span>
<span>{t('TurnOffAccessibleOutput')}</span> <span>{t('KeyboardShortcuts.General.TurnOffAccessibleOutput')}</span>
</li> </li>
</ul> </ul>
</div> </div>

View file

@ -99,59 +99,59 @@ class Preferences extends React.Component {
<Tabs> <Tabs>
<TabList> <TabList>
<div className="tabs__titles"> <div className="tabs__titles">
<Tab><h4 className="tabs__title">{this.props.t('GeneralSettings')}</h4></Tab> <Tab><h4 className="tabs__title">{this.props.t('Preferences.GeneralSettings')}</h4></Tab>
<Tab><h4 className="tabs__title">{this.props.t('Accessibility')}</h4></Tab> <Tab><h4 className="tabs__title">{this.props.t('Preferences.Accessibility')}</h4></Tab>
</div> </div>
</TabList> </TabList>
<TabPanel> <TabPanel>
<div className="preference"> <div className="preference">
<h4 className="preference__title">{this.props.t('Theme')}</h4> <h4 className="preference__title">{this.props.t('Preferences.Theme')}</h4>
<div className="preference__options"> <div className="preference__options">
<input <input
type="radio" type="radio"
onChange={() => this.props.setTheme('light')} onChange={() => this.props.setTheme('light')}
aria-label="light theme on" aria-label={this.props.t('Preferences.LightThemeARIA')}
name="light theme" name="light theme"
id="light-theme-on" id="light-theme-on"
className="preference__radio-button" className="preference__radio-button"
value="light" value="light"
checked={this.props.theme === 'light'} checked={this.props.theme === 'light'}
/> />
<label htmlFor="light-theme-on" className="preference__option">{this.props.t('Light')}</label> <label htmlFor="light-theme-on" className="preference__option">{this.props.t('Preferences.LightTheme')}</label>
<input <input
type="radio" type="radio"
onChange={() => this.props.setTheme('dark')} onChange={() => this.props.setTheme('dark')}
aria-label="dark theme on" aria-label={this.props.t('Preferences.DarkThemeARIA')}
name="dark theme" name="dark theme"
id="dark-theme-on" id="dark-theme-on"
className="preference__radio-button" className="preference__radio-button"
value="dark" value="dark"
checked={this.props.theme === 'dark'} checked={this.props.theme === 'dark'}
/> />
<label htmlFor="dark-theme-on" className="preference__option">{this.props.t('Dark')}</label> <label htmlFor="dark-theme-on" className="preference__option">{this.props.t('Preferences.DarkTheme')}</label>
<input <input
type="radio" type="radio"
onChange={() => this.props.setTheme('contrast')} onChange={() => this.props.setTheme('contrast')}
aria-label="high contrast theme on" aria-label={this.props.t('Preferences.HighContrastThemeARIA')}
name="high contrast theme" name="high contrast theme"
id="high-contrast-theme-on" id="high-contrast-theme-on"
className="preference__radio-button" className="preference__radio-button"
value="contrast" value="contrast"
checked={this.props.theme === 'contrast'} checked={this.props.theme === 'contrast'}
/> />
<label htmlFor="high-contrast-theme-on" className="preference__option">{this.props.t('HighContrast')}</label> <label htmlFor="high-contrast-theme-on" className="preference__option">{this.props.t('Preferences.HighContrastTheme')}</label>
</div> </div>
</div> </div>
<div className="preference"> <div className="preference">
<h4 className="preference__title">{this.props.t('TextSize')}</h4> <h4 className="preference__title">{this.props.t('Preferences.TextSize')}</h4>
<button <button
className="preference__minus-button" className="preference__minus-button"
onClick={this.decreaseFontSize} onClick={this.decreaseFontSize}
aria-label="decrease font size" aria-label={this.props.t('Preferences.DecreaseFontARIA')}
disabled={this.state.fontSize <= 8} disabled={this.state.fontSize <= 8}
> >
<MinusIcon focusable="false" aria-hidden="true" /> <MinusIcon focusable="false" aria-hidden="true" />
<h6 className="preference__label">{this.props.t('Decrease')}</h6> <h6 className="preference__label">{this.props.t('Preferences.DecreaseFont')}</h6>
</button> </button>
<form onSubmit={this.onFontInputSubmit}> <form onSubmit={this.onFontInputSubmit}>
<input <input
@ -168,133 +168,133 @@ class Preferences extends React.Component {
<button <button
className="preference__plus-button" className="preference__plus-button"
onClick={this.increaseFontSize} onClick={this.increaseFontSize}
aria-label="increase font size" aria-label={this.props.t('Preferences.IncreaseFontARIA')}
disabled={this.state.fontSize >= 36} disabled={this.state.fontSize >= 36}
> >
<PlusIcon focusable="false" aria-hidden="true" /> <PlusIcon focusable="false" aria-hidden="true" />
<h6 className="preference__label">{this.props.t('Increase')}</h6> <h6 className="preference__label">{this.props.t('Preferences.IncreaseFont')}</h6>
</button> </button>
</div> </div>
<div className="preference"> <div className="preference">
<h4 className="preference__title">{this.props.t('Autosave')}</h4> <h4 className="preference__title">{this.props.t('Preferences.Autosave')}</h4>
<div className="preference__options"> <div className="preference__options">
<input <input
type="radio" type="radio"
onChange={() => this.props.setAutosave(true)} onChange={() => this.props.setAutosave(true)}
aria-label="autosave on" aria-label={this.props.t('Preferences.AutosaveOnARIA')}
name="autosave" name="autosave"
id="autosave-on" id="autosave-on"
className="preference__radio-button" className="preference__radio-button"
value="On" value="On"
checked={this.props.autosave} checked={this.props.autosave}
/> />
<label htmlFor="autosave-on" className="preference__option">{this.props.t('On')}</label> <label htmlFor="autosave-on" className="preference__option">{this.props.t('Preferences.On')}</label>
<input <input
type="radio" type="radio"
onChange={() => this.props.setAutosave(false)} onChange={() => this.props.setAutosave(false)}
aria-label="autosave off" aria-label={this.props.t('Preferences.AutosaveOffARIA')}
name="autosave" name="autosave"
id="autosave-off" id="autosave-off"
className="preference__radio-button" className="preference__radio-button"
value="Off" value="Off"
checked={!this.props.autosave} checked={!this.props.autosave}
/> />
<label htmlFor="autosave-off" className="preference__option">{this.props.t('Off')}</label> <label htmlFor="autosave-off" className="preference__option">{this.props.t('Preferences.Off')}</label>
</div> </div>
</div> </div>
<div className="preference"> <div className="preference">
<h4 className="preference__title">{this.props.t('WordWrap')}</h4> <h4 className="preference__title">{this.props.t('Preferences.WordWrap')}</h4>
<div className="preference__options"> <div className="preference__options">
<input <input
type="radio" type="radio"
onChange={() => this.props.setLinewrap(true)} onChange={() => this.props.setLinewrap(true)}
aria-label="linewrap on" aria-label={this.props.t('Preferences.LineWrapOnARIA')}
name="linewrap" name="linewrap"
id="linewrap-on" id="linewrap-on"
className="preference__radio-button" className="preference__radio-button"
value="On" value="On"
checked={this.props.linewrap} checked={this.props.linewrap}
/> />
<label htmlFor="linewrap-on" className="preference__option">{this.props.t('On')}</label> <label htmlFor="linewrap-on" className="preference__option">{this.props.t('Preferences.On')}</label>
<input <input
type="radio" type="radio"
onChange={() => this.props.setLinewrap(false)} onChange={() => this.props.setLinewrap(false)}
aria-label="linewrap off" aria-label={this.props.t('Preferences.LineWrapOffARIA')}
name="linewrap" name="linewrap"
id="linewrap-off" id="linewrap-off"
className="preference__radio-button" className="preference__radio-button"
value="Off" value="Off"
checked={!this.props.linewrap} checked={!this.props.linewrap}
/> />
<label htmlFor="linewrap-off" className="preference__option">{this.props.t('Off')}</label> <label htmlFor="linewrap-off" className="preference__option">{this.props.t('Preferences.Off')}</label>
</div> </div>
</div> </div>
</TabPanel> </TabPanel>
<TabPanel> <TabPanel>
<div className="preference"> <div className="preference">
<h4 className="preference__title">{this.props.t('LineNumbers')}</h4> <h4 className="preference__title">{this.props.t('Preferences.LineNumbers')}</h4>
<div className="preference__options"> <div className="preference__options">
<input <input
type="radio" type="radio"
onChange={() => this.props.setLineNumbers(true)} onChange={() => this.props.setLineNumbers(true)}
aria-label="line numbers on" aria-label={this.props.t('Preferences.LineNumbersOnARIA')}
name="line numbers" name="line numbers"
id="line-numbers-on" id="line-numbers-on"
className="preference__radio-button" className="preference__radio-button"
value="On" value="On"
checked={this.props.lineNumbers} checked={this.props.lineNumbers}
/> />
<label htmlFor="line-numbers-on" className="preference__option">{this.props.t('On')}</label> <label htmlFor="line-numbers-on" className="preference__option">{this.props.t('Preferences.On')}</label>
<input <input
type="radio" type="radio"
onChange={() => this.props.setLineNumbers(false)} onChange={() => this.props.setLineNumbers(false)}
aria-label="line numbers off" aria-label={this.props.t('Preferences.LineNumbersOffARIA')}
name="line numbers" name="line numbers"
id="line-numbers-off" id="line-numbers-off"
className="preference__radio-button" className="preference__radio-button"
value="Off" value="Off"
checked={!this.props.lineNumbers} checked={!this.props.lineNumbers}
/> />
<label htmlFor="line-numbers-off" className="preference__option">{this.props.t('Off')}</label> <label htmlFor="line-numbers-off" className="preference__option">{this.props.t('Preferences.Off')}</label>
</div> </div>
</div> </div>
<div className="preference"> <div className="preference">
<h4 className="preference__title">{this.props.t('LintWarningSound')}</h4> <h4 className="preference__title">{this.props.t('Preferences.LintWarningSound')}</h4>
<div className="preference__options"> <div className="preference__options">
<input <input
type="radio" type="radio"
onChange={() => this.props.setLintWarning(true)} onChange={() => this.props.setLintWarning(true)}
aria-label="lint warning on" aria-label={this.props.t('Preferences.LintWarningOnARIA')}
name="lint warning" name="lint warning"
id="lint-warning-on" id="lint-warning-on"
className="preference__radio-button" className="preference__radio-button"
value="On" value="On"
checked={this.props.lintWarning} checked={this.props.lintWarning}
/> />
<label htmlFor="lint-warning-on" className="preference__option">{this.props.t('On')}</label> <label htmlFor="lint-warning-on" className="preference__option">{this.props.t('Preferences.On')}</label>
<input <input
type="radio" type="radio"
onChange={() => this.props.setLintWarning(false)} onChange={() => this.props.setLintWarning(false)}
aria-label="lint warning off" aria-label={this.props.t('Preferences.LintWarningOffARIA')}
name="lint warning" name="lint warning"
id="lint-warning-off" id="lint-warning-off"
className="preference__radio-button" className="preference__radio-button"
value="Off" value="Off"
checked={!this.props.lintWarning} checked={!this.props.lintWarning}
/> />
<label htmlFor="lint-warning-off" className="preference__option">{this.props.t('Off')}</label> <label htmlFor="lint-warning-off" className="preference__option">{this.props.t('Preferences.Off')}</label>
<button <button
className="preference__preview-button" className="preference__preview-button"
onClick={() => beep.play()} onClick={() => beep.play()}
aria-label="preview sound" aria-label={this.props.t('Preferences.PreviewSoundARIA')}
> >
{this.props.t('PreviewSound')} {this.props.t('Preferences.PreviewSound')}
</button> </button>
</div> </div>
</div> </div>
<div className="preference"> <div className="preference">
<h4 className="preference__title">{this.props.t('AccessibleTextBasedCanvas')}</h4> <h4 className="preference__title">{this.props.t('Preferences.AccessibleTextBasedCanvas')}</h4>
<h6 className="preference__subtitle">{this.props.t('UsedScreenReader')}</h6> <h6 className="preference__subtitle">{this.props.t('Preferences.UsedScreenReader')}</h6>
<div className="preference__options"> <div className="preference__options">
<input <input
@ -302,37 +302,37 @@ class Preferences extends React.Component {
onChange={(event) => { onChange={(event) => {
this.props.setTextOutput(event.target.checked); this.props.setTextOutput(event.target.checked);
}} }}
aria-label="text output on" aria-label={this.props.t('Preferences.TextOutputARIA')}
name="text output" name="text output"
id="text-output-on" id="text-output-on"
value="On" value="On"
checked={(this.props.textOutput)} checked={(this.props.textOutput)}
/> />
<label htmlFor="text-output-on" className="preference__option preference__canvas">{this.props.t('PlainText')}</label> <label htmlFor="text-output-on" className="preference__option preference__canvas">{this.props.t('Preferences.PlainText')}</label>
<input <input
type="checkbox" type="checkbox"
onChange={(event) => { onChange={(event) => {
this.props.setGridOutput(event.target.checked); this.props.setGridOutput(event.target.checked);
}} }}
aria-label="table output on" aria-label={this.props.t('Preferences.TableOutputARIA')}
name="table output" name="table output"
id="table-output-on" id="table-output-on"
value="On" value="On"
checked={(this.props.gridOutput)} checked={(this.props.gridOutput)}
/> />
<label htmlFor="table-output-on" className="preference__option preference__canvas">{this.props.t('TableText')}</label> <label htmlFor="table-output-on" className="preference__option preference__canvas">{this.props.t('Preferences.TableText')}</label>
<input <input
type="checkbox" type="checkbox"
onChange={(event) => { onChange={(event) => {
this.props.setSoundOutput(event.target.checked); this.props.setSoundOutput(event.target.checked);
}} }}
aria-label="sound output on" aria-label={this.props.t('Preferences.SoundOutputARIA')}
name="sound output" name="sound output"
id="sound-output-on" id="sound-output-on"
value="On" value="On"
checked={(this.props.soundOutput)} checked={(this.props.soundOutput)}
/> />
<label htmlFor="sound-output-on" className="preference__option preference__canvas">{this.props.t('Sound')}</label> <label htmlFor="sound-output-on" className="preference__option preference__canvas">{this.props.t('Preferences.Sound')}</label>
</div> </div>
</div> </div>
</TabPanel> </TabPanel>
@ -364,4 +364,4 @@ Preferences.propTypes = {
t: PropTypes.func.isRequired, t: PropTypes.func.isRequired,
}; };
export default withTranslation('WebEditor')(Preferences); export default withTranslation()(Preferences);

View file

@ -8,7 +8,7 @@ import * as ToastActions from '../actions/toast';
import ExitIcon from '../../../images/exit.svg'; import ExitIcon from '../../../images/exit.svg';
function Toast(props) { function Toast(props) {
const { t } = useTranslation('WebEditor'); const { t } = useTranslation();
return ( return (
<section className="toast"> <section className="toast">
<p> <p>

View file

@ -3,6 +3,7 @@ import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Link } from 'react-router'; import { Link } from 'react-router';
import classNames from 'classnames'; import classNames from 'classnames';
import { withTranslation } from 'react-i18next';
import * as IDEActions from '../actions/ide'; import * as IDEActions from '../actions/ide';
import * as preferenceActions from '../actions/preferences'; import * as preferenceActions from '../actions/preferences';
import * as projectActions from '../actions/project'; import * as projectActions from '../actions/project';
@ -115,7 +116,7 @@ class Toolbar extends React.Component {
}} }}
/> />
<label htmlFor="autorefresh" className="toolbar__autorefresh-label"> <label htmlFor="autorefresh" className="toolbar__autorefresh-label">
Auto-refresh {this.props.t('Toolbar.Auto-refresh')}
</label> </label>
</div> </div>
<div className={nameContainerClass}> <div className={nameContainerClass}>
@ -197,7 +198,8 @@ Toolbar.propTypes = {
startSketch: PropTypes.func.isRequired, startSketch: PropTypes.func.isRequired,
startAccessibleSketch: PropTypes.func.isRequired, startAccessibleSketch: PropTypes.func.isRequired,
saveProject: PropTypes.func.isRequired, saveProject: PropTypes.func.isRequired,
currentUser: PropTypes.string currentUser: PropTypes.string,
t: PropTypes.func.isRequired
}; };
Toolbar.defaultProps = { Toolbar.defaultProps = {
@ -224,4 +226,5 @@ const mapDispatchToProps = {
}; };
export const ToolbarComponent = Toolbar; export const ToolbarComponent = Toolbar;
export default connect(mapStateToProps, mapDispatchToProps)(Toolbar); // export default connect(mapStateToProps, mapDispatchToProps)(Toolbar);
export default withTranslation()(connect(mapStateToProps, mapDispatchToProps)(Toolbar));

View file

@ -33,6 +33,7 @@ const renderComponent = (extraProps = {}) => {
isEditingName: false, isEditingName: false,
id: 'id', id: 'id',
}, },
t: jest.fn()
}, extraProps); }, extraProps);
render(<ToolbarComponent {...props} />); render(<ToolbarComponent {...props} />);

View file

@ -55,7 +55,7 @@ function warnIfUnsavedChanges(props) { // eslint-disable-line
props.persistState(); props.persistState();
window.onbeforeunload = null; window.onbeforeunload = null;
} else if (props.ide.unsavedChanges) { } else if (props.ide.unsavedChanges) {
if (!window.confirm(props.t('WarningUnsavedChanges'))) { if (!window.confirm(props.t('Nav.WarningUnsavedChanges'))) {
return false; return false;
} }
props.setUnsavedChanges(false); props.setUnsavedChanges(false);
@ -221,8 +221,8 @@ class IDEView extends React.Component {
<Toolbar key={this.props.project.id} /> <Toolbar key={this.props.project.id} />
{this.props.ide.preferencesIsVisible && {this.props.ide.preferencesIsVisible &&
<Overlay <Overlay
title={this.props.t('Settings')} title={this.props.t('Preferences.Settings')}
ariaLabel="settings" ariaLabel={this.props.t('Preferences.Settings')}
closeOverlay={this.props.closePreferences} closeOverlay={this.props.closePreferences}
> >
<Preferences <Preferences
@ -328,7 +328,7 @@ class IDEView extends React.Component {
</SplitPane> </SplitPane>
<section className="preview-frame-holder"> <section className="preview-frame-holder">
<header className="preview-frame__header"> <header className="preview-frame__header">
<h2 className="preview-frame__title">{this.props.t('Preview')}</h2> <h2 className="preview-frame__title">{this.props.t('Toolbar.Preview')}</h2>
</header> </header>
<div className="preview-frame__content"> <div className="preview-frame__content">
<div className="preview-frame-overlay" ref={(element) => { this.overlay = element; }}> <div className="preview-frame-overlay" ref={(element) => { this.overlay = element; }}>
@ -389,16 +389,16 @@ class IDEView extends React.Component {
} }
{ this.props.location.pathname === '/about' && { this.props.location.pathname === '/about' &&
<Overlay <Overlay
title={this.props.t('About')} title={this.props.t('About.Title')}
previousPath={this.props.ide.previousPath} previousPath={this.props.ide.previousPath}
ariaLabel="about" ariaLabel={this.props.t('About.Title')}
> >
<About previousPath={this.props.ide.previousPath} /> <About previousPath={this.props.ide.previousPath} />
</Overlay> </Overlay>
} }
{this.props.location.pathname === '/feedback' && {this.props.location.pathname === '/feedback' &&
<Overlay <Overlay
title="Submit Feedback" title={this.props.t('IDEView.SubmitFeedback')}
previousPath={this.props.ide.previousPath} previousPath={this.props.ide.previousPath}
ariaLabel="submit-feedback" ariaLabel="submit-feedback"
> >
@ -435,8 +435,8 @@ class IDEView extends React.Component {
} }
{this.props.ide.keyboardShortcutVisible && {this.props.ide.keyboardShortcutVisible &&
<Overlay <Overlay
title={this.props.t('KeyboardShortcuts')} title={this.props.t('KeyboardShortcuts.Title')}
ariaLabel="keyboard shortcuts" ariaLabel={this.props.t('KeyboardShortcuts.Title')}
closeOverlay={this.props.closeKeyboardShortcutModal} closeOverlay={this.props.closeKeyboardShortcutModal}
> >
<KeyboardShortcutModal /> <KeyboardShortcutModal />
@ -445,7 +445,7 @@ class IDEView extends React.Component {
{this.props.ide.errorType && {this.props.ide.errorType &&
<Overlay <Overlay
title="Error" title="Error"
ariaLabel="error" ariaLabel={this.props.t('Common.Error')}
closeOverlay={this.props.hideErrorModal} closeOverlay={this.props.hideErrorModal}
> >
<ErrorModal <ErrorModal
@ -640,4 +640,5 @@ function mapDispatchToProps(dispatch) {
); );
} }
export default withTranslation('WebEditor')(withRouter(connect(mapStateToProps, mapDispatchToProps)(IDEView)));
export default withTranslation()(withRouter(connect(mapStateToProps, mapDispatchToProps)(IDEView)));

View file

@ -1,116 +1,177 @@
{ {
"Nav": {
"File": {
"Title": "File",
"New": "New",
"Share": "Share",
"Duplicate": "Duplicate",
"Open": "Open",
"Download": "Download",
"AddToCollection": "Add to Collection",
"Examples": "Examples"
},
"Edit": {
"Title": "Edit",
"TidyCode": "Tidy Code",
"Find": "Find",
"FindNext": "Find Next",
"FindPrevious": "Find Previous"
},
"Sketch": {
"Title": "Sketch",
"AddFile": "Add File",
"AddFolder": "Add Folder",
"Run": "Run",
"Stop": "Stop"
},
"Help": {
"Title": "Help",
"KeyboardShortcuts": "Keyboard Shortcuts",
"Reference": "Reference",
"About": "About"
},
"Lang": "Language",
"BackEditor": "Back to Editor",
"WarningUnsavedChanges": "Are you sure you want to leave this page? You have unsaved changes.",
"Login": {
"Login": "Log in",
"LoginOr": "or",
"SignUp": "Sign up",
"Email": "email",
"Username": "username",
"LoginGithub": "Login with Github",
"LoginGoogle": "Login with Google",
"DontHaveAccount": "Don't have an account?",
"ForgotPassword": "Forgot your password?",
"ResetPassword": "Reset your password"
},
"Auth": {
"Welcome": "Welcome",
"Hello": "Hello",
"MyAccount": "My Account",
"My": "My",
"MySketches": "My Sketches",
"MyCollections": "My Collections",
"Asset": "Asset",
"MyAssets": "My Assets",
"LogOut": "Log Out"
}
},
"About": {
"Title": "About",
"TitleHelmet": "p5.js Web Editor | About",
"Contribute": "Contribute", "Contribute": "Contribute",
"NewP5": "New to p5.js?", "NewP5": "New to p5.js?",
"Report": "Report a bug", "Report": "Report a bug",
"Learn": "Learn", "Learn": "Learn",
"About": "About",
"Resources": "Resources", "Resources": "Resources",
"Libraries": "Libraries", "Libraries": "Libraries",
"Forum": "Forum", "Forum": "Forum",
"File": "File", "Examples": "Examples"
"New": "New", },
"Save": "Save", "Toast": {
"Share": "Share", "OpenedNewSketch": "Opened new sketch.",
"Duplicate": "Duplicate", "SketchSaved": "Sketch saved.",
"Examples": "Examples", "SketchFailedSave": "Failed to save sketch.",
"Edit": "Edit", "AutosaveEnabled": "Autosave enabled.",
"TidyCode": "Tidy Code", "LangChange": "Language changed"
"Find": "Find", },
"AddToCollection": "Add to Collection", "Toolbar": {
"FindNext": "Find Next",
"FindPrevious": "Find Previous",
"Sketch": "Sketch",
"AddFile": "Add File",
"AddFolder": "Add Folder",
"Run": "Run",
"Stop": "Stop",
"Help": "Help",
"KeyboardShortcuts": "Keyboard Shortcuts",
"Reference": "Reference",
"Tidy": "Tidy",
"Lang": "Language",
"FindNextMatch": "Find Next Match",
"FindPrevMatch": "Find Previous Match",
"IndentCodeLeft": "Indent Code Left",
"IndentCodeRight": "Indent Code Right",
"CommentLine": "Comment Line",
"StartSketch": "Start Sketch",
"StopSketch": "StopSketch",
"TurnOnAccessibleOutput": "Turn On Accessible Output",
"TurnOffAccessibleOutput": "Turn Off Accessible Output",
"ToogleSidebar": "Toogle Sidebar",
"ToogleConsole": "Toogle Console",
"Preview": "Preview", "Preview": "Preview",
"Auto-refresh": "Auto-refresh", "Auto-refresh": "Auto-refresh",
"Console": "Console", "OpenPreferencesARIA": "Open Preferences",
"PlaySketchARIA": "Play sketch",
"PlayOnlyVisualSketchARIA": "Play only visual sketch",
"StopSketchARIA": "Stop sketch",
"EditSketchARIA": "Edit sketch name",
"NewSketchNameARIA": "New sketch name"
},
"Console": {
"Title": "Console",
"Clear": "Clear",
"ClearARIA": "Clear console",
"Close": "Close",
"CloseARIA": "Close console",
"Open": "Open",
"OpenARIA": "Open console"
},
"Preferences": {
"Settings": "Settings", "Settings": "Settings",
"GeneralSettings": "General settings", "GeneralSettings": "General settings",
"Accessibility": "Accessibility",
"Theme": "Theme", "Theme": "Theme",
"Light": "Light", "LightTheme": "Light",
"Dark": "Dark", "LightThemeARIA": "light theme on",
"HighContrast": "High Contrast", "DarkTheme": "Dark",
"DarkThemeARIA": "dark theme on",
"HighContrastTheme": "High Contrast",
"HighContrastThemeARIA": "high contrast theme on",
"TextSize": "Text Size", "TextSize": "Text Size",
"Decrease": "Decrease", "DecreaseFont": "Decrease",
"Increase": "Increase", "DecreaseFontARIA": "decrease font size",
"IndentationAmount": "Indentation amount", "IncreaseFont": "Increase",
"IncreaseFontARIA": "increase font size",
"Autosave": "Autosave", "Autosave": "Autosave",
"On": "On", "On": "On",
"AutosaveOnARIA": "autosave on",
"Off": "Off", "Off": "Off",
"SketchSettings": "Sketch Settings", "AutosaveOffARIA": "autosave off",
"SecurityProtocol": "Security Protocol", "WordWrap": "Word Wrap",
"ServeOverHTTPS": "Serve over HTTPS", "LineWrapOnARIA": "linewrap on",
"Accessibility": "Accessibility", "LineWrapOffARIA": "linewrap off",
"LineNumbers": "Line numbers",
"LineNumbersOnARIA": "line numbers on",
"LineNumbersOffARIA": "line numbers off",
"LintWarningSound": "Lint warning sound", "LintWarningSound": "Lint warning sound",
"LintWarningOnARIA": "lint warning on",
"LintWarningOffARIA": "lint warning off",
"PreviewSound": "Preview sound", "PreviewSound": "Preview sound",
"PreviewSoundARIA": "preview sound",
"AccessibleTextBasedCanvas": "Accessible text-based canvas", "AccessibleTextBasedCanvas": "Accessible text-based canvas",
"UsedScreenReader": "Used with screen reader", "UsedScreenReader": "Used with screen reader",
"PlainText": "Plain-text", "PlainText": "Plain-text",
"TextOutputARIA": "text output on",
"TableText": "Table-text", "TableText": "Table-text",
"TableOutputARIA": "table output on",
"Sound": "Sound", "Sound": "Sound",
"WordWrap": "Word Wrap", "SoundOutputARIA": "sound output on"
"LineNumbers": "Line numbers", },
"LangChange": "Language changed", "KeyboardShortcuts": {
"Welcome": "Welcome", "Title": " Keyboard Shortcuts",
"Login": "Log in", "ShortcutsFollow": "Code editing keyboard shortcuts follow",
"LoginOr": "or", "SublimeText": "Sublime Text shortcuts",
"SignUp": "Sign up", "CodeEditing": {
"Email": "email", "Tidy": "Tidy",
"Username": "username", "FindText": "Find Text",
"LoginGithub": "Login with Github", "FindNextMatch": "Find Next Match",
"LoginGoogle": "Login with Google", "FindPrevMatch": "Find Previous Match",
"DontHaveAccount": "Don't have an account?", "IndentCodeLeft": "Indent Code Left",
"ForgotPassword": "Forgot your password?", "IndentCodeRight": "Indent Code Right",
"ResetPassword": "Reset your password", "CommentLine": "Comment Line",
"BackEditor": "Back to Editor", "FindNextTextMatch": "Find Next Text Match",
"UsernameSplit": "User Name", "FindPreviousTextMatch": "Find Previous Text Match",
"Password": "Password", "CodeEditing": "Code Editing"
"ConfirmPassword": "Confirm Password", },
"OpenedNewSketch": "Opened new sketch.", "General": {
"Hello": "Hello", "StartSketch": "Start Sketch",
"MyAccount": "My Account", "StopSketch": "Stop Sketch",
"My":"My", "TurnOnAccessibleOutput": "Turn On Accessible Output",
"MySketches": "My Sketches", "TurnOffAccessibleOutput": "Turn Off Accessible Output"
"MyCollections": "My Collections", }
"Asset": "Asset", },
"MyAssets": "My Assets", "Sidebar": {
"TitleAbout": "p5.js Web Editor | About",
"CodeEditing": "Code Editing",
"Error": "Error",
"In order to save": "In order to save",
"you must be logged in": "you must be logged in",
"Please": "please",
"Find in files": "Find in files",
"Create": "Create", "Create": "Create",
"enter a name": "enter a name", "EnterName": "enter a name",
"Add": "Add", "Add": "Add",
"Folder": "Folder", "Folder": "Folder"
"FindText": "Find Text", },
"FindNextTextMatch": "Find Next Text Match", "Common": {
"FindPreviousTextMatch": "Find Previous Text Match", "Error": "Error",
"Code editing keyboard shortcuts follow": "Code editing keyboard shortcuts follow", "Save": "Save",
"Sublime Text shortcuts": "Sublime Text shortcuts", "p5logoARIA": "p5.js Logo"
"WarningUnsavedChanges": "Are you sure you want to leave this page? You have unsaved changes.",
"LogOut": "Log Out"
},
"IDEView": {
"SubmitFeedback": "Submit Feedback"
}
} }

View file

@ -1,113 +1,180 @@
{ {
"Nav": {
"File": {
"Title": "Archivo",
"New": "Nuevo",
"Share": "Compartir",
"Duplicate": "Duplicar",
"Open": "Abrir",
"Download": "Descargar",
"AddToCollection": "Agregar a colección",
"Examples": "Ejemplos"
},
"Edit": {
"Title": "Editar",
"TidyCode": "Ordenar código",
"Find": "Buscar",
"FindNext": "Buscar siguiente",
"FindPrevious": "Buscar anterior"
},
"Sketch": {
"Title": "Bosquejo",
"AddFile": "Agregar archivo",
"AddFolder": "Agregar directorio",
"Run": "Ejecutar",
"Stop": "Detener"
},
"Help": {
"Title": "Ayuda",
"KeyboardShortcuts": "Atajos",
"Reference": "Referencia",
"About": "Acerca de"
},
"Lang": "Lenguaje",
"BackEditor": "Regresa al editor",
"WarningUnsavedChanges": "¿Realmente quieres salir de la página? Tienes cambios sin guardar.",
"Login": {
"Login": "Ingresa",
"LoginOr": "o",
"SignUp": "registráte",
"Email": "correo electrónico",
"Username": "Identificación",
"LoginGithub": "Ingresa con Github",
"LoginGoogle": "Ingresa con Google",
"DontHaveAccount": "¿No tienes cuenta?",
"ForgotPassword": "¿Olvidaste tu contraseña?",
"ResetPassword": "Regenera tu contraseña"
},
"Auth": {
"Welcome": "Hola",
"Hello": "Hola",
"MyAccount": "Mi Cuenta",
"My": "Mi",
"MySketches": "Mis bosquejos",
"MyCollections": "Mis colecciones",
"Asset": "Asset",
"MyAssets": "Mis assets",
"LogOut": "Cerrar sesión"
}
},
"About": {
"Title": "Acerca de",
"TitleHelmet": "Editor Web p5.js | Acerca de",
"Contribute": "Contribuir", "Contribute": "Contribuir",
"NewP5": "¿Empezando con p5.js?", "NewP5": "¿Empezando con p5.js?",
"Report": "Reporta un error", "Report": "Reporta un error",
"Learn": "Aprende", "Learn": "Aprender",
"About": "Acerca de",
"Resources": "Recursos", "Resources": "Recursos",
"Libraries": "Bibliotecas", "Libraries": "Bibliotecas",
"Forum": "Foro", "Forum": "Foro",
"File": "Archivo", "Examples": "Ejemplos"
"New": "Nuevo", },
"Save": "Guardar", "Toast": {
"Share": "Compartir", "OpenedNewSketch": "Abriste un nuevo bosquejo.",
"Duplicate": "Duplicar", "SketchSaved": "Bosquejo guardado.",
"Examples": "Ejemplos", "SketchFailedSave": "Fallo al guardar el bosquejo.",
"Edit": "Editar", "AutosaveEnabled": "Grabado automático activado.",
"TidyCode": "Ordenar código", "LangChange": "Lenguaje cambiado"
"Find": "Buscar", },
"AddToCollection": "Agregar a colección", "Toolbar": {
"FindNext": "Buscar siguiente",
"FindPrevious": "Buscar anterior",
"Sketch": "Bosquejo",
"AddFile": "Agregar archivo",
"AddFolder": "Agregar directorio",
"Run": "Ejecutar",
"Stop": "Detener",
"Help": "Ayuda",
"KeyboardShortcuts": "Atajos",
"Reference": "Referencia",
"Tidy": "Ordenar",
"Lang": "Lenguaje",
"FindNextMatch": "Encontrar siguiente ocurrencia",
"FindPrevMatch": "Encontrar ocurrencia previa",
"IndentCodeLeft": "Indentar código a la izquierda",
"IndentCodeRight": "Indentar código a la derecha",
"CommentLine": "Comentar línea de código",
"StartSketch": "Iniciar bosquejo",
"StopSketch": "Detener bosquejo",
"TurnOnAccessibleOutput": "Activar salida accesible",
"TurnOffAccessibleOutput": "Desactivar salida accesible",
"ToogleSidebar": "Alternar barra de deslizamiento",
"ToogleConsole": "Alternar consola",
"Preview": "Vista previa", "Preview": "Vista previa",
"Auto-refresh": "Auto-refrescar", "Auto-refresh": "Auto-refrescar",
"Console": "Consola", "OpenPreferencesARIA": "Abrir Preferencias",
"PlaySketchARIA": "Ejecutar bosquejo",
"PlayOnlyVisualSketchARIA": "Ejecutar bosquejo visual",
"StopSketchARIA": "Detener bosquejo",
"EditSketchARIA": "Editar nombre de bosquejo",
"NewSketchNameARIA": "Nuevo nombre de bosquejo"
},
"Console": {
"Title": "Consola",
"Clear": "Limpiar",
"ClearARIA": "limpiar consola",
"Close": "Cerrar",
"CloseARIA": "cerrar consola",
"Open": "Abrir",
"OpenARIA": "Abrir consola"
},
"Preferences": {
"Settings": "Configuración", "Settings": "Configuración",
"GeneralSettings": "Configuración general", "GeneralSettings": "Configuración general",
"Accessibility": "Accesibilidad",
"Theme": "Modo de visualización", "Theme": "Modo de visualización",
"Light": "Claro", "LightTheme": "Claro",
"Dark": "Oscuro", "LightThemeARIA": "Modo de visualización claro activado",
"HighContrast": "Alto contraste", "DarkTheme": "Oscuro",
"DarkThemeARIA": "Modo de visualización oscuro activado",
"HighContrastTheme": "Alto contraste",
"HighContrastThemeARIA": "Modo de visualización de alto contraste activado",
"TextSize": "Tamaño del texto", "TextSize": "Tamaño del texto",
"Decrease": "Disminuir", "DecreaseFont": "Disminuir",
"Increase": "Aumentar", "DecreaseFontARIA": "Disminuir tamaño del texto",
"IndentationAmount": "Cantidad de indentación", "IncreaseFont": "Aumentar",
"IncreaseFontARIA": "Aumentar tamaño del texto",
"Autosave": "Grabar automáticamente", "Autosave": "Grabar automáticamente",
"On": "Activar", "On": "Activar",
"AutosaveOnARIA": "Grabado automático activado",
"Off": "Desactivar", "Off": "Desactivar",
"SketchSettings": "Configuración del bosquejo", "AutosaveOffARIA": "Grabado automático desactivado",
"SecurityProtocol": "Protocolo de seguridad", "WordWrap": "Ajuste automático de línea",
"ServeOverHTTPS": "Usar HTTPS", "LineWrapOnARIA": "Ajuste automático de línea activado",
"Accessibility": "Accesibilidad", "LineWrapOffARIA": "Ajuste automático de línea desactivado",
"LineNumbers": "Número de línea",
"LineNumbersOnARIA": "Número de línea activado",
"LineNumbersOffARIA": "Número de línea desactivado",
"LintWarningSound": "Sonido de alarma Lint", "LintWarningSound": "Sonido de alarma Lint",
"LintWarningOnARIA": "Sonido de alarma Lint activado",
"LintWarningOffARIA": "Sonido de alarma Lint desactivado",
"PreviewSound": "Probar sonido", "PreviewSound": "Probar sonido",
"PreviewSoundARIA": "Probar sonido",
"AccessibleTextBasedCanvas": "Lienzo accesible por texto", "AccessibleTextBasedCanvas": "Lienzo accesible por texto",
"UsedScreenReader": "Uso con screen reader", "UsedScreenReader": "Uso con screen reader",
"PlainText": "Texto sin formato", "PlainText": "Texto sin formato",
"TextOutputARIA": "Salida de texto activado",
"TableText": "Tablero de texto", "TableText": "Tablero de texto",
"TableOutputARIA": "Salida de tablero activado",
"Sound": "Sonido", "Sound": "Sonido",
"WordWrap": "Ajuste automático de línea", "SoundOutputARIA": "Salida de sonido activado"
"LineNumbers": "Número de línea", },
"LangChange": "Lenguaje cambiado", "KeyboardShortcuts": {
"Welcome": "Bienvenida", "Title": " Atajos de teclado",
"Login": "Ingresa", "ShortcutsFollow": "Los atajos para edición son como",
"LoginOr": "o", "SublimeText": "los atajos de Sublime Text ",
"SignUp": "registráte", "CodeEditing": {
"email": "correo electrónico", "Tidy": "Ordenar",
"username": "nombre de usuario", "FindText": "Encontrar texto",
"LoginGithub": "Ingresa con Github", "FindNextMatch": "Encontrar siguiente ocurrencia",
"LoginGoogle": "Ingresa con Google", "FindPrevMatch": "Encontrar ocurrencia previa",
"DontHaveAccount": "No tienes cuenta?", "IndentCodeLeft": "Indentar código a la izquierda",
"ForgotPassword": "¿Olvidaste tu contraseña?", "IndentCodeRight": "Indentar código a la derecha",
"ResetPassword": "Regenera tu contraseña", "CommentLine": "Comentar línea de código",
"BackEditor": "Regresa al editor", "FindNextTextMatch": "Encontrar la siguiente ocurrencia de texto",
"UsernameSplit": "Nombre de usuario", "FindPreviousTextMatch": "Encontrar la ocurrencia previa de texto",
"Password": "Contraseña", "CodeEditing": "Editando Código"
"ConfirmPassword": "Confirma la contraseña", },
"OpenedNewSketch": "Creaste nuevo bosquejo.", "General": {
"Hello": "Hola", "StartSketch": "Iniciar bosquejo",
"MyAccount": "Mi Cuenta", "StopSketch": "Detener bosquejo",
"My": "Mi", "TurnOnAccessibleOutput": "Activar salida accesible",
"MySketches": "Mis bosquejos", "TurnOffAccessibleOutput": "Desactivar salida accesible"
"MyCollections":"Mis colecciones", }
"Asset": "Asset", },
"MyAssets": "Mis assets", "Sidebar": {
"TitleAbout": "Editor Web p5.js | Acerca de", "Create": "Crear",
"CodeEditing": "Editando Código", "EnterName": "Introduce un nombre",
"Add": "Agregar",
"Folder": "Directorio"
},
"Common": {
"Error": "Error", "Error": "Error",
"In order to save": "Para guardar", "Save": "Guardar",
"you must be logged in": "debes ingresar a tu cuenta", "p5logoARIA": "Logo p5.js "
"Please": "Por favor", },
"Find in files": "Encontrar en archivos", "IDEView": {
"Create": "Create", "SubmitFeedback": "Enviar retroalimentación"
"enter a name": "enter a name",
"Add": "Add",
"Folder": "Directorio",
"FindText": "Encontrar texto",
"FindNextTextMatch": "Encontrar la siguiente ocurrencia de texto",
"FindPreviousTextMatch": "Encontrar la ocurrencia previa de texto",
"Code editing keyboard shortcuts follow": "Los atajos para edición son como",
"Sublime Text shortcuts": "los atajos de Sublime Text ",
"WarningUnsavedChanges": "¿Estás seguro de que quieres salir de la página? Tienes cambios sin guardar."
} }
}