Skip to content

Spanish Translation: Copyable/Editable/AddRemove/SearchBar/PreviewNav #1569

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Aug 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions client/components/AddRemoveButton.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import React from 'react';
import PropTypes from 'prop-types';
import { withTranslation } from 'react-i18next';


import AddIcon from '../images/plus.svg';
import RemoveIcon from '../images/minus.svg';

const AddRemoveButton = ({ type, onClick }) => {
const alt = type === 'add' ? 'Add to collection' : 'Remove from collection';
const AddRemoveButton = ({ type, onClick, t }) => {
const alt = type === 'add' ? t('AddRemoveButton.AltAddARIA') : t('AddRemoveButton.AltRemoveARIA');
const Icon = type === 'add' ? AddIcon : RemoveIcon;

return (
Expand All @@ -22,6 +24,7 @@ const AddRemoveButton = ({ type, onClick }) => {
AddRemoveButton.propTypes = {
type: PropTypes.oneOf(['add', 'remove']).isRequired,
onClick: PropTypes.func.isRequired,
t: PropTypes.func.isRequired
};

export default AddRemoveButton;
export default withTranslation()(AddRemoveButton);
12 changes: 7 additions & 5 deletions client/components/PreviewNav.jsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import PropTypes from 'prop-types';
import React from 'react';
import { Link } from 'react-router';
import { withTranslation } from 'react-i18next';

import LogoIcon from '../images/p5js-logo-small.svg';
import CodeIcon from '../images/code.svg';

const PreviewNav = ({ owner, project }) => (
const PreviewNav = ({ owner, project, t }) => (
<nav className="nav preview-nav">
<div className="nav__items-left">
<div className="nav__item-logo">
<LogoIcon role="img" aria-label="p5.js Logo" focusable="false" className="svg__logo" />
<LogoIcon role="img" aria-label={t('Common.p5logoARIA')} focusable="false" className="svg__logo" />
</div>
<Link className="nav__item" to={`/${owner.username}/sketches/${project.id}`}>{project.name}</Link>
<p className="toolbar__project-owner">by</p>
<p className="toolbar__project-owner">{t('PreviewNav.ByUser')}</p>
<Link className="nav__item" to={`/${owner.username}/sketches/`}>{owner.username}</Link>
</div>
<div className="nav__items-right">
<Link to={`/${owner.username}/sketches/${project.id}`} aria-label="Edit Sketch" >
<Link to={`/${owner.username}/sketches/${project.id}`} aria-label={t('PreviewNav.EditSketchARIA')} >
<CodeIcon className="preview-nav__editor-svg" focusable="false" aria-hidden="true" />
</Link>
</div>
Expand All @@ -31,6 +32,7 @@ PreviewNav.propTypes = {
name: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
}).isRequired,
t: PropTypes.func.isRequired
};

export default PreviewNav;
export default withTranslation()(PreviewNav);
27 changes: 15 additions & 12 deletions client/modules/IDE/components/AssetList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { bindActionCreators } from 'redux';
import { Link } from 'react-router';
import { Helmet } from 'react-helmet';
import prettyBytes from 'pretty-bytes';
import { withTranslation } from 'react-i18next';

import Loader from '../../App/components/loader';
import * as AssetActions from '../actions/assets';
Expand Down Expand Up @@ -85,7 +86,7 @@ class AssetListRowBase extends React.Component {
onClick={this.toggleOptions}
onBlur={this.onBlurComponent}
onFocus={this.onFocusComponent}
aria-label="Toggle Open/Close Asset Options"
aria-label={this.props.t('AssetList.ToggleOpenCloseARIA')}
>
<DownFilledTriangleIcon focusable="false" aria-hidden="true" />
</button>
Expand All @@ -100,7 +101,7 @@ class AssetListRowBase extends React.Component {
onBlur={this.onBlurComponent}
onFocus={this.onFocusComponent}
>
Delete
{this.props.t('AssetList.Delete')}
</button>
</li>
<li>
Expand All @@ -111,7 +112,7 @@ class AssetListRowBase extends React.Component {
onFocus={this.onFocusComponent}
className="asset-table__action-option"
>
Open in New Tab
{this.props.t('AssetList.OpenNewTab')}
</Link>
</li>
</ul>}
Expand All @@ -131,7 +132,8 @@ AssetListRowBase.propTypes = {
size: PropTypes.number.isRequired
}).isRequired,
deleteAssetRequest: PropTypes.func.isRequired,
username: PropTypes.string.isRequired
username: PropTypes.string.isRequired,
t: PropTypes.func.isRequired
};

function mapStateToPropsAssetListRow(state) {
Expand All @@ -153,7 +155,7 @@ class AssetList extends React.Component {
}

getAssetsTitle() {
return 'p5.js Web Editor | My assets';
return this.props.t('AssetList.Title');
}

hasAssets() {
Expand All @@ -167,13 +169,13 @@ class AssetList extends React.Component {

renderEmptyTable() {
if (!this.props.loading && this.props.assetList.length === 0) {
return (<p className="asset-table__empty">No uploaded assets.</p>);
return (<p className="asset-table__empty">{this.props.t('AssetList.NoUploadedAssets')}</p>);
}
return null;
}

render() {
const { assetList } = this.props;
const { assetList, t } = this.props;
return (
<article className="asset-table-container">
<Helmet>
Expand All @@ -185,9 +187,9 @@ class AssetList extends React.Component {
<table className="asset-table">
<thead>
<tr>
<th>Name</th>
<th>Size</th>
<th>Sketch</th>
<th>{t('AssetList.HeaderName')}</th>
<th>{t('AssetList.HeaderSize')}</th>
<th>{t('AssetList.HeaderSketch')}</th>
<th scope="col"></th>
</tr>
</thead>
Expand All @@ -212,7 +214,8 @@ AssetList.propTypes = {
sketchId: PropTypes.string
})).isRequired,
getAssets: PropTypes.func.isRequired,
loading: PropTypes.bool.isRequired
loading: PropTypes.bool.isRequired,
t: PropTypes.func.isRequired
};

function mapStateToProps(state) {
Expand All @@ -227,4 +230,4 @@ function mapDispatchToProps(dispatch) {
return bindActionCreators(Object.assign({}, AssetActions), dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(AssetList);
export default withTranslation()(connect(mapStateToProps, mapDispatchToProps)(AssetList));
10 changes: 6 additions & 4 deletions client/modules/IDE/components/CopyableInput.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import Clipboard from 'clipboard';
import classNames from 'classnames';
import { withTranslation } from 'react-i18next';

import ShareIcon from '../../../images/share.svg';

Expand Down Expand Up @@ -45,7 +46,7 @@ class CopyableInput extends React.Component {
<div className={copyableInputClass}>
<div
className="copyable-input__value-container tooltipped-no-delay"
aria-label="Copied to Clipboard!"
aria-label={this.props.t('CopyableInput.CopiedARIA')}
ref={(element) => { this.tooltip = element; }}
onMouseLeave={this.onMouseLeaveHandler}
>
Expand All @@ -69,7 +70,7 @@ class CopyableInput extends React.Component {
rel="noopener noreferrer"
href={value}
className="copyable-input__preview"
aria-label={`Open ${label} view in new tab`}
aria-label={this.props.t('CopyableInput.CopiedARIA', { label })}
>
<ShareIcon focusable="false" aria-hidden="true" />
</a>
Expand All @@ -82,11 +83,12 @@ class CopyableInput extends React.Component {
CopyableInput.propTypes = {
label: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
hasPreviewLink: PropTypes.bool
hasPreviewLink: PropTypes.bool,
t: PropTypes.func.isRequired
};

CopyableInput.defaultProps = {
hasPreviewLink: false
};

export default CopyableInput;
export default withTranslation()(CopyableInput);
11 changes: 7 additions & 4 deletions client/modules/IDE/components/EditableInput.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import PropTypes from 'prop-types';
import React from 'react';

import { withTranslation } from 'react-i18next';
import i18next from 'i18next';
import EditIcon from '../../../images/pencil.svg';


// TODO I think this needs a description prop so that it's accessible
function EditableInput({
validate,
Expand Down Expand Up @@ -58,7 +60,7 @@ function EditableInput({
<button
className="editable-input__label"
onClick={beginEditing}
aria-label={`Edit ${displayValue} value`}
aria-label={this.props.t('EditableInput.EditValue', { display: displayValue })}
>
<span>{displayValue}</span>
<EditIcon
Expand All @@ -84,7 +86,7 @@ function EditableInput({
}

EditableInput.defaultProps = {
emptyPlaceholder: 'No value',
emptyPlaceholder: i18next.t('EditableInput.EmptyPlaceholder'),
InputComponent: 'input',
inputProps: {},
validate: () => true,
Expand All @@ -99,6 +101,7 @@ EditableInput.propTypes = {
onChange: PropTypes.func.isRequired,
validate: PropTypes.func,
value: PropTypes.string,
t: PropTypes.func.isRequired
};

export default EditableInput;
export default withTranslation()(EditableInput);
5 changes: 3 additions & 2 deletions client/modules/IDE/components/Feedback.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React from 'react';
import { Helmet } from 'react-helmet';
import { withTranslation } from 'react-i18next';
import GitHubLogo from '../../../images/github.svg';

function Feedback(props) {
return (
<div className="feedback__content">
<Helmet>
<title>p5.js Web Editor | Feedback</title>
<title>{this.props.t('Feedback.Title')}</title>
</Helmet>
<div className="feedback__content-pane">
<h2 className="feedback__content-pane-header">
Expand Down Expand Up @@ -47,4 +48,4 @@ function Feedback(props) {
);
}

export default Feedback;
export default withTranslation()(Feedback);
4 changes: 3 additions & 1 deletion client/modules/IDE/components/Searchbar/Collection.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import i18next from 'i18next';
import * as SortingActions from '../../actions/sorting';

import Searchbar from './Searchbar';


const scope = 'collection';

function mapStateToProps(state) {
return {
searchLabel: 'Search collections...',
searchLabel: i18next.t('Searchbar.SearchCollection'),
searchTerm: state.search[`${scope}SearchTerm`],
};
}
Expand Down
11 changes: 7 additions & 4 deletions client/modules/IDE/components/Searchbar/Searchbar.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import PropTypes from 'prop-types';
import React from 'react';
import { throttle } from 'lodash';

import { withTranslation } from 'react-i18next';
import i18next from 'i18next';
import SearchIcon from '../../../../images/magnifyingglass.svg';


class Searchbar extends React.Component {
constructor(props) {
super(props);
Expand Down Expand Up @@ -50,7 +52,7 @@ class Searchbar extends React.Component {
<button
className="searchbar__clear-button"
onClick={this.handleResetSearch}
>clear
>{this.props.t('Searchbar.ClearTerm')}
</button>
</div>
);
Expand All @@ -62,10 +64,11 @@ Searchbar.propTypes = {
setSearchTerm: PropTypes.func.isRequired,
resetSearchTerm: PropTypes.func.isRequired,
searchLabel: PropTypes.string,
t: PropTypes.func.isRequired
};

Searchbar.defaultProps = {
searchLabel: 'Search sketches...',
searchLabel: i18next.t('Searchbar.SearchSketch')
};

export default Searchbar;
export default withTranslation()(Searchbar);
2 changes: 2 additions & 0 deletions client/modules/IDE/components/Searchbar/Sketch.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import i18next from 'i18next';
import * as SortingActions from '../../actions/sorting';

import Searchbar from './Searchbar';
Expand All @@ -8,6 +9,7 @@ const scope = 'sketch';

function mapStateToProps(state) {
return {
searchLabel: i18next.t('Searchbar.SearchSketch'),
searchTerm: state.search[`${scope}SearchTerm`],
};
}
Expand Down
40 changes: 40 additions & 0 deletions translations/locales/en-US/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,30 @@
"Verified": "All done, your email address has been verified.",
"InvalidState": "Something went wrong."
},
"AssetList": {
"Title": "p5.js Web Editor | My assets",
"ToggleOpenCloseARIA": "Toggle Open/Close Asset Options",
"Delete": "Delete",
"OpenNewTab": "Open in New Tab",
"NoUploadedAssets": "No uploaded assets.",
"HeaderName": "Name",
"HeaderSize": "Size",
"HeaderSketch": "Sketch"
},
"Feedback": {
"Title": "p5.js Web Editor | Feedback",
"ViaGithubHeader": "Via Github Issues",
"ViaGithubDescription": "If you're familiar with Github, this is our preferred method for receiving bug reports and feedback.",
"GoToGithub": "Go to Github",
"ViaGoogleHeader": "Via Google Form",
"ViaGoogleDescription": "You can also submit this quick form.",
"GoToForm": "Go to Form"
},
"Searchbar": {
"SearchSketch": "Search sketches...",
"SearchCollection": "Search collections...",
"ClearTerm": "clear"
},
"UploadFileModal": {
"Title": "Upload File",
"CloseButtonARIA": "Close upload file modal",
Expand Down Expand Up @@ -491,5 +515,21 @@
"Saved25Seconds": "Saved: 25 seconds ago",
"Saved35Seconds": "Saved: 35 seconds ago",
"SavedAgo": "Saved: {{timeAgo}} ago"
},
"AddRemoveButton": {
"AltAddARIA": "Add to collection",
"AltRemoveARIA": "Remove from collection"
},
"CopyableInput": {
"CopiedARIA": "Copied to Clipboard!",
"OpenViewTabARIA": "Open {{label}} view in new tab"
},
"EditableInput": {
"EditValue": "Edit {{display}} value",
"EmptyPlaceholder": "No value"
},
"PreviewNav": {
"EditSketchARIA": "Edit Sketch",
"ByUser": "by"
}
}
Loading