summaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
authorElias Nahum <nahumhbl@gmail.com>2016-01-31 22:03:30 -0300
committerElias Nahum <nahumhbl@gmail.com>2016-02-01 11:25:07 -0300
commita6102e27d48d00fcc733c4d16754961903a239e0 (patch)
treed93a69e839666a9626ba936b7e44f52ac9d48845 /web
parent4a214cdaa2912f48dec4361722522c424384af49 (diff)
downloadchat-a6102e27d48d00fcc733c4d16754961903a239e0.tar.gz
chat-a6102e27d48d00fcc733c4d16754961903a239e0.tar.bz2
chat-a6102e27d48d00fcc733c4d16754961903a239e0.zip
PLT-7: Refactoring frontend (chunk 8)
- Sidebar and related components - Small Tweak to demotion and add msg for terminal cmd
Diffstat (limited to 'web')
-rw-r--r--web/react/components/about_build_modal.jsx65
-rw-r--r--web/react/components/admin_console/user_item.jsx13
-rw-r--r--web/react/components/change_url_modal.jsx54
-rw-r--r--web/react/components/get_link_modal.jsx22
-rw-r--r--web/react/components/get_team_invite_link_modal.jsx27
-rw-r--r--web/react/components/invite_member_modal.jsx126
-rw-r--r--web/react/components/member_list_team_item.jsx50
-rw-r--r--web/react/components/more_channels.jsx45
-rw-r--r--web/react/components/more_direct_channels.jsx71
-rw-r--r--web/react/components/navbar_dropdown.jsx68
-rw-r--r--web/react/components/new_channel_flow.jsx66
-rw-r--r--web/react/components/new_channel_modal.jsx118
-rw-r--r--web/react/components/setting_upload.jsx21
-rw-r--r--web/react/components/sidebar.jsx109
-rw-r--r--web/react/components/sidebar_header.jsx23
-rw-r--r--web/react/components/team_export_tab.jsx44
-rw-r--r--web/react/components/team_general_tab.jsx176
-rw-r--r--web/react/components/team_import_tab.jsx67
-rw-r--r--web/react/components/team_members_modal.jsx15
-rw-r--r--web/react/components/team_settings_modal.jsx34
-rw-r--r--web/react/components/unread_channel_indicator.jsx2
-rw-r--r--web/static/i18n/en.json156
-rw-r--r--web/static/i18n/es.json159
23 files changed, 1307 insertions, 224 deletions
diff --git a/web/react/components/about_build_modal.jsx b/web/react/components/about_build_modal.jsx
index f70027498..fe48bb48e 100644
--- a/web/react/components/about_build_modal.jsx
+++ b/web/react/components/about_build_modal.jsx
@@ -3,6 +3,8 @@
var Modal = ReactBootstrap.Modal;
+import {FormattedMessage} from 'mm-intl';
+
export default class AboutBuildModal extends React.Component {
constructor(props) {
super(props);
@@ -17,13 +19,28 @@ export default class AboutBuildModal extends React.Component {
const config = global.window.mm_config;
const license = global.window.mm_license;
- let title = 'Team Edition';
+ let title = (
+ <FormattedMessage
+ id='about.teamEdtion'
+ defaultMessage='Team Edition'
+ />
+ );
let licensee;
if (config.BuildEnterpriseReady === 'true' && license.IsLicensed === 'true') {
- title = 'Enterprise Edition';
+ title = (
+ <FormattedMessage
+ id='about.enterpriseEdition'
+ defaultMessage='Enterprise Edition'
+ />
+ );
licensee = (
<div className='row form-group'>
- <div className='col-sm-3 info__label'>{'Licensed by:'}</div>
+ <div className='col-sm-3 info__label'>
+ <FormattedMessage
+ id='about.licensed'
+ defaultMessage='Licensed by:'
+ />
+ </div>
<div className='col-sm-9'>{license.Company}</div>
</div>
);
@@ -35,25 +52,50 @@ export default class AboutBuildModal extends React.Component {
onHide={this.doHide}
>
<Modal.Header closeButton={true}>
- <Modal.Title>{'About Mattermost'}</Modal.Title>
+ <Modal.Title>
+ <FormattedMessage
+ id='about.title'
+ defaultMessage='About Mattermost'
+ />
+ </Modal.Title>
</Modal.Header>
<Modal.Body>
- <h4>{`Mattermost ${title}`}</h4>
+ <h4>{'Mattermost'} {title}</h4>
{licensee}
<div className='row form-group'>
- <div className='col-sm-3 info__label'>{'Version:'}</div>
+ <div className='col-sm-3 info__label'>
+ <FormattedMessage
+ id='about.version'
+ defaultMessage='Version:'
+ />
+ </div>
<div className='col-sm-9'>{config.Version}</div>
</div>
<div className='row form-group'>
- <div className='col-sm-3 info__label'>{'Build Number:'}</div>
+ <div className='col-sm-3 info__label'>
+ <FormattedMessage
+ id='about.number'
+ defaultMessage='Build Number:'
+ />
+ </div>
<div className='col-sm-9'>{config.BuildNumber}</div>
</div>
<div className='row form-group'>
- <div className='col-sm-3 info__label'>{'Build Date:'}</div>
+ <div className='col-sm-3 info__label'>
+ <FormattedMessage
+ id='about.date'
+ defaultMessage='Build Date:'
+ />
+ </div>
<div className='col-sm-9'>{config.BuildDate}</div>
</div>
<div className='row form-group'>
- <div className='col-sm-3 info__label'>{'Build Hash:'}</div>
+ <div className='col-sm-3 info__label'>
+ <FormattedMessage
+ id='about.hash'
+ defaultMessage='Build Hash:'
+ />
+ </div>
<div className='col-sm-9'>{config.BuildHash}</div>
</div>
</Modal.Body>
@@ -63,7 +105,10 @@ export default class AboutBuildModal extends React.Component {
className='btn btn-default'
onClick={this.doHide}
>
- {'Close'}
+ <FormattedMessage
+ id='about.close'
+ defaultMessage='Close'
+ />
</button>
</Modal.Footer>
</Modal>
diff --git a/web/react/components/admin_console/user_item.jsx b/web/react/components/admin_console/user_item.jsx
index 5ab429dd5..02b01b090 100644
--- a/web/react/components/admin_console/user_item.jsx
+++ b/web/react/components/admin_console/user_item.jsx
@@ -9,7 +9,7 @@ import TeamStore from '../../stores/team_store.jsx';
import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
-var messages = defineMessages({
+var holders = defineMessages({
confirmDemoteRoleTitle: {
id: 'admin.user_item.confirmDemoteRoleTitle',
defaultMessage: 'Confirm demotion from System Admin role'
@@ -21,6 +21,10 @@ var messages = defineMessages({
confirmDemoteDescription: {
id: 'admin.user_item.confirmDemoteDescription',
defaultMessage: 'If you demote yourself from the System Admin role and there is not another user with System Admin privileges, you\'ll need to re-assign a System Admin by accessing the Mattermost server through a terminal and running the following command.'
+ },
+ confirmDemotionCmd: {
+ id: 'admin.user_item.confirmDemotionCmd',
+ defaultMessage: 'platform -assign_role -team_name="yourteam" -email="name@yourcompany.com" -role="system_admin"'
}
});
@@ -332,14 +336,15 @@ export default class UserItem extends React.Component {
);
}
const me = UserStore.getCurrentUser();
+ const {formatMessage} = this.props.intl;
let makeDemoteModal = null;
if (this.props.user.id === me.id) {
makeDemoteModal = (
<ConfirmModal
show={this.state.showDemoteModal}
- title={this.props.intl.formatMessage(messages.confirmDemoteRoleTitle)}
- message={[this.props.intl.formatMessage(messages.confirmDemoteDescription), React.createElement('br'), React.createElement('br'), './platform -assign_role -team_name="yourteam" -email="name@yourcompany.com" -role="system_admin"', serverError]}
- confirm_button={this.props.intl.formatMessage(messages.confirmDemotion)}
+ title={formatMessage(holders.confirmDemoteRoleTitle)}
+ message={[formatMessage(holders.confirmDemoteDescription), React.createElement('br'), React.createElement('br'), formatMessage(holders.confirmDemotionCmd), serverError]}
+ confirm_button={formatMessage(holders.confirmDemotion)}
onConfirm={this.handleDemoteSubmit}
onCancel={this.handleDemoteCancel}
/>
diff --git a/web/react/components/change_url_modal.jsx b/web/react/components/change_url_modal.jsx
index bbe93f58d..49d1b86b4 100644
--- a/web/react/components/change_url_modal.jsx
+++ b/web/react/components/change_url_modal.jsx
@@ -4,6 +4,8 @@
var Modal = ReactBootstrap.Modal;
import * as Utils from '../utils/utils.jsx';
+import {FormattedMessage} from 'mm-intl';
+
export default class ChangeUrlModal extends React.Component {
constructor(props) {
super(props);
@@ -39,21 +41,58 @@ export default class ChangeUrlModal extends React.Component {
getURLError(url) {
let error = []; //eslint-disable-line prefer-const
if (url.length < 2) {
- error.push(<span key='error1'>{'Must be longer than two characters'}<br/></span>);
+ error.push(
+ <span key='error1'>
+ <FormattedMessage
+ id='change_url.longer'
+ defaultMessage='Must be longer than two characters'
+ />
+ <br/>
+ </span>
+ );
}
if (url.charAt(0) === '-' || url.charAt(0) === '_') {
- error.push(<span key='error2'>{'Must start with a letter or number'}<br/></span>);
+ error.push(
+ <span key='error2'>
+ <FormattedMessage
+ id='change_url.startWithLetter'
+ defaultMessage='Must start with a letter or number'
+ />
+ <br/>
+ </span>
+ );
}
if (url.length > 1 && (url.charAt(url.length - 1) === '-' || url.charAt(url.length - 1) === '_')) {
- error.push(<span key='error3'>{'Must end with a letter or number'}<br/></span>);
+ error.push(
+ <span key='error3'>
+ <FormattedMessage
+ id='change_url.endWithLetter'
+ defaultMessage='Must end with a letter or number'
+ />
+ <br/>
+ </span>);
}
if (url.indexOf('__') > -1) {
- error.push(<span key='error4'>{'Can not contain two underscores in a row.'}<br/></span>);
+ error.push(
+ <span key='error4'>
+ <FormattedMessage
+ id='change_url.noUnderscore'
+ defaultMessage='Can not contain two underscores in a row.'
+ />
+ <br/>
+ </span>);
}
// In case of error we don't detect
if (error.length === 0) {
- error.push(<span key='errorlast'>{'Invalid URL'}<br/></span>);
+ error.push(
+ <span key='errorlast'>
+ <FormattedMessage
+ id='change_url.invalidUrl'
+ defaultMessage='Invalid URL'
+ />
+ <br/>
+ </span>);
}
return error;
}
@@ -137,7 +176,10 @@ export default class ChangeUrlModal extends React.Component {
className='btn btn-default'
onClick={this.doCancel}
>
- {'Close'}
+ <FormattedMessage
+ id='change_url.close'
+ defaultMessage='Close'
+ />
</button>
<button
onClick={this.doSubmit}
diff --git a/web/react/components/get_link_modal.jsx b/web/react/components/get_link_modal.jsx
index fd20834f4..3fc71ff96 100644
--- a/web/react/components/get_link_modal.jsx
+++ b/web/react/components/get_link_modal.jsx
@@ -1,6 +1,8 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
+import {FormattedMessage} from 'mm-intl';
+
const Modal = ReactBootstrap.Modal;
export default class GetLinkModal extends React.Component {
@@ -59,14 +61,25 @@ export default class GetLinkModal extends React.Component {
className='btn btn-primary pull-left'
onClick={this.copyLink}
>
- {'Copy Link'}
+ <FormattedMessage
+ id='get_link.copy'
+ defaultMessage='Copy Link'
+ />
</button>
);
}
var copyLinkConfirm = null;
if (this.state.copiedLink) {
- copyLinkConfirm = <p className='alert alert-success copy-link-confirm'><i className='fa fa-check'></i>{' Link copied to clipboard.'}</p>;
+ copyLinkConfirm = (
+ <p className='alert alert-success copy-link-confirm'>
+ <i className='fa fa-check'></i>
+ <FormattedMessage
+ id='get_link.clipboard'
+ defaultMessage=' Link copied to clipboard.'
+ />
+ </p>
+ );
}
return (
@@ -92,7 +105,10 @@ export default class GetLinkModal extends React.Component {
className='btn btn-default'
onClick={this.onHide}
>
- {'Close'}
+ <FormattedMessage
+ id='get_link.close'
+ defaultMessage='Close'
+ />
</button>
{copyLink}
{copyLinkConfirm}
diff --git a/web/react/components/get_team_invite_link_modal.jsx b/web/react/components/get_team_invite_link_modal.jsx
index a926c4451..883871267 100644
--- a/web/react/components/get_team_invite_link_modal.jsx
+++ b/web/react/components/get_team_invite_link_modal.jsx
@@ -6,7 +6,20 @@ import GetLinkModal from './get_link_modal.jsx';
import ModalStore from '../stores/modal_store.jsx';
import TeamStore from '../stores/team_store.jsx';
-export default class GetTeamInviteLinkModal extends React.Component {
+import {intlShape, injectIntl, defineMessages} from 'mm-intl';
+
+const holders = defineMessages({
+ title: {
+ id: 'get_team_invite_link_modal.title',
+ defaultMessage: 'Team Invite Link'
+ },
+ help: {
+ id: 'get_team_invite_link_modal.help',
+ defaultMessage: 'Send teammates the link below for them to sign-up to this team site.'
+ }
+});
+
+class GetTeamInviteLinkModal extends React.Component {
constructor(props) {
super(props);
@@ -32,14 +45,22 @@ export default class GetTeamInviteLinkModal extends React.Component {
}
render() {
+ const {formatMessage} = this.props.intl;
+
return (
<GetLinkModal
show={this.state.show}
onHide={() => this.setState({show: false})}
- title='Team Invite Link'
- helpText='Send teammates the link below for them to sign-up to this team site.'
+ title={formatMessage(holders.title)}
+ helpText={formatMessage(holders.help)}
link={TeamStore.getCurrentInviteLink()}
/>
);
}
}
+
+GetTeamInviteLinkModal.propTypes = {
+ intl: intlShape.isRequired
+};
+
+export default injectIntl(GetTeamInviteLinkModal); \ No newline at end of file
diff --git a/web/react/components/invite_member_modal.jsx b/web/react/components/invite_member_modal.jsx
index 7e1627555..f2a0a7565 100644
--- a/web/react/components/invite_member_modal.jsx
+++ b/web/react/components/invite_member_modal.jsx
@@ -12,9 +12,38 @@ import ChannelStore from '../stores/channel_store.jsx';
import TeamStore from '../stores/team_store.jsx';
import ConfirmModal from './confirm_modal.jsx';
+import {intlShape, injectIntl, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
+
const Modal = ReactBootstrap.Modal;
-export default class InviteMemberModal extends React.Component {
+const holders = defineMessages({
+ emailError: {
+ id: 'invite_member.emailError',
+ defaultMessage: 'Please enter a valid email address'
+ },
+ firstname: {
+ id: 'invite_member.firstname',
+ defaultMessage: 'First name'
+ },
+ lastname: {
+ id: 'invite_member.lastname',
+ defaultMessage: 'Last name'
+ },
+ modalTitle: {
+ id: 'invite_member.modalTitle',
+ defaultMessage: 'Discard Invitations?'
+ },
+ modalMessage: {
+ id: 'invite_member.modalMessage',
+ defaultMessage: 'You have unsent invitations, are you sure you want to discard them?'
+ },
+ modalButton: {
+ id: 'invite_member.modalButton',
+ defaultMessage: 'Yes, Discard'
+ }
+});
+
+class InviteMemberModal extends React.Component {
constructor(props) {
super(props);
@@ -72,7 +101,7 @@ export default class InviteMemberModal extends React.Component {
var invite = {};
invite.email = ReactDOM.findDOMNode(this.refs['email' + index]).value.trim();
if (!invite.email || !utils.isEmail(invite.email)) {
- emailErrors[index] = 'Please enter a valid email address';
+ emailErrors[index] = this.props.intl.formatMessage(holders.emailError);
valid = false;
} else {
emailErrors[index] = '';
@@ -103,7 +132,7 @@ export default class InviteMemberModal extends React.Component {
this.setState({isSendingEmails: false});
},
(err) => {
- if (err.message === 'This person is already on your team') {
+ if (err.id === 'api.team.invite_members.already.app_error') {
emailErrors[err.detailed_error] = err.message;
this.setState({emailErrors: emailErrors});
} else {
@@ -199,6 +228,7 @@ export default class InviteMemberModal extends React.Component {
render() {
var currentUser = UserStore.getCurrentUser();
+ const {formatMessage} = this.props.intl;
if (currentUser != null) {
var inviteSections = [];
@@ -252,7 +282,7 @@ export default class InviteMemberModal extends React.Component {
type='text'
className='form-control'
ref={'first_name' + index}
- placeholder='First name'
+ placeholder={formatMessage(holders.firstname)}
maxLength='64'
disabled={!this.state.emailEnabled || !this.state.userCreationEnabled}
spellCheck='false'
@@ -266,7 +296,7 @@ export default class InviteMemberModal extends React.Component {
type='text'
className='form-control'
ref={'last_name' + index}
- placeholder='Last name'
+ placeholder={formatMessage(holders.lastname)}
maxLength='64'
disabled={!this.state.emailEnabled || !this.state.userCreationEnabled}
spellCheck='false'
@@ -318,20 +348,48 @@ export default class InviteMemberModal extends React.Component {
type='button'
className='btn btn-default'
onClick={this.addInviteFields}
- >{'Add another'}</button>
+ >
+ <FormattedMessage
+ id='invite_member.addAnother'
+ defaultMessage='Add another'
+ />
+ </button>
<br/>
<br/>
- <span>{'People invited automatically join the '}<strong>{defaultChannelName}</strong>{' channel.'}</span>
+ <span>
+ <FormattedHTMLMessage
+ id='invite_member.autoJoin'
+ defaultMessage='People invited automatically join the <strong>{channel}</strong> channel.'
+ values={{
+ channel: defaultChannelName
+ }}
+ />
+ </span>
</div>
);
- var sendButtonLabel = 'Send Invitation';
+ var sendButtonLabel = (
+ <FormattedMessage
+ id='invite_member.send'
+ defaultMessage='Send Invitation'
+ />
+ );
if (this.state.isSendingEmails) {
sendButtonLabel = (
- <span><i className='fa fa-spinner fa-spin' />{' Sending'}</span>
+ <span><i className='fa fa-spinner fa-spin' />
+ <FormattedMessage
+ id='invite_member.sending'
+ defaultMessage=' Sending'
+ />
+ </span>
);
} else if (this.state.inviteIds.length > 1) {
- sendButtonLabel = 'Send Invitations';
+ sendButtonLabel = (
+ <FormattedMessage
+ id='invite_member.send2'
+ defaultMessage='Send Invitations'
+ />
+ );
}
sendButton = (
@@ -352,27 +410,46 @@ export default class InviteMemberModal extends React.Component {
href='#'
onClick={this.showGetTeamInviteLinkModal}
>
- {'Team Invite Link'}
+ <FormattedMessage
+ id='invite_member.inviteLink'
+ defaultMessage='Team Invite Link'
+ />
</a>
);
teamInviteLink = (
<p>
- {'You can also invite people using the '}{link}{'.'}
+ <FormattedMessage
+ id='invite_member.teamInviteLink'
+ defaultMessage='You can also invite people using the {link}.'
+ values={{
+ link: (link)
+ }}
+ />
</p>
);
}
content = (
<div>
- <p>{'Email is currently disabled for your team, and email invitations cannot be sent. Contact your system administrator to enable email and email invitations.'}</p>
+ <p>
+ <FormattedMessage
+ id='invite_member.content'
+ defaultMessage='Email is currently disabled for your team, and email invitations cannot be sent. Contact your system administrator to enable email and email invitations.'
+ />
+ </p>
{teamInviteLink}
</div>
);
} else {
content = (
<div>
- <p>{'User creation has been disabled for your team. Please ask your team administrator for details.'}</p>
+ <p>
+ <FormattedMessage
+ id='invite_member.disabled'
+ defaultMessage='User creation has been disabled for your team. Please ask your team administrator for details.'
+ />
+ </p>
</div>
);
}
@@ -387,7 +464,12 @@ export default class InviteMemberModal extends React.Component {
backdrop={this.state.isSendingEmails ? 'static' : true}
>
<Modal.Header closeButton={!this.state.isSendingEmails}>
- <Modal.Title>{'Invite New Member'}</Modal.Title>
+ <Modal.Title>
+ <FormattedMessage
+ id='invite_member.newMember'
+ defaultMessage='Invite New Member'
+ />
+ </Modal.Title>
</Modal.Header>
<Modal.Body ref='modalBody'>
<form role='form'>
@@ -402,15 +484,18 @@ export default class InviteMemberModal extends React.Component {
onClick={this.handleHide.bind(this, true)}
disabled={this.state.isSendingEmails}
>
- {'Cancel'}
+ <FormattedMessage
+ id='invite_member.cancel'
+ defaultMessage='Cancel'
+ />
</button>
{sendButton}
</Modal.Footer>
</Modal>
<ConfirmModal
- title='Discard Invitations?'
- message='You have unsent invitations, are you sure you want to discard them?'
- confirm_button='Yes, Discard'
+ title={formatMessage(holders.modalTitle)}
+ message={formatMessage(holders.modalMessage)}
+ confirm_button={formatMessage(holders.modalButton)}
show={this.state.showConfirmModal}
onConfirm={this.handleHide.bind(this, false)}
onCancel={() => this.setState({showConfirmModal: false})}
@@ -424,4 +509,7 @@ export default class InviteMemberModal extends React.Component {
}
InviteMemberModal.propTypes = {
+ intl: intlShape.isRequired
};
+
+export default injectIntl(InviteMemberModal); \ No newline at end of file
diff --git a/web/react/components/member_list_team_item.jsx b/web/react/components/member_list_team_item.jsx
index 7967c410d..6e1006911 100644
--- a/web/react/components/member_list_team_item.jsx
+++ b/web/react/components/member_list_team_item.jsx
@@ -6,6 +6,8 @@ import * as Client from '../utils/client.jsx';
import * as AsyncClient from '../utils/async_client.jsx';
import * as Utils from '../utils/utils.jsx';
+import {FormattedMessage} from 'mm-intl';
+
export default class MemberListTeamItem extends React.Component {
constructor(props) {
super(props);
@@ -78,14 +80,29 @@ export default class MemberListTeamItem extends React.Component {
}
const user = this.props.user;
- let currentRoles = 'Member';
+ let currentRoles = (
+ <FormattedMessage
+ id='member_team_item.member'
+ defaultMessage='Member'
+ />
+ );
const timestamp = UserStore.getCurrentUser().update_at;
if (user.roles.length > 0) {
if (Utils.isSystemAdmin(user.roles)) {
- currentRoles = 'System Admin';
+ currentRoles = (
+ <FormattedMessage
+ id='member_team_item.systemAdmin'
+ defaultMessage='System Admin'
+ />
+ );
} else if (Utils.isAdmin(user.roles)) {
- currentRoles = 'Team Admin';
+ currentRoles = (
+ <FormattedMessage
+ id='member_team_item.teamAdmin'
+ defaultMessage='Team Admin'
+ />
+ );
} else {
currentRoles = user.roles.charAt(0).toUpperCase() + user.roles.slice(1);
}
@@ -98,7 +115,12 @@ export default class MemberListTeamItem extends React.Component {
let showMakeNotActive = user.roles !== 'system_admin';
if (user.delete_at > 0) {
- currentRoles = 'Inactive';
+ currentRoles = (
+ <FormattedMessage
+ id='member_team_item.inactive'
+ defaultMessage='Inactive'
+ />
+ );
showMakeMember = false;
showMakeAdmin = false;
showMakeActive = true;
@@ -114,7 +136,10 @@ export default class MemberListTeamItem extends React.Component {
href='#'
onClick={this.handleMakeAdmin}
>
- {'Make Team Admin'}
+ <FormattedMessage
+ id='member_team_item.makeAdmin'
+ defaultMessage='Make Team Admin'
+ />
</a>
</li>
);
@@ -129,7 +154,10 @@ export default class MemberListTeamItem extends React.Component {
href='#'
onClick={this.handleMakeMember}
>
- {'Make Member'}
+ <FormattedMessage
+ id='member_team_item.makeMember'
+ defaultMessage='Make Member'
+ />
</a>
</li>
);
@@ -144,7 +172,10 @@ export default class MemberListTeamItem extends React.Component {
href='#'
onClick={this.handleMakeActive}
>
- {'Make Active'}
+ <FormattedMessage
+ id='member_team_item.makeActive'
+ defaultMessage='Make Active'
+ />
</a>
</li>
);
@@ -159,7 +190,10 @@ export default class MemberListTeamItem extends React.Component {
href='#'
onClick={this.handleMakeNotActive}
>
- {'Make Inactive'}
+ <FormattedMessage
+ id='member_team_item.makeInactive'
+ defaultMessage='Make Inactive'
+ />
</a>
</li>
);
diff --git a/web/react/components/more_channels.jsx b/web/react/components/more_channels.jsx
index 29512b9b7..d12ea4703 100644
--- a/web/react/components/more_channels.jsx
+++ b/web/react/components/more_channels.jsx
@@ -8,6 +8,8 @@ import ChannelStore from '../stores/channel_store.jsx';
import LoadingScreen from './loading_screen.jsx';
import NewChannelFlow from './new_channel_flow.jsx';
+import {FormattedMessage} from 'mm-intl';
+
function getStateFromStores() {
return {
channels: ChannelStore.getMoreAll(),
@@ -100,7 +102,10 @@ export default class MoreChannels extends React.Component {
onClick={self.handleJoin.bind(self, channel, index)}
className='btn btn-primary'
>
- Join
+ <FormattedMessage
+ id='more_channels.join'
+ defaultMessage='Join'
+ />
</button>
);
}
@@ -123,8 +128,18 @@ export default class MoreChannels extends React.Component {
} else {
moreChannels = (
<div className='no-channel-message'>
- <p className='primary-message'>No more channels to join</p>
- <p className='secondary-message'>Click 'Create New Channel' to make a new one</p>
+ <p className='primary-message'>
+ <FormattedMessage
+ id='more_channels.noMore'
+ defaultMessage='No more channels to join'
+ />
+ </p>
+ <p className='secondary-message'>
+ <FormattedMessage
+ id='more_channels.createClick'
+ defaultMessage="Click 'Create New Channel' to make a new one"
+ />
+ </p>
</div>
);
}
@@ -148,15 +163,28 @@ export default class MoreChannels extends React.Component {
data-dismiss='modal'
>
<span aria-hidden='true'>{'×'}</span>
- <span className='sr-only'>{'Close'}</span>
+ <span className='sr-only'>
+ <FormattedMessage
+ id='more_channels.close'
+ defaultMessage='Close'
+ />
+ </span>
</button>
- <h4 className='modal-title'>{'More Channels'}</h4>
+ <h4 className='modal-title'>
+ <FormattedMessage
+ id='more_channels.title'
+ defaultMessage='More Channels'
+ />
+ </h4>
<button
type='button'
className='btn btn-primary channel-create-btn'
onClick={this.handleNewChannel}
>
- {'Create New Channel'}
+ <FormattedMessage
+ id='more_channels.create'
+ defaultMessage='Create New Channel'
+ />
</button>
<NewChannelFlow
show={this.state.showNewChannelModal}
@@ -174,7 +202,10 @@ export default class MoreChannels extends React.Component {
className='btn btn-default'
data-dismiss='modal'
>
- {'Close'}
+ <FormattedMessage
+ id='more_channels.close'
+ defaultMessage='Close'
+ />
</button>
</div>
</div>
diff --git a/web/react/components/more_direct_channels.jsx b/web/react/components/more_direct_channels.jsx
index 3661b19e6..f8a6884d0 100644
--- a/web/react/components/more_direct_channels.jsx
+++ b/web/react/components/more_direct_channels.jsx
@@ -5,7 +5,20 @@ const Modal = ReactBootstrap.Modal;
import UserStore from '../stores/user_store.jsx';
import * as Utils from '../utils/utils.jsx';
-export default class MoreDirectChannels extends React.Component {
+import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl';
+
+const holders = defineMessages({
+ member: {
+ id: 'more_direct_channels.member',
+ defaultMessage: 'Member'
+ },
+ search: {
+ id: 'more_direct_channels.search',
+ defaultMessage: 'Search members'
+ }
+});
+
+class MoreDirectChannels extends React.Component {
constructor(props) {
super(props);
@@ -148,7 +161,10 @@ export default class MoreDirectChannels extends React.Component {
className='btn btn-primary btn-message'
onClick={this.handleShowDirectChannel.bind(this, user)}
>
- {'Message'}
+ <FormattedMessage
+ id='more_direct_channels.message'
+ defaultMessage='Message'
+ />
</button>
);
}
@@ -180,6 +196,7 @@ export default class MoreDirectChannels extends React.Component {
}
render() {
+ const {formatMessage} = this.props.intl;
if (!this.props.show) {
return null;
}
@@ -199,19 +216,44 @@ export default class MoreDirectChannels extends React.Component {
const userEntries = users.map(this.createRowForUser);
if (userEntries.length === 0) {
- userEntries.push(<tr key='no-users-found'><td>{'No users found :('}</td></tr>);
+ userEntries.push(
+ <tr key='no-users-found'><td>
+ <FormattedMessage
+ id='more_direct_channels.notFound'
+ defaultMessage='No users found :('
+ />
+ </td></tr>);
}
- let memberString = 'Member';
+ let memberString = formatMessage(holders.member);
if (users.length !== 1) {
memberString += 's';
}
let count;
if (users.length === this.state.users.length) {
- count = `${users.length} ${memberString}`;
+ count = (
+ <FormattedMessage
+ id='more_direct_channels.count'
+ defaultMessage='{count} {member}'
+ values={{
+ count: users.length,
+ member: memberString
+ }}
+ />
+ );
} else {
- count = `${users.length} ${memberString} of ${this.state.users.length} Total`;
+ count = (
+ <FormattedMessage
+ id='more_direct_channels.countTotal'
+ defaultMessage='{count} {member} of {total} Total'
+ values={{
+ count: users.length,
+ member: memberString,
+ total: this.state.users.length
+ }}
+ />
+ );
}
return (
@@ -221,7 +263,12 @@ export default class MoreDirectChannels extends React.Component {
onHide={this.handleHide}
>
<Modal.Header closeButton={true}>
- <Modal.Title>{'Direct Messages'}</Modal.Title>
+ <Modal.Title>
+ <FormattedMessage
+ id='more_direct_channels.title'
+ defaultMessage='Direct Messages'
+ />
+ </Modal.Title>
</Modal.Header>
<Modal.Body ref='modalBody'>
<div className='filter-row'>
@@ -229,7 +276,7 @@ export default class MoreDirectChannels extends React.Component {
<input
ref='filter'
className='form-control filter-textbox'
- placeholder='Search members'
+ placeholder={formatMessage(holders.search)}
onInput={this.handleFilterChange}
/>
</div>
@@ -254,7 +301,10 @@ export default class MoreDirectChannels extends React.Component {
className='btn btn-default'
onClick={this.handleHide}
>
- {'Close'}
+ <FormattedMessage
+ id='more_direct_channels.close'
+ defaultMessage='Close'
+ />
</button>
</Modal.Footer>
</Modal>
@@ -263,6 +313,9 @@ export default class MoreDirectChannels extends React.Component {
}
MoreDirectChannels.propTypes = {
+ intl: intlShape.isRequired,
show: React.PropTypes.bool.isRequired,
onModalDismissed: React.PropTypes.func
};
+
+export default injectIntl(MoreDirectChannels); \ No newline at end of file
diff --git a/web/react/components/navbar_dropdown.jsx b/web/react/components/navbar_dropdown.jsx
index d4ec5a5f5..e9df03c33 100644
--- a/web/react/components/navbar_dropdown.jsx
+++ b/web/react/components/navbar_dropdown.jsx
@@ -14,6 +14,8 @@ import UserSettingsModal from './user_settings/user_settings_modal.jsx';
import Constants from '../utils/constants.jsx';
+import {FormattedMessage} from 'mm-intl';
+
function getStateFromStores() {
const teams = [];
const teamsObject = UserStore.getTeams();
@@ -97,7 +99,10 @@ export default class NavbarDropdown extends React.Component {
href='#'
onClick={EventHelpers.showInviteMemberModal}
>
- {'Invite New Member'}
+ <FormattedMessage
+ id='navbar_dropdown.inviteMember'
+ defaultMessage='Invite New Member'
+ />
</a>
</li>
);
@@ -109,7 +114,10 @@ export default class NavbarDropdown extends React.Component {
href='#'
onClick={EventHelpers.showGetTeamInviteLinkModal}
>
- {'Get Team Invite Link'}
+ <FormattedMessage
+ id='navbar_dropdown.teamLink'
+ defaultMessage='Get Team Invite Link'
+ />
</a>
</li>
);
@@ -120,7 +128,10 @@ export default class NavbarDropdown extends React.Component {
manageLink = (
<li>
<ToggleModalButton dialogType={TeamMembersModal}>
- {'Manage Members'}
+ <FormattedMessage
+ id='navbar_dropdown.manageMembers'
+ defaultMessage='Manage Members'
+ />
</ToggleModalButton>
</li>
);
@@ -134,7 +145,10 @@ export default class NavbarDropdown extends React.Component {
data-toggle='modal'
data-target='#team_settings'
>
- {'Team Settings'}
+ <FormattedMessage
+ id='navbar_dropdown.teamSettings'
+ defaultMessage='Team Settings'
+ />
</a>
</li>
);
@@ -146,7 +160,10 @@ export default class NavbarDropdown extends React.Component {
<a
href={'/admin_console?' + Utils.getSessionIndex()}
>
- {'System Console'}
+ <FormattedMessage
+ id='navbar_dropdown.console'
+ defaultMessage='System Console'
+ />
</a>
</li>
);
@@ -165,7 +182,16 @@ export default class NavbarDropdown extends React.Component {
this.state.teams.forEach((team) => {
if (team.name !== this.props.teamName) {
- teams.push(<li key={team.name}><a href={Utils.getWindowLocationOrigin() + '/' + team.name}>{'Switch to ' + team.display_name}</a></li>);
+ teams.push(
+ <li key={team.name}><a href={Utils.getWindowLocationOrigin() + '/' + team.name}>
+ <FormattedMessage
+ id='navbar_dropdown.switchTeam'
+ defaultMessage='Switch to {team}'
+ values={{
+ team: team.display_name
+ }}
+ />
+ </a></li>);
}
});
}
@@ -178,7 +204,10 @@ export default class NavbarDropdown extends React.Component {
target='_blank'
href={Utils.getWindowLocationOrigin() + '/signup_team'}
>
- {'Create a New Team'}
+ <FormattedMessage
+ id='navbar_dropdown.create'
+ defaultMessage='Create a New Team'
+ />
</a>
</li>
);
@@ -192,7 +221,10 @@ export default class NavbarDropdown extends React.Component {
target='_blank'
href={global.window.mm_config.HelpLink}
>
- {'Help'}
+ <FormattedMessage
+ id='navbar_dropdown.help'
+ defaultMessage='Help'
+ />
</a>
</li>
);
@@ -206,7 +238,10 @@ export default class NavbarDropdown extends React.Component {
target='_blank'
href={global.window.mm_config.ReportAProblemLink}
>
- {'Report a Problem'}
+ <FormattedMessage
+ id='navbar_dropdown.report'
+ defaultMessage='Report a Problem'
+ />
</a>
</li>
);
@@ -239,7 +274,10 @@ export default class NavbarDropdown extends React.Component {
href='#'
onClick={() => this.setState({showUserSettingsModal: true})}
>
- {'Account Settings'}
+ <FormattedMessage
+ id='navbar_dropdown.accountSettings'
+ defaultMessage='Account Settings'
+ />
</a>
</li>
{inviteLink}
@@ -249,7 +287,10 @@ export default class NavbarDropdown extends React.Component {
href='#'
onClick={this.handleLogoutClick}
>
- {'Logout'}
+ <FormattedMessage
+ id='navbar_dropdown.logout'
+ defaultMessage='Logout'
+ />
</a>
</li>
{adminDivider}
@@ -265,7 +306,10 @@ export default class NavbarDropdown extends React.Component {
href='#'
onClick={this.handleAboutModal}
>
- {'About Mattermost'}
+ <FormattedMessage
+ id='navbar_dropdown.about'
+ defaultMessage='About Mattermost'
+ />
</a>
</li>
<UserSettingsModal
diff --git a/web/react/components/new_channel_flow.jsx b/web/react/components/new_channel_flow.jsx
index 3a114aa19..a0bb14e8f 100644
--- a/web/react/components/new_channel_flow.jsx
+++ b/web/react/components/new_channel_flow.jsx
@@ -9,11 +9,47 @@ import UserStore from '../stores/user_store.jsx';
import NewChannelModal from './new_channel_modal.jsx';
import ChangeURLModal from './change_url_modal.jsx';
+import {intlShape, injectIntl, defineMessages} from 'mm-intl';
+
const SHOW_NEW_CHANNEL = 1;
const SHOW_EDIT_URL = 2;
const SHOW_EDIT_URL_THEN_COMPLETE = 3;
+const messages = defineMessages({
+ invalidName: {
+ id: 'channel_flow.invalidName',
+ defaultMessage: 'Invalid Channel Name'
+ },
+ alreadyExist: {
+ id: 'channel_flow.alreadyExist',
+ defaultMessage: 'A channel with that URL already exists'
+ },
+ channel: {
+ id: 'channel_flow.channel',
+ defaultMessage: 'Channel'
+ },
+ group: {
+ id: 'channel_flow.group',
+ defaultMessage: 'Group'
+ },
+ change: {
+ id: 'channel_flow.changeUrlTitle',
+ defaultMessage: 'Change {term} URL'
+ },
+ set: {
+ id: 'channel_flow.set_url_title',
+ defaultMessage: 'Set {term} URL'
+ },
+ create: {
+ id: 'channel_flow.create',
+ defaultMessage: 'Create {term}'
+ },
+ changeUrlDescription: {
+ id: 'channel_flow.changeUrlDescription',
+ defaultMessage: 'Some characters are not allowed in URLs and may be removed.'
+ }
+});
-export default class NewChannelFlow extends React.Component {
+class NewChannelFlow extends React.Component {
constructor(props) {
super(props);
@@ -51,9 +87,10 @@ export default class NewChannelFlow extends React.Component {
doSubmit() {
var channel = {};
+ const {formatMessage} = this.props.intl;
channel.display_name = this.state.channelDisplayName;
if (!channel.display_name) {
- this.setState({serverError: 'Invalid Channel Name'});
+ this.setState({serverError: formatMessage(messages.invalidName)});
return;
}
@@ -75,11 +112,11 @@ export default class NewChannelFlow extends React.Component {
Utils.switchChannel(data);
},
(err) => {
- if (err.message === 'Name must be 2 or more lowercase alphanumeric characters') {
+ if (err.id === 'model.channel.is_valid.2_or_more.app_error') {
this.setState({flowState: SHOW_EDIT_URL_THEN_COMPLETE});
}
- if (err.message === 'A channel with that handle already exists') {
- this.setState({serverError: 'A channel with that URL already exists'});
+ if (err.id === 'store.sql_channel.update.exists.app_error') {
+ this.setState({serverError: formatMessage(messages.alreadyExist)});
return;
}
this.setState({serverError: err.message});
@@ -130,27 +167,29 @@ export default class NewChannelFlow extends React.Component {
let changeURLSubmitButtonText = '';
let channelTerm = '';
+ const {formatMessage} = this.props.intl;
+
// Only listen to flow state if we are being shown
if (this.props.show) {
switch (this.state.flowState) {
case SHOW_NEW_CHANNEL:
if (this.state.channelType === 'O') {
showChannelModal = true;
- channelTerm = 'Channel';
+ channelTerm = formatMessage(messages.channel);
} else {
showGroupModal = true;
- channelTerm = 'Group';
+ channelTerm = formatMessage(messages.group);
}
break;
case SHOW_EDIT_URL:
showChangeURLModal = true;
- changeURLTitle = 'Change ' + channelTerm + ' URL';
- changeURLSubmitButtonText = 'Change ' + channelTerm + ' URL';
+ changeURLTitle = formatMessage(messages.change, {term: channelTerm});
+ changeURLSubmitButtonText = formatMessage(messages.change, {term: channelTerm});
break;
case SHOW_EDIT_URL_THEN_COMPLETE:
showChangeURLModal = true;
- changeURLTitle = 'Set ' + channelTerm + ' URL';
- changeURLSubmitButtonText = 'Create ' + channelTerm;
+ changeURLTitle = formatMessage(messages.set, {term: channelTerm});
+ changeURLSubmitButtonText = formatMessage(messages.create, {term: channelTerm});
break;
}
}
@@ -181,7 +220,7 @@ export default class NewChannelFlow extends React.Component {
<ChangeURLModal
show={showChangeURLModal}
title={changeURLTitle}
- description={'Some characters are not allowed in URLs and may be removed.'}
+ description={formatMessage(messages.changeUrlDescription)}
urlLabel={channelTerm + ' URL'}
submitButtonText={changeURLSubmitButtonText}
currentURL={this.state.channelName}
@@ -200,7 +239,10 @@ NewChannelFlow.defaultProps = {
};
NewChannelFlow.propTypes = {
+ intl: intlShape.isRequired,
show: React.PropTypes.bool.isRequired,
channelType: React.PropTypes.string.isRequired,
onModalDismissed: React.PropTypes.func.isRequired
};
+
+export default injectIntl(NewChannelFlow); \ No newline at end of file
diff --git a/web/react/components/new_channel_modal.jsx b/web/react/components/new_channel_modal.jsx
index 9f733c476..788e6dc1b 100644
--- a/web/react/components/new_channel_modal.jsx
+++ b/web/react/components/new_channel_modal.jsx
@@ -2,9 +2,19 @@
// See License.txt for license information.
import * as Utils from '../utils/utils.jsx';
+
+import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl';
+
var Modal = ReactBootstrap.Modal;
-export default class NewChannelModal extends React.Component {
+const holders = defineMessages({
+ nameEx: {
+ id: 'channel_modal.nameEx',
+ defaultMessage: 'E.g.: "Bugs", "Marketing", "办公室恋情"'
+ }
+});
+
+class NewChannelModal extends React.Component {
constructor(props) {
super(props);
@@ -32,7 +42,7 @@ export default class NewChannelModal extends React.Component {
const displayName = ReactDOM.findDOMNode(this.refs.display_name).value.trim();
if (displayName.length < 1) {
- this.setState({displayNameError: 'This field is required'});
+ this.setState({displayNameError: true});
return;
}
@@ -51,7 +61,15 @@ export default class NewChannelModal extends React.Component {
var displayNameClass = 'form-group';
if (this.state.displayNameError) {
- displayNameError = <p className='input__help error'>{this.state.displayNameError}</p>;
+ displayNameError = (
+ <p className='input__help error'>
+ <FormattedMessage
+ id='channel_modal.displayNameError'
+ defaultMessage='This field is required'
+ />
+ {this.state.displayNameError}
+ </p>
+ );
displayNameClass += ' has-error';
}
@@ -63,29 +81,51 @@ export default class NewChannelModal extends React.Component {
var channelSwitchText = '';
switch (this.props.channelType) {
case 'P':
- channelTerm = 'Group';
+ channelTerm = (
+ <FormattedMessage
+ id='channel_modal.group'
+ defaultMessage='Group'
+ />
+ );
channelSwitchText = (
<div className='modal-intro'>
- {'Create a new private group with restricted membership. '}
+ <FormattedMessage
+ id='channel_modal.privateGroup1'
+ defaultMessage='Create a new private group with restricted membership. '
+ />
<a
href='#'
onClick={this.props.onTypeSwitched}
>
- {'Create a public channel'}
+ <FormattedMessage
+ id='channel_modal.publicChannel1'
+ defaultMessage='Create a public channel'
+ />
</a>
</div>
);
break;
case 'O':
- channelTerm = 'Channel';
+ channelTerm = (
+ <FormattedMessage
+ id='channel_modal.channel'
+ defaultMessage='Channel'
+ />
+ );
channelSwitchText = (
<div className='modal-intro'>
- {'Create a new public channel anyone can join. '}
+ <FormattedMessage
+ id='channel_modal.publicChannel2'
+ defaultMessage='Create a new public channel anyone can join. '
+ />
<a
href='#'
onClick={this.props.onTypeSwitched}
>
- {'Create a private group'}
+ <FormattedMessage
+ id='channel_modal.privateGroup2'
+ defaultMessage='Create a private group'
+ />
</a>
</div>
);
@@ -102,7 +142,13 @@ export default class NewChannelModal extends React.Component {
onHide={this.props.onModalDismissed}
>
<Modal.Header closeButton={true}>
- <Modal.Title>{'New ' + channelTerm}</Modal.Title>
+ <Modal.Title>
+ <FormattedMessage
+ id='channel_modal.modalTitle'
+ defaultMessage='New '
+ />
+ {channelTerm}
+ </Modal.Title>
</Modal.Header>
<form
role='form'
@@ -113,14 +159,19 @@ export default class NewChannelModal extends React.Component {
{channelSwitchText}
</div>
<div className={displayNameClass}>
- <label className='col-sm-3 form__label control-label'>{'Name'}</label>
+ <label className='col-sm-3 form__label control-label'>
+ <FormattedMessage
+ id='channel_modal.name'
+ defaultMessage='Name'
+ />
+ </label>
<div className='col-sm-9'>
<input
onChange={this.handleChange}
type='text'
ref='display_name'
className='form-control'
- placeholder='E.g.: "Bugs", "Marketing", "办公室恋情"'
+ placeholder={this.props.intl.formatMessage(holders.nameEx)}
maxLength='22'
value={this.props.channelData.displayName}
autoFocus={true}
@@ -133,7 +184,10 @@ export default class NewChannelModal extends React.Component {
href='#'
onClick={this.props.onChangeURLPressed}
>
- {'Edit'}
+ <FormattedMessage
+ id='channel_modal.edit'
+ defaultMessage='Edit'
+ />
</a>
{')'}
</p>
@@ -141,22 +195,38 @@ export default class NewChannelModal extends React.Component {
</div>
<div className='form-group less'>
<div className='col-sm-3'>
- <label className='form__label control-label'>{'Purpose'}</label>
- <label className='form__label light'>{'(optional)'}</label>
+ <label className='form__label control-label'>
+ <FormattedMessage
+ id='channel_modal.purpose'
+ defaultMessage='Purpose'
+ />
+ </label>
+ <label className='form__label light'>
+ <FormattedMessage
+ id='channel_modal.optional'
+ defaultMessage='(optional)'
+ />
+ </label>
</div>
<div className='col-sm-9'>
<textarea
className='form-control no-resize'
ref='channel_purpose'
rows='4'
- placeholder='Purpose'
+ placeholder={this.props.intl.formatMessage({id: 'channel_modal.purpose'})}
maxLength='128'
value={this.props.channelData.purpose}
onChange={this.handleChange}
tabIndex='2'
/>
<p className='input__help'>
- {`Describe how this ${channelTerm} should be used.`}
+ <FormattedMessage
+ id='channel_modal.descriptionHelp'
+ defaultMessage='Describe how this {term} should be used.'
+ values={{
+ term: (channelTerm)
+ }}
+ />
</p>
{serverError}
</div>
@@ -168,7 +238,10 @@ export default class NewChannelModal extends React.Component {
className='btn btn-default'
onClick={this.props.onModalDismissed}
>
- {'Cancel'}
+ <FormattedMessage
+ id='channel_modal.cancel'
+ defaultMessage='Cancel'
+ />
</button>
<button
onClick={this.handleSubmit}
@@ -176,7 +249,11 @@ export default class NewChannelModal extends React.Component {
className='btn btn-primary'
tabIndex='3'
>
- {'Create New ' + channelTerm}
+ <FormattedMessage
+ id='channel_modal.createNew'
+ defaultMessage='Create New '
+ />
+ {channelTerm}
</button>
</Modal.Footer>
</form>
@@ -192,6 +269,7 @@ NewChannelModal.defaultProps = {
serverError: ''
};
NewChannelModal.propTypes = {
+ intl: intlShape.isRequired,
show: React.PropTypes.bool.isRequired,
channelType: React.PropTypes.string.isRequired,
channelData: React.PropTypes.object.isRequired,
@@ -202,3 +280,5 @@ NewChannelModal.propTypes = {
onChangeURLPressed: React.PropTypes.func.isRequired,
onDataChanged: React.PropTypes.func.isRequired
};
+
+export default injectIntl(NewChannelModal); \ No newline at end of file
diff --git a/web/react/components/setting_upload.jsx b/web/react/components/setting_upload.jsx
index a25789dff..5d5cdfdf7 100644
--- a/web/react/components/setting_upload.jsx
+++ b/web/react/components/setting_upload.jsx
@@ -1,6 +1,8 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
+import {FormattedMessage} from 'mm-intl';
+
export default class SettingsUpload extends React.Component {
constructor(props) {
super(props);
@@ -41,7 +43,7 @@ export default class SettingsUpload extends React.Component {
if (inputnode.files && inputnode.files[0]) {
this.props.submit(inputnode.files[0]);
} else {
- this.setState({clientError: 'No file selected.'});
+ this.setState({clientError: true});
}
}
@@ -49,7 +51,12 @@ export default class SettingsUpload extends React.Component {
let clientError = null;
if (this.state.clientError) {
clientError = (
- <div className='file-status'>{this.state.clientError}</div>
+ <div className='file-status'>
+ <FormattedMessage
+ id='setting_upload.noFile'
+ defaultMessage='No file selected.'
+ />
+ </div>
);
}
let serverError = null;
@@ -75,7 +82,10 @@ export default class SettingsUpload extends React.Component {
<ul className='setting-list'>
<li className='setting-list-item'>
<span className='btn btn-sm btn-primary btn-file sel-btn'>
- {'Select file'}
+ <FormattedMessage
+ id='setting_upload.select'
+ defaultMessage='Select file'
+ />
<input
ref='uploadinput'
accept={this.props.fileTypesAccepted}
@@ -87,7 +97,10 @@ export default class SettingsUpload extends React.Component {
className={submitButtonClass}
onClick={this.doSubmit}
>
- {'Import'}
+ <FormattedMessage
+ id='setting_upload.import'
+ defaultMessage='Import'
+ />
</a>
{fileNameText}
{serverError}
diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx
index c902731c9..33ef8a851 100644
--- a/web/react/components/sidebar.jsx
+++ b/web/react/components/sidebar.jsx
@@ -17,6 +17,9 @@ import * as Client from '../utils/client.jsx';
import * as Utils from '../utils/utils.jsx';
import Constants from '../utils/constants.jsx';
+
+import {FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
+
const Preferences = Constants.Preferences;
const TutorialSteps = Constants.TutorialSteps;
@@ -275,34 +278,33 @@ export default class Sidebar extends React.Component {
screens.push(
<div>
- <h4>{'Channels'}</h4>
- <p><strong>{'Channels'}</strong>{' organize conversations across different topics. They’re open to everyone on your team. To send private communications use '}<strong>{'Direct Messages'}</strong>{' for a single person or '}<strong>{'Private Groups'}</strong>{' for multiple people.'}
- </p>
+ <FormattedHTMLMessage
+ id='sidebar.tutorialScreen1'
+ defaultMessage='<h4>Channels</h4><p><strong>Channels</strong> organize conversations across different topics. They’re open to everyone on your team. To send private communications use <strong>Direct Messages</strong> for a single person or <strong>Private Groups</strong> for multiple people.</p>'
+ />
</div>
);
screens.push(
<div>
- <h4>{'"Town Square" and "Off-Topic" channels'}</h4>
- <p>{'Here are two public channels to start:'}</p>
- <p>
- <strong>{'Town Square'}</strong>{' is a place for team-wide communication. Everyone in your team is a member of this channel.'}
- </p>
- <p>
- <strong>{'Off-Topic'}</strong>{' is a place for fun and humor outside of work-related channels. You and your team can decide what other channels to create.'}
- </p>
+ <FormattedHTMLMessage
+ id='sidebar.tutorialScreen2'
+ defaultMessage='<h4>"Town Square" and "Off-Topic" channels</h4>
+ <p>Here are two public channels to start:</p>
+ <p><strong>Town Square</strong> is a place for team-wide communication. Everyone in your team is a member of this channel.</p>
+ <p><strong>Off-Topic</strong> is a place for fun and humor outside of work-related channels. You and your team can decide what other channels to create.</p>'
+ />
</div>
);
screens.push(
<div>
- <h4>{'Creating and Joining Channels'}</h4>
- <p>
- {'Click '}<strong>{'"More..."'}</strong>{' to create a new channel or join an existing one.'}
- </p>
- <p>
- {'You can also create a new channel or private group by clicking the '}<strong>{'"+" symbol'}</strong>{' next to the channel or private group header.'}
- </p>
+ <FormattedHTMLMessage
+ id='sidebar.tutorialScreen3'
+ defaultMessage='<h4>Creating and Joining Channels</h4>
+ <p>Click <strong>"More..."</strong> to create a new channel or join an existing one.</p>
+ <p>You can also create a new channel or private group by clicking the <strong>"+" symbol</strong> next to the channel or private group header.</p>'
+ />
</div>
);
@@ -437,7 +439,12 @@ export default class Sidebar extends React.Component {
let closeButton = null;
const removeTooltip = (
- <Tooltip id='remove-dm-tooltip'>{'Remove from list'}</Tooltip>
+ <Tooltip id='remove-dm-tooltip'>
+ <FormattedMessage
+ id='sidebar.removeList'
+ defaultMessage='Remove from list'
+ />
+ </Tooltip>
);
if (handleClose && !badge) {
closeButton = (
@@ -525,7 +532,13 @@ export default class Sidebar extends React.Component {
href='#'
onClick={this.showMoreDirectChannelsModal}
>
- {'More (' + this.state.hiddenDirectChannelCount + ')'}
+ <FormattedMessage
+ id='sidebar.more'
+ defaultMessage='More ({count})'
+ values={{
+ count: this.state.hiddenDirectChannelCount
+ }}
+ />
</a>
</li>
);
@@ -537,10 +550,34 @@ export default class Sidebar extends React.Component {
}
const createChannelTootlip = (
- <Tooltip id='new-channel-tooltip' >{'Create new channel'}</Tooltip>
+ <Tooltip id='new-channel-tooltip' >
+ <FormattedMessage
+ id='sidebar.createChannel'
+ defaultMessage='Create new channel'
+ />
+ </Tooltip>
);
const createGroupTootlip = (
- <Tooltip id='new-group-tooltip'>{'Create new group'}</Tooltip>
+ <Tooltip id='new-group-tooltip'>
+ <FormattedMessage
+ id='sidebar.createGroup'
+ defaultMessage='Create new group'
+ />
+ </Tooltip>
+ );
+
+ const above = (
+ <FormattedMessage
+ id='sidebar.unreadAbove'
+ defaultMessage='Unread post(s) above'
+ />
+ );
+
+ const below = (
+ <FormattedMessage
+ id='sidebar.unreadBelow'
+ defaultMessage='Unread post(s) below'
+ />
);
return (
@@ -564,12 +601,12 @@ export default class Sidebar extends React.Component {
<UnreadChannelIndicator
show={this.state.showTopUnread}
extraClass='nav-pills__unread-indicator-top'
- text={'Unread post(s) above'}
+ text={above}
/>
<UnreadChannelIndicator
show={this.state.showBottomUnread}
extraClass='nav-pills__unread-indicator-bottom'
- text={'Unread post(s) below'}
+ text={below}
/>
<div
@@ -580,7 +617,10 @@ export default class Sidebar extends React.Component {
<ul className='nav nav-pills nav-stacked'>
<li>
<h4>
- {'Channels'}
+ <FormattedMessage
+ id='sidebar.channels'
+ defaultMessage='Channels'
+ />
<OverlayTrigger
delayShow={500}
placement='top'
@@ -603,7 +643,10 @@ export default class Sidebar extends React.Component {
className='nav-more'
onClick={this.showMoreChannelsModal}
>
- {'More...'}
+ <FormattedMessage
+ id='sidebar.moreElips'
+ defaultMessage='More...'
+ />
</a>
</li>
</ul>
@@ -611,7 +654,10 @@ export default class Sidebar extends React.Component {
<ul className='nav nav-pills nav-stacked'>
<li>
<h4>
- {'Private Groups'}
+ <FormattedMessage
+ id='sidebar.pg'
+ defaultMessage='Private Groups'
+ />
<OverlayTrigger
delayShow={500}
placement='top'
@@ -630,7 +676,14 @@ export default class Sidebar extends React.Component {
{privateChannelItems}
</ul>
<ul className='nav nav-pills nav-stacked'>
- <li><h4>{'Direct Messages'}</h4></li>
+ <li>
+ <h4>
+ <FormattedMessage
+ id='sidebar.direct'
+ defaultMessage='Direct Messages'
+ />
+ </h4>
+ </li>
{directMessageItems}
{directMessageMore}
</ul>
diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx
index a9616cfc3..45b0a5fc4 100644
--- a/web/react/components/sidebar_header.jsx
+++ b/web/react/components/sidebar_header.jsx
@@ -9,6 +9,9 @@ import PreferenceStore from '../stores/preference_store.jsx';
import * as Utils from '../utils/utils.jsx';
import Constants from '../utils/constants.jsx';
+
+import {FormattedHTMLMessage} from 'mm-intl';
+
const Preferences = Constants.Preferences;
const TutorialSteps = Constants.TutorialSteps;
@@ -51,20 +54,12 @@ export default class SidebarHeader extends React.Component {
screens.push(
<div>
- <h4>{'Main Menu'}</h4>
- <p>
- {'The '}<strong>{'Main Menu'}</strong>{' is where you can '}
- <strong>{'Invite New Members'}</strong>
- {', access your '}
- <strong>{'Account Settings'}</strong>
- {' and set your '}<strong>{'Theme Color'}</strong>{'.'}
- </p>
- <p>
- {'Team administrators can also access their '}<strong>{'Team Settings'}</strong>{' from this menu.'}
- </p>
- <p>
- {'System administrators will find a '}<strong>{'System Console'}</strong>{' option to administrate the entire system.'}
- </p>
+ <FormattedHTMLMessage
+ id='sidebar_header.tutorial'
+ defaultMessage='<h4>Main Menu</h4>
+ <p>The <strong>Main Menu</strong> is where you can <strong>Invite New Members</strong>, access your <strong>Account Settings</strong> and set your <strong>Theme Color</strong>.</p>
+ <p>Team administrators can also access their <strong>Team Settings</strong> from this menu.</p><p>System administrators will find a <strong>System Console</strong> option to administrate the entire system.</p>'
+ />
</div>
);
diff --git a/web/react/components/team_export_tab.jsx b/web/react/components/team_export_tab.jsx
index 14df7fffc..8330637d8 100644
--- a/web/react/components/team_export_tab.jsx
+++ b/web/react/components/team_export_tab.jsx
@@ -3,6 +3,8 @@
import * as Client from '../utils/client.jsx';
+import {FormattedMessage} from 'mm-intl';
+
export default class TeamExportTab extends React.Component {
constructor(props) {
super(props);
@@ -35,7 +37,10 @@ export default class TeamExportTab extends React.Component {
messageSection = (
<p className='confirm-import alert alert-warning'>
<i className='fa fa-spinner fa-pulse' />
- {' Exporting...'}
+ <FormattedMessage
+ id='team_export_tab.exporting'
+ defaultMessage=' Exporting...'
+ />
</p>
);
break;
@@ -43,12 +48,18 @@ export default class TeamExportTab extends React.Component {
messageSection = (
<p className='confirm-import alert alert-success'>
<i className='fa fa-check' />
- {' Ready for '}
+ <FormattedMessage
+ id='team_export_tab.ready'
+ defaultMessage=' Ready for '
+ />
<a
href={this.state.link}
download={true}
>
- {'download'}
+ <FormattedMessage
+ id='team_export_tab.download'
+ defaultMessage='download'
+ />
</a>
</p>
);
@@ -57,7 +68,13 @@ export default class TeamExportTab extends React.Component {
messageSection = (
<p className='confirm-import alert alert-warning'>
<i className='fa fa-warning' />
- {' Unable to export: ' + this.state.err}
+ <FormattedMessage
+ id='team_export_tab.unable'
+ defaultMessage=' Unable to export: {error}'
+ values={{
+ error: this.state.err
+ }}
+ />
</p>
);
break;
@@ -68,10 +85,20 @@ export default class TeamExportTab extends React.Component {
ref='wrapper'
className='user-settings'
>
- <h3 className='tab-header'>{'Export'}</h3>
+ <h3 className='tab-header'>
+ <FormattedMessage
+ id='team_export_tab.export'
+ defaultMessage='Export'
+ />
+ </h3>
<div className='divider-dark first'/>
<ul className='section-max'>
- <li className='col-xs-12 section-title'>{'Export your team'}</li>
+ <li className='col-xs-12 section-title'>
+ <FormattedMessage
+ id='team_export_tab.exportTeam'
+ defaultMessage='Export your team'
+ />
+ </li>
<li className='col-xs-offset-3 col-xs-8'>
<ul className='setting-list'>
<li className='setting-list-item'>
@@ -80,7 +107,10 @@ export default class TeamExportTab extends React.Component {
href='#'
onClick={this.doExport}
>
- {'Export'}
+ <FormattedMessage
+ id='team_export_tab.export'
+ defaultMessage='Export'
+ />
</a>
</li>
</ul>
diff --git a/web/react/components/team_general_tab.jsx b/web/react/components/team_general_tab.jsx
index b6fb3389f..0656d3b03 100644
--- a/web/react/components/team_general_tab.jsx
+++ b/web/react/components/team_general_tab.jsx
@@ -8,7 +8,56 @@ import * as Client from '../utils/client.jsx';
import * as Utils from '../utils/utils.jsx';
import TeamStore from '../stores/team_store.jsx';
-export default class GeneralTab extends React.Component {
+import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl';
+
+const holders = defineMessages({
+ dirDisabled: {
+ id: 'general_tab.dirDisabled',
+ defaultMessage: 'Team Directory has been disabled. Please ask a System Admin to enable the Team Directory in the System Console team settings.'
+ },
+ required: {
+ id: 'general_tab.required',
+ defaultMessage: 'This field is required'
+ },
+ chooseName: {
+ id: 'general_tab.chooseName',
+ defaultMessage: 'Please choose a new name for your team'
+ },
+ includeDirTitle: {
+ id: 'general_tab.includeDirTitle',
+ defaultMessage: 'Include this team in the Team Directory'
+ },
+ yes: {
+ id: 'general_tab.yes',
+ defaultMessage: 'Yes'
+ },
+ no: {
+ id: 'general_tab.no',
+ defaultMessage: 'No'
+ },
+ dirOff: {
+ id: 'general_tab.dirOff',
+ defaultMessage: 'Team directory is turned off for this system.'
+ },
+ openInviteTitle: {
+ id: 'general_tab.openInviteTitle',
+ defaultMessage: 'Allow anyone to sign-up from login page'
+ },
+ codeTitle: {
+ id: 'general_tab.codeTitle',
+ defaultMessage: 'Invite Code'
+ },
+ codeDesc: {
+ id: 'general_tab.codeDesc',
+ defaultMessage: "Click 'Edit' to regenerate Invite Code."
+ },
+ teamNameInfo: {
+ id: 'general_tab.teamNameInfo',
+ defaultMessage: 'Set the name of the team as it appears on your sign-in screen and at the top of the left-hand sidebar.'
+ }
+});
+
+class GeneralTab extends React.Component {
constructor(props) {
super(props);
@@ -66,7 +115,7 @@ export default class GeneralTab extends React.Component {
handleTeamListingRadio(listing) {
if (global.window.mm_config.EnableTeamListing !== 'true' && listing) {
- this.setState({clientError: 'Team Directory has been disabled. Please ask a System Admin to enable the Team Directory in the System Console team settings.'});
+ this.setState({clientError: this.props.intl.formatMessage(holders.dirDisabled)});
} else {
this.setState({allow_team_listing: listing});
}
@@ -118,12 +167,13 @@ export default class GeneralTab extends React.Component {
var state = {serverError: '', clientError: ''};
let valid = true;
+ const {formatMessage} = this.props.intl;
const name = this.state.name.trim();
if (!name) {
- state.clientError = 'This field is required';
+ state.clientError = formatMessage(holders.required);
valid = false;
} else if (name === this.props.team.display_name) {
- state.clientError = 'Please choose a new name for your team';
+ state.clientError = formatMessage(holders.chooseName);
valid = false;
} else {
state.clientError = '';
@@ -160,7 +210,7 @@ export default class GeneralTab extends React.Component {
if (inviteId) {
state.clientError = '';
} else {
- state.clientError = 'This field is required';
+ state.clientError = this.props.intl.fromatMessage(holders.required);
valid = false;
}
@@ -260,6 +310,7 @@ export default class GeneralTab extends React.Component {
}
const enableTeamListing = global.window.mm_config.EnableTeamListing === 'true';
+ const {formatMessage} = this.props.intl;
let teamListingSection;
if (this.props.activeSection === 'team_listing') {
@@ -279,7 +330,10 @@ export default class GeneralTab extends React.Component {
defaultChecked={this.state.allow_team_listing}
onChange={this.handleTeamListingRadio.bind(this, true)}
/>
- {'Yes'}
+ <FormattedMessage
+ id='general_tab.yes'
+ defaultMessage='Yes'
+ />
</label>
<br/>
</div>
@@ -292,24 +346,39 @@ export default class GeneralTab extends React.Component {
defaultChecked={!this.state.allow_team_listing}
onChange={this.handleTeamListingRadio.bind(this, false)}
/>
- {'No'}
+ <FormattedMessage
+ id='general_tab.no'
+ defaultMessage='No'
+ />
</label>
<br/>
</div>
- <div><br/>{'Including this team will display the team name from the Team Directory section of the Home Page, and provide a link to the sign-in page.'}</div>
+ <div>
+ <br/>
+ <FormattedMessage
+ id='general_tab.includeDirDesc'
+ defaultMessage='Including this team will display the team name from the Team Directory section of the Home Page, and provide a link to the sign-in page.'
+ />
+ </div>
</div>
);
} else {
inputs.push(
<div key='userTeamListingOptions'>
- <div><br/>{'Contact your system administrator to turn on the team directory on the system home page.'}</div>
+ <div>
+ <br/>
+ <FormattedMessage
+ id='general_tab.dirContact'
+ defaultMessage='Contact your system administrator to turn on the team directory on the system home page.'
+ />
+ </div>
</div>
);
}
teamListingSection = (
<SettingItemMax
- title='Include this team in the Team Directory'
+ title={formatMessage(holders.includeDirTitle)}
inputs={inputs}
submit={submitHandle}
server_error={serverError}
@@ -322,17 +391,17 @@ export default class GeneralTab extends React.Component {
if (enableTeamListing) {
if (this.state.allow_team_listing === true) {
- describe = 'Yes';
+ describe = formatMessage(holders.yes);
} else {
- describe = 'No';
+ describe = formatMessage(holders.no);
}
} else {
- describe = 'Team directory is turned off for this system.';
+ describe = formatMessage(holders.dirOff);
}
teamListingSection = (
<SettingItemMin
- title='Include this team in the Team Directory'
+ title={formatMessage(holders.includeDirTitle)}
describe={describe}
updateSection={this.onUpdateTeamListingSection}
/>
@@ -351,7 +420,10 @@ export default class GeneralTab extends React.Component {
defaultChecked={this.state.allow_open_invite}
onChange={this.handleOpenInviteRadio.bind(this, true)}
/>
- {'Yes'}
+ <FormattedMessage
+ id='general_tab.yes'
+ defaultMessage='Yes'
+ />
</label>
<br/>
</div>
@@ -363,17 +435,26 @@ export default class GeneralTab extends React.Component {
defaultChecked={!this.state.allow_open_invite}
onChange={this.handleOpenInviteRadio.bind(this, false)}
/>
- {'No'}
+ <FormattedMessage
+ id='general_tab.no'
+ defaultMessage='No'
+ />
</label>
<br/>
</div>
- <div><br/>{'When allowed, a link to account creation will be included on the sign-in page of this team and allow any visitor to sign-up.'}</div>
+ <div>
+ <br/>
+ <FormattedMessage
+ id='general_tab.openInviteDesc'
+ defaultMessage='When allowed, a link to account creation will be included on the sign-in page of this team and allow any visitor to sign-up.'
+ />
+ </div>
</div>
];
openInviteSection = (
<SettingItemMax
- title='Allow anyone to sign-up from login page'
+ title={formatMessage(holders.openInviteTitle)}
inputs={inputs}
submit={this.handleOpenInviteSubmit}
server_error={serverError}
@@ -383,14 +464,14 @@ export default class GeneralTab extends React.Component {
} else {
let describe = '';
if (this.state.allow_open_invite === true) {
- describe = 'Yes';
+ describe = formatMessage(holders.yes);
} else {
- describe = 'No';
+ describe = formatMessage(holders.no);
}
openInviteSection = (
<SettingItemMin
- title='Allow anyone to sign-up from login page'
+ title={formatMessage(holders.openInviteTitle)}
describe={describe}
updateSection={this.onUpdateOpenInviteSection}
/>
@@ -405,7 +486,12 @@ export default class GeneralTab extends React.Component {
inputs.push(
<div key='teamInviteSetting'>
<div className='row'>
- <label className='col-sm-5 control-label'>{'Invite Code'}</label>
+ <label className='col-sm-5 control-label'>
+ <FormattedMessage
+ id='general_tab.codeTitle'
+ defaultMessage='Invite Code'
+ />
+ </label>
<div className='col-sm-7'>
<input
className='form-control'
@@ -419,18 +505,26 @@ export default class GeneralTab extends React.Component {
href='#'
onClick={this.handleGenerateInviteId}
>
- {'Re-Generate'}
+ <FormattedMessage
+ id='general_tab.regenerate'
+ defaultMessage='Re-Generate'
+ />
</a>
</div>
</div>
</div>
- <div className='setting-list__hint'>{'The Invite Code is used as part of the URL in the team invitation link created by **Get Team Invite Link** in the main menu. Regenerating creates a new team invitation link and invalidates the previous link.'}</div>
+ <div className='setting-list__hint'>
+ <FormattedMessage
+ id='general_tab.codeLongDesc'
+ defaultMessage='The Invite Code is used as part of the URL in the team invitation link created by **Get Team Invite Link** in the main menu. Regenerating creates a new team invitation link and invalidates the previous link.'
+ />
+ </div>
</div>
);
inviteSection = (
<SettingItemMax
- title={`Invite Code`}
+ title={formatMessage(holders.codeTitle)}
inputs={inputs}
submit={this.handleInviteIdSubmit}
server_error={serverError}
@@ -441,8 +535,8 @@ export default class GeneralTab extends React.Component {
} else {
inviteSection = (
<SettingItemMin
- title={`Invite Code`}
- describe={`Click 'Edit' to regenerate Invite Code.`}
+ title={formatMessage(holders.codeTitle)}
+ describe={formatMessage(holders.codeDesc)}
updateSection={this.onUpdateInviteIdSection}
/>
);
@@ -453,7 +547,12 @@ export default class GeneralTab extends React.Component {
if (this.props.activeSection === 'name') {
const inputs = [];
- let teamNameLabel = 'Team Name';
+ let teamNameLabel = (
+ <FormattedMessage
+ id='general_tab.teamName'
+ defaultMessage='Team Name'
+ />
+ );
if (Utils.isMobile()) {
teamNameLabel = '';
}
@@ -478,13 +577,13 @@ export default class GeneralTab extends React.Component {
nameSection = (
<SettingItemMax
- title={`Team Name`}
+ title={formatMessage({id: 'general_tab.teamName'})}
inputs={inputs}
submit={this.handleNameSubmit}
server_error={serverError}
client_error={clientError}
updateSection={this.onUpdateNameSection}
- extraInfo='Set the name of the team as it appears on your sign-in screen and at the top of the left-hand sidebar.'
+ extraInfo={formatMessage(holders.teamNameInfo)}
/>
);
} else {
@@ -492,7 +591,7 @@ export default class GeneralTab extends React.Component {
nameSection = (
<SettingItemMin
- title={`Team Name`}
+ title={formatMessage({id: 'general_tab.teamName'})}
describe={describe}
updateSection={this.onUpdateNameSection}
/>
@@ -515,14 +614,22 @@ export default class GeneralTab extends React.Component {
ref='title'
>
<i className='modal-back'></i>
- {'General Settings'}
+ <FormattedMessage
+ id='general_tab.title'
+ defaultMessage='General Settings'
+ />
</h4>
</div>
<div
ref='wrapper'
className='user-settings'
>
- <h3 className='tab-header'>{'General Settings'}</h3>
+ <h3 className='tab-header'>
+ <FormattedMessage
+ id='general_tab.title'
+ defaultMessage='General Settings'
+ />
+ </h3>
<div className='divider-dark first'/>
{nameSection}
<div className='divider-light'/>
@@ -539,7 +646,10 @@ export default class GeneralTab extends React.Component {
}
GeneralTab.propTypes = {
+ intl: intlShape.isRequired,
updateSection: React.PropTypes.func.isRequired,
team: React.PropTypes.object.isRequired,
activeSection: React.PropTypes.string.isRequired
};
+
+export default injectIntl(GeneralTab); \ No newline at end of file
diff --git a/web/react/components/team_import_tab.jsx b/web/react/components/team_import_tab.jsx
index 37f8746d7..adf990672 100644
--- a/web/react/components/team_import_tab.jsx
+++ b/web/react/components/team_import_tab.jsx
@@ -4,7 +4,16 @@
import * as utils from '../utils/utils.jsx';
import SettingUpload from './setting_upload.jsx';
-export default class TeamImportTab extends React.Component {
+import {intlShape, injectIntl, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
+
+const holders = defineMessages({
+ importSlack: {
+ id: 'team_import_tab.importSlack',
+ defaultMessage: 'Import from Slack (Beta)'
+ }
+});
+
+class TeamImportTab extends React.Component {
constructor(props) {
super(props);
@@ -32,16 +41,19 @@ export default class TeamImportTab extends React.Component {
}
render() {
+ const {formatMessage} = this.props.intl;
var uploadHelpText = (
<div>
- <p>{'To import a team from Slack go to Slack > Team Settings > Import/Export Data > Export > Start Export. Slack does not allow you to export files, images, private groups or direct messages stored in Slack. Therefore, Slack import to Mattermost only supports importing of text messages in your Slack team\'\s public channels.'}</p>
- <p>{'The Slack import to Mattermost is in "Beta". Slack bot posts do not yet import and Slack @mentions are not currently supported.'}</p>
+ <FormattedHTMLMessage
+ id='team_import_tab.importHelp'
+ defaultMessage="<p>To import a team from Slack go to Slack > Team Settings > Import/Export Data > Export > Start Export. Slack does not allow you to export files, images, private groups or direct messages stored in Slack. Therefore, Slack import to Mattermost only supports importing of text messages in your Slack team's public channels.</p><p>The Slack import to Mattermost is in 'Beta'. Slack bot posts do not yet import and Slack @mentions are not currently supported.</p>"
+ />
</div>
);
var uploadSection = (
<SettingUpload
- title='Import from Slack (Beta)'
+ title={formatMessage(holders.importSlack)}
submit={this.doImportSlack}
helpText={uploadHelpText}
fileTypesAccepted='.zip'
@@ -56,19 +68,30 @@ export default class TeamImportTab extends React.Component {
break;
case 'in-progress':
messageSection = (
- <p className='confirm-import alert alert-warning'><i className='fa fa-spinner fa-pulse'></i>{' Importing...'}</p>
+ <p className='confirm-import alert alert-warning'><i className='fa fa-spinner fa-pulse'></i>
+ <FormattedMessage
+ id='team_import_tab.importing'
+ defaultMessage=' Importing...'
+ />
+ </p>
);
break;
case 'done':
messageSection = (
<p className='confirm-import alert alert-success'>
<i className='fa fa-check' />
- {' Import successful: '}
+ <FormattedMessage
+ id='team_import_tab.successful'
+ defaultMessage=' Import successful: '
+ />
<a
href={this.state.link}
download='MattermostImportSummary.txt'
>
- {'View Summary'}
+ <FormattedMessage
+ id='team_import_tab.summary'
+ defaultMessage='View Summary'
+ />
</a>
</p>
);
@@ -77,12 +100,18 @@ export default class TeamImportTab extends React.Component {
messageSection = (
<p className='confirm-import alert alert-warning'>
<i className='fa fa-warning' />
- {' Import failure: '}
+ <FormattedMessage
+ id='team_import_tab.failure'
+ defaultMessage=' Import failure: '
+ />
<a
href={this.state.link}
download='MattermostImportSummary.txt'
>
- {'View Summary'}
+ <FormattedMessage
+ id='team_import_tab.summary'
+ defaultMessage='View Summary'
+ />
</a>
</p>
);
@@ -102,13 +131,23 @@ export default class TeamImportTab extends React.Component {
<h4
className='modal-title'
ref='title'
- ><i className='modal-back'></i>{'Import'}</h4>
+ ><i className='modal-back'></i>
+ <FormattedMessage
+ id='team_import_tab.import'
+ defaultMessage='Import'
+ />
+ </h4>
</div>
<div
ref='wrapper'
className='user-settings'
>
- <h3 className='tab-header'>{'Import'}</h3>
+ <h3 className='tab-header'>
+ <FormattedMessage
+ id='team_import_tab.import'
+ defaultMessage='Import'
+ />
+ </h3>
<div className='divider-dark first'/>
{uploadSection}
<div className='divider-dark'/>
@@ -118,3 +157,9 @@ export default class TeamImportTab extends React.Component {
);
}
}
+
+TeamImportTab.propTypes = {
+ intl: intlShape.isRequired
+};
+
+export default injectIntl(TeamImportTab); \ No newline at end of file
diff --git a/web/react/components/team_members_modal.jsx b/web/react/components/team_members_modal.jsx
index 27224c283..92adb6e2a 100644
--- a/web/react/components/team_members_modal.jsx
+++ b/web/react/components/team_members_modal.jsx
@@ -4,6 +4,8 @@
import MemberListTeam from './member_list_team.jsx';
import TeamStore from '../stores/team_store.jsx';
+import {FormattedMessage} from 'mm-intl';
+
const Modal = ReactBootstrap.Modal;
export default class TeamMembersModal extends React.Component {
@@ -44,7 +46,13 @@ export default class TeamMembersModal extends React.Component {
onHide={this.props.onHide}
>
<Modal.Header closeButton={true}>
- {team.display_name + ' Members'}
+ <FormattedMessage
+ id='team_member_modal.members'
+ defaultMessage='{team} Members'
+ values={{
+ team: team.display_name
+ }}
+ />
</Modal.Header>
<Modal.Body ref='modalBody'>
<div className='team-member-list'>
@@ -57,7 +65,10 @@ export default class TeamMembersModal extends React.Component {
className='btn btn-default'
onClick={this.props.onHide}
>
- {'Close'}
+ <FormattedMessage
+ id='team_member_modal.close'
+ defaultMessage='Close'
+ />
</button>
</Modal.Footer>
</Modal>
diff --git a/web/react/components/team_settings_modal.jsx b/web/react/components/team_settings_modal.jsx
index dbdbde958..d517f92fb 100644
--- a/web/react/components/team_settings_modal.jsx
+++ b/web/react/components/team_settings_modal.jsx
@@ -4,7 +4,24 @@
import SettingsSidebar from './settings_sidebar.jsx';
import TeamSettings from './team_settings.jsx';
-export default class TeamSettingsModal extends React.Component {
+import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl';
+
+const holders = defineMessages({
+ generalTab: {
+ id: 'team_settings_modal.generalTab',
+ defaultMessage: 'General'
+ },
+ importTab: {
+ id: 'team_settings_modal.importTab',
+ defaultMessage: 'Import'
+ },
+ exportTab: {
+ id: 'team_settings_modal.exportTab',
+ defaultMessage: 'Export'
+ }
+});
+
+class TeamSettingsModal extends React.Component {
constructor(props) {
super(props);
@@ -36,12 +53,13 @@ export default class TeamSettingsModal extends React.Component {
this.setState({activeSection: section});
}
render() {
+ const {formatMessage} = this.props.intl;
const tabs = [];
- tabs.push({name: 'general', uiName: 'General', icon: 'glyphicon glyphicon-cog'});
- tabs.push({name: 'import', uiName: 'Import', icon: 'glyphicon glyphicon-upload'});
+ tabs.push({name: 'general', uiName: formatMessage(holders.generalTab), icon: 'glyphicon glyphicon-cog'});
+ tabs.push({name: 'import', uiName: formatMessage(holders.importTab), icon: 'glyphicon glyphicon-upload'});
// To enable export uncomment this line
- //tabs.push({name: 'export', uiName: 'Export', icon: 'glyphicon glyphicon-download'});
+ //tabs.push({name: 'export', uiName: formatMessage(holders.exportTab), icon: 'glyphicon glyphicon-download'});
return (
<div
@@ -67,7 +85,10 @@ export default class TeamSettingsModal extends React.Component {
className='modal-title'
ref='title'
>
- {'Team Settings'}
+ <FormattedMessage
+ id='team_settings_modal.title'
+ defaultMessage='Team Settings'
+ />
</h4>
</div>
<div className='modal-body'>
@@ -96,4 +117,7 @@ export default class TeamSettingsModal extends React.Component {
}
TeamSettingsModal.propTypes = {
+ intl: intlShape.isRequired
};
+
+export default injectIntl(TeamSettingsModal); \ No newline at end of file
diff --git a/web/react/components/unread_channel_indicator.jsx b/web/react/components/unread_channel_indicator.jsx
index c0c34584f..509ac9e4d 100644
--- a/web/react/components/unread_channel_indicator.jsx
+++ b/web/react/components/unread_channel_indicator.jsx
@@ -31,5 +31,5 @@ UnreadChannelIndicator.defaultProps = {
UnreadChannelIndicator.propTypes = {
show: React.PropTypes.bool,
extraClass: React.PropTypes.string,
- text: React.PropTypes.string
+ text: React.PropTypes.object
};
diff --git a/web/static/i18n/en.json b/web/static/i18n/en.json
index 00c2c67f6..62608b85a 100644
--- a/web/static/i18n/en.json
+++ b/web/static/i18n/en.json
@@ -1,4 +1,13 @@
{
+ "about.teamEdtion": "Team Edition",
+ "about.enterpriseEdition": "Enterprise Edition",
+ "about.licensed": "Licensed by:",
+ "about.title": "About Mattermost",
+ "about.version": "Version:",
+ "about.number": "Build Number:",
+ "about.date": "Build Date:",
+ "about.hash": "Build Hash:",
+ "about.close": "Close",
"access_history.sessionRevoked": "The session with id {sessionId} was revoked",
"access_history.channelCreated": "Created the {channelName} channel/group",
"access_history.establishedDM": "Established a direct message channel with {username}",
@@ -446,6 +455,10 @@
"admin.team.save": "Save",
"admin.userList.title": "Users for {team}",
"admin.userList.title2": "Users for {team} ({count})",
+ "admin.user_item.confirmDemoteRoleTitle": "Confirm demotion from System Admin role",
+ "admin.user_item.confirmDemotion": "Confirm Demotion",
+ "admin.user_item.confirmDemoteDescription": "If you demote yourself from the System Admin role and there is not another user with System Admin privileges, you'll need to re-assign a System Admin by accessing the Mattermost server through a terminal and running the following command.",
+ "admin.user_item.confirmDemotionCmd": "platform -assign_role -team_name=\"yourteam\" -email=\"name@yourcompany.com\" -role=\"system_admin\"",
"admin.user_item.member": "Member",
"admin.user_item.sysAdmin": "System Admin",
"admin.user_item.teamAdmin": "Team Admin",
@@ -456,14 +469,17 @@
"admin.user_item.makeActive": "Make Active",
"admin.user_item.makeInactive": "Make Inactive",
"admin.user_item.resetPwd": "Reset Password",
- "admin.user_item.confirmDemoteRoleTitle": "Confirm demotion from System Admin role",
- "admin.user_item.confirmDemotion": "Confirm Demotion",
- "admin.user_item.confirmDemoteDescription": "If you demote yourself from the System Admin role and there is not another user with System Admin privileges, you'll need to re-assign a System Admin by accessing the Mattermost server through a terminal and running the following command.",
"authorize.title": "An application would like to connect to your {teamName} account",
"authorize.app": "The app <strong>{appName}</strong> would like the ability to access and modify your basic information.",
"authorize.access": "Allow <strong>{appName}</strong> access?",
"authorize.deny": "Deny",
"authorize.allow": "Allow",
+ "change_url.longer": "Must be longer than two characters",
+ "change_url.startWithLetter": "Must start with a letter or number",
+ "change_url.endWithLetter": "Must end with a letter or number",
+ "change_url.noUnderscore": "Can not contain two underscores in a row.",
+ "change_url.invalidUrl": "Invalid URL",
+ "change_url.close": "Close",
"claim.account.noEmail": "No email specified",
"claim.email_to_sso.pwdError": "Please enter your password.",
"claim.email_to_sso.pwd": "Password",
@@ -494,6 +510,28 @@
"find_team.getLinks": "Get an email with links to any teams to which you are a member.",
"find_team.email": "Email",
"find_team.send": "Send",
+ "get_link.copy": "Copy Link",
+ "get_link.clipboard": " Link copied to clipboard.",
+ "get_link.close": "Close",
+ "get_team_invite_link_modal.title": "Team Invite Link",
+ "get_team_invite_link_modal.help": "Send teammates the link below for them to sign-up to this team site.",
+ "invite_member.emailError": "Please enter a valid email address",
+ "invite_member.firstname": "First name",
+ "invite_member.lastname": "Last name",
+ "invite_member.modalTitle": "Discard Invitations?",
+ "invite_member.modalMessage": "You have unsent invitations, are you sure you want to discard them?",
+ "invite_member.modalButton": "Yes, Discard",
+ "invite_member.addAnother": "Add another",
+ "invite_member.autoJoin": "People invited automatically join the <strong>{channel}</strong> channel.",
+ "invite_member.send": "Send Invitation",
+ "invite_member.sending": " Sending",
+ "invite_member.send2": "Send Invitations",
+ "invite_member.inviteLink": "Team Invite Link",
+ "invite_member.teamInviteLink": "You can also invite people using the {link}.",
+ "invite_member.content": "Email is currently disabled for your team, and email invitations cannot be sent. Contact your system administrator to enable email and email invitations.",
+ "invite_member.disabled": "User creation has been disabled for your team. Please ask your team administrator for details.",
+ "invite_member.newMember": "Invite New Member",
+ "invite_member.cancel": "Cancel",
"loading_screen.loading": "Loading",
"login_email.badTeam": "Bad team name",
"login_email.emailReq": "An email is required",
@@ -519,6 +557,64 @@
"login.find": "Find your other teams",
"login.signTo": "Sign in to:",
"login.on": "on {siteName}",
+ "member_team_item.member": "Member",
+ "member_team_item.systemAdmin": "System Admin",
+ "member_team_item.teamAdmin": "Team Admin",
+ "member_team_item.inactive": "Inactive",
+ "member_team_item.makeAdmin": "Make Team Admin",
+ "member_team_item.makeMember": "Make Member",
+ "member_team_item.makeActive": "Make Active",
+ "member_team_item.makeInactive": "Make Inactive",
+ "more_channels.join": "Join",
+ "more_channels.noMore": "No more channels to join",
+ "more_channels.createClick": "Click 'Create New Channel' to make a new one",
+ "more_channels.close": "Close",
+ "more_channels.title": "More Channels",
+ "more_channels.create": "Create New Channel",
+ "more_direct_channels.member": "Member",
+ "more_direct_channels.search": "Search members",
+ "more_direct_channels.message": "Message",
+ "more_direct_channels.notFound": "No users found :(",
+ "more_direct_channels.count": "{count} {member}",
+ "more_direct_channels.countTotal": "{count} {member} of {total} Total",
+ "more_direct_channels.title": "Direct Messages",
+ "more_direct_channels.close": "Close",
+ "navbar_dropdown.inviteMember": "Invite New Member",
+ "navbar_dropdown.teamLink": "Get Team Invite Link",
+ "navbar_dropdown.manageMembers": "Manage Members",
+ "navbar_dropdown.teamSettings": "Team Settings",
+ "navbar_dropdown.console": "System Console",
+ "navbar_dropdown.switchTeam": "Switch to {team}",
+ "navbar_dropdown.create": "Create a New Team",
+ "navbar_dropdown.help": "Help",
+ "navbar_dropdown.report": "Report a Problem",
+ "navbar_dropdown.accountSettings": "Account Settings",
+ "navbar_dropdown.logout": "Logout",
+ "navbar_dropdown.about": "About Mattermost",
+ "channel_flow.invalidName": "Invalid Channel Name",
+ "channel_flow.alreadyExist": "A channel with that URL already exists",
+ "channel_flow.channel": "Channel",
+ "channel_flow.group": "Group",
+ "channel_flow.changeUrlTitle": "Change {term} URL",
+ "channel_flow.set_url_title": "Set {term} URL",
+ "channel_flow.create": "Create {term}",
+ "channel_flow.changeUrlDescription": "Some characters are not allowed in URLs and may be removed.",
+ "channel_modal.nameEx": "E.g.: \"Bugs\", \"Marketing\", \"办公室恋情\"",
+ "channel_modal.displayNameError": "This field is required",
+ "channel_modal.group": "Group",
+ "channel_modal.privateGroup1": "Create a new private group with restricted membership. ",
+ "channel_modal.publicChannel1": "Create a public channel",
+ "channel_modal.channel": "Channel",
+ "channel_modal.publicChannel2": "Create a new public channel anyone can join. ",
+ "channel_modal.privateGroup2": "Create a private group",
+ "channel_modal.modalTitle": "New ",
+ "channel_modal.name": "Name",
+ "channel_modal.edit": "Edit",
+ "channel_modal.purpose": "Purpose",
+ "channel_modal.optional": "(optional)",
+ "channel_modal.descriptionHelp": "Describe how this {term} should be used.",
+ "channel_modal.cancel": "Cancel",
+ "channel_modal.createNew": "Create New ",
"password_form.error": "Please enter at least {chars} characters.",
"password_form.update": "Your password has been updated successfully.",
"password_form.pwd": "Password",
@@ -559,6 +655,23 @@
"setting_picture.help": "Upload a profile picture in either JPG or PNG format, at least {width}px in width and {height}px height.",
"setting_picture.select": "Select",
"setting_picture.cancel": "Cancel",
+ "setting_upload.noFile": "No file selected.",
+ "setting_upload.select": "Select file",
+ "setting_upload.import": "Import",
+ "sidebar_header.tutorial": "<h4>Main Menu</h4>\n <p>The <strong>Main Menu</strong> is where you can <strong>Invite New Members</strong>, access your <strong>Account Settings</strong> and set your <strong>Theme Color</strong>.</p>\n <p>Team administrators can also access their <strong>Team Settings</strong> from this menu.</p><p>System administrators will find a <strong>System Console</strong> option to administrate the entire system.</p>",
+ "sidebar.tutorialScreen1": "<h4>Channels</h4><p><strong>Channels</strong> organize conversations across different topics. They’re open to everyone on your team. To send private communications use <strong>Direct Messages</strong> for a single person or <strong>Private Groups</strong> for multiple people.</p>",
+ "sidebar.tutorialScreen2": "<h4>\"Town Square\" and \"Off-Topic\" channels</h4>\n <p>Here are two public channels to start:</p>\n <p><strong>Town Square</strong> is a place for team-wide communication. Everyone in your team is a member of this channel.</p>\n <p><strong>Off-Topic</strong> is a place for fun and humor outside of work-related channels. You and your team can decide what other channels to create.</p>",
+ "sidebar.tutorialScreen3": "<h4>Creating and Joining Channels</h4>\n <p>Click <strong>\"More...\"</strong> to create a new channel or join an existing one.</p>\n <p>You can also create a new channel or private group by clicking the <strong>\"+\" symbol</strong> next to the channel or private group header.</p>",
+ "sidebar.removeList": "Remove from list",
+ "sidebar.more": "More ({count})",
+ "sidebar.createChannel": "Create new channel",
+ "sidebar.createGroup": "Create new group",
+ "sidebar.unreadAbove": "Unread post(s) above",
+ "sidebar.unreadBelow": "Unread post(s) below",
+ "sidebar.channels": "Channels",
+ "sidebar.moreElips": "More...",
+ "sidebar.pg": "Private Groups",
+ "sidebar.direct": "Direct Messages",
"signup_team_complete.completed": "You've already completed the signup process for this invitation or this invitation has expired.",
"signup_team_confirm.title": "Sign up Complete",
"signup_team_confirm.checkEmail": "Please check your email: <strong>{email}</strong><br />Your email contains a link to set up your team",
@@ -589,6 +702,43 @@
"suggestion.mention.channel": "Notifies everyone in the channel",
"suggestion.search.public": "Public Channels",
"suggestion.search.private": "Public Groups",
+ "team_export_tab.exporting": " Exporting...",
+ "team_export_tab.ready": " Ready for ",
+ "team_export_tab.download": "download",
+ "team_export_tab.unable": " Unable to export: {error}",
+ "team_export_tab.export": "Export",
+ "team_export_tab.exportTeam": "Export your team",
+ "general_tab.dirDisabled": "Team Directory has been disabled. Please ask a System Admin to enable the Team Directory in the System Console team settings.",
+ "general_tab.required": "This field is required",
+ "general_tab.chooseName": "Please choose a new name for your team",
+ "general_tab.includeDirTitle": "Include this team in the Team Directory",
+ "general_tab.yes": "Yes",
+ "general_tab.no": "No",
+ "general_tab.dirOff": "Team directory is turned off for this system.",
+ "general_tab.openInviteTitle": "Allow anyone to sign-up from login page",
+ "general_tab.codeTitle": "Invite Code",
+ "general_tab.codeDesc": "Click 'Edit' to regenerate Invite Code.",
+ "general_tab.teamNameInfo": "Set the name of the team as it appears on your sign-in screen and at the top of the left-hand sidebar.",
+ "general_tab.includeDirDesc": "Including this team will display the team name from the Team Directory section of the Home Page, and provide a link to the sign-in page.",
+ "general_tab.dirContact": "Contact your system administrator to turn on the team directory on the system home page.",
+ "general_tab.openInviteDesc": "When allowed, a link to account creation will be included on the sign-in page of this team and allow any visitor to sign-up.",
+ "general_tab.regenerate": "Re-Generate",
+ "general_tab.codeLongDesc": "The Invite Code is used as part of the URL in the team invitation link created by **Get Team Invite Link** in the main menu. Regenerating creates a new team invitation link and invalidates the previous link.",
+ "general_tab.teamName": "Team Name",
+ "general_tab.title": "General Settings",
+ "team_import_tab.importSlack": "Import from Slack (Beta)",
+ "team_import_tab.importHelp": "<p>To import a team from Slack go to Slack > Team Settings > Import/Export Data > Export > Start Export. Slack does not allow you to export files, images, private groups or direct messages stored in Slack. Therefore, Slack import to Mattermost only supports importing of text messages in your Slack team's public channels.</p><p>The Slack import to Mattermost is in 'Beta'. Slack bot posts do not yet import and Slack @mentions are not currently supported.</p>",
+ "team_import_tab.importing": " Importing...",
+ "team_import_tab.successful": " Import successful: ",
+ "team_import_tab.summary": "View Summary",
+ "team_import_tab.failure": " Import failure: ",
+ "team_import_tab.import": "Import",
+ "team_member_modal.members": "{team} Members",
+ "team_member_modal.close": "Close",
+ "team_settings_modal.generalTab": "General",
+ "team_settings_modal.importTab": "Import",
+ "team_settings_modal.exportTab": "Export",
+ "team_settings_modal.title": "Team Settings",
"choose_auth_page.gitlabCreate": "Create new team with GitLab Account",
"choose_auth_page.googleCreate": "Create new team with Google Apps Account",
"choose_auth_page.emailCreate": "Create new team with email address",
diff --git a/web/static/i18n/es.json b/web/static/i18n/es.json
index dd7d22fdd..ee24df1b3 100644
--- a/web/static/i18n/es.json
+++ b/web/static/i18n/es.json
@@ -1,4 +1,13 @@
{
+ "about.close": "Cerrar",
+ "about.date": "Fecha de compilación:",
+ "about.enterpriseEdition": "Edición Enterprise",
+ "about.hash": "Hash de compilación:",
+ "about.licensed": "Licenciado por:",
+ "about.number": "Número de compilación:",
+ "about.teamEdtion": "Edición Team",
+ "about.title": "Acerca de Mattermost",
+ "about.version": "Versión:",
"access_history.accountActive": "La cuenta se ha activado",
"access_history.accountInactive": "La cuenta se ha desactivado",
"access_history.attemptedAllowOAuthAccess": "Intento para permitir acceso a un nuevo servicio de OAuth",
@@ -446,24 +455,55 @@
"admin.team_analytics.totalPosts": "Total de Mensajes",
"admin.userList.title": "Usuarios para ",
"admin.userList.title2": "Usuarios para {team} ({count})",
+ "admin.user_item.confirmDemoteDescription": "Si te degradas a ti mismo de la función de Administrador de Sistema y no hay otro usuario con privilegios de Administrador de Sistema, tendrás que volver a asignar un Administrador del Sistema accediendo al servidor de Mattermost a través de un terminal y ejecutar el siguiente comando.",
+ "admin.user_item.confirmDemoteRoleTitle": "Confirmar el decenso del rol de Administrador de Sistema",
+ "admin.user_item.confirmDemotion": "Confirmar decenso",
+ "admin.user_item.confirmDemotionCmd": "platform -assign_role -team_name=\"tuequipo\" -email=\"nombre@tuempresa.com\" -role=\"system_admin\"",
"admin.user_item.inactive": "Inactivo",
"admin.user_item.makeActive": "Activar",
"admin.user_item.makeInactive": "Inactivar",
"admin.user_item.makeMember": "Hacer Miembro",
"admin.user_item.makeSysAdmin": "Hacer Admin del Sistema",
"admin.user_item.makeTeamAdmin": "Hacer Admin de Equipo",
- "admin.user_item.member": "Meiembro",
+ "admin.user_item.member": "Miembro",
"admin.user_item.resetPwd": "Reiniciar Contraseña",
"admin.user_item.sysAdmin": "Admin de Sistema",
"admin.user_item.teamAdmin": "Admin de Equipo",
- "admin.user_item.confirmDemoteRoleTitle": "Confirm demotion from System Admin role",
- "admin.user_item.confirmDemotion": "Confirm Demotion",
- "admin.user_item.confirmDemoteDescription": "If you demote yourself from the System Admin role and there is not another user with System Admin privileges, you'll need to re-assign a System Admin by accessing the Mattermost server through a terminal and running the following command.",
"authorize.access": "¿Permitir acceso a {appName}?",
"authorize.allow": "Permitir",
"authorize.app": "La app {appName} quiere tener la abilidad de accesar y modificar tu información básica.",
"authorize.deny": "Denegar",
"authorize.title": "Una aplicación quiere conectarse con tu cuenta de {teamName}",
+ "change_url.close": "Cerrar",
+ "change_url.endWithLetter": "Debe terminar con una letra o número",
+ "change_url.invalidUrl": "URL Inválida",
+ "change_url.longer": "Debe ser mayor a 2 caracteres",
+ "change_url.noUnderscore": "No puede tener dos guíones bajos seguidos",
+ "change_url.startWithLetter": "Debe comenzar con una letra o número",
+ "channel_flow.alreadyExist": "Un canal con este identificador ya existe",
+ "channel_flow.changeUrlDescription": "Algunos caracteres no están permitidos en las URLs y pueden ser removidos.",
+ "channel_flow.changeUrlTitle": "Cambiar URL de {term}",
+ "channel_flow.channel": "Canal",
+ "channel_flow.create": "Crear {term}",
+ "channel_flow.group": "Grupo",
+ "channel_flow.invalidName": "Nombre de Canal Inválido",
+ "channel_flow.set_url_title": "Asignar URL de {term}",
+ "channel_modal.cancel": "Cancelar",
+ "channel_modal.channel": "Canal",
+ "channel_modal.createNew": "Crear Nuevo ",
+ "channel_modal.descriptionHelp": "Describe como este {term} debería ser utilizado.",
+ "channel_modal.displayNameError": "Este campo es obligatorio",
+ "channel_modal.edit": "Editar",
+ "channel_modal.group": "Grupo",
+ "channel_modal.modalTitle": "Nuevo ",
+ "channel_modal.name": "Nombre",
+ "channel_modal.nameEx": "Ej: \"Errores\", \"Mercadeo\", \"办公室恋情\"",
+ "channel_modal.optional": "(opcional)",
+ "channel_modal.privateGroup1": "Crear un grupo privado con acceso restringido. ",
+ "channel_modal.privateGroup2": "Crear un grupo privado",
+ "channel_modal.publicChannel1": "Crear un canal público",
+ "channel_modal.publicChannel2": "Crear un canal público al que cualquiera puede unirse. ",
+ "channel_modal.purpose": "Propósito",
"choose_auth_page.emailCreate": "Crea un nuevo equipo con tu cuenta de correo",
"choose_auth_page.find": "Encontrar mi equipo",
"choose_auth_page.gitlabCreate": "Crear un nuevo equipo con una cuenta de GitLab",
@@ -503,6 +543,47 @@
"find_team.placeholder": "tu@ejemplo.com",
"find_team.send": "Enviar",
"find_team.submitError": "Por favor ingresa una dirección válida",
+ "general_tab.chooseName": "Por favor escoge otro nombre para tu equipo",
+ "general_tab.codeDesc": "Pincha 'Editar' para regenerar el código de Invitación.",
+ "general_tab.codeLongDesc": "El Código de Invitación es utilizado como parte del URL del enlace creado por la opción **Obtener Enlace de invitación** en el menú principal. Regenerar este código crea un nuevo enlace e invalida los enlaces anteriores.",
+ "general_tab.codeTitle": "Código de Invitación",
+ "general_tab.dirContact": "Contácta a un administrador del sistema para habilitar el directorio de equipos en la página principal.",
+ "general_tab.dirDisabled": "El directorio de Equipos ha sido deshabilitado. Por favor solicita a un Administrador de Sistema que habilite la opción de Directorio de Equipos en la Consola del Sistema.",
+ "general_tab.dirOff": "El directorio de Equipos ha sido deshabilitado para este sistema.",
+ "general_tab.includeDirDesc": "Incluir este equipo mostrará el nombre del equipo en la sección de Directorio de Equipos en la página de inicio, y proveerá un enlace para la página de inicio de sesión.",
+ "general_tab.includeDirTitle": "Incluir este Equipo en el Directorio de Equipos",
+ "general_tab.no": "No",
+ "general_tab.openInviteDesc": "Cuando está permitido, un enlace para la creación de cuentas será incluido en la página de registro de este equipo y permitirá a cualquier visitante registrarse.",
+ "general_tab.openInviteTitle": "Permitir a cualquiera a inscribirse desde la página de inicio de sesión",
+ "general_tab.regenerate": "Regenerar",
+ "general_tab.required": "Este campo es obligatorio",
+ "general_tab.teamName": "Nombre del Equipo",
+ "general_tab.teamNameInfo": "Asigna el nombre del equipo como aparecerá en la página de inicio de sesión y en la parte superior izquierda de la barra lateral.",
+ "general_tab.title": "Configuración General",
+ "general_tab.yes": "Sí",
+ "get_link.clipboard": " Enlace copiado al portapapeles.",
+ "get_link.close": "Cerrar",
+ "get_link.copy": "Copiar Enlace",
+ "get_team_invite_link_modal.help": "Enviar a los compañeros de equipo el enlace que se muestra a continuación para permitirles registrarse a este equipo.",
+ "get_team_invite_link_modal.title": "Enlace de Invitación al Equipo",
+ "invite_member.addAnother": "Agregar otro",
+ "invite_member.autoJoin": "Las personas invitadas se unirán automáticamente al canal <strong>{channel}</strong>.",
+ "invite_member.cancel": "Cancelar",
+ "invite_member.content": "El envio de correos está actualmente desactivado para tu equipo, por lo que no puedes enviar invitaciones.",
+ "invite_member.disabled": "La creación de usuarios ha sido deshabilitada para tu equipo. Por favor consulta con un administrador de tu equipo.",
+ "invite_member.emailError": "Por favor ingresa un correo electrónico válido",
+ "invite_member.firstname": "Nombre",
+ "invite_member.inviteLink": "Enlace de Invitación al Equipo",
+ "invite_member.lastname": "Apellido",
+ "invite_member.modalButton": "Sí, Borrar",
+ "invite_member.modalMessage": "Tienes invitaciones sin usar, estás seguro que quieres borrarlas?",
+ "invite_member.modalTitle": "¿Descartar Invitaciones?",
+ "invite_member.newMember": "Invitar nuevo Miembro",
+ "invite_member.send": "Enviar Invitaciones",
+ "invite_member.send2": "Enviar Invitaciones",
+ "invite_member.sending": " Enviando",
+ "invite_member.teamInvite": "Invitación de Equipo",
+ "invite_member.teamInviteLink": "También puedes invitar personas usando el {link}.",
"loading_screen.loading": "Cargando",
"login.changed": " Cambiado el método de inicio de sesión satisfactoriamente",
"login.create": "Crea una ahora",
@@ -528,6 +609,40 @@
"login_ldap.pwdReq": "La contraseña LDAP es obligatoria",
"login_ldap.signin": "Entrar",
"login_ldap.username": "Usuario LDAP",
+ "member_team_item.inactive": "Inactivo",
+ "member_team_item.makeActive": "Activar",
+ "member_team_item.makeAdmin": "Convertir a Admin de Equipo",
+ "member_team_item.makeInactive": "Desactivar",
+ "member_team_item.makeMember": "Convertir en Miembro",
+ "member_team_item.member": "Miembro",
+ "member_team_item.systemAdmin": "Administrador de Sistema",
+ "member_team_item.teamAdmin": "Admin de Equipo",
+ "more_channels.close": "Cerrar",
+ "more_channels.create": "Crear Nuevo Canal",
+ "more_channels.createClick": "Pincha 'Crear Nuevo Canal' para crear uno nuevo",
+ "more_channels.join": "Unirme",
+ "more_channels.noMore": "No hay más canales para unirse",
+ "more_channels.title": "Más Canales",
+ "more_direct_channels.close": "Cerrar",
+ "more_direct_channels.count": "{count} {member}",
+ "more_direct_channels.countTotal": "{count} {member} de {total} Total",
+ "more_direct_channels.member": "Miembro",
+ "more_direct_channels.message": "Mensaje",
+ "more_direct_channels.notFound": "No se encontraron usuarios :(",
+ "more_direct_channels.search": "Buscar miembros",
+ "more_direct_channels.title": "Mensajes Directos",
+ "navbar_dropdown.about": "Acerca de Mattermost",
+ "navbar_dropdown.accountSettings": "Configurar Cuenta",
+ "navbar_dropdown.console": "Consola de Sistema",
+ "navbar_dropdown.create": "Crear nuevo Equipo",
+ "navbar_dropdown.help": "Ayuda",
+ "navbar_dropdown.inviteMember": "Invitar Nuevo Miembro",
+ "navbar_dropdown.logout": "Cerrar sesión",
+ "navbar_dropdown.manageMembers": "Administrar Miembros",
+ "navbar_dropdown.report": "Reportar un Problema",
+ "navbar_dropdown.switchTeam": "Cambiar a {team}",
+ "navbar_dropdown.teamLink": "Enlace invitación al equipo",
+ "navbar_dropdown.teamSettings": "Configurar Equipo",
"password_form.change": "Cambiar mi contraseña",
"password_form.click": " Pincha <a href={url}>aquí</a> para iniciar sesión.",
"password_form.enter": "Ingresa una nueva contraseña para tu cuenta en {teamDisplayName} {SiteName}.",
@@ -568,6 +683,23 @@
"setting_picture.help": "Sube una imagen de tu perfil en formato JPG o PNG de al menos {width}px de ancho y {height}px de alto.",
"setting_picture.save": "Guardar",
"setting_picture.select": "Selecciona",
+ "setting_upload.import": "Importar",
+ "setting_upload.noFile": "No ha seleccionado un archivo",
+ "setting_upload.select": "Selecciona un archivo",
+ "sidebar.channels": "Canales",
+ "sidebar.createChannel": "Crear un nuevo canal",
+ "sidebar.createGroup": "Crear un nuevo grupo",
+ "sidebar.direct": "Mensajes Directos",
+ "sidebar.more": "Más ({count})",
+ "sidebar.moreElips": "Más...",
+ "sidebar.pg": "Grupos Privados",
+ "sidebar.removeList": "Remover de la lista",
+ "sidebar.tutorialScreen1": "<h4>Canales</h4><p><strong>Canales</strong> organizan las conversaciones en diferentes tópicos. Son abiertos para cualquier persona de tu equipo. Para enviar comunicaciones privadas con una sola persona utiliza <strong>Mensajes Directos</strong> o con multiples personas utilizando <strong>Grupos Privados</strong>.</p>",
+ "sidebar.tutorialScreen2": "<h4>Canal \"General\"</h4><p>Este es un canal para comenzar:</p><p><strong>General</strong> es el lugar para tener comunicación con todo el equipo. Todos los integrantes de tu equipo son miembros de este canal.</p>",
+ "sidebar.tutorialScreen3": "<h4>Creando y Uniendose a Canales</h4><p>Pincha en <strong>\"Más...\"</strong> para crear un nuevo canal o unirte a uno existente.</p><p>También puedes crear un nuevo canal o grupo privado al pinchar el simbolo de <strong>\"+\"</strong> que se encuentra al lado del encabezado de Canales o Grupos Privados.</p>",
+ "sidebar.unreadAbove": "Mensaje(s) sin leer arriba",
+ "sidebar.unreadBelow": "Mensaje(s) sin leer abajo",
+ "sidebar_header.tutorial": "<h4>Menú Principal</h4><p>El <strong>Menú Principal</strong> es donde puedes <strong>Invitar a nuevos miembros</strong>, podrás <strong>Configurar tu Cuenta</strong> y seleccionar un <strong>Tema</strong> para personalizar la apariencia.</p><p>Los administradores del Equipo podrán <strong>Configurar el Equipo</strong> desde este menú.</p><p>Los administradores del Sistema encontrarán una opción para ir a la <strong>Consola de Sistema</strong> para administrar el sistema completo.</p>",
"signup_team.choose": "Selecciona un Equipo",
"signup_team.createTeam": "O Crea un Equipo",
"signup_team.disabled": "La creación de Equipos ha sido deshabilitada.",
@@ -604,6 +736,25 @@
"suggestion.mention.channel": "Notifica a todas las personas en el canal",
"suggestion.search.private": "Grupos Privados",
"suggestion.search.public": "Canales Públicos",
+ "team_export_tab.download": "descargar",
+ "team_export_tab.export": "Exportar",
+ "team_export_tab.exportTeam": "Exportar tu equipo",
+ "team_export_tab.exporting": " Exportando...",
+ "team_export_tab.ready": " Listo para ",
+ "team_export_tab.unable": " No se pudo exportar: {error}",
+ "team_import_tab.failure": " Fallo al importar: ",
+ "team_import_tab.import": "Importar",
+ "team_import_tab.importHelp": "<p>Para importar un equipo desde Slack dirigete a Slack > Team Settings > Import/Export Data > Export > Start Export. Slack no permite exportar archivos, imágenes, grupos privados o mensajes directos almacenados en Slack. Por ende, La importación desde Slack hacia Mattermost sólo soporta la importación de los mensajes de texto de los canales públicos de tu equipo.</p><p>La importación desde Slack hacia Mattermost está en fase \"Beta\". Los mensajes enviados por Bots en y las @menciones actualmente no son soportados.</p>",
+ "team_import_tab.importSlack": "Importar desde Slack (Beta)",
+ "team_import_tab.importing": " Importando...",
+ "team_import_tab.successful": " Importado con éxito: ",
+ "team_import_tab.summary": "Ver Resumen",
+ "team_member_modal.close": "Cerrar",
+ "team_member_modal.members": "{team} Miembros",
+ "team_settings_modal.exportTab": "Exportar",
+ "team_settings_modal.generalTab": "General",
+ "team_settings_modal.importTab": "Importar",
+ "team_settings_modal.title": "Configuración del Equipo",
"team_signup_display_name.back": "Volver al paso previo",
"team_signup_display_name.charLength": "El nombre debe tener 4 o más caracteres hasta un máximo de 15",
"team_signup_display_name.nameHelp": "Nombre tu equipo en cualquier idioma. El nombre de tu equipo aparecerá en menús y en inicios",