Skip to content

Commit 236cdac

Browse files
authored
Spanish Translation Account form and New Password (#1547)
* Translations From ReduxFormUtils * Translations for Account, AiKey and New Password * NewPasswordForm
1 parent ff40de3 commit 236cdac

File tree

8 files changed

+187
-66
lines changed

8 files changed

+187
-66
lines changed

client/modules/User/components/APIKeyForm.jsx

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import PropTypes from 'prop-types';
22
import React from 'react';
3-
43
import Button from '../../../common/Button';
54
import { PlusIcon } from '../../../common/icons';
65
import CopyableInput from '../../IDE/components/CopyableInput';
@@ -12,7 +11,7 @@ export const APIKeyPropType = PropTypes.shape({
1211
token: PropTypes.object,
1312
label: PropTypes.string.isRequired,
1413
createdAt: PropTypes.string.isRequired,
15-
lastUsedAt: PropTypes.string,
14+
lastUsedAt: PropTypes.string
1615
});
1716

1817
class APIKeyForm extends React.Component {
@@ -39,7 +38,7 @@ class APIKeyForm extends React.Component {
3938
}
4039

4140
removeKey(key) {
42-
const message = `Are you sure you want to delete "${key.label}"?`;
41+
const message = this.props.t('APIKeyForm.ConfirmDelete', { key_label: key.label });
4342

4443
if (window.confirm(message)) {
4544
this.props.removeApiKey(key.id);
@@ -51,10 +50,10 @@ class APIKeyForm extends React.Component {
5150

5251
if (hasApiKeys) {
5352
return (
54-
<APIKeyList apiKeys={this.props.apiKeys} onRemove={this.removeKey} />
53+
<APIKeyList apiKeys={this.props.apiKeys} onRemove={this.removeKey} t={this.props.t} />
5554
);
5655
}
57-
return <p>You have no exsiting tokens.</p>;
56+
return <p>{this.props.t('APIKeyForm.NoTokens')}</p>;
5857
}
5958

6059
render() {
@@ -63,20 +62,18 @@ class APIKeyForm extends React.Component {
6362
return (
6463
<div className="api-key-form">
6564
<p className="api-key-form__summary">
66-
Personal Access Tokens act like your password to allow automated
67-
scripts to access the Editor API. Create a token for each script
68-
that needs access.
65+
{this.props.t('APIKeyForm.Summary')}
6966
</p>
7067

7168
<div className="api-key-form__section">
72-
<h3 className="api-key-form__title">Create new token</h3>
69+
<h3 className="api-key-form__title">{this.props.t('APIKeyForm.CreateToken')}</h3>
7370
<form className="form form--inline" onSubmit={this.addKey}>
74-
<label htmlFor="keyLabel" className="form__label form__label--hidden ">What is this token for?</label>
71+
<label htmlFor="keyLabel" className="form__label form__label--hidden ">{this.props.t('APIKeyForm.TokenLabel')}</label>
7572
<input
7673
className="form__input"
7774
id="keyLabel"
7875
onChange={(event) => { this.setState({ keyLabel: event.target.value }); }}
79-
placeholder="What is this token for? e.g. Example import script"
76+
placeholder={this.props.t('APIKeyForm.TokenPlaceholder')}
8077
type="text"
8178
value={this.state.keyLabel}
8279
/>
@@ -86,17 +83,16 @@ class APIKeyForm extends React.Component {
8683
label="Create new key"
8784
type="submit"
8885
>
89-
Create
86+
{this.props.t('APIKeyForm.CreateTokenSubmit')}
9087
</Button>
9188
</form>
9289

9390
{
9491
keyWithToken && (
9592
<div className="api-key-form__new-token">
96-
<h4 className="api-key-form__new-token__title">Your new access token</h4>
93+
<h4 className="api-key-form__new-token__title">{this.props.t('APIKeyForm.NewTokenTitle')}</h4>
9794
<p className="api-key-form__new-token__info">
98-
Make sure to copy your new personal access token now.
99-
You won’t be able to see it again!
95+
{this.props.t('APIKeyForm.NewTokenInfo')}
10096
</p>
10197
<CopyableInput label={keyWithToken.label} value={keyWithToken.token} />
10298
</div>
@@ -105,7 +101,7 @@ class APIKeyForm extends React.Component {
105101
</div>
106102

107103
<div className="api-key-form__section">
108-
<h3 className="api-key-form__title">Existing tokens</h3>
104+
<h3 className="api-key-form__title">{this.props.t('APIKeyForm.ExistingTokensTitle')}</h3>
109105
{this.renderApiKeys()}
110106
</div>
111107
</div>
@@ -117,6 +113,7 @@ APIKeyForm.propTypes = {
117113
apiKeys: PropTypes.arrayOf(PropTypes.shape(APIKeyPropType)).isRequired,
118114
createApiKey: PropTypes.func.isRequired,
119115
removeApiKey: PropTypes.func.isRequired,
116+
t: PropTypes.func.isRequired
120117
};
121118

122119
export default APIKeyForm;

client/modules/User/components/APIKeyList.jsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,22 @@ import { APIKeyPropType } from './APIKeyForm';
88

99
import TrashCanIcon from '../../../images/trash-can.svg';
1010

11-
function APIKeyList({ apiKeys, onRemove }) {
11+
function APIKeyList({ apiKeys, onRemove, t }) {
1212
return (
1313
<table className="api-key-list">
1414
<thead>
1515
<tr>
16-
<th>Name</th>
17-
<th>Created on</th>
18-
<th>Last used</th>
19-
<th>Actions</th>
16+
<th>{t('APIKeyList.Name')}</th>
17+
<th>{t('APIKeyList.Created')}</th>
18+
<th>{t('APIKeyList.LastUsed')}</th>
19+
<th>{t('APIKeyList.Actions')}</th>
2020
</tr>
2121
</thead>
2222
<tbody>
2323
{orderBy(apiKeys, ['createdAt'], ['desc']).map((key) => {
2424
const lastUsed = key.lastUsedAt ?
2525
distanceInWordsToNow(new Date(key.lastUsedAt), { addSuffix: true }) :
26-
'Never';
26+
t('APIKeyList.Never');
2727

2828
return (
2929
<tr key={key.id}>
@@ -34,7 +34,7 @@ function APIKeyList({ apiKeys, onRemove }) {
3434
<button
3535
className="api-key-list__delete-button"
3636
onClick={() => onRemove(key)}
37-
aria-label="Delete API Key"
37+
aria-label={t('APIKeyList.DeleteARIA')}
3838
>
3939
<TrashCanIcon focusable="false" aria-hidden="true" />
4040
</button>
@@ -50,6 +50,7 @@ function APIKeyList({ apiKeys, onRemove }) {
5050
APIKeyList.propTypes = {
5151
apiKeys: PropTypes.arrayOf(PropTypes.shape(APIKeyPropType)).isRequired,
5252
onRemove: PropTypes.func.isRequired,
53+
t: PropTypes.func.isRequired
5354
};
5455

5556
export default APIKeyList;

client/modules/User/components/AccountForm.jsx

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import PropTypes from 'prop-types';
22
import React from 'react';
3+
import { withTranslation } from 'react-i18next';
34
import { domOnlyProps } from '../../../utils/reduxFormUtils';
45
import Button from '../../../common/Button';
56

@@ -13,7 +14,8 @@ function AccountForm(props) {
1314
initiateVerification,
1415
submitting,
1516
invalid,
16-
pristine
17+
pristine,
18+
t
1719
} = props;
1820

1921
const handleInitiateVerification = (evt) => {
@@ -24,10 +26,10 @@ function AccountForm(props) {
2426
return (
2527
<form className="form" onSubmit={handleSubmit(props.updateSettings)}>
2628
<p className="form__field">
27-
<label htmlFor="email" className="form__label">Email</label>
29+
<label htmlFor="email" className="form__label">{t('AccountForm.Email')}</label>
2830
<input
2931
className="form__input"
30-
aria-label="email"
32+
aria-label={t('AccountForm.EmailARIA')}
3133
type="text"
3234
id="email"
3335
{...domOnlyProps(email)}
@@ -38,27 +40,27 @@ function AccountForm(props) {
3840
user.verified !== 'verified' &&
3941
(
4042
<p className="form__context">
41-
<span className="form__status">Unconfirmed.</span>
43+
<span className="form__status">{t('AccountForm.Unconfirmed')}</span>
4244
{
4345
user.emailVerificationInitiate === true ?
4446
(
45-
<span className="form__status"> Confirmation sent, check your email.</span>
47+
<span className="form__status"> {t('AccountForm.EmailSent')}</span>
4648
) :
4749
(
4850
<Button
4951
onClick={handleInitiateVerification}
50-
>Resend confirmation email
52+
>{t('AccountForm.Resend')}
5153
</Button>
5254
)
5355
}
5456
</p>
5557
)
5658
}
5759
<p className="form__field">
58-
<label htmlFor="username" className="form__label">User Name</label>
60+
<label htmlFor="username" className="form__label">{t('AccountForm.UserName')}</label>
5961
<input
6062
className="form__input"
61-
aria-label="username"
63+
aria-label={t('AccountForm.UserNameARIA')}
6264
type="text"
6365
id="username"
6466
defaultValue={username}
@@ -67,10 +69,10 @@ function AccountForm(props) {
6769
{username.touched && username.error && <span className="form-error">{username.error}</span>}
6870
</p>
6971
<p className="form__field">
70-
<label htmlFor="current password" className="form__label">Current Password</label>
72+
<label htmlFor="current password" className="form__label">{t('AccountForm.CurrentPassword')}</label>
7173
<input
7274
className="form__input"
73-
aria-label="currentPassword"
75+
aria-label={t('AccountForm.CurrentPasswordARIA')}
7476
type="password"
7577
id="currentPassword"
7678
{...domOnlyProps(currentPassword)}
@@ -82,10 +84,10 @@ function AccountForm(props) {
8284
}
8385
</p>
8486
<p className="form__field">
85-
<label htmlFor="new password" className="form__label">New Password</label>
87+
<label htmlFor="new password" className="form__label">{t('AccountForm.NewPassword')}</label>
8688
<input
8789
className="form__input"
88-
aria-label="newPassword"
90+
aria-label={t('AccountForm.NewPasswordARIA')}
8991
type="password"
9092
id="newPassword"
9193
{...domOnlyProps(newPassword)}
@@ -95,7 +97,7 @@ function AccountForm(props) {
9597
<Button
9698
type="submit"
9799
disabled={submitting || invalid || pristine}
98-
>Save All Settings
100+
>{t('AccountForm.SubmitSaveAllSettings')}
99101
</Button>
100102
</form>
101103
);
@@ -118,6 +120,7 @@ AccountForm.propTypes = {
118120
submitting: PropTypes.bool,
119121
invalid: PropTypes.bool,
120122
pristine: PropTypes.bool,
123+
t: PropTypes.func.isRequired
121124
};
122125

123126
AccountForm.defaultProps = {
@@ -126,4 +129,4 @@ AccountForm.defaultProps = {
126129
invalid: false
127130
};
128131

129-
export default AccountForm;
132+
export default withTranslation()(AccountForm);

client/modules/User/components/NewPasswordForm.jsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,33 @@
11
import PropTypes from 'prop-types';
22
import React from 'react';
3-
3+
import { withTranslation } from 'react-i18next';
44
import { domOnlyProps } from '../../../utils/reduxFormUtils';
55
import Button from '../../../common/Button';
66

77
function NewPasswordForm(props) {
88
const {
9-
fields: { password, confirmPassword }, handleSubmit, submitting, invalid, pristine
9+
fields: { password, confirmPassword }, handleSubmit, submitting, invalid, pristine,
10+
t
1011
} = props;
1112
return (
1213
<form className="form" onSubmit={handleSubmit(props.updatePassword.bind(this, props.params.reset_password_token))}>
1314
<p className="form__field">
14-
<label htmlFor="password" className="form__label">Password</label>
15+
<label htmlFor="password" className="form__label">{t('NewPasswordForm.Title')}</label>
1516
<input
1617
className="form__input"
17-
aria-label="password"
18+
aria-label={t('NewPasswordForm.TitleARIA')}
1819
type="password"
1920
id="Password"
2021
{...domOnlyProps(password)}
2122
/>
2223
{password.touched && password.error && <span className="form-error">{password.error}</span>}
2324
</p>
2425
<p className="form__field">
25-
<label htmlFor="confirm password" className="form__label">Confirm Password</label>
26+
<label htmlFor="confirm password" className="form__label">{t('NewPasswordForm.ConfirmPassword')}</label>
2627
<input
2728
className="form__input"
2829
type="password"
29-
aria-label="confirm password"
30+
aria-label={t('NewPasswordForm.ConfirmPasswordARIA')}
3031
id="confirm password"
3132
{...domOnlyProps(confirmPassword)}
3233
/>
@@ -36,7 +37,7 @@ function NewPasswordForm(props) {
3637
<span className="form-error">{confirmPassword.error}</span>
3738
}
3839
</p>
39-
<Button type="submit" disabled={submitting || invalid || pristine}>Set New Password</Button>
40+
<Button type="submit" disabled={submitting || invalid || pristine}>{t('NewPasswordForm.SubmitSetNewPassword')}</Button>
4041
</form>
4142
);
4243
}
@@ -54,6 +55,7 @@ NewPasswordForm.propTypes = {
5455
params: PropTypes.shape({
5556
reset_password_token: PropTypes.string,
5657
}).isRequired,
58+
t: PropTypes.func.isRequired
5759
};
5860

5961
NewPasswordForm.defaultProps = {
@@ -62,4 +64,4 @@ NewPasswordForm.defaultProps = {
6264
submitting: false
6365
};
6466

65-
export default NewPasswordForm;
67+
export default withTranslation()(NewPasswordForm);

client/modules/User/pages/AccountView.jsx

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { reduxForm } from 'redux-form';
44
import { bindActionCreators } from 'redux';
55
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
66
import { Helmet } from 'react-helmet';
7+
import { withTranslation } from 'react-i18next';
78
import { updateSettings, initiateVerification, createApiKey, removeApiKey } from '../actions';
89
import AccountForm from '../components/AccountForm';
910
import apiClient from '../../../utils/apiClient';
@@ -16,9 +17,11 @@ function SocialLoginPanel(props) {
1617
return (
1718
<React.Fragment>
1819
<AccountForm {...props} />
19-
<h2 className="form-container__divider">Social Login</h2>
20+
{/* eslint-disable-next-line react/prop-types */}
21+
<h2 className="form-container__divider">{props.t('AccountView.SocialLogin')}</h2>
2022
<p className="account__social-text">
21-
Use your GitHub or Google account to log into the p5.js Web Editor.
23+
{/* eslint-disable-next-line react/prop-types */}
24+
{props.t('AccountView.SocialLoginDescription')}
2225
</p>
2326
<div className="account__social-stack">
2427
<SocialAuthButton service={SocialAuthButton.services.github} />
@@ -39,21 +42,21 @@ class AccountView extends React.Component {
3942
return (
4043
<div className="account-settings__container">
4144
<Helmet>
42-
<title>p5.js Web Editor | Account Settings</title>
45+
<title>{this.props.t('AccountView.Title')}</title>
4346
</Helmet>
4447

4548
<Nav layout="dashboard" />
4649

4750
<main className="account-settings">
4851
<header className="account-settings__header">
49-
<h1 className="account-settings__title">Account Settings</h1>
52+
<h1 className="account-settings__title">{this.props.t('AccountView.Settings')}</h1>
5053
</header>
5154
{accessTokensUIEnabled &&
5255
<Tabs className="account__tabs">
5356
<TabList>
5457
<div className="tabs__titles">
55-
<Tab><h4 className="tabs__title">Account</h4></Tab>
56-
{accessTokensUIEnabled && <Tab><h4 className="tabs__title">Access Tokens</h4></Tab>}
58+
<Tab><h4 className="tabs__title">{this.props.t('AccountView.AccountTab')}</h4></Tab>
59+
{accessTokensUIEnabled && <Tab><h4 className="tabs__title">{this.props.t('AccountView.AccessTokensTab')}</h4></Tab>}
5760
</div>
5861
</TabList>
5962
<TabPanel>
@@ -107,13 +110,14 @@ function asyncValidate(formProps, dispatch, props) {
107110

108111
AccountView.propTypes = {
109112
previousPath: PropTypes.string.isRequired,
110-
theme: PropTypes.string.isRequired
113+
theme: PropTypes.string.isRequired,
114+
t: PropTypes.func.isRequired
111115
};
112116

113-
export default reduxForm({
117+
export default withTranslation()(reduxForm({
114118
form: 'updateAllSettings',
115119
fields: ['username', 'email', 'currentPassword', 'newPassword'],
116120
validate: validateSettings,
117121
asyncValidate,
118122
asyncBlurFields: ['username', 'email', 'currentPassword']
119-
}, mapStateToProps, mapDispatchToProps)(AccountView);
123+
}, mapStateToProps, mapDispatchToProps)(AccountView));

0 commit comments

Comments
 (0)