diff options
Diffstat (limited to 'web/react')
-rw-r--r-- | web/react/components/email_verify.jsx | 54 | ||||
-rw-r--r-- | web/react/components/signup_team_complete.jsx | 11 | ||||
-rw-r--r-- | web/react/components/signup_user_complete.jsx | 151 | ||||
-rw-r--r-- | web/react/components/team_signup_display_name_page.jsx | 45 | ||||
-rw-r--r-- | web/react/components/team_signup_email_item.jsx | 29 | ||||
-rw-r--r-- | web/react/components/team_signup_password_page.jsx | 83 | ||||
-rw-r--r-- | web/react/components/team_signup_send_invites_page.jsx | 46 | ||||
-rw-r--r-- | web/react/components/team_signup_url_page.jsx | 74 | ||||
-rw-r--r-- | web/react/components/team_signup_username_page.jsx | 69 | ||||
-rw-r--r-- | web/react/components/team_signup_welcome_page.jsx | 75 |
10 files changed, 539 insertions, 98 deletions
diff --git a/web/react/components/email_verify.jsx b/web/react/components/email_verify.jsx index 9c07853b7..ef1a62130 100644 --- a/web/react/components/email_verify.jsx +++ b/web/react/components/email_verify.jsx @@ -1,6 +1,8 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. +import {FormattedMessage, FormattedHTMLMessage} from 'mm-intl'; + export default class EmailVerify extends React.Component { constructor(props) { super(props); @@ -19,21 +21,61 @@ export default class EmailVerify extends React.Component { var resend = ''; var resendConfirm = ''; if (this.props.isVerified === 'true') { - title = global.window.mm_config.SiteName + ' Email Verified'; - body = <p>Your email has been verified! Click <a href={this.props.teamURL + '?email=' + this.props.userEmail}>here</a> to log in.</p>; + title = ( + <FormattedMessage + id='email_verify.verified' + defaultMessage='{siteName} Email Verified' + values={{ + siteName: global.window.mm_config.SiteName + }} + /> + ); + body = ( + <FormattedHTMLMessage + id='email_verify.verifiedBody' + defaultMessage='<p>Your email has been verified! Click <a href={url}>here</a> to log in.</p>' + values={{ + url: this.props.teamURL + '?email=' + this.props.userEmail + }} + /> + ); } else { - title = global.window.mm_config.SiteName + ': You are almost done'; - body = <p>Please verify your email address. Check your inbox for an email.</p>; + title = ( + <FormattedMessage + id='email_verify.almost' + defaultMessage='{siteName}: You are almost done' + values={{ + siteName: global.window.mm_config.SiteName + }} + /> + ); + body = ( + <p> + <FormattedMessage + id='email_verify.notVerifiedBody' + defaultMessage='Please verify your email address. Check your inbox for an email.' + /> + </p> + ); resend = ( <button onClick={this.handleResend} className='btn btn-primary' > - Resend Email + <FormattedMessage + id='email_verify.resend' + defaultMessage='Resend Email' + /> </button> ); if (this.props.resendSuccess) { - resendConfirm = <div><br /><p className='alert alert-success'><i className='fa fa-check'></i>{' Verification email sent.'}</p></div>; + resendConfirm = ( + <div><br /><p className='alert alert-success'><i className='fa fa-check'></i> + <FormattedMessage + id='email_verify.sent' + defaultMessage=' Verification email sent.' + /> + </p></div>); } } diff --git a/web/react/components/signup_team_complete.jsx b/web/react/components/signup_team_complete.jsx index 6c7fd57b3..16553daeb 100644 --- a/web/react/components/signup_team_complete.jsx +++ b/web/react/components/signup_team_complete.jsx @@ -9,6 +9,8 @@ import UsernamePage from './team_signup_username_page.jsx'; import PasswordPage from './team_signup_password_page.jsx'; import BrowserStore from '../stores/browser_store.jsx'; +import {FormattedMessage} from 'mm-intl'; + export default class SignupTeamComplete extends React.Component { constructor(props) { super(props); @@ -96,7 +98,14 @@ export default class SignupTeamComplete extends React.Component { ); } - return (<div>You've already completed the signup process for this invitation or this invitation has expired.</div>); + return ( + <div> + <FormattedMessage + id='signup_team_complete.completed' + defaultMessage="You've already completed the signup process for this invitation or this invitation has expired." + /> + </div> + ); } } diff --git a/web/react/components/signup_user_complete.jsx b/web/react/components/signup_user_complete.jsx index ace0d28ae..47ec58e98 100644 --- a/web/react/components/signup_user_complete.jsx +++ b/web/react/components/signup_user_complete.jsx @@ -7,7 +7,32 @@ import UserStore from '../stores/user_store.jsx'; import BrowserStore from '../stores/browser_store.jsx'; import Constants from '../utils/constants.jsx'; -export default class SignupUserComplete extends React.Component { +import {intlShape, injectIntl, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl'; + +const holders = defineMessages({ + required: { + id: 'signup_user_completed.required', + defaultMessage: 'This field is required' + }, + validEmail: { + id: 'signup_user_completed.validEmail', + defaultMessage: 'Please enter a valid email address' + }, + reserved: { + id: 'signup_user_completed.reserved', + defaultMessage: 'This username is reserved, please choose a new one.' + }, + usernameLength: { + id: 'signup_user_completed.usernameLength', + defaultMessage: 'Username must begin with a letter, and contain between {min} to {max} lowercase characters made up of numbers, letters, and the symbols \'.\', \'-\' and \'_\'.' + }, + passwordLength: { + id: 'signup_user_completed.passwordLength', + defaultMessage: 'Please enter at least {min} characters' + } +}); + +class SignupUserComplete extends React.Component { constructor(props) { super(props); @@ -29,30 +54,31 @@ export default class SignupUserComplete extends React.Component { handleSubmit(e) { e.preventDefault(); + const {formatMessage} = this.props.intl; const providedEmail = ReactDOM.findDOMNode(this.refs.email).value.trim(); if (!providedEmail) { - this.setState({nameError: '', emailError: 'This field is required', passwordError: ''}); + this.setState({nameError: '', emailError: formatMessage(holders.required), passwordError: ''}); return; } if (!Utils.isEmail(providedEmail)) { - this.setState({nameError: '', emailError: 'Please enter a valid email address', passwordError: ''}); + this.setState({nameError: '', emailError: formatMessage(holders.validEmail), passwordError: ''}); return; } const providedUsername = ReactDOM.findDOMNode(this.refs.name).value.trim().toLowerCase(); if (!providedUsername) { - this.setState({nameError: 'This field is required', emailError: '', passwordError: '', serverError: ''}); + this.setState({nameError: formatMessage(holders.required), emailError: '', passwordError: '', serverError: ''}); return; } const usernameError = Utils.isValidUsername(providedUsername); if (usernameError === 'Cannot use a reserved word as a username.') { - this.setState({nameError: 'This username is reserved, please choose a new one.', emailError: '', passwordError: '', serverError: ''}); + this.setState({nameError: formatMessage(holders.reserved), emailError: '', passwordError: '', serverError: ''}); return; } else if (usernameError) { this.setState({ - nameError: 'Username must begin with a letter, and contain between ' + Constants.MIN_USERNAME_LENGTH + ' to ' + Constants.MAX_USERNAME_LENGTH + ' lowercase characters made up of numbers, letters, and the symbols \'.\', \'-\' and \'_\'.', + nameError: formatMessage(holders.usernameLength, {min: Constants.MIN_USERNAME_LENGTH, max: Constants.MAX_USERNAME_LENGTH}), emailError: '', passwordError: '', serverError: '' @@ -62,7 +88,7 @@ export default class SignupUserComplete extends React.Component { const providedPassword = ReactDOM.findDOMNode(this.refs.password).value.trim(); if (!providedPassword || providedPassword.length < Constants.MIN_PASSWORD_LENGTH) { - this.setState({nameError: '', emailError: '', passwordError: 'Please enter at least ' + Constants.MIN_PASSWORD_LENGTH + ' characters', serverError: ''}); + this.setState({nameError: '', emailError: '', passwordError: formatMessage(holders.passwordLength, {min: Constants.MIN_PASSWORD_LENGTH}), serverError: ''}); return; } @@ -95,7 +121,7 @@ export default class SignupUserComplete extends React.Component { window.location.href = '/' + this.props.teamName + '/channels/town-square'; }, (err) => { - if (err.message === 'Login failed because email address has not been verified') { + if (err.id === 'api.user.login.not_verified.app_error') { window.location.href = '/verify_email?email=' + encodeURIComponent(user.email) + '&teamname=' + encodeURIComponent(this.props.teamName); } else { this.setState({serverError: err.message}); @@ -112,7 +138,14 @@ export default class SignupUserComplete extends React.Component { client.track('signup', 'signup_user_01_welcome'); if (this.state.wizard === 'finished') { - return <div>{"You've already completed the signup process for this invitation or this invitation has expired."}</div>; + return ( + <div> + <FormattedMessage + id='signup_user_completed.expired' + defaultMessage="You've already completed the signup process for this invitation or this invitation has expired." + /> + </div> + ); } // set up error labels @@ -124,7 +157,18 @@ export default class SignupUserComplete extends React.Component { } var nameError = null; - var nameHelpText = <span className='help-block'>{'Username must begin with a letter, and contain between ' + Constants.MIN_USERNAME_LENGTH + ' to ' + Constants.MAX_USERNAME_LENGTH + " lowercase characters made up of numbers, letters, and the symbols '.', '-' and '_'"}</span>; + var nameHelpText = ( + <span className='help-block'> + <FormattedMessage + id='signup_user_completed.userHelp' + defaultMessage="Username must begin with a letter, and contain between {min} to {max} lowercase characters made up of numbers, letters, and the symbols '.', '-' and '_'" + values={{ + min: Constants.MIN_USERNAME_LENGTH, + max: Constants.MAX_USERNAME_LENGTH + }} + /> + </span> + ); var nameDivStyle = 'form-group'; if (this.state.nameError) { nameError = <label className='control-label'>{this.state.nameError}</label>; @@ -151,7 +195,16 @@ export default class SignupUserComplete extends React.Component { // set up the email entry and hide it if an email was provided var yourEmailIs = ''; if (this.state.user.email) { - yourEmailIs = <span>{'Your email address is '}<strong>{this.state.user.email}</strong>{". You'll use this address to sign in to " + global.window.mm_config.SiteName + '.'}</span>; + yourEmailIs = ( + <FormattedHTMLMessage + id='signup_user_completed.emailIs' + defaultMessage="Your email address is <strong>{email}</strong>. You'll use this address to sign in to {siteName}." + values={{ + email: this.state.user.email, + siteName: global.window.mm_config.SiteName + }} + /> + ); } var emailContainerStyle = 'margin--extra'; @@ -161,7 +214,12 @@ export default class SignupUserComplete extends React.Component { var email = ( <div className={emailContainerStyle}> - <h5><strong>{"What's your email address?"}</strong></h5> + <h5><strong> + <FormattedMessage + id='signup_user_completed.whatis' + defaultMessage="What's your email address?" + /> + </strong></h5> <div className={emailDivStyle}> <input type='email' @@ -183,10 +241,16 @@ export default class SignupUserComplete extends React.Component { signupMessage.push( <a className='btn btn-custom-login gitlab' + key='gitlab' href={'/' + this.props.teamName + '/signup/gitlab' + window.location.search} > <span className='icon' /> - <span>{'with GitLab'}</span> + <span> + <FormattedMessage + id='signup_user_completed.gitlab' + defaultMessage='with GitLab' + /> + </span> </a> ); } @@ -195,10 +259,16 @@ export default class SignupUserComplete extends React.Component { signupMessage.push( <a className='btn btn-custom-login google' + key='google' href={'/' + this.props.teamName + '/signup/google' + window.location.search} > <span className='icon' /> - <span>{'with Google'}</span> + <span> + <FormattedMessage + id='signup_user_completed.google' + defaultMessage='with Google' + /> + </span> </a> ); } @@ -211,7 +281,12 @@ export default class SignupUserComplete extends React.Component { {email} {yourEmailIs} <div className='margin--extra'> - <h5><strong>{'Choose your username'}</strong></h5> + <h5><strong> + <FormattedMessage + id='signup_user_completed.chooseUser' + defaultMessage='Choose your username' + /> + </strong></h5> <div className={nameDivStyle}> <input type='text' @@ -226,7 +301,12 @@ export default class SignupUserComplete extends React.Component { </div> </div> <div className='margin--extra'> - <h5><strong>{'Choose your password'}</strong></h5> + <h5><strong> + <FormattedMessage + id='signup_user_completed.choosePwd' + defaultMessage='Choose your password' + /> + </strong></h5> <div className={passwordDivStyle}> <input type='password' @@ -246,7 +326,10 @@ export default class SignupUserComplete extends React.Component { onClick={this.handleSubmit} className='btn-primary btn' > - {'Create Account'} + <FormattedMessage + id='signup_user_completed.create' + defaultMessage='Create Account' + /> </button> </p> </div> @@ -258,7 +341,12 @@ export default class SignupUserComplete extends React.Component { <div> {signupMessage} <div className='or__container'> - <span>{'or'}</span> + <span> + <FormattedMessage + id='signup_user_completed.or' + defaultMessage='or' + /> + </span> </div> </div> ); @@ -271,10 +359,28 @@ export default class SignupUserComplete extends React.Component { className='signup-team-logo' src='/static/images/logo.png' /> - <h5 className='margin--less'>{'Welcome to:'}</h5> + <h5 className='margin--less'> + <FormattedMessage + id='signup_user_completed.welcome' + defaultMessage='Welcome to:' + /> + </h5> <h2 className='signup-team__name'>{this.props.teamDisplayName}</h2> - <h2 className='signup-team__subdomain'>{'on ' + global.window.mm_config.SiteName}</h2> - <h4 className='color--light'>{"Let's create your account"}</h4> + <h2 className='signup-team__subdomain'> + <FormattedMessage + id='signup_user_completed.onSite' + defaultMessage='on {siteName}' + values={{ + siteName: global.window.mm_config.SiteName + }} + /> + </h2> + <h4 className='color--light'> + <FormattedMessage + id='signup_user_completed.lets' + defaultMessage="Let's create your account" + /> + </h4> {signupMessage} {emailSignup} {serverError} @@ -293,6 +399,7 @@ SignupUserComplete.defaultProps = { teamDisplayName: '' }; SignupUserComplete.propTypes = { + intl: intlShape.isRequired, teamName: React.PropTypes.string, hash: React.PropTypes.string, teamId: React.PropTypes.string, @@ -300,3 +407,5 @@ SignupUserComplete.propTypes = { data: React.PropTypes.string, teamDisplayName: React.PropTypes.string }; + +export default injectIntl(SignupUserComplete);
\ No newline at end of file diff --git a/web/react/components/team_signup_display_name_page.jsx b/web/react/components/team_signup_display_name_page.jsx index f4d5ea162..f07b50756 100644 --- a/web/react/components/team_signup_display_name_page.jsx +++ b/web/react/components/team_signup_display_name_page.jsx @@ -4,7 +4,20 @@ import * as utils from '../utils/utils.jsx'; import * as client from '../utils/client.jsx'; -export default class TeamSignupDisplayNamePage extends React.Component { +import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl'; + +const holders = defineMessages({ + required: { + id: 'team_signup_display_name.required', + defaultMessage: 'This field is required' + }, + charLength: { + id: 'team_signup_display_name.charLength', + defaultMessage: 'Name must be 4 or more characters up to a maximum of 15' + } +}); + +class TeamSignupDisplayNamePage extends React.Component { constructor(props) { super(props); @@ -21,12 +34,13 @@ export default class TeamSignupDisplayNamePage extends React.Component { submitNext(e) { e.preventDefault(); + const {formatMessage} = this.props.intl; var displayName = ReactDOM.findDOMNode(this.refs.name).value.trim(); if (!displayName) { - this.setState({nameError: 'This field is required'}); + this.setState({nameError: formatMessage(holders.required)}); return; } else if (displayName.length < 4 || displayName.length > 15) { - this.setState({nameError: 'Name must be 4 or more characters up to a maximum of 15'}); + this.setState({nameError: formatMessage(holders.charLength)}); return; } @@ -56,7 +70,12 @@ export default class TeamSignupDisplayNamePage extends React.Component { className='signup-team-logo' src='/static/images/logo.png' /> - <h2>{'Team Name'}</h2> + <h2> + <FormattedMessage + id='team_signup_display_name.teamName' + defaultMessage='Team Name' + /> + </h2> <div className={nameDivClass}> <div className='row'> <div className='col-sm-9'> @@ -76,21 +95,30 @@ export default class TeamSignupDisplayNamePage extends React.Component { {nameError} </div> <div> - {'Name your team in any language. Your team name shows in menus and headings.'} + <FormattedMessage + id='team_signup_display_name.nameHelp' + defaultMessage='Name your team in any language. Your team name shows in menus and headings.' + /> </div> <button type='submit' className='btn btn-primary margin--extra' onClick={this.submitNext} > - Next<i className='glyphicon glyphicon-chevron-right'></i> + <FormattedMessage + id='team_signup_display_name.next' + defaultMessage='Next' + /><i className='glyphicon glyphicon-chevron-right'></i> </button> <div className='margin--extra'> <a href='#' onClick={this.submitBack} > - Back to previous step + <FormattedMessage + id='team_signup_display_name.back' + defaultMessage='Back to previous step' + /> </a> </div> </form> @@ -100,6 +128,9 @@ export default class TeamSignupDisplayNamePage extends React.Component { } TeamSignupDisplayNamePage.propTypes = { + intl: intlShape.isRequired, state: React.PropTypes.object, updateParent: React.PropTypes.func }; + +export default injectIntl(TeamSignupDisplayNamePage);
\ No newline at end of file diff --git a/web/react/components/team_signup_email_item.jsx b/web/react/components/team_signup_email_item.jsx index 59c4771d7..feb70dc71 100644 --- a/web/react/components/team_signup_email_item.jsx +++ b/web/react/components/team_signup_email_item.jsx @@ -3,7 +3,24 @@ import * as Utils from '../utils/utils.jsx'; -export default class TeamSignupEmailItem extends React.Component { +import {intlShape, injectIntl, defineMessages} from 'mm-intl'; + +const holders = defineMessages({ + validEmail: { + id: 'team_signup_email.validEmail', + defaultMessage: 'Please enter a valid email address' + }, + different: { + id: 'team_signup_email.different', + defaultMessage: 'Please use a different email than the one used at signup' + }, + address: { + id: 'team_signup_email.address', + defaultMessage: 'Email Address' + } +}); + +class TeamSignupEmailItem extends React.Component { constructor(props) { super(props); @@ -16,6 +33,7 @@ export default class TeamSignupEmailItem extends React.Component { return ReactDOM.findDOMNode(this.refs.email).value.trim(); } validate(teamEmail) { + const {formatMessage} = this.props.intl; const email = ReactDOM.findDOMNode(this.refs.email).value.trim().toLowerCase(); if (!email) { @@ -23,10 +41,10 @@ export default class TeamSignupEmailItem extends React.Component { } if (!Utils.isEmail(email)) { - this.setState({emailError: 'Please enter a valid email address'}); + this.setState({emailError: formatMessage(holders.validEmail)}); return false; } else if (email === teamEmail) { - this.setState({emailError: 'Please use a different email than the one used at signup'}); + this.setState({emailError: formatMessage(holders.different)}); return false; } @@ -48,7 +66,7 @@ export default class TeamSignupEmailItem extends React.Component { type='email' ref='email' className='form-control' - placeholder='Email Address' + placeholder={this.props.intl.formatMessage(holders.address)} defaultValue={this.props.email} maxLength='128' spellCheck='false' @@ -60,6 +78,9 @@ export default class TeamSignupEmailItem extends React.Component { } TeamSignupEmailItem.propTypes = { + intl: intlShape.isRequired, focus: React.PropTypes.bool, email: React.PropTypes.string }; + +export default injectIntl(TeamSignupEmailItem);
\ No newline at end of file diff --git a/web/react/components/team_signup_password_page.jsx b/web/react/components/team_signup_password_page.jsx index 7e11d38c3..06c04854f 100644 --- a/web/react/components/team_signup_password_page.jsx +++ b/web/react/components/team_signup_password_page.jsx @@ -6,7 +6,20 @@ import BrowserStore from '../stores/browser_store.jsx'; import UserStore from '../stores/user_store.jsx'; import Constants from '../utils/constants.jsx'; -export default class TeamSignupPasswordPage extends React.Component { +import {intlShape, injectIntl, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl'; + +const holders = defineMessages({ + passwordError: { + id: 'team_signup_password.passwordError', + defaultMessage: 'Please enter at least {chars} characters' + }, + creating: { + id: 'team_signup_password.creating', + defaultMessage: 'Creating team...' + } +}); + +class TeamSignupPasswordPage extends React.Component { constructor(props) { super(props); @@ -25,7 +38,7 @@ export default class TeamSignupPasswordPage extends React.Component { var password = ReactDOM.findDOMNode(this.refs.password).value.trim(); if (!password || password.length < Constants.MIN_PASSWORD_LENGTH) { - this.setState({passwordError: 'Please enter at least ' + Constants.MIN_PASSWORD_LENGTH + ' characters'}); + this.setState({passwordError: this.props.intl.formatMessage(holders.passwordError, {chars: Constants.MIN_PASSWORD_LENGTH})}); return; } @@ -56,7 +69,7 @@ export default class TeamSignupPasswordPage extends React.Component { window.location.href = '/' + teamSignup.team.name + '/channels/town-square'; }, (err) => { - if (err.message === 'Login failed because email address has not been verified') { + if (err.id === 'api.user.login.not_verified.app_error') { window.location.href = '/verify_email?email=' + encodeURIComponent(teamSignup.team.email) + '&teamname=' + encodeURIComponent(teamSignup.team.name); } else { this.setState({serverError: err.message}); @@ -93,15 +106,35 @@ export default class TeamSignupPasswordPage extends React.Component { className='signup-team-logo' src='/static/images/logo.png' /> - <h2 className='margin--less'>{'Your password'}</h2> - <h5 className='color--light'>{"Select a password that you'll use to login with your email address:"}</h5> + <h2 className='margin--less'> + <FormattedMessage + id='team_signup_password.yourPassword' + defaultMessage='Your password' + /> + </h2> + <h5 className='color--light'> + <FormattedMessage + id='team_signup_password.selectPassword' + defaultMessage="Select a password that you'll use to login with your email address:" + /> + </h5> <div className='inner__content margin--extra'> - <h5><strong>{'Email'}</strong></h5> + <h5><strong> + <FormattedMessage + id='team_signup_password.email' + defaultMessage='Email' + /> + </strong></h5> <div className='block--gray form-group'>{this.props.state.team.email}</div> <div className={passwordDivStyle}> <div className='row'> <div className='col-sm-11'> - <h5><strong>{'Choose your password'}</strong></h5> + <h5><strong> + <FormattedMessage + id='team_signup_password.choosePwd' + defaultMessage='Choose your password' + /> + </strong></h5> <input autoFocus={true} type='password' @@ -111,7 +144,16 @@ export default class TeamSignupPasswordPage extends React.Component { maxLength='128' spellCheck='false' /> - <span className='color--light help-block'>{'Passwords must contain ' + Constants.MIN_PASSWORD_LENGTH + ' to ' + Constants.MAX_PASSWORD_LENGTH + ' characters. Your password will be strongest if it contains a mix of symbols, numbers, and upper and lowercase characters.'}</span> + <span className='color--light help-block'> + <FormattedMessage + id='team_signup_password.hint' + defaultMessage='Passwords must contain {min} to {max} characters. Your password will be strongest if it contains a mix of symbols, numbers, and upper and lowercase characters.' + values={{ + min: Constants.MIN_PASSWORD_LENGTH, + max: Constants.MAX_PASSWORD_LENGTH + }} + /> + </span> </div> </div> {passwordError} @@ -123,19 +165,33 @@ export default class TeamSignupPasswordPage extends React.Component { type='submit' className='btn btn-primary margin--extra' id='finish-button' - data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Creating team...'} + data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + this.props.intl.formatMessage(holders.creating)} onClick={this.submitNext} > - {'Finish'} + <FormattedMessage + id='team_signup_password.finish' + defaultMessage='Finish' + /> </button> </div> - <p>By proceeding to create your account and use {global.window.mm_config.SiteName}, you agree to our <a href='/static/help/terms.html'>Terms of Service</a> and <a href='/static/help/privacy.html'>Privacy Policy</a>. If you do not agree, you cannot use {global.window.mm_config.SiteName}.</p> + <p> + <FormattedHTMLMessage + id='team_signup_password.agreement' + defaultMessage="By proceeding to create your account and use {siteName}, you agree to our <a href='/static/help/terms.html'>Terms of Service</a> and <a href='/static/help/privacy.html'>Privacy Policy</a>. If you do not agree, you cannot use {siteName}." + values={{ + siteName: global.window.mm_config.SiteName + }} + /> + </p> <div className='margin--extra'> <a href='#' onClick={this.submitBack} > - {'Back to previous step'} + <FormattedMessage + id='team_signup_password.back' + defaultMessage='Back to previous step' + /> </a> </div> </form> @@ -149,7 +205,10 @@ TeamSignupPasswordPage.defaultProps = { hash: '' }; TeamSignupPasswordPage.propTypes = { + intl: intlShape.isRequired, state: React.PropTypes.object, hash: React.PropTypes.string, updateParent: React.PropTypes.func }; + +export default injectIntl(TeamSignupPasswordPage);
\ No newline at end of file diff --git a/web/react/components/team_signup_send_invites_page.jsx b/web/react/components/team_signup_send_invites_page.jsx index a580623e4..46a6bc68e 100644 --- a/web/react/components/team_signup_send_invites_page.jsx +++ b/web/react/components/team_signup_send_invites_page.jsx @@ -4,6 +4,8 @@ import EmailItem from './team_signup_email_item.jsx'; import * as Client from '../utils/client.jsx'; +import {FormattedMessage, FormattedHTMLMessage} from 'mm-intl'; + export default class TeamSignupSendInvitesPage extends React.Component { constructor(props) { super(props); @@ -117,7 +119,10 @@ export default class TeamSignupSendInvitesPage extends React.Component { href='#' onClick={this.submitAddInvite} > - Add Invitation + <FormattedMessage + id='team_signup_send_invites.addInvitation' + defaultMessage='Add Invitation' + /> </a> </div> </div> @@ -125,22 +130,32 @@ export default class TeamSignupSendInvitesPage extends React.Component { bottomContent = ( <p className='color--light'> - {'if you prefer, you can invite team members later'} - <br /> - {' and '} + <FormattedHTMLMessage + id='team_signup_send_invites.prefer' + defaultMessage='if you prefer, you can invite team members later<br /> and ' + /> <a href='#' onClick={this.submitSkip} > - {'skip this step '} + <FormattedMessage + id='team_signup_send_invites.skip' + defaultMessage='skip this step ' + /> </a> - {'for now.'} + <FormattedMessage + id='team_signup_send_invites.forNow' + defaultMessage='for now.' + /> </p> ); } else { content = ( <div className='form-group color--light'> - {'Email is currently disabled for your team, and emails cannot be sent. Contact your system administrator to enable email and email invitations.'} + <FormattedMessage + id='team_signup_send_invites.disabled' + defaultMessage='Email is currently disabled for your team, and emails cannot be sent. Contact your system administrator to enable email and email invitations.' + /> </div> ); } @@ -152,7 +167,12 @@ export default class TeamSignupSendInvitesPage extends React.Component { className='signup-team-logo' src='/static/images/logo.png' /> - <h2>{'Invite Team Members'}</h2> + <h2> + <FormattedMessage + id='team_signup_send_invites.title' + defaultMessage='Invite Team Members' + /> + </h2> {content} <div className='form-group'> <button @@ -160,7 +180,10 @@ export default class TeamSignupSendInvitesPage extends React.Component { className='btn-primary btn' onClick={this.submitNext} > - Next<i className='glyphicon glyphicon-chevron-right' /> + <FormattedMessage + id='team_signup_send_invites.next' + defaultMessage='Next' + /><i className='glyphicon glyphicon-chevron-right' /> </button> </div> </form> @@ -170,7 +193,10 @@ export default class TeamSignupSendInvitesPage extends React.Component { href='#' onClick={this.submitBack} > - Back to previous step + <FormattedMessage + id='team_signup_send_invites.back' + defaultMessage='Back to previous step' + /> </a> </div> </div> diff --git a/web/react/components/team_signup_url_page.jsx b/web/react/components/team_signup_url_page.jsx index 30459fc67..2f6c3df49 100644 --- a/web/react/components/team_signup_url_page.jsx +++ b/web/react/components/team_signup_url_page.jsx @@ -5,7 +5,32 @@ import * as Utils from '../utils/utils.jsx'; import * as Client from '../utils/client.jsx'; import Constants from '../utils/constants.jsx'; -export default class TeamSignupUrlPage extends React.Component { +import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl'; + +const holders = defineMessages({ + required: { + id: 'team_signup_url.required', + defaultMessage: 'This field is required' + }, + regex: { + id: 'team_signup_url.regex', + defaultMessage: "Use only lower case letters, numbers and dashes. Must start with a letter and can't end in a dash." + }, + charLength: { + id: 'team_signup_url.charLength', + defaultMessage: 'Name must be 4 or more characters up to a maximum of 15' + }, + taken: { + id: 'team_signup_url.taken', + defaultMessage: 'URL is taken or contains a reserved word' + }, + unavailable: { + id: 'team_signup_url.unavailable', + defaultMessage: 'This URL is unavailable. Please try another.' + } +}); + +class TeamSignupUrlPage extends React.Component { constructor(props) { super(props); @@ -23,9 +48,10 @@ export default class TeamSignupUrlPage extends React.Component { submitNext(e) { e.preventDefault(); + const {formatMessage} = this.props.intl; const name = ReactDOM.findDOMNode(this.refs.name).value.trim(); if (!name) { - this.setState({nameError: 'This field is required'}); + this.setState({nameError: formatMessage(holders.required)}); return; } @@ -33,17 +59,17 @@ export default class TeamSignupUrlPage extends React.Component { const urlRegex = /^[a-z]+([a-z\-0-9]+|(__)?)[a-z0-9]+$/g; if (cleanedName !== name || !urlRegex.test(name)) { - this.setState({nameError: "Use only lower case letters, numbers and dashes. Must start with a letter and can't end in a dash."}); + this.setState({nameError: formatMessage(holders.regex)}); return; } else if (cleanedName.length < 4 || cleanedName.length > 15) { - this.setState({nameError: 'Name must be 4 or more characters up to a maximum of 15'}); + this.setState({nameError: formatMessage(holders.charLength)}); return; } if (global.window.mm_config.RestrictTeamNames === 'true') { for (let index = 0; index < Constants.RESERVED_TEAM_NAMES.length; index++) { if (cleanedName.indexOf(Constants.RESERVED_TEAM_NAMES[index]) === 0) { - this.setState({nameError: 'URL is taken or contains a reserved word'}); + this.setState({nameError: formatMessage(holders.taken)}); return; } } @@ -52,7 +78,7 @@ export default class TeamSignupUrlPage extends React.Component { Client.findTeamByName(name, (data) => { if (data) { - this.setState({nameError: 'This URL is unavailable. Please try another.'}); + this.setState({nameError: formatMessage(holders.unavailable)}); } else { if (global.window.mm_config.SendEmailNotifications === 'true') { this.props.state.wizard = 'send_invites'; @@ -96,7 +122,12 @@ export default class TeamSignupUrlPage extends React.Component { className='signup-team-logo' src='/static/images/logo.png' /> - <h2>{`Team URL`}</h2> + <h2> + <FormattedMessage + id='team_signup_url.teamUrl' + defaultMessage='Team URL' + /> + </h2> <div className={nameDivClass}> <div className='row'> <div className='col-sm-11'> @@ -124,25 +155,39 @@ export default class TeamSignupUrlPage extends React.Component { </div> {nameError} </div> - <p>{`Choose the web address of your new team:`}</p> + <p> + <FormattedMessage + id='team_signup_url.webAddress' + defaultMessage='Choose the web address of your new team:' + /> + </p> <ul className='color--light'> - <li>Short and memorable is best</li> - <li>Use lowercase letters, numbers and dashes</li> - <li>Must start with a letter and can't end in a dash</li> + <FormattedHTMLMessage + id='team_signup_url.hint' + defaultMessage="<li>Short and memorable is best</li> + <li>Use lowercase letters, numbers and dashes</li> + <li>Must start with a letter and can't end in a dash</li>" + /> </ul> <button type='submit' className='btn btn-primary margin--extra' onClick={this.submitNext} > - Next<i className='glyphicon glyphicon-chevron-right'></i> + <FormattedMessage + id='team_signup_url.next' + defaultMessage='Next' + /><i className='glyphicon glyphicon-chevron-right'></i> </button> <div className='margin--extra'> <a href='#' onClick={this.submitBack} > - Back to previous step + <FormattedMessage + id='team_signup_url.back' + defaultMessage='Back to previous step' + /> </a> </div> </form> @@ -152,6 +197,9 @@ export default class TeamSignupUrlPage extends React.Component { } TeamSignupUrlPage.propTypes = { + intl: intlShape.isRequired, state: React.PropTypes.object, updateParent: React.PropTypes.func }; + +export default injectIntl(TeamSignupUrlPage);
\ No newline at end of file diff --git a/web/react/components/team_signup_username_page.jsx b/web/react/components/team_signup_username_page.jsx index 6ccab6656..a7332975d 100644 --- a/web/react/components/team_signup_username_page.jsx +++ b/web/react/components/team_signup_username_page.jsx @@ -5,7 +5,20 @@ import * as Utils from '../utils/utils.jsx'; import * as Client from '../utils/client.jsx'; import Constants from '../utils/constants.jsx'; -export default class TeamSignupUsernamePage extends React.Component { +import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl'; + +const holders = defineMessages({ + reserved: { + id: 'team_signup_username.reserved', + defaultMessage: 'This username is reserved, please choose a new one.' + }, + invalid: { + id: 'team_signup_username.invalid', + defaultMessage: 'Username must begin with a letter, and contain between {min} to {max} characters in total, which may be numbers, lowercase letters, or any of the symbols \'.\', \'-\', or \'_\'' + } +}); + +class TeamSignupUsernamePage extends React.Component { constructor(props) { super(props); @@ -27,14 +40,15 @@ export default class TeamSignupUsernamePage extends React.Component { submitNext(e) { e.preventDefault(); + const {formatMessage} = this.props.intl; var name = ReactDOM.findDOMNode(this.refs.name).value.trim().toLowerCase(); var usernameError = Utils.isValidUsername(name); - if (usernameError === 'Cannot use a reserved word as a username.') { - this.setState({nameError: 'This username is reserved, please choose a new one.'}); + if (usernameError === 'Cannot use a reserved word as a username.') { //this should be change to some kind of ID + this.setState({nameError: formatMessage(holders.reserved)}); return; } else if (usernameError) { - this.setState({nameError: 'Username must begin with a letter, and contain between ' + Constants.MIN_USERNAME_LENGTH + ' to ' + Constants.MAX_USERNAME_LENGTH + ' characters in total, which may be numbers, lowercase letters, or any of the symbols \'.\', \'-\', or \'_\''}); + this.setState({nameError: formatMessage(holders.invalid, {min: Constants.MIN_USERNAME_LENGTH, max: Constants.MAX_USERNAME_LENGTH})}); return; } @@ -46,7 +60,18 @@ export default class TeamSignupUsernamePage extends React.Component { Client.track('signup', 'signup_team_06_username'); var nameError = null; - var nameHelpText = <span className='color--light help-block'>{'Usernames must begin with a letter and contain between ' + Constants.MIN_USERNAME_LENGTH + ' to ' + Constants.MAX_USERNAME_LENGTH + " characters made up of lowercase letters, numbers, and the symbols '.', '-' and '_'"}</span>; + var nameHelpText = ( + <span className='color--light help-block'> + <FormattedMessage + id='team_signup_username.hint' + defaultMessage="Usernames must begin with a letter and contain between {min} to {max} characters made up of lowercase letters, numbers, and the symbols '.', '-' and '_'" + values={{ + min: Constants.MIN_USERNAME_LENGTH, + max: Constants.MAX_USERNAME_LENGTH + }} + /> + </span> + ); var nameDivClass = 'form-group'; if (this.state.nameError) { nameError = <label className='control-label'>{this.state.nameError}</label>; @@ -61,13 +86,28 @@ export default class TeamSignupUsernamePage extends React.Component { className='signup-team-logo' src='/static/images/logo.png' /> - <h2 className='margin--less'>{'Your username'}</h2> - <h5 className='color--light'>{'Select a memorable username that makes it easy for teammates to identify you:'}</h5> + <h2 className='margin--less'> + <FormattedMessage + id='team_signup_username.username' + defaultMessage='Your username' + /> + </h2> + <h5 className='color--light'> + <FormattedMessage + id='team_signup_username.memorable' + defaultMessage='Select a memorable username that makes it easy for teammates to identify you:' + /> + </h5> <div className='inner__content margin--extra'> <div className={nameDivClass}> <div className='row'> <div className='col-sm-11'> - <h5><strong>{'Choose your username'}</strong></h5> + <h5><strong> + <FormattedMessage + id='team_signup_username.chooseUsername' + defaultMessage='Choose your username' + /> + </strong></h5> <input autoFocus={true} type='text' @@ -89,7 +129,10 @@ export default class TeamSignupUsernamePage extends React.Component { className='btn btn-primary margin--extra' onClick={this.submitNext} > - {'Next'} + <FormattedMessage + id='team_signup_username.next' + defaultMessage='Next' + /> <i className='glyphicon glyphicon-chevron-right'></i> </button> <div className='margin--extra'> @@ -97,7 +140,10 @@ export default class TeamSignupUsernamePage extends React.Component { href='#' onClick={this.submitBack} > - {'Back to previous step'} + <FormattedMessage + id='team_signup_username.back' + defaultMessage='Back to previous step' + /> </a> </div> </form> @@ -110,6 +156,9 @@ TeamSignupUsernamePage.defaultProps = { state: null }; TeamSignupUsernamePage.propTypes = { + intl: intlShape.isRequired, state: React.PropTypes.object, updateParent: React.PropTypes.func }; + +export default injectIntl(TeamSignupUsernamePage);
\ No newline at end of file diff --git a/web/react/components/team_signup_welcome_page.jsx b/web/react/components/team_signup_welcome_page.jsx index a374dd363..18951be72 100644 --- a/web/react/components/team_signup_welcome_page.jsx +++ b/web/react/components/team_signup_welcome_page.jsx @@ -5,7 +5,24 @@ import * as Utils from '../utils/utils.jsx'; import * as Client from '../utils/client.jsx'; import BrowserStore from '../stores/browser_store.jsx'; -export default class TeamSignupWelcomePage extends React.Component { +import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl'; + +const holders = defineMessages({ + storageError: { + id: 'team_signup_welcome.storageError', + defaultMessage: 'This service requires local storage to be enabled. Please enable it or exit private browsing.' + }, + validEmailError: { + id: 'team_signup_welcome.validEmailError', + defaultMessage: 'Please enter a valid email address' + }, + address: { + id: 'team_signup_welcome.address', + defaultMessage: 'Email Address' + } +}); + +class TeamSignupWelcomePage extends React.Component { constructor(props) { super(props); @@ -20,7 +37,7 @@ export default class TeamSignupWelcomePage extends React.Component { } submitNext(e) { if (!BrowserStore.isLocalStorageSupported()) { - this.setState({storageError: 'This service requires local storage to be enabled. Please enable it or exit private browsing.'}); + this.setState({storageError: this.props.intl.formatMessage(holders.storageError)}); return; } e.preventDefault(); @@ -34,15 +51,16 @@ export default class TeamSignupWelcomePage extends React.Component { handleDiffSubmit(e) { e.preventDefault(); + const {formatMessage} = this.props.intl; var state = {useDiff: true, serverError: ''}; var email = ReactDOM.findDOMNode(this.refs.email).value.trim().toLowerCase(); if (!email || !Utils.isEmail(email)) { - state.emailError = 'Please enter a valid email address'; + state.emailError = formatMessage(holders.validEmailError); this.setState(state); return; } else if (!BrowserStore.isLocalStorageSupported()) { - state.emailError = 'This service requires local storage to be enabled. Please enable it or exit private browsing.'; + state.emailError = formatMessage(holders.storageError); this.setState(state); return; } @@ -62,7 +80,7 @@ export default class TeamSignupWelcomePage extends React.Component { let errorMsg = err.message; if (err.detailed_error.indexOf('Invalid RCPT TO address provided') >= 0) { - errorMsg = 'Please enter a valid email address'; + errorMsg = formatMessage(holders.validEmailError); } this.setState({emailError: '', serverError: errorMsg}); @@ -114,18 +132,35 @@ export default class TeamSignupWelcomePage extends React.Component { className='signup-team-logo' src='/static/images/logo.png' /> - <h3 className='sub-heading'>Welcome to:</h3> + <h3 className='sub-heading'> + <FormattedMessage + id='team_signup_welcome.welcome' + defaultMessage='Welcome to:' + /> + </h3> <h1 className='margin--top-none'>{global.window.mm_config.SiteName}</h1> - <p className='margin--less'>Let's set up your new team</p> + <p className='margin--less'> + <FormattedMessage + id='team_signup_welcome.lets' + defaultMessage="Let's set up your new team" + /> + </p> <div> - Please confirm your email address:<br /> + <FormattedMessage + id='team_signup_welcome.confirm' + defaultMessage='Please confirm your email address:' + /> + <br /> <div className='inner__content'> <div className='block--gray'>{this.props.state.team.email}</div> </div> </div> <p className='margin--extra color--light'> - Your account will administer the new team site. <br /> - You can add other administrators later. + <FormattedHTMLMessage + id='team_signup_welcome.admin' + defaultMessage='Your account will administer the new team site. <br /> + You can add other administrators later.' + /> </p> <div className='form-group'> <button @@ -134,7 +169,10 @@ export default class TeamSignupWelcomePage extends React.Component { onClick={this.submitNext} > <i className='glyphicon glyphicon-ok'></i> - Yes, this address is correct + <FormattedMessage + id='team_signup_welcome.yes' + defaultMessage='Yes, this address is correct' + /> </button> {storageError} </div> @@ -147,7 +185,7 @@ export default class TeamSignupWelcomePage extends React.Component { type='email' ref='email' className='form-control' - placeholder='Email Address' + placeholder={this.props.intl.formatMessage(holders.address)} maxLength='128' spellCheck='false' /> @@ -161,7 +199,10 @@ export default class TeamSignupWelcomePage extends React.Component { type='button' onClick={this.handleDiffSubmit} > - Use this instead + <FormattedMessage + id='team_signup_welcome.instead' + defaultMessage='Use this instead' + /> </button> </div> <a @@ -169,7 +210,10 @@ export default class TeamSignupWelcomePage extends React.Component { onClick={this.handleDiffEmail} className={differentEmailLinkClass} > - Use a different email + <FormattedMessage + id='team_signup_welcome.different' + defaultMessage='Use a different email' + /> </a> </div> ); @@ -180,6 +224,9 @@ TeamSignupWelcomePage.defaultProps = { state: {} }; TeamSignupWelcomePage.propTypes = { + intl: intlShape.isRequired, updateParent: React.PropTypes.func.isRequired, state: React.PropTypes.object }; + +export default injectIntl(TeamSignupWelcomePage);
\ No newline at end of file |