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:
ov 2020-08-13 11:12:02 +01:00 committed by GitHub
parent 9694719e02
commit ff40de36ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 96 additions and 45 deletions

View file

@ -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);

View file

@ -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&apos;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>
&nbsp;or&nbsp; &nbsp;{props.t('ResetPasswordView.LoginOr')}&nbsp;
<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));

View file

@ -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;
} }

View file

@ -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"
@ -197,7 +196,7 @@
"NewFileForm": { "NewFileForm": {
"AddFileSubmit": "Add File", "AddFileSubmit": "Add File",
"Placeholder": "Name" "Placeholder": "Name"
}, },
"NewFolderModal": { "NewFolderModal": {
"Title": "Create Folder", "Title": "Create Folder",
"CloseButtonARIA": "Close New Folder Modal", "CloseButtonARIA": "Close New Folder Modal",
@ -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."
} }
} }

View file

@ -203,13 +203,37 @@
"EnterName": "Por favor introduce un nombre", "EnterName": "Por favor introduce un nombre",
"EmptyName": " El nombre del directorio no debe contener solo espacios vacíos", "EmptyName": " El nombre del directorio no debe contener solo espacios vacíos",
"InvalidExtension": "El nombre del directorio no debe contener una extensión" "InvalidExtension": "El nombre del directorio no debe contener una extensión"
}, },
"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."
} }
} }