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
This commit is contained in:
parent
af1a5cc2f1
commit
f918669116
11 changed files with 136 additions and 35 deletions
|
@ -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 (
|
||||
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
@ -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);
|
||||
|
|
|
@ -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';
|
||||
|
@ -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>
|
||||
|
@ -100,7 +101,7 @@ class AssetListRowBase extends React.Component {
|
|||
onBlur={this.onBlurComponent}
|
||||
onFocus={this.onFocusComponent}
|
||||
>
|
||||
Delete
|
||||
{this.props.t('AssetList.Delete')}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
|
@ -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>}
|
||||
|
@ -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) {
|
||||
|
@ -153,7 +155,7 @@ class AssetList extends React.Component {
|
|||
}
|
||||
|
||||
getAssetsTitle() {
|
||||
return 'p5.js Web Editor | My assets';
|
||||
return this.props.t('AssetList.Title');
|
||||
}
|
||||
|
||||
hasAssets() {
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
@ -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}
|
||||
>
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -84,7 +86,7 @@ function EditableInput({
|
|||
}
|
||||
|
||||
EditableInput.defaultProps = {
|
||||
emptyPlaceholder: 'No value',
|
||||
emptyPlaceholder: i18next.t('EditableInput.EmptyPlaceholder'),
|
||||
InputComponent: 'input',
|
||||
inputProps: {},
|
||||
validate: () => true,
|
||||
|
@ -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);
|
||||
|
|
|
@ -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">
|
||||
|
@ -47,4 +48,4 @@ function Feedback(props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default Feedback;
|
||||
export default withTranslation()(Feedback);
|
||||
|
|
|
@ -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`],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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);
|
||||
|
|
|
@ -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';
|
||||
|
@ -8,6 +9,7 @@ const scope = 'sketch';
|
|||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
searchLabel: i18next.t('Searchbar.SearchSketch'),
|
||||
searchTerm: state.search[`${scope}SearchTerm`],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -341,6 +341,30 @@
|
|||
"Verified": "Concluido, tu correo electrónico ha sido verificado.",
|
||||
"InvalidState": "Algo salió mal."
|
||||
},
|
||||
"AssetList": {
|
||||
"Title": "Editor Web p5.js | Mis assets",
|
||||
"ToggleOpenCloseARIA": "Alternar Abrir/Cerrar Opciones de Asset",
|
||||
"Delete": "Borrar",
|
||||
"OpenNewTab": "Abrir en Nueva Pestaña",
|
||||
"NoUploadedAssets": "No has subido archivos.",
|
||||
"HeaderName": "Nombre",
|
||||
"HeaderSize": "Tamaño",
|
||||
"HeaderSketch": "Bosquejo"
|
||||
},
|
||||
"Feedback": {
|
||||
"Title": "Editor Web p5.js | Retroalimentación",
|
||||
"ViaGithubHeader": "Vía Github Issues",
|
||||
"ViaGithubDescription": " Si estas familiarizado con Github, este es nuestro método favorito para recibir reporte de errores y retroalimentación.",
|
||||
"GoToGithub": "Ir a Github",
|
||||
"ViaGoogleHeader": "Vía Formulario de Google",
|
||||
"ViaGoogleDescription": "También puedes enviar tu retroalimetnación usando esta vía rapida.",
|
||||
"GoToForm": "Ir a Formulario"
|
||||
},
|
||||
"Searchbar": {
|
||||
"SearchSketch": "Buscar en bosquejos...",
|
||||
"SearchCollection": "Buscar en colecciones...",
|
||||
"ClearTerm": "limpiar"
|
||||
},
|
||||
"UploadFileModal": {
|
||||
"Title": "Subir Archivo",
|
||||
"CloseButtonARIA": "Cerrar diálogo para subir archivo",
|
||||
|
@ -491,5 +515,21 @@
|
|||
"Saved25Seconds": "Guardado: hace 25 segundos",
|
||||
"Saved35Seconds": "Guardado: hace 35 segundos",
|
||||
"SavedAgo": "Guardado: hace {{timeAgo}}"
|
||||
},
|
||||
"AddRemoveButton": {
|
||||
"AltAddARIA": "Agregar a colección",
|
||||
"AltRemoveARIA": "Remover de colección"
|
||||
},
|
||||
"CopyableInput": {
|
||||
"CopiedARIA": "¡Copiado en el portapapeles!",
|
||||
"OpenViewTabARIA": "Abrir la vista {{label}} en nueva pestaña"
|
||||
},
|
||||
"EditableInput": {
|
||||
"EditValue": "Editar valor de {{display}}",
|
||||
"EmptyPlaceholder": "Sin valor"
|
||||
},
|
||||
"PreviewNav": {
|
||||
"EditSketchARIA": "Editar Bosquejo",
|
||||
"ByUser": "por"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue