Prototype with proposed i18n architecture (#1478)
* Branch with i18n functionality * Translation files with new entries * includes Loader in index.jsx * Uses WithTranslation In Nav * New Namespace * Shortcuts Modal Complete * Preferences complete * About overlay title translated
This commit is contained in:
parent
69bd6cb4a0
commit
b05d1b1a02
16 changed files with 550 additions and 158 deletions
|
@ -4,6 +4,8 @@ import { connect } from 'react-redux';
|
||||||
import { withRouter } from 'react-router';
|
import { withRouter } from 'react-router';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { withTranslation } from 'react-i18next';
|
||||||
|
import i18next from 'i18next';
|
||||||
import * as IDEActions from '../modules/IDE/actions/ide';
|
import * as IDEActions from '../modules/IDE/actions/ide';
|
||||||
import * as toastActions from '../modules/IDE/actions/toast';
|
import * as toastActions from '../modules/IDE/actions/toast';
|
||||||
import * as projectActions from '../modules/IDE/actions/project';
|
import * as projectActions from '../modules/IDE/actions/project';
|
||||||
|
@ -55,6 +57,10 @@ class Nav extends React.PureComponent {
|
||||||
this.handleFocusForHelp = this.handleFocus.bind(this, 'help');
|
this.handleFocusForHelp = this.handleFocus.bind(this, 'help');
|
||||||
this.toggleDropdownForAccount = this.toggleDropdown.bind(this, 'account');
|
this.toggleDropdownForAccount = this.toggleDropdown.bind(this, 'account');
|
||||||
this.handleFocusForAccount = this.handleFocus.bind(this, 'account');
|
this.handleFocusForAccount = this.handleFocus.bind(this, 'account');
|
||||||
|
this.toggleDropdownForLang = this.toggleDropdown.bind(this, 'lang');
|
||||||
|
this.handleFocusForLang = this.handleFocus.bind(this, 'lang');
|
||||||
|
this.handleLangSelection = this.handleLangSelection.bind(this);
|
||||||
|
|
||||||
this.closeDropDown = this.closeDropDown.bind(this);
|
this.closeDropDown = this.closeDropDown.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,6 +169,13 @@ class Nav extends React.PureComponent {
|
||||||
this.setDropdown('none');
|
this.setDropdown('none');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleLangSelection(event) {
|
||||||
|
i18next.changeLanguage(event.target.value);
|
||||||
|
this.props.showToast(1500);
|
||||||
|
this.props.setToastText('LangChange');
|
||||||
|
this.setDropdown('none');
|
||||||
|
}
|
||||||
|
|
||||||
handleLogout() {
|
handleLogout() {
|
||||||
this.props.logoutUser();
|
this.props.logoutUser();
|
||||||
this.setDropdown('none');
|
this.setDropdown('none');
|
||||||
|
@ -233,7 +246,7 @@ class Nav extends React.PureComponent {
|
||||||
<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">
|
||||||
Back to Editor
|
{this.props.t('BackEditor')}
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
|
@ -258,7 +271,7 @@ class Nav extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="nav__item-header">File</span>
|
<span className="nav__item-header">{this.props.t('File')}</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">
|
||||||
|
@ -268,7 +281,7 @@ class Nav extends React.PureComponent {
|
||||||
onFocus={this.handleFocusForFile}
|
onFocus={this.handleFocusForFile}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
>
|
>
|
||||||
New
|
{this.props.t('New')}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
{ getConfig('LOGIN_ENABLED') && (!this.props.project.owner || this.isUserOwner()) &&
|
{ getConfig('LOGIN_ENABLED') && (!this.props.project.owner || this.isUserOwner()) &&
|
||||||
|
@ -278,7 +291,7 @@ class Nav extends React.PureComponent {
|
||||||
onFocus={this.handleFocusForFile}
|
onFocus={this.handleFocusForFile}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
>
|
>
|
||||||
Save
|
{this.props.t('Save')}
|
||||||
<span className="nav__keyboard-shortcut">{metaKeyName}+S</span>
|
<span className="nav__keyboard-shortcut">{metaKeyName}+S</span>
|
||||||
</button>
|
</button>
|
||||||
</li> }
|
</li> }
|
||||||
|
@ -289,7 +302,7 @@ class Nav extends React.PureComponent {
|
||||||
onFocus={this.handleFocusForFile}
|
onFocus={this.handleFocusForFile}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
>
|
>
|
||||||
Duplicate
|
{this.props.t('Duplicate')}
|
||||||
</button>
|
</button>
|
||||||
</li> }
|
</li> }
|
||||||
{ this.props.project.id &&
|
{ this.props.project.id &&
|
||||||
|
@ -299,7 +312,7 @@ class Nav extends React.PureComponent {
|
||||||
onFocus={this.handleFocusForFile}
|
onFocus={this.handleFocusForFile}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
>
|
>
|
||||||
Share
|
{this.props.t('Share')}
|
||||||
</button>
|
</button>
|
||||||
</li> }
|
</li> }
|
||||||
{ this.props.project.id &&
|
{ this.props.project.id &&
|
||||||
|
@ -309,7 +322,7 @@ class Nav extends React.PureComponent {
|
||||||
onFocus={this.handleFocusForFile}
|
onFocus={this.handleFocusForFile}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
>
|
>
|
||||||
Download
|
{this.props.t('Download')}
|
||||||
</button>
|
</button>
|
||||||
</li> }
|
</li> }
|
||||||
{ this.props.user.authenticated &&
|
{ this.props.user.authenticated &&
|
||||||
|
@ -320,7 +333,7 @@ class Nav extends React.PureComponent {
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
onClick={this.setDropdownForNone}
|
onClick={this.setDropdownForNone}
|
||||||
>
|
>
|
||||||
Open
|
{this.props.t('Open')}
|
||||||
</Link>
|
</Link>
|
||||||
</li> }
|
</li> }
|
||||||
{getConfig('UI_COLLECTIONS_ENABLED') &&
|
{getConfig('UI_COLLECTIONS_ENABLED') &&
|
||||||
|
@ -333,7 +346,7 @@ class Nav extends React.PureComponent {
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
onClick={this.setDropdownForNone}
|
onClick={this.setDropdownForNone}
|
||||||
>
|
>
|
||||||
Add to Collection
|
{this.props.t('AddToCollection')}
|
||||||
</Link>
|
</Link>
|
||||||
</li>}
|
</li>}
|
||||||
{ getConfig('EXAMPLES_ENABLED') &&
|
{ getConfig('EXAMPLES_ENABLED') &&
|
||||||
|
@ -344,7 +357,7 @@ class Nav extends React.PureComponent {
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
onClick={this.setDropdownForNone}
|
onClick={this.setDropdownForNone}
|
||||||
>
|
>
|
||||||
Examples
|
{this.props.t('Examples')}
|
||||||
</Link>
|
</Link>
|
||||||
</li> }
|
</li> }
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -360,7 +373,7 @@ class Nav extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="nav__item-header">Edit</span>
|
<span className="nav__item-header">{this.props.t('Edit')}</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" >
|
||||||
|
@ -373,7 +386,7 @@ class Nav extends React.PureComponent {
|
||||||
onFocus={this.handleFocusForEdit}
|
onFocus={this.handleFocusForEdit}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
>
|
>
|
||||||
Tidy Code
|
{this.props.t('TidyCode')}
|
||||||
<span className="nav__keyboard-shortcut">{'\u21E7'}+Tab</span>
|
<span className="nav__keyboard-shortcut">{'\u21E7'}+Tab</span>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
@ -383,7 +396,7 @@ class Nav extends React.PureComponent {
|
||||||
onFocus={this.handleFocusForEdit}
|
onFocus={this.handleFocusForEdit}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
>
|
>
|
||||||
Find
|
{this.props.t('Find')}
|
||||||
<span className="nav__keyboard-shortcut">{metaKeyName}+F</span>
|
<span className="nav__keyboard-shortcut">{metaKeyName}+F</span>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
@ -393,7 +406,7 @@ class Nav extends React.PureComponent {
|
||||||
onFocus={this.handleFocusForEdit}
|
onFocus={this.handleFocusForEdit}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
>
|
>
|
||||||
Find Next
|
{this.props.t('FindNext')}
|
||||||
<span className="nav__keyboard-shortcut">{metaKeyName}+G</span>
|
<span className="nav__keyboard-shortcut">{metaKeyName}+G</span>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
@ -403,7 +416,7 @@ class Nav extends React.PureComponent {
|
||||||
onFocus={this.handleFocusForEdit}
|
onFocus={this.handleFocusForEdit}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
>
|
>
|
||||||
Find Previous
|
{this.props.t('FindPrevious')}
|
||||||
<span className="nav__keyboard-shortcut">{'\u21E7'}+{metaKeyName}+G</span>
|
<span className="nav__keyboard-shortcut">{'\u21E7'}+{metaKeyName}+G</span>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
@ -420,7 +433,7 @@ class Nav extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="nav__item-header">Sketch</span>
|
<span className="nav__item-header">{this.props.t('Sketch')}</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">
|
||||||
|
@ -430,7 +443,7 @@ class Nav extends React.PureComponent {
|
||||||
onFocus={this.handleFocusForSketch}
|
onFocus={this.handleFocusForSketch}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
>
|
>
|
||||||
Add File
|
{this.props.t('AddFile')}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li className="nav__dropdown-item">
|
<li className="nav__dropdown-item">
|
||||||
|
@ -439,7 +452,7 @@ class Nav extends React.PureComponent {
|
||||||
onFocus={this.handleFocusForSketch}
|
onFocus={this.handleFocusForSketch}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
>
|
>
|
||||||
Add Folder
|
{this.props.t('AddFolder')}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li className="nav__dropdown-item">
|
<li className="nav__dropdown-item">
|
||||||
|
@ -448,7 +461,7 @@ class Nav extends React.PureComponent {
|
||||||
onFocus={this.handleFocusForSketch}
|
onFocus={this.handleFocusForSketch}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
>
|
>
|
||||||
Run
|
{this.props.t('Run')}
|
||||||
<span className="nav__keyboard-shortcut">{metaKeyName}+Enter</span>
|
<span className="nav__keyboard-shortcut">{metaKeyName}+Enter</span>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
@ -458,7 +471,7 @@ class Nav extends React.PureComponent {
|
||||||
onFocus={this.handleFocusForSketch}
|
onFocus={this.handleFocusForSketch}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
>
|
>
|
||||||
Stop
|
{this.props.t('Stop')}
|
||||||
<span className="nav__keyboard-shortcut">{'\u21E7'}+{metaKeyName}+Enter</span>
|
<span className="nav__keyboard-shortcut">{'\u21E7'}+{metaKeyName}+Enter</span>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
@ -495,7 +508,7 @@ class Nav extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="nav__item-header">Help</span>
|
<span className="nav__item-header">{this.props.t('Help')}</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">
|
||||||
|
@ -505,7 +518,7 @@ class Nav extends React.PureComponent {
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
onClick={this.handleKeyboardShortcuts}
|
onClick={this.handleKeyboardShortcuts}
|
||||||
>
|
>
|
||||||
Keyboard Shortcuts
|
{this.props.t('KeyboardShortcuts')}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li className="nav__dropdown-item">
|
<li className="nav__dropdown-item">
|
||||||
|
@ -516,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}
|
||||||
>Reference
|
>{this.props.t('Reference')}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li className="nav__dropdown-item">
|
<li className="nav__dropdown-item">
|
||||||
|
@ -526,7 +539,7 @@ class Nav extends React.PureComponent {
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
onClick={this.setDropdownForNone}
|
onClick={this.setDropdownForNone}
|
||||||
>
|
>
|
||||||
About
|
{this.props.t('About')}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -535,18 +548,73 @@ class Nav extends React.PureComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderLanguageMenu(navDropdownState) {
|
||||||
|
return (
|
||||||
|
<ul className="nav__items-right" title="user-menu">
|
||||||
|
<li className={navDropdownState.lang}>
|
||||||
|
<button
|
||||||
|
onClick={this.toggleDropdownForLang}
|
||||||
|
onBlur={this.handleBlur}
|
||||||
|
onFocus={this.clearHideTimeout}
|
||||||
|
onMouseOver={() => {
|
||||||
|
if (this.state.dropdownOpen !== 'none') {
|
||||||
|
this.setDropdown('lang');
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="nav__item-header"> {this.props.t('Lang')}</span>
|
||||||
|
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
|
||||||
|
</button>
|
||||||
|
<ul className="nav__dropdown">
|
||||||
|
|
||||||
|
<li className="nav__dropdown-item">
|
||||||
|
<button
|
||||||
|
onFocus={this.handleFocusForLang}
|
||||||
|
onBlur={this.handleBlur}
|
||||||
|
value="it"
|
||||||
|
onClick={e => this.handleLangSelection(e)}
|
||||||
|
>
|
||||||
|
Italian (Test Fallback)
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li className="nav__dropdown-item">
|
||||||
|
<button
|
||||||
|
onFocus={this.handleFocusForLang}
|
||||||
|
onBlur={this.handleBlur}
|
||||||
|
value="en-US"
|
||||||
|
onClick={e => this.handleLangSelection(e)}
|
||||||
|
>English
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li className="nav__dropdown-item">
|
||||||
|
<button
|
||||||
|
onFocus={this.handleFocusForLang}
|
||||||
|
onBlur={this.handleBlur}
|
||||||
|
value="es-419"
|
||||||
|
onClick={e => this.handleLangSelection(e)}
|
||||||
|
>
|
||||||
|
Español
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
renderUnauthenticatedUserMenu(navDropdownState) {
|
renderUnauthenticatedUserMenu(navDropdownState) {
|
||||||
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">
|
||||||
<Link to="/login" className="nav__auth-button">
|
<Link to="/login" className="nav__auth-button">
|
||||||
<span className="nav__item-header">Log in</span>
|
<span className="nav__item-header">{this.props.t('Login')}</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
<span className="nav__item-or">or</span>
|
<span className="nav__item-or">{this.props.t('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">Sign up</span>
|
<span className="nav__item-header">{this.props.t('SignUp')}</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -557,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>Hello, {this.props.user.username}!</span>
|
<span>{this.props.t('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}>
|
||||||
|
@ -572,7 +640,7 @@ class Nav extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
My Account
|
{this.props.t('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">
|
||||||
|
@ -583,7 +651,7 @@ class Nav extends React.PureComponent {
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
onClick={this.setDropdownForNone}
|
onClick={this.setDropdownForNone}
|
||||||
>
|
>
|
||||||
My sketches
|
{this.props.t('MySketches')}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
{getConfig('UI_COLLECTIONS_ENABLED') &&
|
{getConfig('UI_COLLECTIONS_ENABLED') &&
|
||||||
|
@ -594,7 +662,7 @@ class Nav extends React.PureComponent {
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
onClick={this.setDropdownForNone}
|
onClick={this.setDropdownForNone}
|
||||||
>
|
>
|
||||||
My collections
|
{this.props.t('MyCollections')}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
|
@ -605,7 +673,7 @@ class Nav extends React.PureComponent {
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
onClick={this.setDropdownForNone}
|
onClick={this.setDropdownForNone}
|
||||||
>
|
>
|
||||||
My assets
|
{this.props.t('MyAssets')}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
<li className="nav__dropdown-item">
|
<li className="nav__dropdown-item">
|
||||||
|
@ -615,7 +683,7 @@ class Nav extends React.PureComponent {
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
onClick={this.setDropdownForNone}
|
onClick={this.setDropdownForNone}
|
||||||
>
|
>
|
||||||
Settings
|
{this.props.t('Settings')}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
<li className="nav__dropdown-item">
|
<li className="nav__dropdown-item">
|
||||||
|
@ -624,7 +692,7 @@ class Nav extends React.PureComponent {
|
||||||
onFocus={this.handleFocusForAccount}
|
onFocus={this.handleFocusForAccount}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
>
|
>
|
||||||
Log out
|
{this.props.t('LogOut')}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -677,6 +745,10 @@ class Nav extends React.PureComponent {
|
||||||
account: classNames({
|
account: classNames({
|
||||||
'nav__item': true,
|
'nav__item': true,
|
||||||
'nav__item--open': this.state.dropdownOpen === 'account'
|
'nav__item--open': this.state.dropdownOpen === 'account'
|
||||||
|
}),
|
||||||
|
lang: classNames({
|
||||||
|
'nav__item': true,
|
||||||
|
'nav__item--open': this.state.dropdownOpen === 'lang'
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -684,6 +756,7 @@ class Nav extends React.PureComponent {
|
||||||
<header>
|
<header>
|
||||||
<nav className="nav" title="main-navigation" ref={(node) => { this.node = node; }}>
|
<nav className="nav" title="main-navigation" ref={(node) => { this.node = node; }}>
|
||||||
{this.renderLeftLayout(navDropdownState)}
|
{this.renderLeftLayout(navDropdownState)}
|
||||||
|
{getConfig('TRANSLATIONS_ENABLED') && this.renderLanguageMenu(navDropdownState)}
|
||||||
{this.renderUserMenu(navDropdownState)}
|
{this.renderUserMenu(navDropdownState)}
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
@ -734,7 +807,9 @@ Nav.propTypes = {
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
params: PropTypes.shape({
|
params: PropTypes.shape({
|
||||||
username: PropTypes.string
|
username: PropTypes.string
|
||||||
})
|
}),
|
||||||
|
t: PropTypes.func.isRequired
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Nav.defaultProps = {
|
Nav.defaultProps = {
|
||||||
|
@ -767,5 +842,5 @@ const mapDispatchToProps = {
|
||||||
setAllAccessibleOutput
|
setAllAccessibleOutput
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Nav));
|
export default withTranslation('WebEditor')(withRouter(connect(mapStateToProps, mapDispatchToProps)(Nav)));
|
||||||
export { Nav as NavComponent };
|
export { Nav as NavComponent };
|
||||||
|
|
|
@ -44,7 +44,8 @@ describe('Nav', () => {
|
||||||
setToastText: jest.fn(),
|
setToastText: jest.fn(),
|
||||||
rootFile: {
|
rootFile: {
|
||||||
id: 'root-file'
|
id: 'root-file'
|
||||||
}
|
},
|
||||||
|
t: jest.fn()
|
||||||
};
|
};
|
||||||
const getWrapper = () => shallow(<NavComponent {...props} />);
|
const getWrapper = () => shallow(<NavComponent {...props} />);
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,7 @@ exports[`Nav renders correctly 1`] = `
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="nav__item-header"
|
className="nav__item-header"
|
||||||
>
|
/>
|
||||||
File
|
|
||||||
</span>
|
|
||||||
<test-file-stub
|
<test-file-stub
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
className="nav__item-header-triangle"
|
className="nav__item-header-triangle"
|
||||||
|
@ -49,9 +47,7 @@ exports[`Nav renders correctly 1`] = `
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
>
|
/>
|
||||||
New
|
|
||||||
</button>
|
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
className="nav__dropdown-item"
|
className="nav__dropdown-item"
|
||||||
|
@ -60,9 +56,7 @@ exports[`Nav renders correctly 1`] = `
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
>
|
/>
|
||||||
Duplicate
|
|
||||||
</button>
|
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
className="nav__dropdown-item"
|
className="nav__dropdown-item"
|
||||||
|
@ -71,9 +65,7 @@ exports[`Nav renders correctly 1`] = `
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
>
|
/>
|
||||||
Share
|
|
||||||
</button>
|
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
className="nav__dropdown-item"
|
className="nav__dropdown-item"
|
||||||
|
@ -82,9 +74,7 @@ exports[`Nav renders correctly 1`] = `
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
>
|
/>
|
||||||
Download
|
|
||||||
</button>
|
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
className="nav__dropdown-item"
|
className="nav__dropdown-item"
|
||||||
|
@ -94,9 +84,7 @@ exports[`Nav renders correctly 1`] = `
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
style={Object {}}
|
style={Object {}}
|
||||||
>
|
/>
|
||||||
Open
|
|
||||||
</a>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
@ -111,9 +99,7 @@ exports[`Nav renders correctly 1`] = `
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="nav__item-header"
|
className="nav__item-header"
|
||||||
>
|
/>
|
||||||
Edit
|
|
||||||
</span>
|
|
||||||
<test-file-stub
|
<test-file-stub
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
className="nav__item-header-triangle"
|
className="nav__item-header-triangle"
|
||||||
|
@ -131,7 +117,6 @@ exports[`Nav renders correctly 1`] = `
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
>
|
>
|
||||||
Tidy Code
|
|
||||||
<span
|
<span
|
||||||
className="nav__keyboard-shortcut"
|
className="nav__keyboard-shortcut"
|
||||||
>
|
>
|
||||||
|
@ -148,7 +133,6 @@ exports[`Nav renders correctly 1`] = `
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
>
|
>
|
||||||
Find
|
|
||||||
<span
|
<span
|
||||||
className="nav__keyboard-shortcut"
|
className="nav__keyboard-shortcut"
|
||||||
>
|
>
|
||||||
|
@ -165,7 +149,6 @@ exports[`Nav renders correctly 1`] = `
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
>
|
>
|
||||||
Find Next
|
|
||||||
<span
|
<span
|
||||||
className="nav__keyboard-shortcut"
|
className="nav__keyboard-shortcut"
|
||||||
>
|
>
|
||||||
|
@ -182,7 +165,6 @@ exports[`Nav renders correctly 1`] = `
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
>
|
>
|
||||||
Find Previous
|
|
||||||
<span
|
<span
|
||||||
className="nav__keyboard-shortcut"
|
className="nav__keyboard-shortcut"
|
||||||
>
|
>
|
||||||
|
@ -206,9 +188,7 @@ exports[`Nav renders correctly 1`] = `
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="nav__item-header"
|
className="nav__item-header"
|
||||||
>
|
/>
|
||||||
Sketch
|
|
||||||
</span>
|
|
||||||
<test-file-stub
|
<test-file-stub
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
className="nav__item-header-triangle"
|
className="nav__item-header-triangle"
|
||||||
|
@ -225,9 +205,16 @@ exports[`Nav renders correctly 1`] = `
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
className="nav__dropdown-item"
|
||||||
>
|
>
|
||||||
Add File
|
<button
|
||||||
</button>
|
onBlur={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
/>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
className="nav__dropdown-item"
|
className="nav__dropdown-item"
|
||||||
|
@ -237,18 +224,6 @@ exports[`Nav renders correctly 1`] = `
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
>
|
>
|
||||||
Add Folder
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
className="nav__dropdown-item"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
onBlur={[Function]}
|
|
||||||
onClick={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
>
|
|
||||||
Run
|
|
||||||
<span
|
<span
|
||||||
className="nav__keyboard-shortcut"
|
className="nav__keyboard-shortcut"
|
||||||
>
|
>
|
||||||
|
@ -265,7 +240,6 @@ exports[`Nav renders correctly 1`] = `
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
>
|
>
|
||||||
Stop
|
|
||||||
<span
|
<span
|
||||||
className="nav__keyboard-shortcut"
|
className="nav__keyboard-shortcut"
|
||||||
>
|
>
|
||||||
|
@ -289,9 +263,7 @@ exports[`Nav renders correctly 1`] = `
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="nav__item-header"
|
className="nav__item-header"
|
||||||
>
|
/>
|
||||||
Help
|
|
||||||
</span>
|
|
||||||
<test-file-stub
|
<test-file-stub
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
className="nav__item-header-triangle"
|
className="nav__item-header-triangle"
|
||||||
|
@ -308,9 +280,7 @@ exports[`Nav renders correctly 1`] = `
|
||||||
onBlur={[Function]}
|
onBlur={[Function]}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
>
|
/>
|
||||||
Keyboard Shortcuts
|
|
||||||
</button>
|
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
className="nav__dropdown-item"
|
className="nav__dropdown-item"
|
||||||
|
@ -322,9 +292,7 @@ exports[`Nav renders correctly 1`] = `
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
/>
|
||||||
Reference
|
|
||||||
</a>
|
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
className="nav__dropdown-item"
|
className="nav__dropdown-item"
|
||||||
|
@ -334,9 +302,7 @@ exports[`Nav renders correctly 1`] = `
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onFocus={[Function]}
|
onFocus={[Function]}
|
||||||
style={Object {}}
|
style={Object {}}
|
||||||
>
|
/>
|
||||||
About
|
|
||||||
</a>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
38
client/i18n.js
Normal file
38
client/i18n.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import i18n from 'i18next';
|
||||||
|
import { initReactI18next } from 'react-i18next';
|
||||||
|
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||||
|
import Backend from 'i18next-http-backend';
|
||||||
|
|
||||||
|
const fallbackLng = ['en-US'];
|
||||||
|
const availableLanguages = ['en-US', 'es-419'];
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
loadPath: '/translations/{{lng}}/translations.json',
|
||||||
|
requestOptions: { // used for fetch, can also be a function (payload) => ({ method: 'GET' })
|
||||||
|
mode: 'no-cors'
|
||||||
|
},
|
||||||
|
allowMultiLoading: false, // set loadPath: '/locales/resources.json?lng={{lng}}&ns={{ns}}' to adapt to multiLoading
|
||||||
|
};
|
||||||
|
|
||||||
|
i18n
|
||||||
|
.use(initReactI18next) // pass the i18n instance to react-i18next.
|
||||||
|
.use(LanguageDetector)// to detect the language from currentBrowser
|
||||||
|
.use(Backend) // to fetch the data from server
|
||||||
|
.init({
|
||||||
|
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
|
||||||
|
debug: false,
|
||||||
|
backend: options,
|
||||||
|
getAsync: false,
|
||||||
|
initImmediate: false,
|
||||||
|
useSuspense: true,
|
||||||
|
whitelist: availableLanguages,
|
||||||
|
interpolation: {
|
||||||
|
escapeValue: false, // react already safes from xss
|
||||||
|
},
|
||||||
|
saveMissing: false, // if a key is not found AND this flag is set to true, i18next will call the handler missingKeyHandler
|
||||||
|
missingKeyHandler: false // function(lng, ns, key, fallbackValue) { } custom logic about how to handle the missing keys
|
||||||
|
});
|
||||||
|
|
||||||
|
export default i18n;
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { Suspense } from 'react';
|
||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
import { hot } from 'react-hot-loader/root';
|
import { hot } from 'react-hot-loader/root';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
|
@ -7,6 +7,8 @@ import { Router, browserHistory } from 'react-router';
|
||||||
import configureStore from './store';
|
import configureStore from './store';
|
||||||
import routes from './routes';
|
import routes from './routes';
|
||||||
import ThemeProvider from './modules/App/components/ThemeProvider';
|
import ThemeProvider from './modules/App/components/ThemeProvider';
|
||||||
|
import Loader from './modules/App/components/loader';
|
||||||
|
import i18n from './i18n';
|
||||||
|
|
||||||
require('./styles/main.scss');
|
require('./styles/main.scss');
|
||||||
|
|
||||||
|
@ -29,6 +31,8 @@ const App = () => (
|
||||||
const HotApp = hot(App);
|
const HotApp = hot(App);
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<HotApp />,
|
<Suspense fallback={(<Loader />)}>
|
||||||
|
<HotApp />
|
||||||
|
</Suspense>,
|
||||||
document.getElementById('root')
|
document.getElementById('root')
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import SquareLogoIcon from '../../../images/p5js-square-logo.svg';
|
import SquareLogoIcon from '../../../images/p5js-square-logo.svg';
|
||||||
// import PlayIcon from '../../../images/play.svg';
|
// import PlayIcon from '../../../images/play.svg';
|
||||||
import AsteriskIcon from '../../../images/p5-asterisk.svg';
|
import AsteriskIcon from '../../../images/p5-asterisk.svg';
|
||||||
|
|
||||||
function About(props) {
|
function About(props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<div className="about__content">
|
<div className="about__content">
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>p5.js Web Editor | About</title>
|
<title>p5.js Web Editor | About </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="p5.js Logo" focusable="false" />
|
||||||
|
@ -25,7 +26,7 @@ function About(props) {
|
||||||
</p> */}
|
</p> */}
|
||||||
</div>
|
</div>
|
||||||
<div className="about__content-column">
|
<div className="about__content-column">
|
||||||
<h3 className="about__content-column-title">New to p5.js?</h3>
|
<h3 className="about__content-column-title">{t('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/"
|
||||||
|
@ -33,7 +34,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" />
|
||||||
Examples
|
{t('Examples')}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p className="about__content-column-list">
|
<p className="about__content-column-list">
|
||||||
|
@ -43,12 +44,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" />
|
||||||
Learn
|
{t('Learn')}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="about__content-column">
|
<div className="about__content-column">
|
||||||
<h3 className="about__content-column-title">Resources</h3>
|
<h3 className="about__content-column-title">{t('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/"
|
||||||
|
@ -56,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" />
|
||||||
Libraries
|
{t('Libraries')}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p className="about__content-column-list">
|
<p className="about__content-column-list">
|
||||||
|
@ -66,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" />
|
||||||
Reference
|
{t('Reference')}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p className="about__content-column-list">
|
<p className="about__content-column-list">
|
||||||
|
@ -76,7 +77,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" />
|
||||||
Forum
|
{t('Forum')}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -86,7 +87,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"
|
||||||
>Contribute
|
>{t('Contribute')}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p className="about__footer-list">
|
<p className="about__footer-list">
|
||||||
|
@ -94,7 +95,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"
|
||||||
>Report a bug
|
>{t('Report')}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p className="about__footer-list">
|
<p className="about__footer-list">
|
||||||
|
|
|
@ -1,53 +1,55 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { metaKeyName, } from '../../../utils/metaKey';
|
import { metaKeyName, } from '../../../utils/metaKey';
|
||||||
|
|
||||||
function KeyboardShortcutModal() {
|
function KeyboardShortcutModal() {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<div className="keyboard-shortcuts">
|
<div className="keyboard-shortcuts">
|
||||||
<h3 className="keyboard-shortcuts__title">Code Editing</h3>
|
<h3 className="keyboard-shortcuts__title">{t('CodeEditing')}</h3>
|
||||||
<p className="keyboard-shortcuts__description">
|
<p className="keyboard-shortcuts__description">
|
||||||
Code editing keyboard shortcuts follow <a href="https://shortcuts.design/toolspage-sublimetext.html" target="_blank" rel="noopener noreferrer">Sublime Text shortcuts</a>.
|
{t('Code editing keyboard shortcuts follow')} <a href="https://shortcuts.design/toolspage-sublimetext.html" target="_blank" rel="noopener noreferrer">{t('Sublime Text shortcuts')}</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>Tidy</span>
|
<span>{t('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>Find Text</span>
|
<span>{t('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>Find Next Text Match</span>
|
<span>{t('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>Find Previous Text Match</span>
|
<span>{t('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>Indent Code Left</span>
|
<span>{t('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>Indent Code Right</span>
|
<span>{t('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>Comment Line</span>
|
<span>{t('CommentLine')}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h3 className="keyboard-shortcuts__title">General</h3>
|
<h3 className="keyboard-shortcuts__title">General</h3>
|
||||||
|
@ -56,31 +58,31 @@ function KeyboardShortcutModal() {
|
||||||
<span className="keyboard-shortcut__command">
|
<span className="keyboard-shortcut__command">
|
||||||
{metaKeyName} + S
|
{metaKeyName} + S
|
||||||
</span>
|
</span>
|
||||||
<span>Save</span>
|
<span>{t('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>Start Sketch</span>
|
<span>{t('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>Stop Sketch</span>
|
<span>{t('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>Turn on Accessible Output</span>
|
<span>{t('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>Turn off Accessible Output</span>
|
<span>{t('TurnOffAccessibleOutput')}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
|
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
|
||||||
|
import { withTranslation } from 'react-i18next';
|
||||||
// import { bindActionCreators } from 'redux';
|
// import { bindActionCreators } from 'redux';
|
||||||
// import { connect } from 'react-redux';
|
// import { connect } from 'react-redux';
|
||||||
// import * as PreferencesActions from '../actions/preferences';
|
// import * as PreferencesActions from '../actions/preferences';
|
||||||
|
@ -98,13 +99,13 @@ class Preferences extends React.Component {
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<TabList>
|
<TabList>
|
||||||
<div className="tabs__titles">
|
<div className="tabs__titles">
|
||||||
<Tab><h4 className="tabs__title">General Settings</h4></Tab>
|
<Tab><h4 className="tabs__title">{this.props.t('GeneralSettings')}</h4></Tab>
|
||||||
<Tab><h4 className="tabs__title">Accessibility</h4></Tab>
|
<Tab><h4 className="tabs__title">{this.props.t('Accessibility')}</h4></Tab>
|
||||||
</div>
|
</div>
|
||||||
</TabList>
|
</TabList>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<div className="preference">
|
<div className="preference">
|
||||||
<h4 className="preference__title">Theme</h4>
|
<h4 className="preference__title">{this.props.t('Theme')}</h4>
|
||||||
<div className="preference__options">
|
<div className="preference__options">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
|
@ -116,7 +117,7 @@ class Preferences extends React.Component {
|
||||||
value="light"
|
value="light"
|
||||||
checked={this.props.theme === 'light'}
|
checked={this.props.theme === 'light'}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="light-theme-on" className="preference__option">Light</label>
|
<label htmlFor="light-theme-on" className="preference__option">{this.props.t('Light')}</label>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
onChange={() => this.props.setTheme('dark')}
|
onChange={() => this.props.setTheme('dark')}
|
||||||
|
@ -127,7 +128,7 @@ class Preferences extends React.Component {
|
||||||
value="dark"
|
value="dark"
|
||||||
checked={this.props.theme === 'dark'}
|
checked={this.props.theme === 'dark'}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="dark-theme-on" className="preference__option">Dark</label>
|
<label htmlFor="dark-theme-on" className="preference__option">{this.props.t('Dark')}</label>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
onChange={() => this.props.setTheme('contrast')}
|
onChange={() => this.props.setTheme('contrast')}
|
||||||
|
@ -138,11 +139,11 @@ class Preferences extends React.Component {
|
||||||
value="contrast"
|
value="contrast"
|
||||||
checked={this.props.theme === 'contrast'}
|
checked={this.props.theme === 'contrast'}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="high-contrast-theme-on" className="preference__option">High Contrast</label>
|
<label htmlFor="high-contrast-theme-on" className="preference__option">{this.props.t('HighContrast')}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="preference">
|
<div className="preference">
|
||||||
<h4 className="preference__title">Text size</h4>
|
<h4 className="preference__title">{this.props.t('TextSize')}</h4>
|
||||||
<button
|
<button
|
||||||
className="preference__minus-button"
|
className="preference__minus-button"
|
||||||
onClick={this.decreaseFontSize}
|
onClick={this.decreaseFontSize}
|
||||||
|
@ -150,7 +151,7 @@ class Preferences extends React.Component {
|
||||||
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">Decrease</h6>
|
<h6 className="preference__label">{this.props.t('Decrease')}</h6>
|
||||||
</button>
|
</button>
|
||||||
<form onSubmit={this.onFontInputSubmit}>
|
<form onSubmit={this.onFontInputSubmit}>
|
||||||
<input
|
<input
|
||||||
|
@ -171,11 +172,11 @@ class Preferences extends React.Component {
|
||||||
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">Increase</h6>
|
<h6 className="preference__label">{this.props.t('Increase')}</h6>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="preference">
|
<div className="preference">
|
||||||
<h4 className="preference__title">Autosave</h4>
|
<h4 className="preference__title">{this.props.t('Autosave')}</h4>
|
||||||
<div className="preference__options">
|
<div className="preference__options">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
|
@ -187,7 +188,7 @@ class Preferences extends React.Component {
|
||||||
value="On"
|
value="On"
|
||||||
checked={this.props.autosave}
|
checked={this.props.autosave}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="autosave-on" className="preference__option">On</label>
|
<label htmlFor="autosave-on" className="preference__option">{this.props.t('On')}</label>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
onChange={() => this.props.setAutosave(false)}
|
onChange={() => this.props.setAutosave(false)}
|
||||||
|
@ -198,11 +199,11 @@ class Preferences extends React.Component {
|
||||||
value="Off"
|
value="Off"
|
||||||
checked={!this.props.autosave}
|
checked={!this.props.autosave}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="autosave-off" className="preference__option">Off</label>
|
<label htmlFor="autosave-off" className="preference__option">{this.props.t('Off')}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="preference">
|
<div className="preference">
|
||||||
<h4 className="preference__title">Word Wrap</h4>
|
<h4 className="preference__title">{this.props.t('WordWrap')}</h4>
|
||||||
<div className="preference__options">
|
<div className="preference__options">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
|
@ -214,7 +215,7 @@ class Preferences extends React.Component {
|
||||||
value="On"
|
value="On"
|
||||||
checked={this.props.linewrap}
|
checked={this.props.linewrap}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="linewrap-on" className="preference__option">On</label>
|
<label htmlFor="linewrap-on" className="preference__option">{this.props.t('On')}</label>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
onChange={() => this.props.setLinewrap(false)}
|
onChange={() => this.props.setLinewrap(false)}
|
||||||
|
@ -225,13 +226,13 @@ class Preferences extends React.Component {
|
||||||
value="Off"
|
value="Off"
|
||||||
checked={!this.props.linewrap}
|
checked={!this.props.linewrap}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="linewrap-off" className="preference__option">Off</label>
|
<label htmlFor="linewrap-off" className="preference__option">{this.props.t('Off')}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<div className="preference">
|
<div className="preference">
|
||||||
<h4 className="preference__title">Line numbers</h4>
|
<h4 className="preference__title">{this.props.t('LineNumbers')}</h4>
|
||||||
<div className="preference__options">
|
<div className="preference__options">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
|
@ -243,7 +244,7 @@ class Preferences extends React.Component {
|
||||||
value="On"
|
value="On"
|
||||||
checked={this.props.lineNumbers}
|
checked={this.props.lineNumbers}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="line-numbers-on" className="preference__option">On</label>
|
<label htmlFor="line-numbers-on" className="preference__option">{this.props.t('On')}</label>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
onChange={() => this.props.setLineNumbers(false)}
|
onChange={() => this.props.setLineNumbers(false)}
|
||||||
|
@ -254,11 +255,11 @@ class Preferences extends React.Component {
|
||||||
value="Off"
|
value="Off"
|
||||||
checked={!this.props.lineNumbers}
|
checked={!this.props.lineNumbers}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="line-numbers-off" className="preference__option">Off</label>
|
<label htmlFor="line-numbers-off" className="preference__option">{this.props.t('Off')}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="preference">
|
<div className="preference">
|
||||||
<h4 className="preference__title">Lint warning sound</h4>
|
<h4 className="preference__title">{this.props.t('LintWarningSound')}</h4>
|
||||||
<div className="preference__options">
|
<div className="preference__options">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
|
@ -270,7 +271,7 @@ class Preferences extends React.Component {
|
||||||
value="On"
|
value="On"
|
||||||
checked={this.props.lintWarning}
|
checked={this.props.lintWarning}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="lint-warning-on" className="preference__option">On</label>
|
<label htmlFor="lint-warning-on" className="preference__option">{this.props.t('On')}</label>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
onChange={() => this.props.setLintWarning(false)}
|
onChange={() => this.props.setLintWarning(false)}
|
||||||
|
@ -281,19 +282,19 @@ class Preferences extends React.Component {
|
||||||
value="Off"
|
value="Off"
|
||||||
checked={!this.props.lintWarning}
|
checked={!this.props.lintWarning}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="lint-warning-off" className="preference__option">Off</label>
|
<label htmlFor="lint-warning-off" className="preference__option">{this.props.t('Off')}</label>
|
||||||
<button
|
<button
|
||||||
className="preference__preview-button"
|
className="preference__preview-button"
|
||||||
onClick={() => beep.play()}
|
onClick={() => beep.play()}
|
||||||
aria-label="preview sound"
|
aria-label="preview sound"
|
||||||
>
|
>
|
||||||
Preview sound
|
{this.props.t('PreviewSound')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="preference">
|
<div className="preference">
|
||||||
<h4 className="preference__title">Accessible text-based canvas</h4>
|
<h4 className="preference__title">{this.props.t('AccessibleTextBasedCanvas')}</h4>
|
||||||
<h6 className="preference__subtitle">Used with screen reader</h6>
|
<h6 className="preference__subtitle">{this.props.t('UsedScreenReader')}</h6>
|
||||||
|
|
||||||
<div className="preference__options">
|
<div className="preference__options">
|
||||||
<input
|
<input
|
||||||
|
@ -307,7 +308,7 @@ class Preferences extends React.Component {
|
||||||
value="On"
|
value="On"
|
||||||
checked={(this.props.textOutput)}
|
checked={(this.props.textOutput)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="text-output-on" className="preference__option preference__canvas">Plain-text</label>
|
<label htmlFor="text-output-on" className="preference__option preference__canvas">{this.props.t('PlainText')}</label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
|
@ -319,7 +320,7 @@ class Preferences extends React.Component {
|
||||||
value="On"
|
value="On"
|
||||||
checked={(this.props.gridOutput)}
|
checked={(this.props.gridOutput)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="table-output-on" className="preference__option preference__canvas">Table-text</label>
|
<label htmlFor="table-output-on" className="preference__option preference__canvas">{this.props.t('TableText')}</label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
|
@ -331,7 +332,7 @@ class Preferences extends React.Component {
|
||||||
value="On"
|
value="On"
|
||||||
checked={(this.props.soundOutput)}
|
checked={(this.props.soundOutput)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="sound-output-on" className="preference__option preference__canvas">Sound</label>
|
<label htmlFor="sound-output-on" className="preference__option preference__canvas">{this.props.t('Sound')}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
@ -360,6 +361,7 @@ Preferences.propTypes = {
|
||||||
setLintWarning: PropTypes.func.isRequired,
|
setLintWarning: PropTypes.func.isRequired,
|
||||||
theme: PropTypes.string.isRequired,
|
theme: PropTypes.string.isRequired,
|
||||||
setTheme: PropTypes.func.isRequired,
|
setTheme: PropTypes.func.isRequired,
|
||||||
|
t: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Preferences;
|
export default withTranslation('WebEditor')(Preferences);
|
||||||
|
|
|
@ -2,15 +2,17 @@ import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import * as ToastActions from '../actions/toast';
|
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');
|
||||||
return (
|
return (
|
||||||
<section className="toast">
|
<section className="toast">
|
||||||
<p>
|
<p>
|
||||||
{props.text}
|
{t(props.text)}
|
||||||
</p>
|
</p>
|
||||||
<button className="toast__close" onClick={props.hideToast} aria-label="Close Alert" >
|
<button className="toast__close" onClick={props.hideToast} aria-label="Close Alert" >
|
||||||
<ExitIcon focusable="false" aria-hidden="true" />
|
<ExitIcon focusable="false" aria-hidden="true" />
|
||||||
|
|
|
@ -3,6 +3,7 @@ import React from 'react';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { withRouter } from 'react-router';
|
import { withRouter } from 'react-router';
|
||||||
|
import { withTranslation } from 'react-i18next';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import SplitPane from 'react-split-pane';
|
import SplitPane from 'react-split-pane';
|
||||||
import Editor from '../components/Editor';
|
import Editor from '../components/Editor';
|
||||||
|
@ -196,7 +197,7 @@ class IDEView extends React.Component {
|
||||||
this.props.persistState();
|
this.props.persistState();
|
||||||
window.onbeforeunload = null;
|
window.onbeforeunload = null;
|
||||||
} else if (this.props.ide.unsavedChanges) {
|
} else if (this.props.ide.unsavedChanges) {
|
||||||
if (!window.confirm('Are you sure you want to leave this page? You have unsaved changes.')) {
|
if (!window.confirm(this.props.t('WarningUnsavedChanges'))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.props.setUnsavedChanges(false);
|
this.props.setUnsavedChanges(false);
|
||||||
|
@ -218,7 +219,7 @@ class IDEView extends React.Component {
|
||||||
<Toolbar />
|
<Toolbar />
|
||||||
{this.props.ide.preferencesIsVisible &&
|
{this.props.ide.preferencesIsVisible &&
|
||||||
<Overlay
|
<Overlay
|
||||||
title="Settings"
|
title={this.props.t('Settings')}
|
||||||
ariaLabel="settings"
|
ariaLabel="settings"
|
||||||
closeOverlay={this.props.closePreferences}
|
closeOverlay={this.props.closePreferences}
|
||||||
>
|
>
|
||||||
|
@ -334,7 +335,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">Preview</h2>
|
<h2 className="preview-frame__title">{this.props.t('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; }}>
|
||||||
|
@ -395,7 +396,7 @@ class IDEView extends React.Component {
|
||||||
}
|
}
|
||||||
{ this.props.location.pathname === '/about' &&
|
{ this.props.location.pathname === '/about' &&
|
||||||
<Overlay
|
<Overlay
|
||||||
title="About"
|
title={this.props.t('About')}
|
||||||
previousPath={this.props.ide.previousPath}
|
previousPath={this.props.ide.previousPath}
|
||||||
ariaLabel="about"
|
ariaLabel="about"
|
||||||
>
|
>
|
||||||
|
@ -441,7 +442,7 @@ class IDEView extends React.Component {
|
||||||
}
|
}
|
||||||
{this.props.ide.keyboardShortcutVisible &&
|
{this.props.ide.keyboardShortcutVisible &&
|
||||||
<Overlay
|
<Overlay
|
||||||
title="Keyboard Shortcuts"
|
title={this.props.t('KeyboardShortcuts')}
|
||||||
ariaLabel="keyboard shortcuts"
|
ariaLabel="keyboard shortcuts"
|
||||||
closeOverlay={this.props.closeKeyboardShortcutModal}
|
closeOverlay={this.props.closeKeyboardShortcutModal}
|
||||||
>
|
>
|
||||||
|
@ -609,7 +610,8 @@ IDEView.propTypes = {
|
||||||
hideRuntimeErrorWarning: PropTypes.func.isRequired,
|
hideRuntimeErrorWarning: PropTypes.func.isRequired,
|
||||||
startSketch: PropTypes.func.isRequired,
|
startSketch: PropTypes.func.isRequired,
|
||||||
openUploadFileModal: PropTypes.func.isRequired,
|
openUploadFileModal: PropTypes.func.isRequired,
|
||||||
closeUploadFileModal: PropTypes.func.isRequired
|
closeUploadFileModal: PropTypes.func.isRequired,
|
||||||
|
t: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
|
@ -646,4 +648,6 @@ function mapDispatchToProps(dispatch) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(IDEView));
|
|
||||||
|
export default withTranslation('WebEditor')(withRouter(connect(mapStateToProps, mapDispatchToProps)(IDEView)));
|
||||||
|
|
||||||
|
|
66
package-lock.json
generated
66
package-lock.json
generated
|
@ -16272,6 +16272,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"html-parse-stringify2": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/html-parse-stringify2/-/html-parse-stringify2-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-3FZwtyksoVi3vJFsmmc1rIhyg0o=",
|
||||||
|
"requires": {
|
||||||
|
"void-elements": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"html-tags": {
|
"html-tags": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz",
|
||||||
|
@ -16692,6 +16700,52 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"i18next": {
|
||||||
|
"version": "19.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/i18next/-/i18next-19.5.1.tgz",
|
||||||
|
"integrity": "sha512-e6lGMiTyb51F9PPInUTTDg8YbwcWXZYX18svaX2NUUWEphJKP7oG5HMlbZ+K84AXqw4AeBnwRrOlS9ickqcCBg==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.10.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": {
|
||||||
|
"version": "7.10.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.3.tgz",
|
||||||
|
"integrity": "sha512-RzGO0RLSdokm9Ipe/YD+7ww8X2Ro79qiXZF3HU9ljrM+qnJmH1Vqth+hbiQZy761LnMJTMitHDuKVYTk3k4dLw==",
|
||||||
|
"requires": {
|
||||||
|
"regenerator-runtime": "^0.13.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"regenerator-runtime": {
|
||||||
|
"version": "0.13.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
|
||||||
|
"integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"i18next-browser-languagedetector": {
|
||||||
|
"version": "4.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-4.3.1.tgz",
|
||||||
|
"integrity": "sha512-KIToAzf8zwWvacgnRwJp63ase26o24AuNUlfNVJ5YZAFmdGhsJpmFClxXPuk9rv1FMI4lnc8zLSqgZPEZMrW4g==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.5.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"i18next-http-backend": {
|
||||||
|
"version": "1.0.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-1.0.15.tgz",
|
||||||
|
"integrity": "sha512-AOGNcB47n0S4GANyVhGUeLRzUUgvh6Lf5vNs/+G3cCP2Mri0OseO2rX0VLHE6PcL21mswW7ka1nmjGKviXKnjQ==",
|
||||||
|
"requires": {
|
||||||
|
"node-fetch": "2.6.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"node-fetch": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"iconv-lite": {
|
"iconv-lite": {
|
||||||
"version": "0.4.24",
|
"version": "0.4.24",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
|
@ -27010,6 +27064,15 @@
|
||||||
"prop-types": "^15.6.1"
|
"prop-types": "^15.6.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-i18next": {
|
||||||
|
"version": "11.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.7.0.tgz",
|
||||||
|
"integrity": "sha512-8tvVkpuxQlubcszZON+jmoCgiA9gCZ74OAYli9KChPhETtq8pJsANBTe9KRLRLmX3ubumgvidURWr0VvKz1tww==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.3.1",
|
||||||
|
"html-parse-stringify2": "2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-input-autosize": {
|
"react-input-autosize": {
|
||||||
"version": "2.2.2",
|
"version": "2.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-2.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-2.2.2.tgz",
|
||||||
|
@ -32181,8 +32244,7 @@
|
||||||
"void-elements": {
|
"void-elements": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
|
||||||
"integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=",
|
"integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"vue-docgen-api": {
|
"vue-docgen-api": {
|
||||||
"version": "4.20.0",
|
"version": "4.20.0",
|
||||||
|
|
|
@ -151,6 +151,9 @@
|
||||||
"express-session": "^1.17.0",
|
"express-session": "^1.17.0",
|
||||||
"friendly-words": "^1.1.10",
|
"friendly-words": "^1.1.10",
|
||||||
"htmlhint": "^0.10.1",
|
"htmlhint": "^0.10.1",
|
||||||
|
"i18next": "^19.4.5",
|
||||||
|
"i18next-browser-languagedetector": "^4.2.0",
|
||||||
|
"i18next-http-backend": "^1.0.15",
|
||||||
"is-url": "^1.2.4",
|
"is-url": "^1.2.4",
|
||||||
"jest-express": "^1.11.0",
|
"jest-express": "^1.11.0",
|
||||||
"js-beautify": "^1.10.3",
|
"js-beautify": "^1.10.3",
|
||||||
|
@ -178,6 +181,7 @@
|
||||||
"react-dom": "^16.12.0",
|
"react-dom": "^16.12.0",
|
||||||
"react-helmet": "^5.1.3",
|
"react-helmet": "^5.1.3",
|
||||||
"react-hot-loader": "^4.12.19",
|
"react-hot-loader": "^4.12.19",
|
||||||
|
"react-i18next": "^11.5.0",
|
||||||
"react-redux": "^5.1.2",
|
"react-redux": "^5.1.2",
|
||||||
"react-router": "^3.2.5",
|
"react-router": "^3.2.5",
|
||||||
"react-split-pane": "^0.1.89",
|
"react-split-pane": "^0.1.89",
|
||||||
|
|
|
@ -79,6 +79,7 @@ app.options('*', corsMiddleware);
|
||||||
app.use(Express.static(path.resolve(__dirname, '../dist/static'), {
|
app.use(Express.static(path.resolve(__dirname, '../dist/static'), {
|
||||||
maxAge: process.env.STATIC_MAX_AGE || (process.env.NODE_ENV === 'production' ? '1d' : '0')
|
maxAge: process.env.STATIC_MAX_AGE || (process.env.NODE_ENV === 'production' ? '1d' : '0')
|
||||||
}));
|
}));
|
||||||
|
app.use('/translations', Express.static('translations/locales/'));
|
||||||
app.use(bodyParser.urlencoded({ limit: '50mb', extended: true }));
|
app.use(bodyParser.urlencoded({ limit: '50mb', extended: true }));
|
||||||
app.use(bodyParser.json({ limit: '50mb' }));
|
app.use(bodyParser.json({ limit: '50mb' }));
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
|
|
|
@ -33,6 +33,8 @@ export function renderIndex() {
|
||||||
window.process.env.UI_COLLECTIONS_ENABLED = ${process.env.UI_COLLECTIONS_ENABLED === 'false' ? false : true};
|
window.process.env.UI_COLLECTIONS_ENABLED = ${process.env.UI_COLLECTIONS_ENABLED === 'false' ? false : true};
|
||||||
window.process.env.UPLOAD_LIMIT = ${process.env.UPLOAD_LIMIT ? `${process.env.UPLOAD_LIMIT}` : undefined};
|
window.process.env.UPLOAD_LIMIT = ${process.env.UPLOAD_LIMIT ? `${process.env.UPLOAD_LIMIT}` : undefined};
|
||||||
window.process.env.MOBILE_ENABLED = ${process.env.MOBILE_ENABLED ? `${process.env.MOBILE_ENABLED}` : undefined};
|
window.process.env.MOBILE_ENABLED = ${process.env.MOBILE_ENABLED ? `${process.env.MOBILE_ENABLED}` : undefined};
|
||||||
|
window.process.env.TRANSLATIONS_ENABLED = ${process.env.TRANSLATIONS_ENABLED === 'true' ? true :false};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
115
translations/locales/en-US/translations.json
Normal file
115
translations/locales/en-US/translations.json
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
{
|
||||||
|
"Contribute": "Contribute",
|
||||||
|
"NewP5": "New to p5.js?",
|
||||||
|
"Report": "Report a bug",
|
||||||
|
"Learn": "Learn",
|
||||||
|
"About": "About",
|
||||||
|
"Resources": "Resources",
|
||||||
|
"Libraries": "Libraries",
|
||||||
|
"Forum": "Forum",
|
||||||
|
"File": "File",
|
||||||
|
"New": "New",
|
||||||
|
"Save": "Save",
|
||||||
|
"Share": "Share",
|
||||||
|
"Duplicate": "Duplicate",
|
||||||
|
"Examples": "Examples",
|
||||||
|
"Edit": "Edit",
|
||||||
|
"TidyCode": "Tidy Code",
|
||||||
|
"Find": "Find",
|
||||||
|
"AddToCollection": "Add to Collection",
|
||||||
|
"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",
|
||||||
|
"Auto-refresh": "Auto-refresh",
|
||||||
|
"Console": "Console",
|
||||||
|
"Settings": "Settings",
|
||||||
|
"GeneralSettings": "General settings",
|
||||||
|
"Theme": "Theme",
|
||||||
|
"Light": "Light",
|
||||||
|
"Dark": "Dark",
|
||||||
|
"HighContrast": "High Contrast",
|
||||||
|
"TextSize": "Text Size",
|
||||||
|
"Decrease": "Decrease",
|
||||||
|
"Increase": "Increase",
|
||||||
|
"IndentationAmount": "Indentation amount",
|
||||||
|
"Autosave": "Autosave",
|
||||||
|
"On": "On",
|
||||||
|
"Off": "Off",
|
||||||
|
"SketchSettings": "Sketch Settings",
|
||||||
|
"SecurityProtocol": "Security Protocol",
|
||||||
|
"ServeOverHTTPS": "Serve over HTTPS",
|
||||||
|
"Accessibility": "Accessibility",
|
||||||
|
"LintWarningSound": "Lint warning sound",
|
||||||
|
"PreviewSound": "Preview sound",
|
||||||
|
"AccessibleTextBasedCanvas": "Accessible text-based canvas",
|
||||||
|
"UsedScreenReader": "Used with screen reader",
|
||||||
|
"PlainText": "Plain-text",
|
||||||
|
"TableText": "Table-text",
|
||||||
|
"Sound": "Sound",
|
||||||
|
"WordWrap": "Word Wrap",
|
||||||
|
"LineNumbers": "Line numbers",
|
||||||
|
"LangChange": "Language changed",
|
||||||
|
"Welcome": "Welcome",
|
||||||
|
"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",
|
||||||
|
"BackEditor": "Back to Editor",
|
||||||
|
"UsernameSplit": "User Name",
|
||||||
|
"Password": "Password",
|
||||||
|
"ConfirmPassword": "Confirm Password",
|
||||||
|
"OpenedNewSketch": "Opened new sketch.",
|
||||||
|
"Hello": "Hello",
|
||||||
|
"MyAccount": "My Account",
|
||||||
|
"My":"My",
|
||||||
|
"Sketches": "My sketches",
|
||||||
|
"Collections": "My collections",
|
||||||
|
"Asset": "Asset",
|
||||||
|
"MyAssets": "My assets",
|
||||||
|
"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",
|
||||||
|
"enter a name": "enter a name",
|
||||||
|
"Add": "Add",
|
||||||
|
"Folder": "Folder",
|
||||||
|
"FindText": "Find Text",
|
||||||
|
"FindNextTextMatch": "Find Next Text Match",
|
||||||
|
"FindPreviousTextMatch": "Find Previous Text Match",
|
||||||
|
"Code editing keyboard shortcuts follow": "Code editing keyboard shortcuts follow",
|
||||||
|
"Sublime Text shortcuts": "Sublime Text shortcuts",
|
||||||
|
"WarningUnsavedChanges": "Are you sure you want to leave this page? You have unsaved changes."
|
||||||
|
|
||||||
|
}
|
||||||
|
|
113
translations/locales/es-419/translations.json
Normal file
113
translations/locales/es-419/translations.json
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
{
|
||||||
|
"Contribute": "Contribuir",
|
||||||
|
"NewP5": "¿Empezando con p5.js?",
|
||||||
|
"Report": "Reporta un error",
|
||||||
|
"Learn": "Aprende",
|
||||||
|
"About": "Acerca de",
|
||||||
|
"Resources": "Recursos",
|
||||||
|
"Libraries": "Bibliotecas",
|
||||||
|
"Forum": "Foro",
|
||||||
|
"File": "Archivo",
|
||||||
|
"New": "Nuevo",
|
||||||
|
"Save": "Guardar",
|
||||||
|
"Share": "Compartir",
|
||||||
|
"Duplicate": "Duplicar",
|
||||||
|
"Examples": "Ejemplos",
|
||||||
|
"Edit": "Editar",
|
||||||
|
"TidyCode": "Ordenar código",
|
||||||
|
"Find": "Buscar",
|
||||||
|
"AddToCollection": "Agregar a colección",
|
||||||
|
"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",
|
||||||
|
"Auto-refresh": "Auto-refrescar",
|
||||||
|
"Console": "Consola",
|
||||||
|
"Settings": "Configuración",
|
||||||
|
"GeneralSettings": "Configuración general",
|
||||||
|
"Theme": "Modo de visualización",
|
||||||
|
"Light": "Claro",
|
||||||
|
"Dark": "Oscuro",
|
||||||
|
"HighContrast": "Alto contraste",
|
||||||
|
"TextSize": "Tamaño del texto",
|
||||||
|
"Decrease": "Disminuir",
|
||||||
|
"Increase": "Aumentar",
|
||||||
|
"IndentationAmount": "Cantidad de indentación",
|
||||||
|
"Autosave": "Grabar automáticamente",
|
||||||
|
"On": "Activar",
|
||||||
|
"Off": "Desactivar",
|
||||||
|
"SketchSettings": "Configuración del bosquejo",
|
||||||
|
"SecurityProtocol": "Protocolo de seguridad",
|
||||||
|
"ServeOverHTTPS": "Usar HTTPS",
|
||||||
|
"Accessibility": "Accesibilidad",
|
||||||
|
"LintWarningSound": "Sonido de alarma Lint",
|
||||||
|
"PreviewSound": "Probar sonido",
|
||||||
|
"AccessibleTextBasedCanvas": "Lienzo accesible por texto",
|
||||||
|
"UsedScreenReader": "Uso con screen reader",
|
||||||
|
"PlainText": "Texto sin formato",
|
||||||
|
"TableText": "Tablero de texto",
|
||||||
|
"Sound": "Sonido",
|
||||||
|
"WordWrap": "Ajuste automático de línea",
|
||||||
|
"LineNumbers": "Número de línea",
|
||||||
|
"LangChange": "Lenguaje cambiado",
|
||||||
|
"Welcome": "Bienvenida",
|
||||||
|
"Login": "Ingresa",
|
||||||
|
"LoginOr": "o",
|
||||||
|
"SignUp": "registráte",
|
||||||
|
"email": "correo electrónico",
|
||||||
|
"username": "nombre de usuario",
|
||||||
|
"LoginGithub": "Ingresa con Github",
|
||||||
|
"LoginGoogle": "Ingresa con Google",
|
||||||
|
"DontHaveAccount": "No tienes cuenta?",
|
||||||
|
"ForgotPassword": "¿Olvidaste tu contraseña?",
|
||||||
|
"ResetPassword": "Regenera tu contraseña",
|
||||||
|
"BackEditor": "Regresa al editor",
|
||||||
|
"UsernameSplit": "Nombre de usuario",
|
||||||
|
"Password": "Contraseña",
|
||||||
|
"ConfirmPassword": "Confirma la contraseña",
|
||||||
|
"OpenedNewSketch": "Creaste nuevo bosquejo.",
|
||||||
|
"Hello": "Hola",
|
||||||
|
"MyAccount": "Mi Cuenta",
|
||||||
|
"My": "Mi",
|
||||||
|
"MySketches": "Mis bosquejos",
|
||||||
|
"MyCollections":"Mis colecciones",
|
||||||
|
"Asset": "Asset",
|
||||||
|
"MyAssets": "Mis assets",
|
||||||
|
"TitleAbout": "Editor Web p5.js | Acerca de",
|
||||||
|
"CodeEditing": "Editando Código",
|
||||||
|
"Error": "Error",
|
||||||
|
"In order to save": "Para guardar",
|
||||||
|
"you must be logged in": "debes ingresar a tu cuenta",
|
||||||
|
"Please": "Por favor",
|
||||||
|
"Find in files": "Encontrar en archivos",
|
||||||
|
"Create": "Create",
|
||||||
|
"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."
|
||||||
|
}
|
Loading…
Reference in a new issue