Spanish Translation: Reset password Form and View (#1545)
* Reset Password Form using login view translation keys * reduxFormUtils.js with i18 functionality to translate validations
This commit is contained in:
parent
9694719e02
commit
ff40de36ca
5 changed files with 96 additions and 45 deletions
|
@ -1,20 +1,20 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { withTranslation } from 'react-i18next';
|
||||||
import { domOnlyProps } from '../../../utils/reduxFormUtils';
|
import { domOnlyProps } from '../../../utils/reduxFormUtils';
|
||||||
import Button from '../../../common/Button';
|
import Button from '../../../common/Button';
|
||||||
|
|
||||||
function ResetPasswordForm(props) {
|
function ResetPasswordForm(props) {
|
||||||
const {
|
const {
|
||||||
fields: { email }, handleSubmit, submitting, invalid, pristine
|
fields: { email }, handleSubmit, submitting, invalid, pristine, t
|
||||||
} = props;
|
} = props;
|
||||||
return (
|
return (
|
||||||
<form className="form" onSubmit={handleSubmit(props.initiateResetPassword.bind(this))}>
|
<form className="form" onSubmit={handleSubmit(props.initiateResetPassword.bind(this))}>
|
||||||
<p className="form__field">
|
<p className="form__field">
|
||||||
<label htmlFor="email" className="form__label">Email used for registration</label>
|
<label htmlFor="email" className="form__label">{t('ResetPasswordForm.Email')}</label>
|
||||||
<input
|
<input
|
||||||
className="form__input"
|
className="form__input"
|
||||||
aria-label="email"
|
aria-label={t('ResetPasswordForm.EmailARIA')}
|
||||||
type="text"
|
type="text"
|
||||||
id="email"
|
id="email"
|
||||||
{...domOnlyProps(email)}
|
{...domOnlyProps(email)}
|
||||||
|
@ -24,7 +24,7 @@ function ResetPasswordForm(props) {
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={submitting || invalid || pristine || props.user.resetPasswordInitiate}
|
disabled={submitting || invalid || pristine || props.user.resetPasswordInitiate}
|
||||||
>Send Password Reset Email
|
>{t('ResetPasswordForm.Submit')}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
@ -41,7 +41,8 @@ ResetPasswordForm.propTypes = {
|
||||||
pristine: PropTypes.bool,
|
pristine: PropTypes.bool,
|
||||||
user: PropTypes.shape({
|
user: PropTypes.shape({
|
||||||
resetPasswordInitiate: PropTypes.bool
|
resetPasswordInitiate: PropTypes.bool
|
||||||
}).isRequired
|
}).isRequired,
|
||||||
|
t: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
ResetPasswordForm.defaultProps = {
|
ResetPasswordForm.defaultProps = {
|
||||||
|
@ -50,4 +51,4 @@ ResetPasswordForm.defaultProps = {
|
||||||
invalid: false
|
invalid: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ResetPasswordForm;
|
export default withTranslation()(ResetPasswordForm);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import classNames from 'classnames';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { reduxForm } from 'redux-form';
|
import { reduxForm } from 'redux-form';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
|
import { withTranslation } from 'react-i18next';
|
||||||
import * as UserActions from '../actions';
|
import * as UserActions from '../actions';
|
||||||
import ResetPasswordForm from '../components/ResetPasswordForm';
|
import ResetPasswordForm from '../components/ResetPasswordForm';
|
||||||
import { validateResetPassword } from '../../../utils/reduxFormUtils';
|
import { validateResetPassword } from '../../../utils/reduxFormUtils';
|
||||||
|
@ -23,19 +24,18 @@ function ResetPasswordView(props) {
|
||||||
<Nav layout="dashboard" />
|
<Nav layout="dashboard" />
|
||||||
<div className={resetPasswordClass}>
|
<div className={resetPasswordClass}>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>p5.js Web Editor | Reset Password</title>
|
<title>{props.t('ResetPasswordView.Title')}</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div className="form-container__content">
|
<div className="form-container__content">
|
||||||
<h2 className="form-container__title">Reset Your Password</h2>
|
<h2 className="form-container__title">{props.t('ResetPasswordView.Reset')}</h2>
|
||||||
<ResetPasswordForm {...props} />
|
<ResetPasswordForm {...props} />
|
||||||
<p className="reset-password__submitted">
|
<p className="reset-password__submitted">
|
||||||
Your password reset email should arrive shortly. If you don't see it, check
|
{props.t('ResetPasswordView.Submitted')}
|
||||||
in your spam folder as sometimes it can end up there.
|
|
||||||
</p>
|
</p>
|
||||||
<p className="form__navigation-options">
|
<p className="form__navigation-options">
|
||||||
<Link className="form__login-button" to="/login">Log In</Link>
|
<Link className="form__login-button" to="/login">{props.t('ResetPasswordView.Login')}</Link>
|
||||||
or
|
{props.t('ResetPasswordView.LoginOr')}
|
||||||
<Link className="form__signup-button" to="/signup">Sign Up</Link>
|
<Link className="form__signup-button" to="/signup">{props.t('ResetPasswordView.SignUp')}</Link>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -48,6 +48,7 @@ ResetPasswordView.propTypes = {
|
||||||
user: PropTypes.shape({
|
user: PropTypes.shape({
|
||||||
resetPasswordInitiate: PropTypes.bool
|
resetPasswordInitiate: PropTypes.bool
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
|
t: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
|
@ -60,8 +61,8 @@ function mapDispatchToProps(dispatch) {
|
||||||
return bindActionCreators(UserActions, dispatch);
|
return bindActionCreators(UserActions, dispatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default reduxForm({
|
export default withTranslation()(reduxForm({
|
||||||
form: 'reset-password',
|
form: 'reset-password',
|
||||||
fields: ['email'],
|
fields: ['email'],
|
||||||
validate: validateResetPassword
|
validate: validateResetPassword
|
||||||
}, mapStateToProps, mapDispatchToProps)(ResetPasswordView);
|
}, mapStateToProps, mapDispatchToProps)(ResetPasswordView));
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
|
import i18n from 'i18next';
|
||||||
export const domOnlyProps = ({
|
export const domOnlyProps = ({
|
||||||
initialValue,
|
initialValue,
|
||||||
autofill,
|
autofill,
|
||||||
|
@ -20,19 +21,19 @@ const EMAIL_REGEX = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))
|
||||||
|
|
||||||
function validateNameEmail(formProps, errors) {
|
function validateNameEmail(formProps, errors) {
|
||||||
if (!formProps.username) {
|
if (!formProps.username) {
|
||||||
errors.username = 'Please enter a username.';
|
errors.username = i18n.t('ReduxFormUtils.errorEmptyUsername');
|
||||||
} else if (!formProps.username.match(/^.{1,20}$/)) {
|
} else if (!formProps.username.match(/^.{1,20}$/)) {
|
||||||
errors.username = 'Username must be less than 20 characters.';
|
errors.username = i18n.t('ReduxFormUtils.errorLongUsername');
|
||||||
} else if (!formProps.username.match(/^[a-zA-Z0-9._-]{1,20}$/)) {
|
} else if (!formProps.username.match(/^[a-zA-Z0-9._-]{1,20}$/)) {
|
||||||
errors.username = 'Username must only consist of numbers, letters, periods, dashes, and underscores.';
|
errors.username = i18n.t('ReduxFormUtils.errorValidUsername');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formProps.email) {
|
if (!formProps.email) {
|
||||||
errors.email = 'Please enter an email.';
|
errors.email = i18n.t('ReduxFormUtils.errorEmptyEmail');
|
||||||
} else if (
|
} else if (
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
!formProps.email.match(EMAIL_REGEX)) {
|
!formProps.email.match(EMAIL_REGEX)) {
|
||||||
errors.email = 'Please enter a valid email address.';
|
errors.email = i18n.t('ReduxFormUtils.errorInvalidEmail');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,10 +43,10 @@ export function validateSettings(formProps) {
|
||||||
validateNameEmail(formProps, errors);
|
validateNameEmail(formProps, errors);
|
||||||
|
|
||||||
if (formProps.currentPassword && !formProps.newPassword) {
|
if (formProps.currentPassword && !formProps.newPassword) {
|
||||||
errors.newPassword = 'Please enter a new password or leave the current password empty.';
|
errors.newPassword = i18n.t('ReduxFormUtils.errorNewPassword');
|
||||||
}
|
}
|
||||||
if (formProps.newPassword && formProps.newPassword.length < 6) {
|
if (formProps.newPassword && formProps.newPassword.length < 6) {
|
||||||
errors.newPassword = 'Password must be at least 6 characters';
|
errors.newPassword = i18n.t('ReduxFormUtils.errorShortPassword');
|
||||||
}
|
}
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
@ -53,10 +54,10 @@ export function validateSettings(formProps) {
|
||||||
export function validateLogin(formProps) {
|
export function validateLogin(formProps) {
|
||||||
const errors = {};
|
const errors = {};
|
||||||
if (!formProps.email) {
|
if (!formProps.email) {
|
||||||
errors.email = 'Please enter an email';
|
errors.email = i18n.t('ReduxFormUtils.errorEmptyEmail');
|
||||||
}
|
}
|
||||||
if (!formProps.password) {
|
if (!formProps.password) {
|
||||||
errors.password = 'Please enter a password';
|
errors.password = i18n.t('ReduxFormUtils.errorEmptyPassword');
|
||||||
}
|
}
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
@ -67,17 +68,17 @@ export function validateSignup(formProps) {
|
||||||
validateNameEmail(formProps, errors);
|
validateNameEmail(formProps, errors);
|
||||||
|
|
||||||
if (!formProps.password) {
|
if (!formProps.password) {
|
||||||
errors.password = 'Please enter a password';
|
errors.password = i18n.t('ReduxFormUtils.errorEmptyPassword');
|
||||||
}
|
}
|
||||||
if (formProps.password && formProps.password.length < 6) {
|
if (formProps.password && formProps.password.length < 6) {
|
||||||
errors.password = 'Password must be at least 6 characters';
|
errors.password = i18n.t('ReduxFormUtils.errorShortPassword');
|
||||||
}
|
}
|
||||||
if (!formProps.confirmPassword) {
|
if (!formProps.confirmPassword) {
|
||||||
errors.confirmPassword = 'Please enter a password confirmation';
|
errors.confirmPassword = i18n.t('ReduxFormUtils.errorConfirmPassword');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (formProps.password !== formProps.confirmPassword && formProps.confirmPassword) {
|
if (formProps.password !== formProps.confirmPassword && formProps.confirmPassword) {
|
||||||
errors.confirmPassword = 'Passwords must match';
|
errors.confirmPassword = i18n.t('ReduxFormUtils.errorPasswordMismatch');
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
|
@ -85,11 +86,11 @@ export function validateSignup(formProps) {
|
||||||
export function validateResetPassword(formProps) {
|
export function validateResetPassword(formProps) {
|
||||||
const errors = {};
|
const errors = {};
|
||||||
if (!formProps.email) {
|
if (!formProps.email) {
|
||||||
errors.email = 'Please enter an email.';
|
errors.email = i18n.t('ReduxFormUtils.errorEmptyEmail');
|
||||||
} else if (
|
} else if (
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
!formProps.email.match(EMAIL_REGEX)) {
|
!formProps.email.match(EMAIL_REGEX)) {
|
||||||
errors.email = 'Please enter a valid email address.';
|
errors.email = i18n.t('ReduxFormUtils.errorInvalidEmail');
|
||||||
}
|
}
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,7 +183,6 @@
|
||||||
"Error": "Error",
|
"Error": "Error",
|
||||||
"Save": "Save",
|
"Save": "Save",
|
||||||
"p5logoARIA": "p5.js Logo"
|
"p5logoARIA": "p5.js Logo"
|
||||||
|
|
||||||
},
|
},
|
||||||
"IDEView": {
|
"IDEView": {
|
||||||
"SubmitFeedback": "Submit Feedback"
|
"SubmitFeedback": "Submit Feedback"
|
||||||
|
@ -208,5 +207,30 @@
|
||||||
"NewFolderForm": {
|
"NewFolderForm": {
|
||||||
"AddFolderSubmit": "Add Folder",
|
"AddFolderSubmit": "Add Folder",
|
||||||
"Placeholder": "Name"
|
"Placeholder": "Name"
|
||||||
|
},
|
||||||
|
"ResetPasswordForm": {
|
||||||
|
"Email": "Email used for registration",
|
||||||
|
"EmailARIA": "email",
|
||||||
|
"Submit": "Send Password Reset Email"
|
||||||
|
},
|
||||||
|
"ResetPasswordView": {
|
||||||
|
"Title": "p5.js Web Editor | Reset Password",
|
||||||
|
"Reset": "Reset Your Password",
|
||||||
|
"Submitted": "Your password reset email should arrive shortly. If you don't see it, check\n in your spam folder as sometimes it can end up there.",
|
||||||
|
"Login": "Log In",
|
||||||
|
"LoginOr": "or",
|
||||||
|
"SignUp": "Sign Up"
|
||||||
|
},
|
||||||
|
"ReduxFormUtils": {
|
||||||
|
"errorInvalidEmail": "Please enter a valid email address",
|
||||||
|
"errorEmptyEmail": "Please enter an email",
|
||||||
|
"errorPasswordMismatch": "Passwords must match",
|
||||||
|
"errorEmptyPassword": "Please enter a password",
|
||||||
|
"errorShortPassword": "Password must be at least 6 characters",
|
||||||
|
"errorConfirmPassword": "Please enter a password confirmation",
|
||||||
|
"errorNewPassword": "Please enter a new password or leave the current password empty.",
|
||||||
|
"errorEmptyUsername": "Please enter a username.",
|
||||||
|
"errorLongUsername": "Username must be less than 20 characters.",
|
||||||
|
"errorValidUsername": "Username must only consist of numbers, letters, periods, dashes, and underscores."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,9 +207,33 @@
|
||||||
"NewFolderForm": {
|
"NewFolderForm": {
|
||||||
"AddFolderSubmit": "Agregar Directorio",
|
"AddFolderSubmit": "Agregar Directorio",
|
||||||
"Placeholder": "Nombre"
|
"Placeholder": "Nombre"
|
||||||
|
},
|
||||||
|
"ResetPasswordForm": {
|
||||||
|
"Email": "Correo electrónico usado al registrarse",
|
||||||
|
"EmailARIA": "correo electrónico",
|
||||||
|
"Submit": "Enviar correo para regenerar contraseña"
|
||||||
|
},
|
||||||
|
"ResetPasswordView": {
|
||||||
|
"Title": "Editor Web p5.js | Regenerar Contraseña",
|
||||||
|
"Reset": "Regenerar Contraseña",
|
||||||
|
"Submitted": "Your password reset email should arrive shortly. If you don't see it, check\n in your spam folder as sometimes it can end up there.",
|
||||||
|
"Login": "Ingresa",
|
||||||
|
"LoginOr": "o",
|
||||||
|
"SignUp": "Registráte"
|
||||||
|
},
|
||||||
|
"ReduxFormUtils": {
|
||||||
|
"errorInvalidEmail": "Por favor introduce un correo electrónico válido",
|
||||||
|
"errorEmptyEmail": "Por favor introduce un correo electrónico",
|
||||||
|
"errorPasswordMismatch": "Las contraseñas deben coincidir",
|
||||||
|
"errorEmptyPassword": "Por favor introduce una contraseña",
|
||||||
|
"errorShortPassword": "La contraseña debe tener al menos 6 caracteres",
|
||||||
|
"errorConfirmPassword": "Por favor confirma una contraseña",
|
||||||
|
"errorNewPassword": "Por favor introduce una nueva contraseña o deja la actual contraseña vacía",
|
||||||
|
"errorEmptyUsername": "Por favor introduce tu identificación",
|
||||||
|
"errorLongUsername": "La identificación debe ser menor a 20 caracteres.",
|
||||||
|
"errorValidUsername": "La identificación debe consistir solamente de números, letras, puntos, guiones y guiones bajos."
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue