Skip to content

Commit f918669

Browse files
authored
Spanish Translation: Copyable/Editable/AddRemove/SearchBar/PreviewNav (#1569)
* AddRemoveButton Translation * CopyableInput EditableInput translations.json * Translation in PreviewNav.jsx * Translation in Feedback.jsx * Translation in AssetList.jsx * Translation in SearchBarComponent * Translations.json merged * Translations.json AddRemoved, feedback and Preview Nav
1 parent af1a5cc commit f918669

File tree

11 files changed

+136
-35
lines changed

11 files changed

+136
-35
lines changed

client/components/AddRemoveButton.jsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import React from 'react';
22
import PropTypes from 'prop-types';
3+
import { withTranslation } from 'react-i18next';
4+
35

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

7-
const AddRemoveButton = ({ type, onClick }) => {
8-
const alt = type === 'add' ? 'Add to collection' : 'Remove from collection';
9+
const AddRemoveButton = ({ type, onClick, t }) => {
10+
const alt = type === 'add' ? t('AddRemoveButton.AltAddARIA') : t('AddRemoveButton.AltRemoveARIA');
911
const Icon = type === 'add' ? AddIcon : RemoveIcon;
1012

1113
return (
@@ -22,6 +24,7 @@ const AddRemoveButton = ({ type, onClick }) => {
2224
AddRemoveButton.propTypes = {
2325
type: PropTypes.oneOf(['add', 'remove']).isRequired,
2426
onClick: PropTypes.func.isRequired,
27+
t: PropTypes.func.isRequired
2528
};
2629

27-
export default AddRemoveButton;
30+
export default withTranslation()(AddRemoveButton);

client/components/PreviewNav.jsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
import PropTypes from 'prop-types';
22
import React from 'react';
33
import { Link } from 'react-router';
4+
import { withTranslation } from 'react-i18next';
45

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

8-
const PreviewNav = ({ owner, project }) => (
9+
const PreviewNav = ({ owner, project, t }) => (
910
<nav className="nav preview-nav">
1011
<div className="nav__items-left">
1112
<div className="nav__item-logo">
12-
<LogoIcon role="img" aria-label="p5.js Logo" focusable="false" className="svg__logo" />
13+
<LogoIcon role="img" aria-label={t('Common.p5logoARIA')} focusable="false" className="svg__logo" />
1314
</div>
1415
<Link className="nav__item" to={`/${owner.username}/sketches/${project.id}`}>{project.name}</Link>
15-
<p className="toolbar__project-owner">by</p>
16+
<p className="toolbar__project-owner">{t('PreviewNav.ByUser')}</p>
1617
<Link className="nav__item" to={`/${owner.username}/sketches/`}>{owner.username}</Link>
1718
</div>
1819
<div className="nav__items-right">
19-
<Link to={`/${owner.username}/sketches/${project.id}`} aria-label="Edit Sketch" >
20+
<Link to={`/${owner.username}/sketches/${project.id}`} aria-label={t('PreviewNav.EditSketchARIA')} >
2021
<CodeIcon className="preview-nav__editor-svg" focusable="false" aria-hidden="true" />
2122
</Link>
2223
</div>
@@ -31,6 +32,7 @@ PreviewNav.propTypes = {
3132
name: PropTypes.string.isRequired,
3233
id: PropTypes.string.isRequired,
3334
}).isRequired,
35+
t: PropTypes.func.isRequired
3436
};
3537

36-
export default PreviewNav;
38+
export default withTranslation()(PreviewNav);

client/modules/IDE/components/AssetList.jsx

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { bindActionCreators } from 'redux';
55
import { Link } from 'react-router';
66
import { Helmet } from 'react-helmet';
77
import prettyBytes from 'pretty-bytes';
8+
import { withTranslation } from 'react-i18next';
89

910
import Loader from '../../App/components/loader';
1011
import * as AssetActions from '../actions/assets';
@@ -85,7 +86,7 @@ class AssetListRowBase extends React.Component {
8586
onClick={this.toggleOptions}
8687
onBlur={this.onBlurComponent}
8788
onFocus={this.onFocusComponent}
88-
aria-label="Toggle Open/Close Asset Options"
89+
aria-label={this.props.t('AssetList.ToggleOpenCloseARIA')}
8990
>
9091
<DownFilledTriangleIcon focusable="false" aria-hidden="true" />
9192
</button>
@@ -100,7 +101,7 @@ class AssetListRowBase extends React.Component {
100101
onBlur={this.onBlurComponent}
101102
onFocus={this.onFocusComponent}
102103
>
103-
Delete
104+
{this.props.t('AssetList.Delete')}
104105
</button>
105106
</li>
106107
<li>
@@ -111,7 +112,7 @@ class AssetListRowBase extends React.Component {
111112
onFocus={this.onFocusComponent}
112113
className="asset-table__action-option"
113114
>
114-
Open in New Tab
115+
{this.props.t('AssetList.OpenNewTab')}
115116
</Link>
116117
</li>
117118
</ul>}
@@ -131,7 +132,8 @@ AssetListRowBase.propTypes = {
131132
size: PropTypes.number.isRequired
132133
}).isRequired,
133134
deleteAssetRequest: PropTypes.func.isRequired,
134-
username: PropTypes.string.isRequired
135+
username: PropTypes.string.isRequired,
136+
t: PropTypes.func.isRequired
135137
};
136138

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

155157
getAssetsTitle() {
156-
return 'p5.js Web Editor | My assets';
158+
return this.props.t('AssetList.Title');
157159
}
158160

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

168170
renderEmptyTable() {
169171
if (!this.props.loading && this.props.assetList.length === 0) {
170-
return (<p className="asset-table__empty">No uploaded assets.</p>);
172+
return (<p className="asset-table__empty">{this.props.t('AssetList.NoUploadedAssets')}</p>);
171173
}
172174
return null;
173175
}
174176

175177
render() {
176-
const { assetList } = this.props;
178+
const { assetList, t } = this.props;
177179
return (
178180
<article className="asset-table-container">
179181
<Helmet>
@@ -185,9 +187,9 @@ class AssetList extends React.Component {
185187
<table className="asset-table">
186188
<thead>
187189
<tr>
188-
<th>Name</th>
189-
<th>Size</th>
190-
<th>Sketch</th>
190+
<th>{t('AssetList.HeaderName')}</th>
191+
<th>{t('AssetList.HeaderSize')}</th>
192+
<th>{t('AssetList.HeaderSketch')}</th>
191193
<th scope="col"></th>
192194
</tr>
193195
</thead>
@@ -212,7 +214,8 @@ AssetList.propTypes = {
212214
sketchId: PropTypes.string
213215
})).isRequired,
214216
getAssets: PropTypes.func.isRequired,
215-
loading: PropTypes.bool.isRequired
217+
loading: PropTypes.bool.isRequired,
218+
t: PropTypes.func.isRequired
216219
};
217220

218221
function mapStateToProps(state) {
@@ -227,4 +230,4 @@ function mapDispatchToProps(dispatch) {
227230
return bindActionCreators(Object.assign({}, AssetActions), dispatch);
228231
}
229232

230-
export default connect(mapStateToProps, mapDispatchToProps)(AssetList);
233+
export default withTranslation()(connect(mapStateToProps, mapDispatchToProps)(AssetList));

client/modules/IDE/components/CopyableInput.jsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
22
import React from 'react';
33
import Clipboard from 'clipboard';
44
import classNames from 'classnames';
5+
import { withTranslation } from 'react-i18next';
56

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

@@ -45,7 +46,7 @@ class CopyableInput extends React.Component {
4546
<div className={copyableInputClass}>
4647
<div
4748
className="copyable-input__value-container tooltipped-no-delay"
48-
aria-label="Copied to Clipboard!"
49+
aria-label={this.props.t('CopyableInput.CopiedARIA')}
4950
ref={(element) => { this.tooltip = element; }}
5051
onMouseLeave={this.onMouseLeaveHandler}
5152
>
@@ -69,7 +70,7 @@ class CopyableInput extends React.Component {
6970
rel="noopener noreferrer"
7071
href={value}
7172
className="copyable-input__preview"
72-
aria-label={`Open ${label} view in new tab`}
73+
aria-label={this.props.t('CopyableInput.CopiedARIA', { label })}
7374
>
7475
<ShareIcon focusable="false" aria-hidden="true" />
7576
</a>
@@ -82,11 +83,12 @@ class CopyableInput extends React.Component {
8283
CopyableInput.propTypes = {
8384
label: PropTypes.string.isRequired,
8485
value: PropTypes.string.isRequired,
85-
hasPreviewLink: PropTypes.bool
86+
hasPreviewLink: PropTypes.bool,
87+
t: PropTypes.func.isRequired
8688
};
8789

8890
CopyableInput.defaultProps = {
8991
hasPreviewLink: false
9092
};
9193

92-
export default CopyableInput;
94+
export default withTranslation()(CopyableInput);

client/modules/IDE/components/EditableInput.jsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import PropTypes from 'prop-types';
22
import React from 'react';
3-
3+
import { withTranslation } from 'react-i18next';
4+
import i18next from 'i18next';
45
import EditIcon from '../../../images/pencil.svg';
56

7+
68
// TODO I think this needs a description prop so that it's accessible
79
function EditableInput({
810
validate,
@@ -58,7 +60,7 @@ function EditableInput({
5860
<button
5961
className="editable-input__label"
6062
onClick={beginEditing}
61-
aria-label={`Edit ${displayValue} value`}
63+
aria-label={this.props.t('EditableInput.EditValue', { display: displayValue })}
6264
>
6365
<span>{displayValue}</span>
6466
<EditIcon
@@ -84,7 +86,7 @@ function EditableInput({
8486
}
8587

8688
EditableInput.defaultProps = {
87-
emptyPlaceholder: 'No value',
89+
emptyPlaceholder: i18next.t('EditableInput.EmptyPlaceholder'),
8890
InputComponent: 'input',
8991
inputProps: {},
9092
validate: () => true,
@@ -99,6 +101,7 @@ EditableInput.propTypes = {
99101
onChange: PropTypes.func.isRequired,
100102
validate: PropTypes.func,
101103
value: PropTypes.string,
104+
t: PropTypes.func.isRequired
102105
};
103106

104-
export default EditableInput;
107+
export default withTranslation()(EditableInput);

client/modules/IDE/components/Feedback.jsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import React from 'react';
22
import { Helmet } from 'react-helmet';
3+
import { withTranslation } from 'react-i18next';
34
import GitHubLogo from '../../../images/github.svg';
45

56
function Feedback(props) {
67
return (
78
<div className="feedback__content">
89
<Helmet>
9-
<title>p5.js Web Editor | Feedback</title>
10+
<title>{this.props.t('Feedback.Title')}</title>
1011
</Helmet>
1112
<div className="feedback__content-pane">
1213
<h2 className="feedback__content-pane-header">
@@ -47,4 +48,4 @@ function Feedback(props) {
4748
);
4849
}
4950

50-
export default Feedback;
51+
export default withTranslation()(Feedback);

client/modules/IDE/components/Searchbar/Collection.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import { bindActionCreators } from 'redux';
22
import { connect } from 'react-redux';
3+
import i18next from 'i18next';
34
import * as SortingActions from '../../actions/sorting';
45

56
import Searchbar from './Searchbar';
67

8+
79
const scope = 'collection';
810

911
function mapStateToProps(state) {
1012
return {
11-
searchLabel: 'Search collections...',
13+
searchLabel: i18next.t('Searchbar.SearchCollection'),
1214
searchTerm: state.search[`${scope}SearchTerm`],
1315
};
1416
}

client/modules/IDE/components/Searchbar/Searchbar.jsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import PropTypes from 'prop-types';
22
import React from 'react';
33
import { throttle } from 'lodash';
4-
4+
import { withTranslation } from 'react-i18next';
5+
import i18next from 'i18next';
56
import SearchIcon from '../../../../images/magnifyingglass.svg';
67

8+
79
class Searchbar extends React.Component {
810
constructor(props) {
911
super(props);
@@ -50,7 +52,7 @@ class Searchbar extends React.Component {
5052
<button
5153
className="searchbar__clear-button"
5254
onClick={this.handleResetSearch}
53-
>clear
55+
>{this.props.t('Searchbar.ClearTerm')}
5456
</button>
5557
</div>
5658
);
@@ -62,10 +64,11 @@ Searchbar.propTypes = {
6264
setSearchTerm: PropTypes.func.isRequired,
6365
resetSearchTerm: PropTypes.func.isRequired,
6466
searchLabel: PropTypes.string,
67+
t: PropTypes.func.isRequired
6568
};
6669

6770
Searchbar.defaultProps = {
68-
searchLabel: 'Search sketches...',
71+
searchLabel: i18next.t('Searchbar.SearchSketch')
6972
};
7073

71-
export default Searchbar;
74+
export default withTranslation()(Searchbar);

client/modules/IDE/components/Searchbar/Sketch.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { bindActionCreators } from 'redux';
22
import { connect } from 'react-redux';
3+
import i18next from 'i18next';
34
import * as SortingActions from '../../actions/sorting';
45

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

910
function mapStateToProps(state) {
1011
return {
12+
searchLabel: i18next.t('Searchbar.SearchSketch'),
1113
searchTerm: state.search[`${scope}SearchTerm`],
1214
};
1315
}

translations/locales/en-US/translations.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,30 @@
341341
"Verified": "All done, your email address has been verified.",
342342
"InvalidState": "Something went wrong."
343343
},
344+
"AssetList": {
345+
"Title": "p5.js Web Editor | My assets",
346+
"ToggleOpenCloseARIA": "Toggle Open/Close Asset Options",
347+
"Delete": "Delete",
348+
"OpenNewTab": "Open in New Tab",
349+
"NoUploadedAssets": "No uploaded assets.",
350+
"HeaderName": "Name",
351+
"HeaderSize": "Size",
352+
"HeaderSketch": "Sketch"
353+
},
354+
"Feedback": {
355+
"Title": "p5.js Web Editor | Feedback",
356+
"ViaGithubHeader": "Via Github Issues",
357+
"ViaGithubDescription": "If you're familiar with Github, this is our preferred method for receiving bug reports and feedback.",
358+
"GoToGithub": "Go to Github",
359+
"ViaGoogleHeader": "Via Google Form",
360+
"ViaGoogleDescription": "You can also submit this quick form.",
361+
"GoToForm": "Go to Form"
362+
},
363+
"Searchbar": {
364+
"SearchSketch": "Search sketches...",
365+
"SearchCollection": "Search collections...",
366+
"ClearTerm": "clear"
367+
},
344368
"UploadFileModal": {
345369
"Title": "Upload File",
346370
"CloseButtonARIA": "Close upload file modal",
@@ -491,5 +515,21 @@
491515
"Saved25Seconds": "Saved: 25 seconds ago",
492516
"Saved35Seconds": "Saved: 35 seconds ago",
493517
"SavedAgo": "Saved: {{timeAgo}} ago"
518+
},
519+
"AddRemoveButton": {
520+
"AltAddARIA": "Add to collection",
521+
"AltRemoveARIA": "Remove from collection"
522+
},
523+
"CopyableInput": {
524+
"CopiedARIA": "Copied to Clipboard!",
525+
"OpenViewTabARIA": "Open {{label}} view in new tab"
526+
},
527+
"EditableInput": {
528+
"EditValue": "Edit {{display}} value",
529+
"EmptyPlaceholder": "No value"
530+
},
531+
"PreviewNav": {
532+
"EditSketchARIA": "Edit Sketch",
533+
"ByUser": "by"
494534
}
495535
}

0 commit comments

Comments
 (0)