summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author=Corey Hulen <corey@hulen.com>2016-01-28 11:59:38 -0500
committer=Corey Hulen <corey@hulen.com>2016-01-28 11:59:38 -0500
commite37b2c62f3148ec26f9eddd57d208a640715e68e (patch)
tree27e9484181d1b20ef4e78513f66866d4b82ec900
parent2138b46f6cdab5fca49680c2e1994703ab71b1c3 (diff)
parentdb37897538f134b29784453797510c20e1e9303c (diff)
downloadchat-e37b2c62f3148ec26f9eddd57d208a640715e68e.tar.gz
chat-e37b2c62f3148ec26f9eddd57d208a640715e68e.tar.bz2
chat-e37b2c62f3148ec26f9eddd57d208a640715e68e.zip
Merge branch 'master' into PLT-1765
-rw-r--r--Makefile2
-rw-r--r--utils/i18n.go22
-rw-r--r--web/react/components/admin_console/analytics.jsx119
-rw-r--r--web/react/components/admin_console/gitlab_settings.jsx150
-rw-r--r--web/react/components/admin_console/image_settings.jsx295
-rw-r--r--web/react/components/admin_console/ldap_settings.jsx266
-rw-r--r--web/react/components/admin_console/legal_and_support_settings.jsx100
-rw-r--r--web/react/components/admin_console/license_settings.jsx153
-rw-r--r--web/react/components/admin_console/log_settings.jsx173
-rw-r--r--web/react/components/admin_console/logs.jsx14
-rw-r--r--web/react/components/admin_console/privacy_settings.jsx72
-rw-r--r--web/react/components/admin_console/rate_settings.jsx141
-rw-r--r--web/react/components/admin_console/reset_password_modal.jsx38
-rw-r--r--web/react/components/admin_console/service_settings.jsx322
-rw-r--r--web/react/components/admin_console/sql_settings.jsx145
-rw-r--r--web/react/components/admin_console/system_analytics.jsx29
-rw-r--r--web/react/components/admin_console/team_analytics.jsx23
-rw-r--r--web/react/components/admin_console/team_settings.jsx171
-rw-r--r--web/react/components/admin_console/team_users.jsx23
-rw-r--r--web/react/components/admin_console/user_item.jsx60
-rw-r--r--web/react/components/center_panel.jsx6
-rw-r--r--web/react/components/claim/claim_account.jsx11
-rw-r--r--web/react/components/claim/email_to_sso.jsx61
-rw-r--r--web/react/components/claim/sso_to_email.jsx72
-rw-r--r--web/react/components/new_channel_modal.jsx5
-rw-r--r--web/react/components/suggestion/at_mention_provider.jsx16
-rw-r--r--web/react/components/suggestion/search_suggestion_list.jsx17
-rw-r--r--web/react/components/tutorial/tutorial_intro_screens.jsx65
-rw-r--r--web/react/components/tutorial/tutorial_tip.jsx25
-rw-r--r--web/sass-files/sass/partials/_content.scss1
-rw-r--r--web/sass-files/sass/partials/_markdown.scss2
-rw-r--r--web/sass-files/sass/partials/_modal.scss5
-rw-r--r--web/sass-files/sass/partials/_post.scss8
-rw-r--r--web/static/i18n/en.json349
-rw-r--r--web/static/i18n/es.json349
35 files changed, 2820 insertions, 490 deletions
diff --git a/Makefile b/Makefile
index 1012b786e..9c4e6ee1f 100644
--- a/Makefile
+++ b/Makefile
@@ -255,7 +255,7 @@ nuke: | clean clean-docker
touch $@
-.prepare-jsx:
+.prepare-jsx: web/react/package.json
@echo Preparation for compiling jsx code
cd web/react/ && npm install
diff --git a/utils/i18n.go b/utils/i18n.go
index 05154bd92..e809ae883 100644
--- a/utils/i18n.go
+++ b/utils/i18n.go
@@ -44,7 +44,7 @@ func GetTranslationsBySystemLocale() i18n.TranslateFunc {
panic("Failed to load system translations for '" + model.DEFAULT_LOCALE + "'")
}
- translations, _ := i18n.Tfunc(locale)
+ translations := TfuncWithFallback(locale)
if translations == nil {
panic("Failed to load system translations")
}
@@ -58,22 +58,34 @@ func GetUserTranslations(locale string) i18n.TranslateFunc {
locale = model.DEFAULT_LOCALE
}
- translations, _ := i18n.Tfunc(locale)
+ translations := TfuncWithFallback(locale)
return translations
}
func SetTranslations(locale string) i18n.TranslateFunc {
- translations, _ := i18n.Tfunc(locale)
+ translations := TfuncWithFallback(locale)
return translations
}
func GetTranslationsAndLocale(w http.ResponseWriter, r *http.Request) (i18n.TranslateFunc, string) {
headerLocale := strings.Split(strings.Split(r.Header.Get("Accept-Language"), ",")[0], "-")[0]
if locales[headerLocale] != "" {
- translations, _ := i18n.Tfunc(headerLocale)
+ translations := TfuncWithFallback(headerLocale)
return translations, headerLocale
}
- translations, _ := i18n.Tfunc(model.DEFAULT_LOCALE)
+ translations := TfuncWithFallback(model.DEFAULT_LOCALE)
return translations, model.DEFAULT_LOCALE
}
+
+func TfuncWithFallback(pref string) i18n.TranslateFunc {
+ t, _ := i18n.Tfunc(pref)
+ return func(translationID string, args ...interface{}) string {
+ if translated := t(translationID, args...); translated != translationID {
+ return translated
+ }
+
+ t, _ := i18n.Tfunc("en")
+ return t(translationID, args...)
+ }
+}
diff --git a/web/react/components/admin_console/analytics.jsx b/web/react/components/admin_console/analytics.jsx
index 70ef1ecab..ff5903c62 100644
--- a/web/react/components/admin_console/analytics.jsx
+++ b/web/react/components/admin_console/analytics.jsx
@@ -8,6 +8,8 @@ import LineChart from './line_chart.jsx';
var Tooltip = ReactBootstrap.Tooltip;
var OverlayTrigger = ReactBootstrap.OverlayTrigger;
+import {FormattedMessage} from 'mm-intl';
+
export default class Analytics extends React.Component {
constructor(props) {
super(props);
@@ -21,11 +23,23 @@ export default class Analytics extends React.Component {
serverError = <div className='form-group has-error'><label className='control-label'>{this.props.serverError}</label></div>;
}
+ let loading = (
+ <FormattedMessage
+ id='admin.analytics.loading'
+ defaultMessage='Loading...'
+ />
+ );
+
var totalCount = (
<div className='col-sm-3'>
<div className='total-count'>
- <div className='title'>{'Total Users'}<i className='fa fa-users'/></div>
- <div className='content'>{this.props.uniqueUserCount == null ? 'Loading...' : this.props.uniqueUserCount}</div>
+ <div className='title'>
+ <FormattedMessage
+ id='admin.analytics.totalUsers'
+ defaultMessage='Total Users'
+ />
+ <i className='fa fa-users'/></div>
+ <div className='content'>{this.props.uniqueUserCount == null ? loading : this.props.uniqueUserCount}</div>
</div>
</div>
);
@@ -33,8 +47,13 @@ export default class Analytics extends React.Component {
var openChannelCount = (
<div className='col-sm-3'>
<div className='total-count'>
- <div className='title'>{'Public Channels'}<i className='fa fa-globe'/></div>
- <div className='content'>{this.props.channelOpenCount == null ? 'Loading...' : this.props.channelOpenCount}</div>
+ <div className='title'>
+ <FormattedMessage
+ id='admin.analytics.publicChannels'
+ defaultMessage='Public Channels'
+ />
+ <i className='fa fa-globe'/></div>
+ <div className='content'>{this.props.channelOpenCount == null ? loading : this.props.channelOpenCount}</div>
</div>
</div>
);
@@ -42,8 +61,13 @@ export default class Analytics extends React.Component {
var openPrivateCount = (
<div className='col-sm-3'>
<div className='total-count'>
- <div className='title'>{'Private Groups'}<i className='fa fa-lock'/></div>
- <div className='content'>{this.props.channelPrivateCount == null ? 'Loading...' : this.props.channelPrivateCount}</div>
+ <div className='title'>
+ <FormattedMessage
+ id='admin.analytics.privateGroups'
+ defaultMessage='Private Groups'
+ />
+ <i className='fa fa-lock'/></div>
+ <div className='content'>{this.props.channelPrivateCount == null ? loading : this.props.channelPrivateCount}</div>
</div>
</div>
);
@@ -51,8 +75,13 @@ export default class Analytics extends React.Component {
var postCount = (
<div className='col-sm-3'>
<div className='total-count'>
- <div className='title'>{'Total Posts'}<i className='fa fa-comment'/></div>
- <div className='content'>{this.props.postCount == null ? 'Loading...' : this.props.postCount}</div>
+ <div className='title'>
+ <FormattedMessage
+ id='admin.analytics.totalPosts'
+ defaultMessage='Total Posts'
+ />
+ <i className='fa fa-comment'/></div>
+ <div className='content'>{this.props.postCount == null ? loading : this.props.postCount}</div>
</div>
</div>
);
@@ -60,8 +89,13 @@ export default class Analytics extends React.Component {
var postCountsByDay = (
<div className='col-sm-12'>
<div className='total-count by-day'>
- <div className='title'>{'Total Posts'}</div>
- <div className='content'>{'Loading...'}</div>
+ <div className='title'>
+ <FormattedMessage
+ id='admin.analytics.totalPosts'
+ defaultMessage='Total Posts'
+ />
+ </div>
+ <div className='content'>{loading}</div>
</div>
</div>
);
@@ -69,7 +103,12 @@ export default class Analytics extends React.Component {
if (this.props.postCountsDay != null) {
let content;
if (this.props.postCountsDay.labels.length === 0) {
- content = 'Not enough data for a meaningful representation.';
+ content = (
+ <FormattedMessage
+ id='admin.analytics.meaningful'
+ defaultMessage='Not enough data for a meaningful representation.'
+ />
+ );
} else {
content = (
<LineChart
@@ -82,7 +121,12 @@ export default class Analytics extends React.Component {
postCountsByDay = (
<div className='col-sm-12'>
<div className='total-count by-day'>
- <div className='title'>{'Total Posts'}</div>
+ <div className='title'>
+ <FormattedMessage
+ id='admin.analytics.totalPosts'
+ defaultMessage='Total Posts'
+ />
+ </div>
<div className='content'>
{content}
</div>
@@ -94,8 +138,13 @@ export default class Analytics extends React.Component {
var usersWithPostsByDay = (
<div className='col-sm-12'>
<div className='total-count by-day'>
- <div className='title'>{'Active Users With Posts'}</div>
- <div className='content'>{'Loading...'}</div>
+ <div className='title'>
+ <FormattedMessage
+ id='admin.analytics.activeUsers'
+ defaultMessage='Active Users With Posts'
+ />
+ </div>
+ <div className='content'>{loading}</div>
</div>
</div>
);
@@ -103,7 +152,12 @@ export default class Analytics extends React.Component {
if (this.props.userCountsWithPostsDay != null) {
let content;
if (this.props.userCountsWithPostsDay.labels.length === 0) {
- content = 'Not enough data for a meaningful representation.';
+ content = (
+ <FormattedMessage
+ id='admin.analytics.meaningful'
+ defaultMessage='Not enough data for a meaningful representation.'
+ />
+ );
} else {
content = (
<LineChart
@@ -116,7 +170,12 @@ export default class Analytics extends React.Component {
usersWithPostsByDay = (
<div className='col-sm-12'>
<div className='total-count by-day'>
- <div className='title'>{'Active Users With Posts'}</div>
+ <div className='title'>
+ <FormattedMessage
+ id='admin.analytics.activeUsers'
+ defaultMessage='Active Users With Posts'
+ />
+ </div>
<div className='content'>
{content}
</div>
@@ -129,7 +188,7 @@ export default class Analytics extends React.Component {
if (this.props.recentActiveUsers != null) {
let content;
if (this.props.recentActiveUsers.length === 0) {
- content = 'Loading...';
+ content = loading;
} else {
content = (
<table>
@@ -167,7 +226,12 @@ export default class Analytics extends React.Component {
recentActiveUser = (
<div className='col-sm-6'>
<div className='total-count recent-active-users'>
- <div className='title'>{'Recent Active Users'}</div>
+ <div className='title'>
+ <FormattedMessage
+ id='admin.analytics.recentActive'
+ defaultMessage='Recent Active Users'
+ />
+ </div>
<div className='content'>
{content}
</div>
@@ -180,7 +244,7 @@ export default class Analytics extends React.Component {
if (this.props.newlyCreatedUsers != null) {
let content;
if (this.props.newlyCreatedUsers.length === 0) {
- content = 'Loading...';
+ content = loading;
} else {
content = (
<table>
@@ -218,7 +282,12 @@ export default class Analytics extends React.Component {
newUsers = (
<div className='col-sm-6'>
<div className='total-count recent-active-users'>
- <div className='title'>{'Newly Created Users'}</div>
+ <div className='title'>
+ <FormattedMessage
+ id='admin.analytics.newlyCreated'
+ defaultMessage='Newly Created Users'
+ />
+ </div>
<div className='content'>
{content}
</div>
@@ -229,7 +298,15 @@ export default class Analytics extends React.Component {
return (
<div className='wrapper--fixed team_statistics'>
- <h3>{'Statistics for ' + this.props.title}</h3>
+ <h3>
+ <FormattedMessage
+ id='admin.analytics.title'
+ defaultMessage='Statistics for {title}'
+ values={{
+ title: this.props.title
+ }}
+ />
+ </h3>
{serverError}
<div className='row'>
{totalCount}
diff --git a/web/react/components/admin_console/gitlab_settings.jsx b/web/react/components/admin_console/gitlab_settings.jsx
index 8c689a2d8..744fa3b19 100644
--- a/web/react/components/admin_console/gitlab_settings.jsx
+++ b/web/react/components/admin_console/gitlab_settings.jsx
@@ -4,7 +4,36 @@
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
-export default class GitLabSettings extends React.Component {
+import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
+
+const holders = defineMessages({
+ clientIdExample: {
+ id: 'admin.gitlab.clientIdExample',
+ defaultMessage: 'Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'
+ },
+ clientSecretExample: {
+ id: 'admin.gitlab.clientSecretExample',
+ defaultMessage: 'Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'
+ },
+ authExample: {
+ id: 'admin.gitlab.authExample',
+ defaultMessage: 'Ex ""'
+ },
+ tokenExample: {
+ id: 'admin.gitlab.tokenExample',
+ defaultMessage: 'Ex ""'
+ },
+ userExample: {
+ id: 'admin.gitlab.userExample',
+ defaultMessage: 'Ex ""'
+ },
+ saving: {
+ id: 'admin.gitlab.saving',
+ defaultMessage: 'Saving Config...'
+ }
+});
+
+class GitLabSettings extends React.Component {
constructor(props) {
super(props);
@@ -65,6 +94,7 @@ export default class GitLabSettings extends React.Component {
}
render() {
+ const {formatMessage} = this.props.intl;
var serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
@@ -78,7 +108,12 @@ export default class GitLabSettings extends React.Component {
return (
<div className='wrapper--fixed'>
- <h3>{'GitLab Settings'}</h3>
+ <h3>
+ <FormattedMessage
+ id='admin.gitlab.settingsTitle'
+ defaultMessage='GitLab Settings'
+ />
+ </h3>
<form
className='form-horizontal'
role='form'
@@ -89,7 +124,10 @@ export default class GitLabSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='Enable'
>
- {'Enable Sign Up With GitLab: '}
+ <FormattedMessage
+ id='admin.gitlab.enableTitle'
+ defaultMessage='Enable Sign Up With GitLab: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -101,7 +139,10 @@ export default class GitLabSettings extends React.Component {
defaultChecked={this.props.config.GitLabSettings.Enable}
onChange={this.handleChange.bind(this, 'EnableTrue')}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.gitlab.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -111,18 +152,23 @@ export default class GitLabSettings extends React.Component {
defaultChecked={!this.props.config.GitLabSettings.Enable}
onChange={this.handleChange.bind(this, 'EnableFalse')}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.gitlab.false'
+ defaultMessage='false'
+ />
</label>
<p className='help-text'>
- {'When true, Mattermost allows team creation and account signup using GitLab OAuth.'} <br/>
+ <FormattedMessage
+ id='admin.gitlab.enableDescription'
+ defaultMessage='When true, Mattermost allows team creation and account signup using GitLab OAuth.'
+ />
+ <br/>
</p>
<div className='help-text'>
- <ol>
- <li>{'Log in to your GitLab account and go to Applications -> Profile Settings.'}</li>
- <li>{'Enter Redirect URIs "<your-mattermost-url>/login/gitlab/complete" (example: http://localhost:8065/login/gitlab/complete) and "<your-mattermost-url>/signup/gitlab/complete". '}</li>
- <li>{'Then use "Secret" and "Id" fields from GitLab to complete the options below.'}</li>
- <li>{'Complete the Endpoint URLs below. '}</li>
- </ol>
+ <FormattedHTMLMessage
+ id='admin.gitlab.EnableHtmlDesc'
+ defaultMessage='<ol><li>Log in to your GitLab account and go to Applications -> Profile Settings.</li><li>Enter Redirect URIs "<your-mattermost-url>/login/gitlab/complete" (example: http://localhost:8065/login/gitlab/complete) and "<your-mattermost-url>/signup/gitlab/complete". </li><li>Then use "Secret" and "Id" fields from GitLab to complete the options below.</li><li>Complete the Endpoint URLs below. </li></ol>'
+ />
</div>
</div>
</div>
@@ -132,7 +178,10 @@ export default class GitLabSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='Id'
>
- {'Id:'}
+ <FormattedMessage
+ id='admin.gitlab.clientIdTitle'
+ defaultMessage='Id:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -140,12 +189,17 @@ export default class GitLabSettings extends React.Component {
className='form-control'
id='Id'
ref='Id'
- placeholder='Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'
+ placeholder={formatMessage(holders.clientIdExample)}
defaultValue={this.props.config.GitLabSettings.Id}
onChange={this.handleChange}
disabled={!this.state.Enable}
/>
- <p className='help-text'>{'Obtain this value via the instructions above for logging into GitLab'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.gitlab.clientIdDescription'
+ defaultMessage='Obtain this value via the instructions above for logging into GitLab'
+ />
+ </p>
</div>
</div>
@@ -154,7 +208,10 @@ export default class GitLabSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='Secret'
>
- {'Secret:'}
+ <FormattedMessage
+ id='admin.gitlab.clientSecretTitle'
+ defaultMessage='Secret:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -162,12 +219,17 @@ export default class GitLabSettings extends React.Component {
className='form-control'
id='Secret'
ref='Secret'
- placeholder='Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'
+ placeholder={formatMessage(holders.clientSecretExample)}
defaultValue={this.props.config.GitLabSettings.Secret}
onChange={this.handleChange}
disabled={!this.state.Enable}
/>
- <p className='help-text'>{'Obtain this value via the instructions above for logging into GitLab.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.gitab.clientSecretDescription'
+ defaultMessage='Obtain this value via the instructions above for logging into GitLab.'
+ />
+ </p>
</div>
</div>
@@ -176,7 +238,10 @@ export default class GitLabSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='AuthEndpoint'
>
- {'Auth Endpoint:'}
+ <FormattedMessage
+ id='admin.gitlab.authTitle'
+ defaultMessage='Auth Endpoint:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -184,12 +249,17 @@ export default class GitLabSettings extends React.Component {
className='form-control'
id='AuthEndpoint'
ref='AuthEndpoint'
- placeholder='Ex ""'
+ placeholder={formatMessage(holders.authExample)}
defaultValue={this.props.config.GitLabSettings.AuthEndpoint}
onChange={this.handleChange}
disabled={!this.state.Enable}
/>
- <p className='help-text'>{'Enter https://<your-gitlab-url>/oauth/authorize (example https://example.com:3000/oauth/authorize). Make sure you use HTTP or HTTPS in your URL depending on your server configuration.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.gitlab.authDescription'
+ defaultMessage='Enter https://<your-gitlab-url>/oauth/authorize (example https://example.com:3000/oauth/authorize). Make sure you use HTTP or HTTPS in your URL depending on your server configuration.'
+ />
+ </p>
</div>
</div>
@@ -198,7 +268,10 @@ export default class GitLabSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='TokenEndpoint'
>
- {'Token Endpoint:'}
+ <FormattedMessage
+ id='admin.gitlab.tokenTitle'
+ defaultMessage='Token Endpoint:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -206,12 +279,17 @@ export default class GitLabSettings extends React.Component {
className='form-control'
id='TokenEndpoint'
ref='TokenEndpoint'
- placeholder='Ex ""'
+ placeholder={formatMessage(holders.tokenExample)}
defaultValue={this.props.config.GitLabSettings.TokenEndpoint}
onChange={this.handleChange}
disabled={!this.state.Enable}
/>
- <p className='help-text'>{'Enter https://<your-gitlab-url>/oauth/token. Make sure you use HTTP or HTTPS in your URL depending on your server configuration.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.gitlab.tokenDescription'
+ defaultMessage='Enter https://<your-gitlab-url>/oauth/token. Make sure you use HTTP or HTTPS in your URL depending on your server configuration.'
+ />
+ </p>
</div>
</div>
@@ -220,7 +298,10 @@ export default class GitLabSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='UserApiEndpoint'
>
- {'User API Endpoint:'}
+ <FormattedMessage
+ id='admin.gitlab.userTitle'
+ defaultMessage='User API Endpoint:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -228,12 +309,17 @@ export default class GitLabSettings extends React.Component {
className='form-control'
id='UserApiEndpoint'
ref='UserApiEndpoint'
- placeholder='Ex ""'
+ placeholder={formatMessage(holders.userExample)}
defaultValue={this.props.config.GitLabSettings.UserApiEndpoint}
onChange={this.handleChange}
disabled={!this.state.Enable}
/>
- <p className='help-text'>{'Enter https://<your-gitlab-url>/api/v3/user. Make sure you use HTTP or HTTPS in your URL depending on your server configuration.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.gitlab.userDescription'
+ defaultMessage='Enter https://<your-gitlab-url>/api/v3/user. Make sure you use HTTP or HTTPS in your URL depending on your server configuration.'
+ />
+ </p>
</div>
</div>
@@ -246,9 +332,12 @@ export default class GitLabSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
- data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
+ data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
>
- {'Save'}
+ <FormattedMessage
+ id='admin.gitlab.save'
+ defaultMessage='Save'
+ />
</button>
</div>
</div>
@@ -283,5 +372,8 @@ export default class GitLabSettings extends React.Component {
// </div>
GitLabSettings.propTypes = {
+ intl: intlShape.isRequired,
config: React.PropTypes.object
};
+
+export default injectIntl(GitLabSettings); \ No newline at end of file
diff --git a/web/react/components/admin_console/image_settings.jsx b/web/react/components/admin_console/image_settings.jsx
index e1ffad7d3..12bf554ea 100644
--- a/web/react/components/admin_console/image_settings.jsx
+++ b/web/react/components/admin_console/image_settings.jsx
@@ -5,7 +5,76 @@ import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
import crypto from 'crypto';
-export default class FileSettings extends React.Component {
+import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
+
+const holders = defineMessages({
+ storeDisabled: {
+ id: 'admin.image.storeDisabled',
+ defaultMessage: 'Disable File Storage'
+ },
+ storeLocal: {
+ id: 'admin.image.storeLocal',
+ defaultMessage: 'Local File System'
+ },
+ storeAmazonS3: {
+ id: 'admin.image.storeAmazonS3',
+ defaultMessage: 'Amazon S3'
+ },
+ localExample: {
+ id: 'admin.image.localExample',
+ defaultMessage: 'Ex "./data/"'
+ },
+ amazonS3IdExample: {
+ id: 'admin.image.amazonS3IdExample',
+ defaultMessage: 'Ex "AKIADTOVBGERKLCBV"'
+ },
+ amazonS3SecretExample: {
+ id: 'admin.image.amazonS3SecretExample',
+ defaultMessage: 'Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'
+ },
+ amazonS3BucketExample: {
+ id: 'admin.image.amazonS3BucketExample',
+ defaultMessage: 'Ex "mattermost-media"'
+ },
+ amazonS3RegionExample: {
+ id: 'admin.image.amazonS3RegionExample',
+ defaultMessage: 'Ex "us-east-1"'
+ },
+ thumbWidthExample: {
+ id: 'admin.image.thumbWidthExample',
+ defaultMessage: 'Ex "120"'
+ },
+ thumbHeightExample: {
+ id: 'admin.image.thumbHeightExample',
+ defaultMessage: 'Ex "100"'
+ },
+ previewWidthExample: {
+ id: 'admin.image.previewWidthExample',
+ defaultMessage: 'Ex "1024"'
+ },
+ previewHeightExample: {
+ id: 'admin.image.previewHeightExample',
+ defaultMessage: 'Ex "0"'
+ },
+ profileWidthExample: {
+ id: 'admin.image.profileWidthExample',
+ defaultMessage: 'Ex "1024"'
+ },
+ profileHeightExample: {
+ id: 'admin.image.profileHeightExample',
+ defaultMessage: 'Ex "0"'
+ },
+ publicLinkExample: {
+ id: 'admin.image.publicLinkExample',
+ defaultMessage: 'Ex "gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6"'
+ },
+ saving: {
+ id: 'admin.image.saving',
+ defaultMessage: 'Saving Config...'
+ }
+});
+
+class FileSettings extends React.Component {
constructor(props) {
super(props);
@@ -120,6 +189,7 @@ export default class FileSettings extends React.Component {
}
render() {
+ const {formatMessage} = this.props.intl;
var serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
@@ -143,7 +213,12 @@ export default class FileSettings extends React.Component {
return (
<div className='wrapper--fixed'>
- <h3>{'File Settings'}</h3>
+ <h3>
+ <FormattedMessage
+ id='admin.image.fileSettings'
+ defaultMessage='File Settings'
+ />
+ </h3>
<form
className='form-horizontal'
role='form'
@@ -154,7 +229,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='DriverName'
>
- {'Store Files In:'}
+ <FormattedMessage
+ id='admin.image.storeTitle'
+ defaultMessage='Store Files In:'
+ />
</label>
<div className='col-sm-8'>
<select
@@ -164,9 +242,9 @@ export default class FileSettings extends React.Component {
defaultValue={this.props.config.FileSettings.DriverName}
onChange={this.handleChange.bind(this, 'DriverName')}
>
- <option value=''>{'Disable File Storage'}</option>
- <option value='local'>{'Local File System'}</option>
- <option value='amazons3'>{'Amazon S3'}</option>
+ <option value=''>{formatMessage(holders.storeDisabled)}</option>
+ <option value='local'>{formatMessage(holders.storeLocal)}</option>
+ <option value='amazons3'>{formatMessage(holders.storeAmazonS3)}</option>
</select>
</div>
</div>
@@ -176,7 +254,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='Directory'
>
- {'Local Directory Location:'}
+ <FormattedMessage
+ id='admin.image.localTitle'
+ defaultMessage='Local Directory Location:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -184,12 +265,17 @@ export default class FileSettings extends React.Component {
className='form-control'
id='Directory'
ref='Directory'
- placeholder='Ex "./data/"'
+ placeholder={formatMessage(holders.localExample)}
defaultValue={this.props.config.FileSettings.Directory}
onChange={this.handleChange}
disabled={!enableFile}
/>
- <p className='help-text'>{'Directory to which image files are written. If blank, will be set to ./data/.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.image.localDescription'
+ defaultMessage='Directory to which image files are written. If blank, will be set to ./data/.'
+ />
+ </p>
</div>
</div>
@@ -198,7 +284,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='AmazonS3AccessKeyId'
>
- {'Amazon S3 Access Key Id:'}
+ <FormattedMessage
+ id='admin.image.amazonS3IdTitle'
+ defaultMessage='Amazon S3 Access Key Id:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -206,12 +295,17 @@ export default class FileSettings extends React.Component {
className='form-control'
id='AmazonS3AccessKeyId'
ref='AmazonS3AccessKeyId'
- placeholder='Ex "AKIADTOVBGERKLCBV"'
+ placeholder={formatMessage(holders.amazonS3IdExample)}
defaultValue={this.props.config.FileSettings.AmazonS3AccessKeyId}
onChange={this.handleChange}
disabled={!enableS3}
/>
- <p className='help-text'>{'Obtain this credential from your Amazon EC2 administrator.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.image.amazonS3IdDescription'
+ defaultMessage='Obtain this credential from your Amazon EC2 administrator.'
+ />
+ </p>
</div>
</div>
@@ -220,7 +314,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='AmazonS3SecretAccessKey'
>
- {'Amazon S3 Secret Access Key:'}
+ <FormattedMessage
+ id='admin.image.amazonS3SecretTitle'
+ defaultMessage='Amazon S3 Secret Access Key:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -228,12 +325,17 @@ export default class FileSettings extends React.Component {
className='form-control'
id='AmazonS3SecretAccessKey'
ref='AmazonS3SecretAccessKey'
- placeholder='Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'
+ placeholder={formatMessage(holders.amazonS3SecretExample)}
defaultValue={this.props.config.FileSettings.AmazonS3SecretAccessKey}
onChange={this.handleChange}
disabled={!enableS3}
/>
- <p className='help-text'>{'Obtain this credential from your Amazon EC2 administrator.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.image.amazonS3SecretDescription'
+ defaultMessage='Obtain this credential from your Amazon EC2 administrator.'
+ />
+ </p>
</div>
</div>
@@ -242,7 +344,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='AmazonS3Bucket'
>
- {'Amazon S3 Bucket:'}
+ <FormattedMessage
+ id='admin.image.amazonS3BucketTitle'
+ defaultMessage='Amazon S3 Bucket:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -250,12 +355,17 @@ export default class FileSettings extends React.Component {
className='form-control'
id='AmazonS3Bucket'
ref='AmazonS3Bucket'
- placeholder='Ex "mattermost-media"'
+ placeholder={formatMessage(holders.amazonS3BucketExample)}
defaultValue={this.props.config.FileSettings.AmazonS3Bucket}
onChange={this.handleChange}
disabled={!enableS3}
/>
- <p className='help-text'>{'Name you selected for your S3 bucket in AWS.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.image.amazonS3BucketDescription'
+ defaultMessage='Name you selected for your S3 bucket in AWS.'
+ />
+ </p>
</div>
</div>
@@ -264,7 +374,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='AmazonS3Region'
>
- {'Amazon S3 Region:'}
+ <FormattedMessage
+ id='admin.image.amazonS3RegionTitle'
+ defaultMessage='Amazon S3 Region:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -272,12 +385,17 @@ export default class FileSettings extends React.Component {
className='form-control'
id='AmazonS3Region'
ref='AmazonS3Region'
- placeholder='Ex "us-east-1"'
+ placeholder={formatMessage(holders.amazonS3RegionExample)}
defaultValue={this.props.config.FileSettings.AmazonS3Region}
onChange={this.handleChange}
disabled={!enableS3}
/>
- <p className='help-text'>{'AWS region you selected for creating your S3 bucket.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.image.amazonS3RegionDescription'
+ defaultMessage='AWS region you selected for creating your S3 bucket.'
+ />
+ </p>
</div>
</div>
@@ -286,7 +404,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='ThumbnailWidth'
>
- {'Thumbnail Width:'}
+ <FormattedMessage
+ id='admin.image.thumbWidthTitle'
+ defaultMessage='Thumbnail Width:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -294,11 +415,16 @@ export default class FileSettings extends React.Component {
className='form-control'
id='ThumbnailWidth'
ref='ThumbnailWidth'
- placeholder='Ex "120"'
+ placeholder={formatMessage(holders.thumbWidthExample)}
defaultValue={this.props.config.FileSettings.ThumbnailWidth}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Width of thumbnails generated from uploaded images. Updating this value changes how thumbnail images render in future, but does not change images created in the past.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.image.thumbWidthDescription'
+ defaultMessage='Width of thumbnails generated from uploaded images. Updating this value changes how thumbnail images render in future, but does not change images created in the past.'
+ />
+ </p>
</div>
</div>
@@ -307,7 +433,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='ThumbnailHeight'
>
- {'Thumbnail Height:'}
+ <FormattedMessage
+ id='admin.image.thumbHeightTitle'
+ defaultMessage='Thumbnail Height:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -315,11 +444,16 @@ export default class FileSettings extends React.Component {
className='form-control'
id='ThumbnailHeight'
ref='ThumbnailHeight'
- placeholder='Ex "100"'
+ placeholder={formatMessage(holders.thumbHeightExample)}
defaultValue={this.props.config.FileSettings.ThumbnailHeight}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Height of thumbnails generated from uploaded images. Updating this value changes how thumbnail images render in future, but does not change images created in the past.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.image.thumbHeightDescription'
+ defaultMessage='Height of thumbnails generated from uploaded images. Updating this value changes how thumbnail images render in future, but does not change images created in the past.'
+ />
+ </p>
</div>
</div>
@@ -328,7 +462,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='PreviewWidth'
>
- {'Preview Width:'}
+ <FormattedMessage
+ id='admin.image.previewWidthTitle'
+ defaultMessage='Preview Width:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -336,11 +473,16 @@ export default class FileSettings extends React.Component {
className='form-control'
id='PreviewWidth'
ref='PreviewWidth'
- placeholder='Ex "1024"'
+ placeholder={formatMessage(holders.previewWidthExample)}
defaultValue={this.props.config.FileSettings.PreviewWidth}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Maximum width of preview image. Updating this value changes how preview images render in future, but does not change images created in the past.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.image.previewWidthDescription'
+ defaultMessage='Maximum width of preview image. Updating this value changes how preview images render in future, but does not change images created in the past.'
+ />
+ </p>
</div>
</div>
@@ -349,7 +491,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='PreviewHeight'
>
- {'Preview Height:'}
+ <FormattedMessage
+ id='admin.image.previewHeightTitle'
+ defaultMessage='Preview Height:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -357,11 +502,16 @@ export default class FileSettings extends React.Component {
className='form-control'
id='PreviewHeight'
ref='PreviewHeight'
- placeholder='Ex "0"'
+ placeholder={formatMessage(holders.previewHeightExample)}
defaultValue={this.props.config.FileSettings.PreviewHeight}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Maximum height of preview image ("0": Sets to auto-size). Updating this value changes how preview images render in future, but does not change images created in the past.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.image.previewHeightDescription'
+ defaultMessage='Maximum height of preview image ("0": Sets to auto-size). Updating this value changes how preview images render in future, but does not change images created in the past.'
+ />
+ </p>
</div>
</div>
@@ -370,7 +520,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='ProfileWidth'
>
- {'Profile Width:'}
+ <FormattedMessage
+ id='admin.image.profileWidthTitle'
+ defaultMessage='Profile Width:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -378,11 +531,16 @@ export default class FileSettings extends React.Component {
className='form-control'
id='ProfileWidth'
ref='ProfileWidth'
- placeholder='Ex "1024"'
+ placeholder={formatMessage(holders.profileWidthExample)}
defaultValue={this.props.config.FileSettings.ProfileWidth}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Width of profile picture.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.image.profileWidthDescription'
+ defaultMessage='Width of profile picture.'
+ />
+ </p>
</div>
</div>
@@ -391,7 +549,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='ProfileHeight'
>
- {'Profile Height:'}
+ <FormattedMessage
+ id='admin.image.profileHeightTitle'
+ defaultMessage='Profile Height:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -399,11 +560,16 @@ export default class FileSettings extends React.Component {
className='form-control'
id='ProfileHeight'
ref='ProfileHeight'
- placeholder='Ex "0"'
+ placeholder={formatMessage(holders.profileHeightExample)}
defaultValue={this.props.config.FileSettings.ProfileHeight}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Height of profile picture.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.image.profileHeightDescription'
+ defaultMessage='Height of profile picture.'
+ />
+ </p>
</div>
</div>
@@ -412,7 +578,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnablePublicLink'
>
- {'Share Public File Link: '}
+ <FormattedMessage
+ id='admin.image.shareTitle'
+ defaultMessage='Share Public File Link: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -424,7 +593,10 @@ export default class FileSettings extends React.Component {
defaultChecked={this.props.config.FileSettings.EnablePublicLink}
onChange={this.handleChange}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.image.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -434,9 +606,17 @@ export default class FileSettings extends React.Component {
defaultChecked={!this.props.config.FileSettings.EnablePublicLink}
onChange={this.handleChange}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.image.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'Allow users to share public links to files and images.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.image.shareDescription'
+ defaultMessage='Allow users to share public links to files and images.'
+ />
+ </p>
</div>
</div>
@@ -445,7 +625,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='PublicLinkSalt'
>
- {'Public Link Salt:'}
+ <FormattedMessage
+ id='admin.image.publicLinkTitle'
+ defaultMessage='Public Link Salt:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -453,17 +636,25 @@ export default class FileSettings extends React.Component {
className='form-control'
id='PublicLinkSalt'
ref='PublicLinkSalt'
- placeholder='Ex "gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6"'
+ placeholder={formatMessage(holders.publicLinkExample)}
defaultValue={this.props.config.FileSettings.PublicLinkSalt}
onChange={this.handleChange}
/>
- <p className='help-text'>{'32-character salt added to signing of public image links. Randomly generated on install. Click "Re-Generate" to create new salt.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.image.publicLinkDescription'
+ defaultMessage='32-character salt added to signing of public image links. Randomly generated on install. Click "Re-Generate" to create new salt.'
+ />
+ </p>
<div className='help-text'>
<button
className='btn btn-default'
onClick={this.handleGenerate}
>
- {'Re-Generate'}
+ <FormattedMessage
+ id='admin.image.regenerate'
+ defaultMessage='Re-Generate'
+ />
</button>
</div>
</div>
@@ -478,9 +669,12 @@ export default class FileSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
- data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
+ data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
>
- {'Save'}
+ <FormattedMessage
+ id='admin.image.save'
+ defaultMessage='Save'
+ />
</button>
</div>
</div>
@@ -492,5 +686,8 @@ export default class FileSettings extends React.Component {
}
FileSettings.propTypes = {
+ intl: intlShape.isRequired,
config: React.PropTypes.object
};
+
+export default injectIntl(FileSettings); \ No newline at end of file
diff --git a/web/react/components/admin_console/ldap_settings.jsx b/web/react/components/admin_console/ldap_settings.jsx
index 1447f3bd7..bc13b3bcd 100644
--- a/web/react/components/admin_console/ldap_settings.jsx
+++ b/web/react/components/admin_console/ldap_settings.jsx
@@ -4,10 +4,55 @@
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
+import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
+
const DEFAULT_LDAP_PORT = 389;
const DEFAULT_QUERY_TIMEOUT = 60;
-export default class LdapSettings extends React.Component {
+var holders = defineMessages({
+ serverEx: {
+ id: 'admin.ldap.serverEx',
+ defaultMessage: 'Ex "10.0.0.23"'
+ },
+ portEx: {
+ id: 'admin.ldap.portEx',
+ defaultMessage: 'Ex "389"'
+ },
+ baseEx: {
+ id: 'admin.ldap.baseEx',
+ defaultMessage: 'Ex "dc=mydomain,dc=com"'
+ },
+ firstnameAttrEx: {
+ id: 'admin.ldap.firstnameAttrEx',
+ defaultMessage: 'Ex "givenName"'
+ },
+ lastnameAttrEx: {
+ id: 'admin.ldap.lastnameAttrEx',
+ defaultMessage: 'Ex "sn"'
+ },
+ emailAttrEx: {
+ id: 'admin.ldap.emailAttrEx',
+ defaultMessage: 'Ex "mail"'
+ },
+ usernameAttrEx: {
+ id: 'admin.ldap.usernameAttrEx',
+ defaultMessage: 'Ex "sAMAccountName"'
+ },
+ idAttrEx: {
+ id: 'admin.ldap.idAttrEx',
+ defaultMessage: 'Ex "sAMAccountName"'
+ },
+ queryEx: {
+ id: 'admin.ldap.queryEx',
+ defaultMessage: 'Ex "60"'
+ },
+ saving: {
+ id: 'admin.ldap.saving',
+ defaultMessage: 'Saving Config...'
+ }
+});
+
+class LdapSettings extends React.Component {
constructor(props) {
super(props);
@@ -80,6 +125,7 @@ export default class LdapSettings extends React.Component {
);
}
render() {
+ const {formatMessage} = this.props.intl;
let serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
@@ -97,8 +143,18 @@ export default class LdapSettings extends React.Component {
bannerContent = (
<div className='banner'>
<div className='banner__content'>
- <h4 className='banner__heading'>{'Note:'}</h4>
- <p>{'If a user attribute changes on the LDAP server it will be updated the next time the user enters their credentials to log in to Mattermost. This includes if a user is made inactive or removed from an LDAP server. Synchronization with LDAP servers is planned in a future release.'}</p>
+ <h4 className='banner__heading'>
+ <FormattedMessage
+ id='admin.ldap.bannerHeading'
+ defaultMessage='Note:'
+ />
+ </h4>
+ <p>
+ <FormattedMessage
+ id='admin.ldap.bannerDesc'
+ defaultMessage='If a user attribute changes on the LDAP server it will be updated the next time the user enters their credentials to log in to Mattermost. This includes if a user is made inactive or removed from an LDAP server. Synchronization with LDAP servers is planned in a future release.'
+ />
+ </p>
</div>
</div>
);
@@ -106,17 +162,10 @@ export default class LdapSettings extends React.Component {
bannerContent = (
<div className='banner warning'>
<div className='banner__content'>
- <h4 className='banner__heading'>{'Note:'}</h4>
- <p>
- {'LDAP is an enterprise feature. Your current license does not support LDAP. Click '}
- <a
- href='http://mattermost.com'
- target='_blank'
- >
- {'here'}
- </a>
- {' for information and pricing on enterprise licenses.'}
- </p>
+ <FormattedHTMLMessage
+ id='admin.ldap.noLicense'
+ defaultMessage='<h4 className="banner__heading">Note:</h4><p>LDAP is an enterprise feature. Your current license does not support LDAP. Click <a href="http://mattermost.com"target="_blank">here</a> for information and pricing on enterprise licenses.</p>'
+ />
</div>
</div>
);
@@ -125,7 +174,12 @@ export default class LdapSettings extends React.Component {
return (
<div className='wrapper--fixed'>
{bannerContent}
- <h3>{'LDAP Settings'}</h3>
+ <h3>
+ <FormattedMessage
+ id='admin.ldap.title'
+ defaultMessage='LDAP Settings'
+ />
+ </h3>
<form
className='form-horizontal'
role='form'
@@ -135,7 +189,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='Enable'
>
- {'Enable Login With LDAP:'}
+ <FormattedMessage
+ id='admin.ldap.enableTitle'
+ defaultMessage='Enable Login With LDAP:'
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -148,7 +205,10 @@ export default class LdapSettings extends React.Component {
onChange={this.handleEnable}
disabled={!licenseEnabled}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.ldap.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -158,9 +218,17 @@ export default class LdapSettings extends React.Component {
defaultChecked={!this.props.config.LdapSettings.Enable}
onChange={this.handleDisable}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.ldap.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'When true, Mattermost allows login using LDAP'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.ldap.enableDesc'
+ defaultMessage='When true, Mattermost allows login using LDAP'
+ />
+ </p>
</div>
</div>
<div className='form-group'>
@@ -168,7 +236,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='LdapServer'
>
- {'LDAP Server:'}
+ <FormattedMessage
+ id='admin.ldap.serverTitle'
+ defaultMessage='LDAP Server:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -176,12 +247,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='LdapServer'
ref='LdapServer'
- placeholder='Ex "10.0.0.23"'
+ placeholder={formatMessage(holders.serverEx)}
defaultValue={this.props.config.LdapSettings.LdapServer}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
- <p className='help-text'>{'The domain or IP address of LDAP server.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.ldap.serverDesc'
+ defaultMessage='The domain or IP address of LDAP server.'
+ />
+ </p>
</div>
</div>
<div className='form-group'>
@@ -189,7 +265,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='LdapPort'
>
- {'LDAP Port:'}
+ <FormattedMessage
+ id='admin.ldap.portTitle'
+ defaultMessage='LDAP Port:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -197,12 +276,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='LdapPort'
ref='LdapPort'
- placeholder='Ex "389"'
+ placeholder={formatMessage(holders.portEx)}
defaultValue={this.props.config.LdapSettings.LdapPort}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
- <p className='help-text'>{'The port Mattermost will use to connect to the LDAP server. Default is 389.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.ldap.portDesc'
+ defaultMessage='The port Mattermost will use to connect to the LDAP server. Default is 389.'
+ />
+ </p>
</div>
</div>
<div className='form-group'>
@@ -210,7 +294,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='BaseDN'
>
- {'BaseDN:'}
+ <FormattedMessage
+ id='admin.ldap.baseTitle'
+ defaultMessage='BaseDN:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -218,12 +305,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='BaseDN'
ref='BaseDN'
- placeholder='Ex "dc=mydomain,dc=com"'
+ placeholder={formatMessage(holders.baseEx)}
defaultValue={this.props.config.LdapSettings.BaseDN}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
- <p className='help-text'>{'The Base DN is the Distinguished Name of the location where Mattermost should start its search for users in the LDAP tree.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.ldap.baseDesc'
+ defaultMessage='The Base DN is the Distinguished Name of the location where Mattermost should start its search for users in the LDAP tree.'
+ />
+ </p>
</div>
</div>
<div className='form-group'>
@@ -231,7 +323,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='BindUsername'
>
- {'Bind Username:'}
+ <FormattedMessage
+ id='admin.ldap.bindUserTitle'
+ defaultMessage='Bind Username:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -244,7 +339,12 @@ export default class LdapSettings extends React.Component {
onChange={this.handleChange}
disabled={!this.state.enable}
/>
- <p className='help-text'>{'The username used to perform the LDAP search. This should typically be an account created specifically for use with Mattermost. It should have access limited to read the portion of the LDAP tree specified in the BaseDN field.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.ldap.bindUserDesc'
+ defaultMessage='The username used to perform the LDAP search. This should typically be an account created specifically for use with Mattermost. It should have access limited to read the portion of the LDAP tree specified in the BaseDN field.'
+ />
+ </p>
</div>
</div>
<div className='form-group'>
@@ -252,7 +352,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='BindPassword'
>
- {'Bind Password:'}
+ <FormattedMessage
+ id='admin.ldap.bindPwdTitle'
+ defaultMessage='Bind Password:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -265,7 +368,12 @@ export default class LdapSettings extends React.Component {
onChange={this.handleChange}
disabled={!this.state.enable}
/>
- <p className='help-text'>{'Password of the user given in "Bind Username".'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.ldap.bindPwdDesc'
+ defaultMessage='Password of the user given in "Bind Username".'
+ />
+ </p>
</div>
</div>
<div className='form-group'>
@@ -273,7 +381,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='FirstNameAttribute'
>
- {'First Name Attrubute'}
+ <FormattedMessage
+ id='admin.ldap.firstnameAttrTitle'
+ defaultMessage='First Name Attrubute'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -281,12 +392,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='FirstNameAttribute'
ref='FirstNameAttribute'
- placeholder='Ex "givenName"'
+ placeholder={formatMessage(holders.firstnameAttrEx)}
defaultValue={this.props.config.LdapSettings.FirstNameAttribute}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
- <p className='help-text'>{'The attribute in the LDAP server that will be used to populate the first name of users in Mattermost.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.ldap.firstnameAttrDesc'
+ defaultMessage='The attribute in the LDAP server that will be used to populate the first name of users in Mattermost.'
+ />
+ </p>
</div>
</div>
<div className='form-group'>
@@ -294,7 +410,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='LastNameAttribute'
>
- {'Last Name Attribute:'}
+ <FormattedMessage
+ id='admin.ldap.lastnameAttrTitle'
+ defaultMessage='Last Name Attribute:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -302,12 +421,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='LastNameAttribute'
ref='LastNameAttribute'
- placeholder='Ex "sn"'
+ placeholder={formatMessage(holders.lastnameAttrEx)}
defaultValue={this.props.config.LdapSettings.LastNameAttribute}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
- <p className='help-text'>{'The attribute in the LDAP server that will be used to populate the last name of users in Mattermost.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.ldap.lastnameAttrDesc'
+ defaultMessage='The attribute in the LDAP server that will be used to populate the last name of users in Mattermost.'
+ />
+ </p>
</div>
</div>
<div className='form-group'>
@@ -315,7 +439,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EmailAttribute'
>
- {'Email Attribute:'}
+ <FormattedMessage
+ id='admin.ldap.emailAttrTitle'
+ defaultMessage='Email Attribute:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -323,12 +450,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='EmailAttribute'
ref='EmailAttribute'
- placeholder='Ex "mail"'
+ placeholder={formatMessage(holders.emailAttrEx)}
defaultValue={this.props.config.LdapSettings.EmailAttribute}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
- <p className='help-text'>{'The attribute in the LDAP server that will be used to populate the email addresses of users in Mattermost.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.ldap.emailAttrDesc'
+ defaultMessage='The attribute in the LDAP server that will be used to populate the email addresses of users in Mattermost.'
+ />
+ </p>
</div>
</div>
<div className='form-group'>
@@ -336,7 +468,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='UsernameAttribute'
>
- {'Username Attribute:'}
+ <FormattedMessage
+ id='admin.ldap.usernameAttrTitle'
+ defaultMessage='Username Attribute:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -344,12 +479,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='UsernameAttribute'
ref='UsernameAttribute'
- placeholder='Ex "sAMAccountName"'
+ placeholder={formatMessage(holders.usernameAttrEx)}
defaultValue={this.props.config.LdapSettings.UsernameAttribute}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
- <p className='help-text'>{'The attribute in the LDAP server that will be used to populate the username field in Mattermost. This may be the same as the ID Attribute.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.ldap.uernameAttrDesc'
+ defaultMessage='The attribute in the LDAP server that will be used to populate the username field in Mattermost. This may be the same as the ID Attribute.'
+ />
+ </p>
</div>
</div>
<div className='form-group'>
@@ -357,7 +497,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='IdAttribute'
>
- {'Id Attribute: '}
+ <FormattedMessage
+ id='admin.ldap.idAttrTitle'
+ defaultMessage='Id Attribute: '
+ />
</label>
<div className='col-sm-8'>
<input
@@ -365,12 +508,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='IdAttribute'
ref='IdAttribute'
- placeholder='Ex "sAMAccountName"'
+ placeholder={formatMessage(holders.idAttrEx)}
defaultValue={this.props.config.LdapSettings.IdAttribute}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
- <p className='help-text'>{'The attribute in the LDAP server that will be used as a unique identifier in Mattermost. It should be an LDAP attribute with a value that does not change, such as username or uid. If a user’s Id Attribute changes, it will create a new Mattermost account unassociated with their old one. This is the value used to log in to Mattermost in the "LDAP Username" field on the sign in page. Normally this attribute is the same as the “Username Attribute” field above. If your team typically uses domain\\username to sign in to other services with LDAP, you may choose to put domain\\username in this field to maintain consistency between sites.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.ldap.idAttrDesc'
+ defaultMessage='The attribute in the LDAP server that will be used as a unique identifier in Mattermost. It should be an LDAP attribute with a value that does not change, such as username or uid. If a user’s Id Attribute changes, it will create a new Mattermost account unassociated with their old one. This is the value used to log in to Mattermost in the "LDAP Username" field on the sign in page. Normally this attribute is the same as the “Username Attribute” field above. If your team typically uses domain\\username to sign in to other services with LDAP, you may choose to put domain\\username in this field to maintain consistency between sites.'
+ />
+ </p>
</div>
</div>
<div className='form-group'>
@@ -378,7 +526,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='QueryTimeout'
>
- {'Query Timeout (seconds):'}
+ <FormattedMessage
+ id='admin.ldap.queryTitle'
+ defaultMessage='Query Timeout (seconds):'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -386,12 +537,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='QueryTimeout'
ref='QueryTimeout'
- placeholder='Ex "60"'
+ placeholder={formatMessage(holders.queryEx)}
defaultValue={this.props.config.LdapSettings.QueryTimeout}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
- <p className='help-text'>{'The timeout value for queries to the LDAP server. Increase if you are getting timeout errors caused by a slow LDAP server.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.ldap.queryDesc'
+ defaultMessage='The timeout value for queries to the LDAP server. Increase if you are getting timeout errors caused by a slow LDAP server.'
+ />
+ </p>
</div>
</div>
<div className='form-group'>
@@ -403,9 +559,12 @@ export default class LdapSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
- data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
+ data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
>
- {'Save'}
+ <FormattedMessage
+ id='admin.ldap.save'
+ defaultMessage='Save'
+ />
</button>
</div>
</div>
@@ -418,5 +577,8 @@ LdapSettings.defaultProps = {
};
LdapSettings.propTypes = {
+ intl: intlShape.isRequired,
config: React.PropTypes.object
};
+
+export default injectIntl(LdapSettings); \ No newline at end of file
diff --git a/web/react/components/admin_console/legal_and_support_settings.jsx b/web/react/components/admin_console/legal_and_support_settings.jsx
index b00e4b6bd..a6c6a0626 100644
--- a/web/react/components/admin_console/legal_and_support_settings.jsx
+++ b/web/react/components/admin_console/legal_and_support_settings.jsx
@@ -4,7 +4,16 @@
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
-export default class LegalAndSupportSettings extends React.Component {
+import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
+
+var holders = defineMessages({
+ saving: {
+ id: 'admin.support.saving',
+ defaultMessage: 'Saving Config...'
+ }
+});
+
+class LegalAndSupportSettings extends React.Component {
constructor(props) {
super(props);
@@ -69,7 +78,12 @@ export default class LegalAndSupportSettings extends React.Component {
return (
<div className='wrapper--fixed'>
- <h3>{'Legal and Support Settings'}</h3>
+ <h3>
+ <FormattedMessage
+ id='admin.support.title'
+ defaultMessage='Legal and Support Settings'
+ />
+ </h3>
<form
className='form-horizontal'
role='form'
@@ -80,7 +94,10 @@ export default class LegalAndSupportSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='TermsOfServiceLink'
>
- {'Terms of Service link:'}
+ <FormattedMessage
+ id='admin.support.termsTitle'
+ defaultMessage='Terms of Service link:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -91,7 +108,12 @@ export default class LegalAndSupportSettings extends React.Component {
defaultValue={this.props.config.SupportSettings.TermsOfServiceLink}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Link to Terms of Service available to users on desktop and on mobile. Leaving this blank will hide the option to display a notice.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.support.termsDesc'
+ defaultMessage='Link to Terms of Service available to users on desktop and on mobile. Leaving this blank will hide the option to display a notice.'
+ />
+ </p>
</div>
</div>
@@ -100,7 +122,10 @@ export default class LegalAndSupportSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='PrivacyPolicyLink'
>
- {'Privacy Policy link:'}
+ <FormattedMessage
+ id='admin.support.privacyTitle'
+ defaultMessage='Privacy Policy link:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -111,7 +136,12 @@ export default class LegalAndSupportSettings extends React.Component {
defaultValue={this.props.config.SupportSettings.PrivacyPolicyLink}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Link to Privacy Policy available to users on desktop and on mobile. Leaving this blank will hide the option to display a notice.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.support.privacyDesc'
+ defaultMessage='Link to Privacy Policy available to users on desktop and on mobile. Leaving this blank will hide the option to display a notice.'
+ />
+ </p>
</div>
</div>
@@ -120,7 +150,10 @@ export default class LegalAndSupportSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='AboutLink'
>
- {'About link:'}
+ <FormattedMessage
+ id='admin.support.aboutTitle'
+ defaultMessage='About link:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -131,7 +164,12 @@ export default class LegalAndSupportSettings extends React.Component {
defaultValue={this.props.config.SupportSettings.AboutLink}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Link to About page for more information on your Mattermost deployment, for example its purpose and audience within your organization. Defaults to Mattermost information page.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.support.aboutDesc'
+ defaultMessage='Link to About page for more information on your Mattermost deployment, for example its purpose and audience within your organization. Defaults to Mattermost information page.'
+ />
+ </p>
</div>
</div>
@@ -140,7 +178,10 @@ export default class LegalAndSupportSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='HelpLink'
>
- {'Help link:'}
+ <FormattedMessage
+ id='admin.support.helpTitle'
+ defaultMessage='Help link:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -151,7 +192,12 @@ export default class LegalAndSupportSettings extends React.Component {
defaultValue={this.props.config.SupportSettings.HelpLink}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Link to help documentation from team site main menu. Typically not changed unless your organization chooses to create custom documentation.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.support.helpDesc'
+ defaultMessage='Link to help documentation from team site main menu. Typically not changed unless your organization chooses to create custom documentation.'
+ />
+ </p>
</div>
</div>
@@ -160,7 +206,10 @@ export default class LegalAndSupportSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='ReportAProblemLink'
>
- {'Report a Problem link:'}
+ <FormattedMessage
+ id='admin.support.problemTitle'
+ defaultMessage='Report a Problem link:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -171,7 +220,12 @@ export default class LegalAndSupportSettings extends React.Component {
defaultValue={this.props.config.SupportSettings.ReportAProblemLink}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Link to help documentation from team site main menu. By default this points to the peer-to-peer troubleshooting forum where users can search for, find and request help with technical issues.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.support.problemDesc'
+ defaultMessage='Link to help documentation from team site main menu. By default this points to the peer-to-peer troubleshooting forum where users can search for, find and request help with technical issues.'
+ />
+ </p>
</div>
</div>
@@ -180,7 +234,10 @@ export default class LegalAndSupportSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='SupportEmail'
>
- {'Support email:'}
+ <FormattedMessage
+ id='admin.support.emailTitle'
+ defaultMessage='Support email:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -191,7 +248,12 @@ export default class LegalAndSupportSettings extends React.Component {
defaultValue={this.props.config.SupportSettings.SupportEmail}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Email shown during tutorial for end users to ask support questions.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.support.emailHelp'
+ defaultMessage='Email shown during tutorial for end users to ask support questions.'
+ />
+ </p>
</div>
</div>
@@ -204,9 +266,12 @@ export default class LegalAndSupportSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
- data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
+ data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + this.props.intl.formatMessage(holders.saving)}
>
- {'Save'}
+ <FormattedMessage
+ id='admin.support.save'
+ defaultMessage='Save'
+ />
</button>
</div>
</div>
@@ -218,5 +283,8 @@ export default class LegalAndSupportSettings extends React.Component {
}
LegalAndSupportSettings.propTypes = {
+ intl: intlShape.isRequired,
config: React.PropTypes.object
};
+
+export default injectIntl(LegalAndSupportSettings); \ No newline at end of file
diff --git a/web/react/components/admin_console/license_settings.jsx b/web/react/components/admin_console/license_settings.jsx
index ba953f3bd..539acd869 100644
--- a/web/react/components/admin_console/license_settings.jsx
+++ b/web/react/components/admin_console/license_settings.jsx
@@ -4,7 +4,20 @@
import * as Utils from '../../utils/utils.jsx';
import * as Client from '../../utils/client.jsx';
-export default class LicenseSettings extends React.Component {
+import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
+
+const holders = defineMessages({
+ removing: {
+ id: 'admin.license.removing',
+ defaultMessage: 'Removing License...'
+ },
+ uploading: {
+ id: 'admin.license.uploading',
+ defaultMessage: 'Uploading License...'
+ }
+});
+
+class LicenseSettings extends React.Component {
constructor(props) {
super(props);
@@ -88,41 +101,26 @@ export default class LicenseSettings extends React.Component {
let licenseKey;
if (global.window.mm_license.IsLicensed === 'true') {
- edition = 'Mattermost Enterprise Edition. Designed for enterprise-scale communication.';
+ edition = (
+ <FormattedMessage
+ id='admin.license.enterpriseEdition'
+ defaultMessage='Mattermost Enterprise Edition. Designed for enterprise-scale communication.'
+ />
+ );
licenseType = (
- <div>
- <p>
- {'This compiled release of Mattermost platform is provided under a '}
- <a
- href='http://mattermost.com'
- target='_blank'
- >
- {'commercial license'}
- </a>
- {' from Mattermost, Inc. based on your subscription level and is subject to the '}
- <a
- href={global.window.mm_config.TermsOfServiceLink}
- target='_blank'
- >
- {'Terms of Service.'}
- </a>
- </p>
- <p>{'Your subscription details are as follows:'}</p>
- {'Name: ' + global.window.mm_license.Name}
- <br/>
- {'Company or organization name: ' + global.window.mm_license.Company}
- <br/>
- {'Number of users: ' + global.window.mm_license.Users}
- <br/>
- {`License issued: ${Utils.displayDate(parseInt(global.window.mm_license.IssuedAt, 10))} ${Utils.displayTime(parseInt(global.window.mm_license.IssuedAt, 10), true)}`}
- <br/>
- {'Start date of license: ' + Utils.displayDate(parseInt(global.window.mm_license.StartsAt, 10))}
- <br/>
- {'Expiry date of license: ' + Utils.displayDate(parseInt(global.window.mm_license.ExpiresAt, 10))}
- <br/>
- {'LDAP: ' + global.window.mm_license.LDAP}
- <br/>
- </div>
+ <FormattedHTMLMessage
+ id='admin.license.entrepriseType'
+ defaultMessage='<div><p>This compiled release of Mattermost platform is provided under a <a href="http://mattermost.com" target="_blank">commercial license</a>
+ from Mattermost, Inc. based on your subscription level and is subject to the <a href="{terms}" target="_blank">Terms of Service.</a></p>
+ <p>Your subscription details are as follows:</p>
+ Name: {name}<br />
+ Company or organization name: {company}<br/>
+ Number of users: {users}<br/>
+ License issued: {issued}<br/>
+ Start date of license: {start}<br/>
+ Expiry date of license: {expires}<br/>
+ LDAP: {ldap}<br/></div>'
+ />
);
licenseKey = (
@@ -131,32 +129,39 @@ export default class LicenseSettings extends React.Component {
className='btn btn-danger'
onClick={this.handleRemove}
id='remove-button'
- data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Removing License...'}
+ data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + this.props.intl.formatMessage(holders.removing)}
>
- {'Remove Enterprise License and Downgrade Server'}
+ <FormattedMessage
+ id='admin.license.keyRemove'
+ defaultMessage='Remove Enterprise License and Downgrade Server'
+ />
</button>
<br/>
<br/>
<p className='help-text'>
- {'If you’re migrating servers you may need to remove your license key from this server in order to install it on a new server. To start, '}
- <a
- href='http://mattermost.com'
- target='_blank'
- >
- {'disable all Enterprise Edition features on this server'}
- </a>
- {'. This will enable the ability to remove the license key and downgrade this server from Enterprise Edition to Team Edition.'}
+ <FormattedHTMLMessage
+ id='admin.licence.keyMigration'
+ defaultMessage='If you’re migrating servers you may need to remove your license key from this server in order to install it on a new server. To start,
+ <a href="http://mattermost.com" target="_blank">disable all Enterprise Edition features on this server</a>.
+ This will enable the ability to remove the license key and downgrade this server from Enterprise Edition to Team Edition.'
+ />
</p>
</div>
);
} else {
- edition = 'Mattermost Team Edition. Designed for teams from 5 to 50 users.';
+ edition = (
+ <FormattedMessage
+ id='admin.license.teamEdition'
+ defaultMessage='Mattermost Team Edition. Designed for teams from 5 to 50 users.'
+ />
+ );
licenseType = (
- <span>
- <p>{'This compiled release of Mattermost platform is offered under an MIT license.'}</p>
- <p>{'See MIT-COMPILED-LICENSE.txt in your root install directory for details. See NOTICES.txt for information about open source software used in this system.'}</p>
- </span>
+ <FormattedHTMLMessage
+ id='admin.license.teamType'
+ defaultMessage='<span><p>This compiled release of Mattermost platform is offered under an MIT license.</p>
+ <p>See MIT-COMPILED-LICENSE.txt in your root install directory for details. See NOTICES.txt for information about open source software used in this system.</p></span>'
+ />
);
licenseKey = (
@@ -173,23 +178,23 @@ export default class LicenseSettings extends React.Component {
disabled={!this.state.fileSelected}
onClick={this.handleSubmit}
id='upload-button'
- data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Uploading License...'}
+ data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + this.props.intl.formatMessage(holders.uploading)}
>
- {'Upload'}
+ <FormattedMessage
+ id='admin.license.upload'
+ defaultMessage='Upload'
+ />
</button>
<br/>
<br/>
<br/>
{serverError}
<p className='help-text'>
- {'Upload a license key for Mattermost Enterprise Edition to upgrade this server. '}
- <a
- href='http://mattermost.com'
- target='_blank'
- >
- {'Visit us online'}
- </a>
- {' to learn more about the benefits of Enterprise Edition or to purchase a key.'}
+ <FormattedHTMLMessage
+ id='admin.license.uploadDesc'
+ defaultMessage='Upload a license key for Mattermost Enterprise Edition to upgrade this server. <a href="http://mattermost.com" target="_blank">Visit us online</a>
+ to learn more about the benefits of Enterprise Edition or to purchase a key.'
+ />
</p>
</div>
);
@@ -197,7 +202,12 @@ export default class LicenseSettings extends React.Component {
return (
<div className='wrapper--fixed'>
- <h3>{'Edition and License'}</h3>
+ <h3>
+ <FormattedMessage
+ id='admin.license.title'
+ defaultMessage='Edition and License'
+ />
+ </h3>
<form
className='form-horizontal'
role='form'
@@ -206,7 +216,10 @@ export default class LicenseSettings extends React.Component {
<label
className='control-label col-sm-4'
>
- {'Edition: '}
+ <FormattedMessage
+ id='admin.license.edition'
+ defaultMessage='Edition: '
+ />
</label>
<div className='col-sm-8'>
{edition}
@@ -216,7 +229,10 @@ export default class LicenseSettings extends React.Component {
<label
className='control-label col-sm-4'
>
- {'License: '}
+ <FormattedMessage
+ id='admin.license.type'
+ defaultMessage='License: '
+ />
</label>
<div className='col-sm-8'>
{licenseType}
@@ -226,7 +242,10 @@ export default class LicenseSettings extends React.Component {
<label
className='control-label col-sm-4'
>
- {'License Key: '}
+ <FormattedMessage
+ id='admin.license.key'
+ defaultMessage='License Key: '
+ />
</label>
{licenseKey}
</div>
@@ -235,3 +254,9 @@ export default class LicenseSettings extends React.Component {
);
}
}
+
+LicenseSettings.propTypes = {
+ intl: intlShape.isRequired
+};
+
+export default injectIntl(LicenseSettings); \ No newline at end of file
diff --git a/web/react/components/admin_console/log_settings.jsx b/web/react/components/admin_console/log_settings.jsx
index a91cc57ab..cefe6afba 100644
--- a/web/react/components/admin_console/log_settings.jsx
+++ b/web/react/components/admin_console/log_settings.jsx
@@ -4,7 +4,24 @@
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
-export default class LogSettings extends React.Component {
+import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
+
+const holders = defineMessages({
+ locationPlaceholder: {
+ id: 'admin.log.locationPlaceholder',
+ defaultMessage: 'Enter your file location'
+ },
+ formatPlaceholder: {
+ id: 'admin.log.formatPlaceholder',
+ defaultMessage: 'Enter your file format'
+ },
+ saving: {
+ id: 'admin.log.saving',
+ defaultMessage: 'Saving Config...'
+ }
+});
+
+class LogSettings extends React.Component {
constructor(props) {
super(props);
@@ -78,6 +95,7 @@ export default class LogSettings extends React.Component {
}
render() {
+ const {formatMessage} = this.props.intl;
var serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
@@ -90,7 +108,12 @@ export default class LogSettings extends React.Component {
return (
<div className='wrapper--fixed'>
- <h3>{'Log Settings'}</h3>
+ <h3>
+ <FormattedMessage
+ id='admin.log.logSettings'
+ defaultMessage='Log Settings'
+ />
+ </h3>
<form
className='form-horizontal'
role='form'
@@ -101,7 +124,10 @@ export default class LogSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='consoleEnable'
>
- {'Log To The Console: '}
+ <FormattedMessage
+ id='admin.log.consoleTitle'
+ defaultMessage='Log To The Console: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -113,7 +139,10 @@ export default class LogSettings extends React.Component {
defaultChecked={this.props.config.LogSettings.EnableConsole}
onChange={this.handleChange.bind(this, 'console_true')}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.log.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -123,9 +152,17 @@ export default class LogSettings extends React.Component {
defaultChecked={!this.props.config.LogSettings.EnableConsole}
onChange={this.handleChange.bind(this, 'console_false')}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.log.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'Typically set to false in production. Developers may set this field to true to output log messages to console based on the console level option. If true, server writes messages to the standard output stream (stdout).'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.log.consoleDescription'
+ defaultMessage='Typically set to false in production. Developers may set this field to true to output log messages to console based on the console level option. If true, server writes messages to the standard output stream (stdout).'
+ />
+ </p>
</div>
</div>
@@ -134,7 +171,10 @@ export default class LogSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='consoleLevel'
>
- {'Console Log Level:'}
+ <FormattedMessage
+ id='admin.log.levelTitle'
+ defaultMessage='Console Log Level:'
+ />
</label>
<div className='col-sm-8'>
<select
@@ -149,7 +189,12 @@ export default class LogSettings extends React.Component {
<option value='INFO'>{'INFO'}</option>
<option value='ERROR'>{'ERROR'}</option>
</select>
- <p className='help-text'>{'This setting determines the level of detail at which log events are written to the console. ERROR: Outputs only error messages. INFO: Outputs error messages and information around startup and initialization. DEBUG: Prints high detail for developers working on debugging issues.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.log.levelDescription'
+ defaultMessage='This setting determines the level of detail at which log events are written to the console. ERROR: Outputs only error messages. INFO: Outputs error messages and information around startup and initialization. DEBUG: Prints high detail for developers working on debugging issues.'
+ />
+ </p>
</div>
</div>
@@ -157,7 +202,10 @@ export default class LogSettings extends React.Component {
<label
className='control-label col-sm-4'
>
- {'Log To File: '}
+ <FormattedMessage
+ id='admin.log.fileTitle'
+ defaultMessage='Log To File: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -169,7 +217,10 @@ export default class LogSettings extends React.Component {
defaultChecked={this.props.config.LogSettings.EnableFile}
onChange={this.handleChange.bind(this, 'file_true')}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.log.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -179,9 +230,17 @@ export default class LogSettings extends React.Component {
defaultChecked={!this.props.config.LogSettings.EnableFile}
onChange={this.handleChange.bind(this, 'file_false')}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.log.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'Typically set to true in production. When true, log files are written to the log file specified in file location field below.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.log.fileDescription'
+ defaultMessage='Typically set to true in production. When true, log files are written to the log file specified in file location field below.'
+ />
+ </p>
</div>
</div>
@@ -190,7 +249,10 @@ export default class LogSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='fileLevel'
>
- {'File Log Level:'}
+ <FormattedMessage
+ id='admin.log.fileLevelTitle'
+ defaultMessage='File Log Level:'
+ />
</label>
<div className='col-sm-8'>
<select
@@ -205,7 +267,12 @@ export default class LogSettings extends React.Component {
<option value='INFO'>{'INFO'}</option>
<option value='ERROR'>{'ERROR'}</option>
</select>
- <p className='help-text'>{'This setting determines the level of detail at which log events are written to the log file. ERROR: Outputs only error messages. INFO: Outputs error messages and information around startup and initialization. DEBUG: Prints high detail for developers working on debugging issues.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.log.fileLevelDescription'
+ defaultMessage='This setting determines the level of detail at which log events are written to the log file. ERROR: Outputs only error messages. INFO: Outputs error messages and information around startup and initialization. DEBUG: Prints high detail for developers working on debugging issues.'
+ />
+ </p>
</div>
</div>
@@ -214,7 +281,10 @@ export default class LogSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='fileLocation'
>
- {'File Location:'}
+ <FormattedMessage
+ id='admin.log.locationTitle'
+ defaultMessage='File Location:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -222,12 +292,17 @@ export default class LogSettings extends React.Component {
className='form-control'
id='fileLocation'
ref='fileLocation'
- placeholder='Enter your file location'
+ placeholder={formatMessage(holders.locationPlaceholder)}
defaultValue={this.props.config.LogSettings.FileLocation}
onChange={this.handleChange}
disabled={!this.state.fileEnable}
/>
- <p className='help-text'>{'File to which log files are written. If blank, will be set to ./logs/mattermost, which writes logs to mattermost.log. Log rotation is enabled and every 10,000 lines of log information is written to new files stored in the same directory, for example mattermost.2015-09-23.001, mattermost.2015-09-23.002, and so forth.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.log.locationDescription'
+ defaultMessage='File to which log files are written. If blank, will be set to ./logs/mattermost, which writes logs to mattermost.log. Log rotation is enabled and every 10,000 lines of log information is written to new files stored in the same directory, for example mattermost.2015-09-23.001, mattermost.2015-09-23.002, and so forth.'
+ />
+ </p>
</div>
</div>
@@ -236,7 +311,10 @@ export default class LogSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='fileFormat'
>
- {'File Format:'}
+ <FormattedMessage
+ id='admin.log.formatTitle'
+ defaultMessage='File Format:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -244,25 +322,58 @@ export default class LogSettings extends React.Component {
className='form-control'
id='fileFormat'
ref='fileFormat'
- placeholder='Enter your file format'
+ placeholder={formatMessage(holders.formatPlaceholder)}
defaultValue={this.props.config.LogSettings.FileFormat}
onChange={this.handleChange}
disabled={!this.state.fileEnable}
/>
<div className='help-text'>
- {'Format of log message output. If blank will be set to "[%D %T] [%L] %M", where:'}
+ <FormattedMessage
+ id='admin.log.formatDescription'
+ defaultMessage='Format of log message output. If blank will be set to "[%D %T] [%L] %M", where:'
+ />
<div className='help-text'>
<table
className='table table-bordered'
cellPadding='5'
>
<tbody>
- <tr><td className='help-text'>{'%T'}</td><td className='help-text'>{'Time (15:04:05 MST)'}</td></tr>
- <tr><td className='help-text'>{'%D'}</td><td className='help-text'>{'Date (2006/01/02)'}</td></tr>
- <tr><td className='help-text'>{'%d'}</td><td className='help-text'>{'Date (01/02/06)'}</td></tr>
- <tr><td className='help-text'>{'%L'}</td><td className='help-text'>{'Level (DEBG, INFO, EROR)'}</td></tr>
- <tr><td className='help-text'>{'%S'}</td><td className='help-text'>{'Source'}</td></tr>
- <tr><td className='help-text'>{'%M'}</td><td className='help-text'>{'Message'}</td></tr>
+ <tr><td className='help-text'>{'%T'}</td><td className='help-text'>
+ <FormattedMessage
+ id='admin.log.formatTime'
+ defaultMessage='Time (15:04:05 MST)'
+ />
+ </td></tr>
+ <tr><td className='help-text'>{'%D'}</td><td className='help-text'>
+ <FormattedMessage
+ id='admin.log.formatDateLong'
+ defaultMessage='Date (2006/01/02)'
+ />
+ </td></tr>
+ <tr><td className='help-text'>{'%d'}</td><td className='help-text'>
+ <FormattedMessage
+ id='admin.log.formatDateShort'
+ defaultMessage='Date (01/02/06)'
+ />
+ </td></tr>
+ <tr><td className='help-text'>{'%L'}</td><td className='help-text'>
+ <FormattedMessage
+ id='admin.log.formatLevel'
+ defaultMessage='Level (DEBG, INFO, EROR)'
+ />
+ </td></tr>
+ <tr><td className='help-text'>{'%S'}</td><td className='help-text'>
+ <FormattedMessage
+ id='admin.log.formatSource'
+ defaultMessage='Source'
+ />
+ </td></tr>
+ <tr><td className='help-text'>{'%M'}</td><td className='help-text'>
+ <FormattedMessage
+ id='admin.log.formatMessage'
+ defaultMessage='Message'
+ />
+ </td></tr>
</tbody>
</table>
</div>
@@ -279,9 +390,12 @@ export default class LogSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
- data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
+ data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
>
- {'Save'}
+ <FormattedMessage
+ id='admin.log.save'
+ defaultMessage='Save'
+ />
</button>
</div>
</div>
@@ -293,5 +407,8 @@ export default class LogSettings extends React.Component {
}
LogSettings.propTypes = {
+ intl: intlShape.isRequired,
config: React.PropTypes.object
};
+
+export default injectIntl(LogSettings); \ No newline at end of file
diff --git a/web/react/components/admin_console/logs.jsx b/web/react/components/admin_console/logs.jsx
index 01135f1b8..71a4a5d8c 100644
--- a/web/react/components/admin_console/logs.jsx
+++ b/web/react/components/admin_console/logs.jsx
@@ -5,6 +5,8 @@ import AdminStore from '../../stores/admin_store.jsx';
import LoadingScreen from '../loading_screen.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
+import {FormattedMessage} from 'mm-intl';
+
export default class Logs extends React.Component {
constructor(props) {
super(props);
@@ -73,13 +75,21 @@ export default class Logs extends React.Component {
return (
<div className='panel'>
- <h3>{'Server Logs'}</h3>
+ <h3>
+ <FormattedMessage
+ id='admin.logs.title'
+ defaultMessage='Server Logs'
+ />
+ </h3>
<button
type='submit'
className='btn btn-primary'
onClick={this.reload}
>
- {'Reload'}
+ <FormattedMessage
+ id='admin.logs.reload'
+ defaultMessage='Reload'
+ />
</button>
<div className='log__panel'>
{content}
diff --git a/web/react/components/admin_console/privacy_settings.jsx b/web/react/components/admin_console/privacy_settings.jsx
index 78747d9f2..1ab625049 100644
--- a/web/react/components/admin_console/privacy_settings.jsx
+++ b/web/react/components/admin_console/privacy_settings.jsx
@@ -4,7 +4,16 @@
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
-export default class PrivacySettings extends React.Component {
+import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
+
+const holders = defineMessages({
+ saving: {
+ id: 'admin.privacy.saving',
+ defaultMessage: 'Saving Config...'
+ }
+});
+
+class PrivacySettings extends React.Component {
constructor(props) {
super(props);
@@ -64,7 +73,12 @@ export default class PrivacySettings extends React.Component {
return (
<div className='wrapper--fixed'>
- <h3>{'Privacy Settings'}</h3>
+ <h3>
+ <FormattedMessage
+ id='admin.privacy.title'
+ defaultMessage='Privacy Settings'
+ />
+ </h3>
<form
className='form-horizontal'
role='form'
@@ -75,7 +89,10 @@ export default class PrivacySettings extends React.Component {
className='control-label col-sm-4'
htmlFor='ShowEmailAddress'
>
- {'Show Email Address: '}
+ <FormattedMessage
+ id='admin.privacy.showEmailTitle'
+ defaultMessage='Show Email Address: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -87,7 +104,10 @@ export default class PrivacySettings extends React.Component {
defaultChecked={this.props.config.PrivacySettings.ShowEmailAddress}
onChange={this.handleChange}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.privacy.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -97,9 +117,17 @@ export default class PrivacySettings extends React.Component {
defaultChecked={!this.props.config.PrivacySettings.ShowEmailAddress}
onChange={this.handleChange}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.privacy.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'When false, hides email address of users from other users in the user interface, including team owners and team administrators. Used when system is set up for managing teams where some users choose to keep their contact information private.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.privacy.showEmailDescription'
+ defaultMessage='When false, hides email address of users from other users in the user interface, including team owners and team administrators. Used when system is set up for managing teams where some users choose to keep their contact information private.'
+ />
+ </p>
</div>
</div>
@@ -108,7 +136,10 @@ export default class PrivacySettings extends React.Component {
className='control-label col-sm-4'
htmlFor='ShowFullName'
>
- {'Show Full Name: '}
+ <FormattedMessage
+ id='admin.privacy.showFullNameTitle'
+ defaultMessage='Show Full Name: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -120,7 +151,10 @@ export default class PrivacySettings extends React.Component {
defaultChecked={this.props.config.PrivacySettings.ShowFullName}
onChange={this.handleChange}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.privacy.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -130,9 +164,17 @@ export default class PrivacySettings extends React.Component {
defaultChecked={!this.props.config.PrivacySettings.ShowFullName}
onChange={this.handleChange}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.privacy.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'When false, hides full name of users from other users, including team owners and team administrators. Username is shown in place of full name.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.privacy.showFullNameDescription'
+ defaultMessage='When false, hides full name of users from other users, including team owners and team administrators. Username is shown in place of full name.'
+ />
+ </p>
</div>
</div>
@@ -145,9 +187,12 @@ export default class PrivacySettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
- data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
+ data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + this.props.intl.formatMessage(holders.saving)}
>
- {'Save'}
+ <FormattedMessage
+ id='admin.privacy.save'
+ defaultMessage='Save'
+ />
</button>
</div>
</div>
@@ -159,5 +204,8 @@ export default class PrivacySettings extends React.Component {
}
PrivacySettings.propTypes = {
+ intl: intlShape.isRequired,
config: React.PropTypes.object
};
+
+export default injectIntl(PrivacySettings); \ No newline at end of file
diff --git a/web/react/components/admin_console/rate_settings.jsx b/web/react/components/admin_console/rate_settings.jsx
index aabb24326..d3c1bffa2 100644
--- a/web/react/components/admin_console/rate_settings.jsx
+++ b/web/react/components/admin_console/rate_settings.jsx
@@ -4,7 +4,28 @@
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
-export default class RateSettings extends React.Component {
+import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
+
+const holders = defineMessages({
+ queriesExample: {
+ id: 'admin.rate.queriesExample',
+ defaultMessage: 'Ex "10"'
+ },
+ memoryExample: {
+ id: 'admin.rate.memoryExample',
+ defaultMessage: 'Ex "10000"'
+ },
+ httpHeaderExample: {
+ id: 'admin.rate.httpHeaderExample',
+ defaultMessage: 'Ex "X-Real-IP", "X-Forwarded-For"'
+ },
+ saving: {
+ id: 'admin.rate.saving',
+ defaultMessage: 'Saving Config...'
+ }
+});
+
+class RateSettings extends React.Component {
constructor(props) {
super(props);
@@ -85,6 +106,7 @@ export default class RateSettings extends React.Component {
}
render() {
+ const {formatMessage} = this.props.intl;
var serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
@@ -100,12 +122,27 @@ export default class RateSettings extends React.Component {
<div className='banner'>
<div className='banner__content'>
- <h4 className='banner__heading'>{'Note:'}</h4>
- <p>{'Changing properties in this section will require a server restart before taking effect.'}</p>
+ <h4 className='banner__heading'>
+ <FormattedMessage
+ id='admin.rate.noteTitle'
+ defaultMessage='Note:'
+ />
+ </h4>
+ <p>
+ <FormattedMessage
+ id='admin.rate.noteDescription'
+ defaultMessage='Changing properties in this section will require a server restart before taking effect.'
+ />
+ </p>
</div>
</div>
- <h3>{'Rate Limit Settings'}</h3>
+ <h3>
+ <FormattedMessage
+ id='admin.rate.title'
+ defaultMessage='Rate Limit Settings'
+ />
+ </h3>
<form
className='form-horizontal'
role='form'
@@ -116,7 +153,10 @@ export default class RateSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableRateLimiter'
>
- {'Enable Rate Limiter: '}
+ <FormattedMessage
+ id='admin.rate.enableLimiterTitle'
+ defaultMessage='Enable Rate Limiter: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -128,7 +168,10 @@ export default class RateSettings extends React.Component {
defaultChecked={this.props.config.RateLimitSettings.EnableRateLimiter}
onChange={this.handleChange.bind(this, 'EnableRateLimiterTrue')}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.rate.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -138,9 +181,17 @@ export default class RateSettings extends React.Component {
defaultChecked={!this.props.config.RateLimitSettings.EnableRateLimiter}
onChange={this.handleChange.bind(this, 'EnableRateLimiterFalse')}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.rate.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'When true, APIs are throttled at rates specified below.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.rate.enableLimiterDescription'
+ defaultMessage='When true, APIs are throttled at rates specified below.'
+ />
+ </p>
</div>
</div>
@@ -149,7 +200,10 @@ export default class RateSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='PerSec'
>
- {'Number Of Queries Per Second:'}
+ <FormattedMessage
+ id='admin.rate.queriesTitle'
+ defaultMessage='Number Of Queries Per Second:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -157,12 +211,17 @@ export default class RateSettings extends React.Component {
className='form-control'
id='PerSec'
ref='PerSec'
- placeholder='Ex "10"'
+ placeholder={formatMessage(holders.queriesExample)}
defaultValue={this.props.config.RateLimitSettings.PerSec}
onChange={this.handleChange}
disabled={!this.state.EnableRateLimiter}
/>
- <p className='help-text'>{'Throttles API at this number of requests per second.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.rate.queriesDescription'
+ defaultMessage='Throttles API at this number of requests per second.'
+ />
+ </p>
</div>
</div>
@@ -171,7 +230,10 @@ export default class RateSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='MemoryStoreSize'
>
- {'Memory Store Size:'}
+ <FormattedMessage
+ id='admin.rate.memoryTitle'
+ defaultMessage='Memory Store Size:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -179,12 +241,17 @@ export default class RateSettings extends React.Component {
className='form-control'
id='MemoryStoreSize'
ref='MemoryStoreSize'
- placeholder='Ex "10000"'
+ placeholder={formatMessage(holders.memoryExample)}
defaultValue={this.props.config.RateLimitSettings.MemoryStoreSize}
onChange={this.handleChange}
disabled={!this.state.EnableRateLimiter}
/>
- <p className='help-text'>{'Maximum number of users sessions connected to the system as determined by "Vary By Remote Address" and "Vary By Header" settings below.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.rate.memoryDescription'
+ defaultMessage='Maximum number of users sessions connected to the system as determined by "Vary By Remote Address" and "Vary By Header" settings below.'
+ />
+ </p>
</div>
</div>
@@ -193,7 +260,10 @@ export default class RateSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='VaryByRemoteAddr'
>
- {'Vary By Remote Address: '}
+ <FormattedMessage
+ id='admin.rate.remoteTitle'
+ defaultMessage='Vary By Remote Address: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -206,7 +276,10 @@ export default class RateSettings extends React.Component {
onChange={this.handleChange.bind(this, 'VaryByRemoteAddrTrue')}
disabled={!this.state.EnableRateLimiter}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.rate.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -217,9 +290,17 @@ export default class RateSettings extends React.Component {
onChange={this.handleChange.bind(this, 'VaryByRemoteAddrFalse')}
disabled={!this.state.EnableRateLimiter}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.rate.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'When true, rate limit API access by IP address.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.rate.remoteDescription'
+ defaultMessage='When true, rate limit API access by IP address.'
+ />
+ </p>
</div>
</div>
@@ -228,7 +309,10 @@ export default class RateSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='VaryByHeader'
>
- {'Vary By HTTP Header:'}
+ <FormattedMessage
+ id='admin.rate.httpHeaderTitle'
+ defaultMessage='Vary By HTTP Header:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -236,12 +320,17 @@ export default class RateSettings extends React.Component {
className='form-control'
id='VaryByHeader'
ref='VaryByHeader'
- placeholder='Ex "X-Real-IP", "X-Forwarded-For"'
+ placeholder={formatMessage(holders.httpHeaderExample)}
defaultValue={this.props.config.RateLimitSettings.VaryByHeader}
onChange={this.handleChange}
disabled={!this.state.EnableRateLimiter || this.state.VaryByRemoteAddr}
/>
- <p className='help-text'>{'When filled in, vary rate limiting by HTTP header field specified (e.g. when configuring NGINX set to "X-Real-IP", when configuring AmazonELB set to "X-Forwarded-For").'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.rate.httpHeaderDescription'
+ defaultMessage='When filled in, vary rate limiting by HTTP header field specified (e.g. when configuring NGINX set to "X-Real-IP", when configuring AmazonELB set to "X-Forwarded-For").'
+ />
+ </p>
</div>
</div>
@@ -254,9 +343,12 @@ export default class RateSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
- data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
+ data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
>
- {'Save'}
+ <FormattedMessage
+ id='admin.rate.save'
+ defaultMessage='Save'
+ />
</button>
</div>
</div>
@@ -268,5 +360,8 @@ export default class RateSettings extends React.Component {
}
RateSettings.propTypes = {
+ intl: intlShape.isRequired,
config: React.PropTypes.object
};
+
+export default injectIntl(RateSettings); \ No newline at end of file
diff --git a/web/react/components/admin_console/reset_password_modal.jsx b/web/react/components/admin_console/reset_password_modal.jsx
index bf7d5f7e5..8ed519ffb 100644
--- a/web/react/components/admin_console/reset_password_modal.jsx
+++ b/web/react/components/admin_console/reset_password_modal.jsx
@@ -5,7 +5,16 @@ import * as Client from '../../utils/client.jsx';
import Constants from '../../utils/constants.jsx';
var Modal = ReactBootstrap.Modal;
-export default class ResetPasswordModal extends React.Component {
+import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
+
+var holders = defineMessages({
+ submit: {
+ id: 'admin.reset_password.submit',
+ defaultMessage: 'Please enter at least {chars} characters.'
+ }
+});
+
+class ResetPasswordModal extends React.Component {
constructor(props) {
super(props);
@@ -22,7 +31,7 @@ export default class ResetPasswordModal extends React.Component {
var password = ReactDOM.findDOMNode(this.refs.password).value;
if (!password || password.length < Constants.MIN_PASSWORD_LENGTH) {
- this.setState({serverError: 'Please enter at least ' + Constants.MIN_PASSWORD_LENGTH + ' characters.'});
+ this.setState({serverError: this.props.intl.formatMessage(holders.submit, {chars: Constants.MIN_PASSWORD_LENGTH})});
return;
}
@@ -67,7 +76,12 @@ export default class ResetPasswordModal extends React.Component {
onHide={this.doCancel}
>
<Modal.Header closeButton={true}>
- <Modal.Title>{'Reset Password'}</Modal.Title>
+ <Modal.Title>
+ <FormattedMessage
+ id='admin.reset_password.title'
+ defaultMessage='Reset Password'
+ />
+ </Modal.Title>
</Modal.Header>
<form
role='form'
@@ -82,7 +96,10 @@ export default class ResetPasswordModal extends React.Component {
title='New Password'
className='input-group-addon'
>
- {'New Password'}
+ <FormattedMessage
+ id='admin.reset_password.newPassword'
+ defaultMessage='New Password'
+ />
</span>
<input
type='password'
@@ -103,7 +120,10 @@ export default class ResetPasswordModal extends React.Component {
className='btn btn-default'
onClick={this.doCancel}
>
- {'Close'}
+ <FormattedMessage
+ id='admin.reset_password.close'
+ defaultMessage='Close'
+ />
</button>
<button
onClick={this.doSubmit}
@@ -111,7 +131,10 @@ export default class ResetPasswordModal extends React.Component {
className='btn btn-primary'
tabIndex='2'
>
- {'Select'}
+ <FormattedMessage
+ id='admin.reset_password.select'
+ defaultMessage='Select'
+ />
</button>
</Modal.Footer>
</form>
@@ -125,9 +148,12 @@ ResetPasswordModal.defaultProps = {
};
ResetPasswordModal.propTypes = {
+ intl: intlShape.isRequired,
user: React.PropTypes.object,
team: React.PropTypes.object,
show: React.PropTypes.bool.isRequired,
onModalSubmit: React.PropTypes.func,
onModalDismissed: React.PropTypes.func
};
+
+export default injectIntl(ResetPasswordModal); \ No newline at end of file
diff --git a/web/react/components/admin_console/service_settings.jsx b/web/react/components/admin_console/service_settings.jsx
index f10721ffa..7021900eb 100644
--- a/web/react/components/admin_console/service_settings.jsx
+++ b/web/react/components/admin_console/service_settings.jsx
@@ -4,11 +4,40 @@
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
+import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
+
const DefaultSessionLength = 30;
const DefaultMaximumLoginAttempts = 10;
const DefaultSessionCacheInMinutes = 10;
-export default class ServiceSettings extends React.Component {
+var holders = defineMessages({
+ listenExample: {
+ id: 'admin.service.listenExample',
+ defaultMessage: 'Ex ":8065"'
+ },
+ attemptExample: {
+ id: 'admin.service.attemptExample',
+ defaultMessage: 'Ex "10"'
+ },
+ segmentExample: {
+ id: 'admin.service.segmentExample',
+ defaultMessage: 'Ex "g3fgGOXJAQ43QV7rAh6iwQCkV4cA1Gs"'
+ },
+ googleExample: {
+ id: 'admin.service.googleExample',
+ defaultMessage: 'Ex "7rAh6iwQCkV4cA1Gsg3fgGOXJAQ43QV"'
+ },
+ sessionDaysEx: {
+ id: 'admin.service.sessionDaysEx',
+ defaultMessage: 'Ex "30"'
+ },
+ saving: {
+ id: 'admin.service.saving',
+ defaultMessage: 'Saving Config...'
+ }
+});
+
+class ServiceSettings extends React.Component {
constructor(props) {
super(props);
@@ -120,6 +149,7 @@ export default class ServiceSettings extends React.Component {
}
render() {
+ const {formatMessage} = this.props.intl;
var serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
@@ -133,7 +163,12 @@ export default class ServiceSettings extends React.Component {
return (
<div className='wrapper--fixed'>
- <h3>{'Service Settings'}</h3>
+ <h3>
+ <FormattedMessage
+ id='admin.service.title'
+ defaultMessage='Service Settings'
+ />
+ </h3>
<form
className='form-horizontal'
role='form'
@@ -144,7 +179,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='ListenAddress'
>
- {'Listen Address:'}
+ <FormattedMessage
+ id='admin.service.listenAddress'
+ defaultMessage='Listen Address:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -152,11 +190,16 @@ export default class ServiceSettings extends React.Component {
className='form-control'
id='ListenAddress'
ref='ListenAddress'
- placeholder='Ex ":8065"'
+ placeholder={formatMessage(holders.listenExample)}
defaultValue={this.props.config.ServiceSettings.ListenAddress}
onChange={this.handleChange}
/>
- <p className='help-text'>{'The address to which to bind and listen. Entering ":8065" will bind to all interfaces or you can choose one like "127.0.0.1:8065". Changing this will require a server restart before taking effect.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.service.listenDescription'
+ defaultMessage='The address to which to bind and listen. Entering ":8065" will bind to all interfaces or you can choose one like "127.0.0.1:8065". Changing this will require a server restart before taking effect.'
+ />
+ </p>
</div>
</div>
@@ -165,7 +208,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='MaximumLoginAttempts'
>
- {'Maximum Login Attempts:'}
+ <FormattedMessage
+ id='admin.service.attemptTitle'
+ defaultMessage='Maximum Login Attempts:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -173,11 +219,16 @@ export default class ServiceSettings extends React.Component {
className='form-control'
id='MaximumLoginAttempts'
ref='MaximumLoginAttempts'
- placeholder='Ex "10"'
+ placeholder={formatMessage(holders.attemptExample)}
defaultValue={this.props.config.ServiceSettings.MaximumLoginAttempts}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Login attempts allowed before user is locked out and required to reset password via email.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.service.attemptDescription'
+ defaultMessage='Login attempts allowed before user is locked out and required to reset password via email.'
+ />
+ </p>
</div>
</div>
@@ -186,7 +237,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='SegmentDeveloperKey'
>
- {'Segment Developer Key:'}
+ <FormattedMessage
+ id='admin.service.segmentTitle'
+ defaultMessage='Segment Developer Key:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -194,11 +248,16 @@ export default class ServiceSettings extends React.Component {
className='form-control'
id='SegmentDeveloperKey'
ref='SegmentDeveloperKey'
- placeholder='Ex "g3fgGOXJAQ43QV7rAh6iwQCkV4cA1Gs"'
+ placeholder={formatMessage(holders.segmentExample)}
defaultValue={this.props.config.ServiceSettings.SegmentDeveloperKey}
onChange={this.handleChange}
/>
- <p className='help-text'>{'For users running a SaaS services, sign up for a key at Segment.com to track metrics.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.service.segmentDescription'
+ defaultMessage='For users running a SaaS services, sign up for a key at Segment.com to track metrics.'
+ />
+ </p>
</div>
</div>
@@ -207,7 +266,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='GoogleDeveloperKey'
>
- {'Google Developer Key:'}
+ <FormattedMessage
+ id='admin.service.googleTitle'
+ defaultMessage='Google Developer Key:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -215,19 +277,17 @@ export default class ServiceSettings extends React.Component {
className='form-control'
id='GoogleDeveloperKey'
ref='GoogleDeveloperKey'
- placeholder='Ex "7rAh6iwQCkV4cA1Gsg3fgGOXJAQ43QV"'
+ placeholder={formatMessage(holders.googleExample)}
defaultValue={this.props.config.ServiceSettings.GoogleDeveloperKey}
onChange={this.handleChange}
/>
<p className='help-text'>
- {'Set this key to enable embedding of YouTube video previews based on hyperlinks appearing in messages or comments. Instructions to obtain a key available at '}
- <a
- href='https://www.youtube.com/watch?v=Im69kzhpR3I'
- target='_blank'
- >
- {'https://www.youtube.com/watch?v=Im69kzhpR3I'}
- </a>
- {'. Leaving the field blank disables the automatic generation of YouTube video previews from links.'}
+ <FormattedHTMLMessage
+ id='admin.service.googleDescription'
+ defaultMessage='Set this key to enable embedding of YouTube video previews based on hyperlinks appearing in messages or comments. Instructions to obtain a key available at
+ <a href="https://www.youtube.com/watch?v=Im69kzhpR3I" target="_blank">https://www.youtube.com/watch?v=Im69kzhpR3I</a>.
+ Leaving the field blank disables the automatic generation of YouTube video previews from links.'
+ />
</p>
</div>
</div>
@@ -237,7 +297,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableIncomingWebhooks'
>
- {'Enable Incoming Webhooks: '}
+ <FormattedMessage
+ id='admin.service.webhooksTitle'
+ defaultMessage='Enable Incoming Webhooks: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -249,7 +312,10 @@ export default class ServiceSettings extends React.Component {
defaultChecked={this.props.config.ServiceSettings.EnableIncomingWebhooks}
onChange={this.handleChange}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.service.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -259,9 +325,17 @@ export default class ServiceSettings extends React.Component {
defaultChecked={!this.props.config.ServiceSettings.EnableIncomingWebhooks}
onChange={this.handleChange}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.service.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'When true, incoming webhooks will be allowed. To help combat phishing attacks, all posts from webhooks will be labelled by a BOT tag.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.service.webhooksDescription'
+ defaultMessage='When true, incoming webhooks will be allowed. To help combat phishing attacks, all posts from webhooks will be labelled by a BOT tag.'
+ />
+ </p>
</div>
</div>
@@ -270,7 +344,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableOutgoingWebhooks'
>
- {'Enable Outgoing Webhooks: '}
+ <FormattedMessage
+ id='admin.service.outWebhooksTitle'
+ defaultMessage='Enable Outgoing Webhooks: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -282,7 +359,10 @@ export default class ServiceSettings extends React.Component {
defaultChecked={this.props.config.ServiceSettings.EnableOutgoingWebhooks}
onChange={this.handleChange}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.service.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -292,9 +372,17 @@ export default class ServiceSettings extends React.Component {
defaultChecked={!this.props.config.ServiceSettings.EnableOutgoingWebhooks}
onChange={this.handleChange}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.service.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'When true, outgoing webhooks will be allowed.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.service.outWebhooksDesc'
+ defaultMessage='When true, outgoing webhooks will be allowed.'
+ />
+ </p>
</div>
</div>
@@ -303,7 +391,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnablePostUsernameOverride'
>
- {'Enable Overriding Usernames from Webhooks: '}
+ <FormattedMessage
+ id='admin.service.overrideTitle'
+ defaultMessage='Enable Overriding Usernames from Webhooks: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -315,7 +406,10 @@ export default class ServiceSettings extends React.Component {
defaultChecked={this.props.config.ServiceSettings.EnablePostUsernameOverride}
onChange={this.handleChange}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.service.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -325,9 +419,17 @@ export default class ServiceSettings extends React.Component {
defaultChecked={!this.props.config.ServiceSettings.EnablePostUsernameOverride}
onChange={this.handleChange}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.service.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'When true, webhooks will be allowed to change the username they are posting as. Note, combined with allowing icon overriding, this could open users up to phishing attacks.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.service.overrideDescription'
+ defaultMessage='When true, webhooks will be allowed to change the username they are posting as. Note, combined with allowing icon overriding, this could open users up to phishing attacks.'
+ />
+ </p>
</div>
</div>
@@ -336,7 +438,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnablePostIconOverride'
>
- {'Enable Overriding Icon from Webhooks: '}
+ <FormattedMessage
+ id='admin.service.iconTitle'
+ defaultMessage='Enable Overriding Icon from Webhooks: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -348,7 +453,10 @@ export default class ServiceSettings extends React.Component {
defaultChecked={this.props.config.ServiceSettings.EnablePostIconOverride}
onChange={this.handleChange}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.service.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -358,9 +466,17 @@ export default class ServiceSettings extends React.Component {
defaultChecked={!this.props.config.ServiceSettings.EnablePostIconOverride}
onChange={this.handleChange}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.service.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'When true, webhooks will be allowed to change the icon they post with. Note, combined with allowing username overriding, this could open users up to phishing attacks.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.service.iconDescription'
+ defaultMessage='When true, webhooks will be allowed to change the icon they post with. Note, combined with allowing username overriding, this could open users up to phishing attacks.'
+ />
+ </p>
</div>
</div>
@@ -369,7 +485,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableTesting'
>
- {'Enable Testing: '}
+ <FormattedMessage
+ id='admin.service.testingTitle'
+ defaultMessage='Enable Testing: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -381,7 +500,10 @@ export default class ServiceSettings extends React.Component {
defaultChecked={this.props.config.ServiceSettings.EnableTesting}
onChange={this.handleChange}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.service.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -391,9 +513,17 @@ export default class ServiceSettings extends React.Component {
defaultChecked={!this.props.config.ServiceSettings.EnableTesting}
onChange={this.handleChange}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.service.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'(Developer Option) When true, /loadtest slash command is enabled to load test accounts and test data. Changing this will require a server restart before taking effect.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.service.testingDescription'
+ defaultMessage='(Developer Option) When true, /loadtest slash command is enabled to load test accounts and test data. Changing this will require a server restart before taking effect.'
+ />
+ </p>
</div>
</div>
@@ -402,7 +532,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableDeveloper'
>
- {'Enable Developer Mode: '}
+ <FormattedMessage
+ id='admin.service.developerTitle'
+ defaultMessage='Enable Developer Mode: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -414,7 +547,10 @@ export default class ServiceSettings extends React.Component {
defaultChecked={this.props.config.ServiceSettings.EnableDeveloper}
onChange={this.handleChange}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.service.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -424,9 +560,17 @@ export default class ServiceSettings extends React.Component {
defaultChecked={!this.props.config.ServiceSettings.EnableDeveloper}
onChange={this.handleChange}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.service.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'(Developer Option) When true, extra information around errors will be displayed in the UI.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.service.developerDesc'
+ defaultMessage='(Developer Option) When true, extra information around errors will be displayed in the UI.'
+ />
+ </p>
</div>
</div>
@@ -435,7 +579,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableSecurityFixAlert'
>
- {'Enable Security Alerts: '}
+ <FormattedMessage
+ id='admin.service.securityTitle'
+ defaultMessage='Enable Security Alerts: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -447,7 +594,10 @@ export default class ServiceSettings extends React.Component {
defaultChecked={this.props.config.ServiceSettings.EnableSecurityFixAlert}
onChange={this.handleChange}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.service.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -457,9 +607,17 @@ export default class ServiceSettings extends React.Component {
defaultChecked={!this.props.config.ServiceSettings.EnableSecurityFixAlert}
onChange={this.handleChange}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.service.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'When true, System Administrators are notified by email if a relevant security fix alert has been announced in the last 12 hours. Requires email to be enabled.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.service.securityDesc'
+ defaultMessage='When true, System Administrators are notified by email if a relevant security fix alert has been announced in the last 12 hours. Requires email to be enabled.'
+ />
+ </p>
</div>
</div>
@@ -468,7 +626,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='SessionLengthWebInDays'
>
- {'Session Length for Web in Days:'}
+ <FormattedMessage
+ id='admin.service.webSessionDays'
+ defaultMessage='Session Length for Web in Days:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -476,11 +637,16 @@ export default class ServiceSettings extends React.Component {
className='form-control'
id='SessionLengthWebInDays'
ref='SessionLengthWebInDays'
- placeholder='Ex "30"'
+ placeholder={formatMessage(holders.sessionDaysEx)}
defaultValue={this.props.config.ServiceSettings.SessionLengthWebInDays}
onChange={this.handleChange}
/>
- <p className='help-text'>{'The web session will expire after the number of days specified and will require a user to login again.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.service.webSessionDaysDesc'
+ defaultMessage='The web session will expire after the number of days specified and will require a user to login again.'
+ />
+ </p>
</div>
</div>
@@ -489,7 +655,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='SessionLengthMobileInDays'
>
- {'Session Length for Mobile Device in Days:'}
+ <FormattedMessage
+ id='admin.service.mobileSessionDays'
+ defaultMessage='Session Length for Mobile Device in Days:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -497,11 +666,16 @@ export default class ServiceSettings extends React.Component {
className='form-control'
id='SessionLengthMobileInDays'
ref='SessionLengthMobileInDays'
- placeholder='Ex "30"'
+ placeholder={formatMessage(holders.sessionDaysEx)}
defaultValue={this.props.config.ServiceSettings.SessionLengthMobileInDays}
onChange={this.handleChange}
/>
- <p className='help-text'>{'The native mobile session will expire after the number of days specified and will require a user to login again.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.service.mobileSessionDaysDesc'
+ defaultMessage='The native mobile session will expire after the number of days specified and will require a user to login again.'
+ />
+ </p>
</div>
</div>
@@ -510,7 +684,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='SessionLengthSSOInDays'
>
- {'Session Length for SSO in Days:'}
+ <FormattedMessage
+ id='admin.service.ssoSessionDays'
+ defaultMessage='Session Length for SSO in Days:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -518,11 +695,16 @@ export default class ServiceSettings extends React.Component {
className='form-control'
id='SessionLengthSSOInDays'
ref='SessionLengthSSOInDays'
- placeholder='Ex "30"'
+ placeholder={formatMessage(holders.sessionDaysEx)}
defaultValue={this.props.config.ServiceSettings.SessionLengthSSOInDays}
onChange={this.handleChange}
/>
- <p className='help-text'>{'The SSO session will expire after the number of days specified and will require a user to login again.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.service.ssoSessionDaysDesc'
+ defaultMessage='The SSO session will expire after the number of days specified and will require a user to login again.'
+ />
+ </p>
</div>
</div>
@@ -531,7 +713,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='SessionCacheInMinutes'
>
- {'Session Cache in Minutes:'}
+ <FormattedMessage
+ id='admin.service.sessionCache'
+ defaultMessage='Session Cache in Minutes:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -539,11 +724,16 @@ export default class ServiceSettings extends React.Component {
className='form-control'
id='SessionCacheInMinutes'
ref='SessionCacheInMinutes'
- placeholder='Ex "30"'
+ placeholder={formatMessage(holders.sessionDaysEx)}
defaultValue={this.props.config.ServiceSettings.SessionCacheInMinutes}
onChange={this.handleChange}
/>
- <p className='help-text'>{'The number of minutes to cache a session in memory.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.service.sessionCacheDesc'
+ defaultMessage='The number of minutes to cache a session in memory.'
+ />
+ </p>
</div>
</div>
@@ -556,9 +746,12 @@ export default class ServiceSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
- data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
+ data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
>
- {'Save'}
+ <FormattedMessage
+ id='admin.service.save'
+ defaultMessage='Save'
+ />
</button>
</div>
</div>
@@ -603,5 +796,8 @@ export default class ServiceSettings extends React.Component {
// </div>
ServiceSettings.propTypes = {
+ intl: intlShape.isRequired,
config: React.PropTypes.object
};
+
+export default injectIntl(ServiceSettings); \ No newline at end of file
diff --git a/web/react/components/admin_console/sql_settings.jsx b/web/react/components/admin_console/sql_settings.jsx
index 2a55f7324..69ae808f6 100644
--- a/web/react/components/admin_console/sql_settings.jsx
+++ b/web/react/components/admin_console/sql_settings.jsx
@@ -5,7 +5,32 @@ import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
import crypto from 'crypto';
-export default class SqlSettings extends React.Component {
+import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
+
+const holders = defineMessages({
+ warning: {
+ id: 'admin.sql.warning',
+ defaultMessage: 'Warning: re-generating this salt may cause some columns in the database to return empty results.'
+ },
+ maxConnectionsExample: {
+ id: 'admin.sql.maxConnectionsExample',
+ defaultMessage: 'Ex "10"'
+ },
+ maxOpenExample: {
+ id: 'admin.sql.maxOpenExample',
+ defaultMessage: 'Ex "10"'
+ },
+ keyExample: {
+ id: 'admin.sql.keyExample',
+ defaultMessage: 'Ex "gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6"'
+ },
+ saving: {
+ id: 'admin.sql.saving',
+ defaultMessage: 'Saving Config...'
+ }
+});
+
+class SqlSettings extends React.Component {
constructor(props) {
super(props);
@@ -74,7 +99,7 @@ export default class SqlSettings extends React.Component {
handleGenerate(e) {
e.preventDefault();
- var cfm = global.window.confirm('Warning: re-generating this salt may cause some columns in the database to return empty results.');
+ var cfm = global.window.confirm(this.props.intl.formatMessage(holders.warning));
if (cfm === false) {
return;
}
@@ -85,6 +110,7 @@ export default class SqlSettings extends React.Component {
}
render() {
+ const {formatMessage} = this.props.intl;
var serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
@@ -111,12 +137,27 @@ export default class SqlSettings extends React.Component {
<div className='banner'>
<div className='banner__content'>
- <h4 className='banner__heading'>{'Note:'}</h4>
- <p>{'Changing properties in this section will require a server restart before taking effect.'}</p>
+ <h4 className='banner__heading'>
+ <FormattedMessage
+ id='admin.sql.noteTitle'
+ defaultMessage='Note:'
+ />
+ </h4>
+ <p>
+ <FormattedMessage
+ id='admin.sql.noteDescription'
+ defaultMessage='Changing properties in this section will require a server restart before taking effect.'
+ />
+ </p>
</div>
</div>
- <h3>{'SQL Settings'}</h3>
+ <h3>
+ <FormattedMessage
+ id='admin.sql.title'
+ defaultMessage='SQL Settings'
+ />
+ </h3>
<form
className='form-horizontal'
role='form'
@@ -127,7 +168,10 @@ export default class SqlSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='DriverName'
>
- {'Driver Name:'}
+ <FormattedMessage
+ id='admin.sql.driverName'
+ defaultMessage='Driver Name:'
+ />
</label>
<div className='col-sm-8'>
<p className='help-text'>{this.props.config.SqlSettings.DriverName}</p>
@@ -139,7 +183,10 @@ export default class SqlSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='DataSource'
>
- {'Data Source:'}
+ <FormattedMessage
+ id='admin.sql.dataSource'
+ defaultMessage='Data Source:'
+ />
</label>
<div className='col-sm-8'>
<p className='help-text'>{dataSource}</p>
@@ -151,7 +198,10 @@ export default class SqlSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='DataSourceReplicas'
>
- {'Data Source Replicas:'}
+ <FormattedMessage
+ id='admin.sql.replicas'
+ defaultMessage='Data Source Replicas:'
+ />
</label>
<div className='col-sm-8'>
<p className='help-text'>{dataSourceReplicas}</p>
@@ -163,7 +213,10 @@ export default class SqlSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='MaxIdleConns'
>
- {'Maximum Idle Connections:'}
+ <FormattedMessage
+ id='admin.sql.maxConnectionsTitle'
+ defaultMessage='Maximum Idle Connections:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -171,11 +224,16 @@ export default class SqlSettings extends React.Component {
className='form-control'
id='MaxIdleConns'
ref='MaxIdleConns'
- placeholder='Ex "10"'
+ placeholder={formatMessage(holders.maxConnectionsExample)}
defaultValue={this.props.config.SqlSettings.MaxIdleConns}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Maximum number of idle connections held open to the database.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.sql.maxConnectionsDescription'
+ defaultMessage='Maximum number of idle connections held open to the database.'
+ />
+ </p>
</div>
</div>
@@ -184,7 +242,10 @@ export default class SqlSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='MaxOpenConns'
>
- {'Maximum Open Connections:'}
+ <FormattedMessage
+ id='admin.sql.maxOpenTitle'
+ defaultMessage='Maximum Open Connections:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -192,11 +253,16 @@ export default class SqlSettings extends React.Component {
className='form-control'
id='MaxOpenConns'
ref='MaxOpenConns'
- placeholder='Ex "10"'
+ placeholder={formatMessage(holders.maxOpenExample)}
defaultValue={this.props.config.SqlSettings.MaxOpenConns}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Maximum number of open connections held open to the database.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.sql.maxOpenDescription'
+ defaultMessage='Maximum number of open connections held open to the database.'
+ />
+ </p>
</div>
</div>
@@ -205,7 +271,10 @@ export default class SqlSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='AtRestEncryptKey'
>
- {'At Rest Encrypt Key:'}
+ <FormattedMessage
+ id='admin.sql.keyTitle'
+ defaultMessage='At Rest Encrypt Key:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -213,17 +282,25 @@ export default class SqlSettings extends React.Component {
className='form-control'
id='AtRestEncryptKey'
ref='AtRestEncryptKey'
- placeholder='Ex "gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6"'
+ placeholder={formatMessage(holders.keyExample)}
defaultValue={this.props.config.SqlSettings.AtRestEncryptKey}
onChange={this.handleChange}
/>
- <p className='help-text'>{'32-character salt available to encrypt and decrypt sensitive fields in database.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.sql.keyDescription'
+ defaultMessage='32-character salt available to encrypt and decrypt sensitive fields in database.'
+ />
+ </p>
<div className='help-text'>
<button
className='btn btn-default'
onClick={this.handleGenerate}
>
- {'Re-Generate'}
+ <FormattedMessage
+ id='admin.sql.regenerate'
+ defaultMessage='Re-Generate'
+ />
</button>
</div>
</div>
@@ -234,7 +311,10 @@ export default class SqlSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='Trace'
>
- {'Trace: '}
+ <FormattedMessage
+ id='admin.sql.traceTitle'
+ defaultMessage='Trace: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -246,7 +326,10 @@ export default class SqlSettings extends React.Component {
defaultChecked={this.props.config.SqlSettings.Trace}
onChange={this.handleChange}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.sql.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -256,9 +339,17 @@ export default class SqlSettings extends React.Component {
defaultChecked={!this.props.config.SqlSettings.Trace}
onChange={this.handleChange}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.sql.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'(Development Mode) When true, executing SQL statements are written to the log.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.sql.traceDescription'
+ defaultMessage='(Development Mode) When true, executing SQL statements are written to the log.'
+ />
+ </p>
</div>
</div>
@@ -271,9 +362,12 @@ export default class SqlSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
- data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
+ data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
>
- {'Save'}
+ <FormattedMessage
+ id='admin.sql.save'
+ defaultMessage='Save'
+ />
</button>
</div>
</div>
@@ -285,5 +379,8 @@ export default class SqlSettings extends React.Component {
}
SqlSettings.propTypes = {
+ intl: intlShape.isRequired,
config: React.PropTypes.object
};
+
+export default injectIntl(SqlSettings); \ No newline at end of file
diff --git a/web/react/components/admin_console/system_analytics.jsx b/web/react/components/admin_console/system_analytics.jsx
index f54813a94..2dd833fb2 100644
--- a/web/react/components/admin_console/system_analytics.jsx
+++ b/web/react/components/admin_console/system_analytics.jsx
@@ -4,7 +4,24 @@
import Analytics from './analytics.jsx';
import * as Client from '../../utils/client.jsx';
-export default class SystemAnalytics extends React.Component {
+import {injectIntl, intlShape, defineMessages} from 'mm-intl';
+
+const labels = defineMessages({
+ totalPosts: {
+ id: 'admin.system_analytics.totalPosts',
+ defaultMessage: 'Total Posts'
+ },
+ activeUsers: {
+ id: 'admin.system_analytics.activeUsers',
+ defaultMessage: 'Active Users With Posts'
+ },
+ title: {
+ id: 'admin.system_analytics.title',
+ defaultMessage: 'the System'
+ }
+});
+
+class SystemAnalytics extends React.Component {
constructor(props) {
super(props);
@@ -29,6 +46,7 @@ export default class SystemAnalytics extends React.Component {
}
getData() { // should be moved to an action creator eventually
+ const {formatMessage} = this.props.intl;
Client.getSystemAnalytics(
'standard',
(data) => {
@@ -63,7 +81,7 @@ export default class SystemAnalytics extends React.Component {
var chartData = {
labels: [],
datasets: [{
- label: 'Total Posts',
+ label: formatMessage(labels.totalPosts),
fillColor: 'rgba(151,187,205,0.2)',
strokeColor: 'rgba(151,187,205,1)',
pointColor: 'rgba(151,187,205,1)',
@@ -97,7 +115,7 @@ export default class SystemAnalytics extends React.Component {
var chartData = {
labels: [],
datasets: [{
- label: 'Active Users With Posts',
+ label: formatMessage(labels.activeUsers),
fillColor: 'rgba(151,187,205,0.2)',
strokeColor: 'rgba(151,187,205,1)',
pointColor: 'rgba(151,187,205,1)',
@@ -142,7 +160,7 @@ export default class SystemAnalytics extends React.Component {
return (
<div>
<Analytics
- title={'the System'}
+ title={this.props.intl.formatMessage(labels.title)}
channelOpenCount={this.state.channel_open_count}
channelPrivateCount={this.state.channel_private_count}
postCount={this.state.post_count}
@@ -157,5 +175,8 @@ export default class SystemAnalytics extends React.Component {
}
SystemAnalytics.propTypes = {
+ intl: intlShape.isRequired,
team: React.PropTypes.object
};
+
+export default injectIntl(SystemAnalytics); \ No newline at end of file
diff --git a/web/react/components/admin_console/team_analytics.jsx b/web/react/components/admin_console/team_analytics.jsx
index c164dd98c..ee59b0e66 100644
--- a/web/react/components/admin_console/team_analytics.jsx
+++ b/web/react/components/admin_console/team_analytics.jsx
@@ -4,7 +4,20 @@
import Analytics from './analytics.jsx';
import * as Client from '../../utils/client.jsx';
-export default class TeamAnalytics extends React.Component {
+import {injectIntl, intlShape, defineMessages} from 'mm-intl';
+
+const labels = defineMessages({
+ totalPosts: {
+ id: 'admin.team_analytics.totalPosts',
+ defaultMessage: 'Total Posts'
+ },
+ activeUsers: {
+ id: 'admin.team_analytics.activeUsers',
+ defaultMessage: 'Active Users With Posts'
+ }
+});
+
+class TeamAnalytics extends React.Component {
constructor(props) {
super(props);
@@ -29,6 +42,7 @@ export default class TeamAnalytics extends React.Component {
}
getData(teamId) { // should be moved to an action creator eventually
+ const {formatMessage} = this.props.intl;
Client.getTeamAnalytics(
teamId,
'standard',
@@ -65,7 +79,7 @@ export default class TeamAnalytics extends React.Component {
var chartData = {
labels: [],
datasets: [{
- label: 'Total Posts',
+ label: formatMessage(labels.totalPosts),
fillColor: 'rgba(151,187,205,0.2)',
strokeColor: 'rgba(151,187,205,1)',
pointColor: 'rgba(151,187,205,1)',
@@ -100,7 +114,7 @@ export default class TeamAnalytics extends React.Component {
var chartData = {
labels: [],
datasets: [{
- label: 'Active Users With Posts',
+ label: formatMessage(labels.activeUsers),
fillColor: 'rgba(151,187,205,0.2)',
strokeColor: 'rgba(151,187,205,1)',
pointColor: 'rgba(151,187,205,1)',
@@ -231,5 +245,8 @@ export default class TeamAnalytics extends React.Component {
}
TeamAnalytics.propTypes = {
+ intl: intlShape.isRequired,
team: React.PropTypes.object
};
+
+export default injectIntl(TeamAnalytics); \ No newline at end of file
diff --git a/web/react/components/admin_console/team_settings.jsx b/web/react/components/admin_console/team_settings.jsx
index 9d958ce91..cc4ff38ba 100644
--- a/web/react/components/admin_console/team_settings.jsx
+++ b/web/react/components/admin_console/team_settings.jsx
@@ -4,7 +4,28 @@
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
-export default class TeamSettings extends React.Component {
+import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
+
+const holders = defineMessages({
+ siteNameExample: {
+ id: 'admin.team.siteNameExample',
+ defaultMessage: 'Ex "Mattermost"'
+ },
+ maxUsersExample: {
+ id: 'admin.team.maxUsersExample',
+ defaultMessage: 'Ex "25"'
+ },
+ restrictExample: {
+ id: 'admin.team.restrictExample',
+ defaultMessage: 'Ex "corp.mattermost.com, mattermost.org"'
+ },
+ saving: {
+ id: 'admin.team.saving',
+ defaultMessage: 'Saving Config...'
+ }
+});
+
+class TeamSettings extends React.Component {
constructor(props) {
super(props);
@@ -62,6 +83,7 @@ export default class TeamSettings extends React.Component {
}
render() {
+ const {formatMessage} = this.props.intl;
var serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
@@ -75,7 +97,12 @@ export default class TeamSettings extends React.Component {
return (
<div className='wrapper--fixed'>
- <h3>{'Team Settings'}</h3>
+ <h3>
+ <FormattedMessage
+ id='admin.team.title'
+ defaultMessage='Team Settings'
+ />
+ </h3>
<form
className='form-horizontal'
role='form'
@@ -86,7 +113,10 @@ export default class TeamSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='SiteName'
>
- {'Site Name:'}
+ <FormattedMessage
+ id='admin.team.siteNameTitle'
+ defaultMessage='Site Name:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -94,11 +124,16 @@ export default class TeamSettings extends React.Component {
className='form-control'
id='SiteName'
ref='SiteName'
- placeholder='Ex "Mattermost"'
+ placeholder={formatMessage(holders.siteNameExample)}
defaultValue={this.props.config.TeamSettings.SiteName}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Name of service shown in login screens and UI.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.team.siteNameDescription'
+ defaultMessage='Name of service shown in login screens and UI.'
+ />
+ </p>
</div>
</div>
@@ -107,7 +142,10 @@ export default class TeamSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='MaxUsersPerTeam'
>
- {'Max Users Per Team:'}
+ <FormattedMessage
+ id='admin.team.maxUsersTitle'
+ defaultMessage='Max Users Per Team:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -115,11 +153,16 @@ export default class TeamSettings extends React.Component {
className='form-control'
id='MaxUsersPerTeam'
ref='MaxUsersPerTeam'
- placeholder='Ex "25"'
+ placeholder={formatMessage(holders.maxUsersExample)}
defaultValue={this.props.config.TeamSettings.MaxUsersPerTeam}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Maximum total number of users per team, including both active and inactive users.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.team.maxUsersDescription'
+ defaultMessage='Maximum total number of users per team, including both active and inactive users.'
+ />
+ </p>
</div>
</div>
@@ -128,7 +171,10 @@ export default class TeamSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableTeamCreation'
>
- {'Enable Team Creation: '}
+ <FormattedMessage
+ id='admin.team.teamCreationTitle'
+ defaultMessage='Enable Team Creation: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -140,7 +186,10 @@ export default class TeamSettings extends React.Component {
defaultChecked={this.props.config.TeamSettings.EnableTeamCreation}
onChange={this.handleChange}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.team.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -150,9 +199,17 @@ export default class TeamSettings extends React.Component {
defaultChecked={!this.props.config.TeamSettings.EnableTeamCreation}
onChange={this.handleChange}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.team.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'When false, the ability to create teams is disabled. The create team button displays error when pressed.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.team.teamCreationDescription'
+ defaultMessage='When false, the ability to create teams is disabled. The create team button displays error when pressed.'
+ />
+ </p>
</div>
</div>
@@ -161,7 +218,10 @@ export default class TeamSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableUserCreation'
>
- {'Enable User Creation: '}
+ <FormattedMessage
+ id='admin.team.userCreationTitle'
+ defaultMessage='Enable User Creation: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -173,7 +233,10 @@ export default class TeamSettings extends React.Component {
defaultChecked={this.props.config.TeamSettings.EnableUserCreation}
onChange={this.handleChange}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.team.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -183,9 +246,17 @@ export default class TeamSettings extends React.Component {
defaultChecked={!this.props.config.TeamSettings.EnableUserCreation}
onChange={this.handleChange}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.team.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'When false, the ability to create accounts is disabled. The create account button displays error when pressed.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.team.userCreationDescription'
+ defaultMessage='When false, the ability to create accounts is disabled. The create account button displays error when pressed.'
+ />
+ </p>
</div>
</div>
@@ -194,7 +265,10 @@ export default class TeamSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='RestrictCreationToDomains'
>
- {'Restrict Creation To Domains:'}
+ <FormattedMessage
+ id='admin.team.restrictTitle'
+ defaultMessage='Restrict Creation To Domains:'
+ />
</label>
<div className='col-sm-8'>
<input
@@ -202,11 +276,16 @@ export default class TeamSettings extends React.Component {
className='form-control'
id='RestrictCreationToDomains'
ref='RestrictCreationToDomains'
- placeholder='Ex "corp.mattermost.com, mattermost.org"'
+ placeholder={formatMessage(holders.restrictExample)}
defaultValue={this.props.config.TeamSettings.RestrictCreationToDomains}
onChange={this.handleChange}
/>
- <p className='help-text'>{'Teams and user accounts can only be created from a specific domain (e.g. "mattermost.org") or list of comma-separated domains (e.g. "corp.mattermost.com, mattermost.org").'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.team.restrictDescription'
+ defaultMessage='Teams and user accounts can only be created from a specific domain (e.g. "mattermost.org") or list of comma-separated domains (e.g. "corp.mattermost.com, mattermost.org").'
+ />
+ </p>
</div>
</div>
@@ -215,7 +294,10 @@ export default class TeamSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='RestrictTeamNames'
>
- {'Restrict Team Names: '}
+ <FormattedMessage
+ id='admin.team.restrictNameTitle'
+ defaultMessage='Restrict Team Names: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -227,7 +309,10 @@ export default class TeamSettings extends React.Component {
defaultChecked={this.props.config.TeamSettings.RestrictTeamNames}
onChange={this.handleChange}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.team.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -237,9 +322,17 @@ export default class TeamSettings extends React.Component {
defaultChecked={!this.props.config.TeamSettings.RestrictTeamNames}
onChange={this.handleChange}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.team.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'When true, You cannot create a team name with reserved words like www, admin, support, test, channel, etc'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.team.restrictNameDesc'
+ defaultMessage='When true, You cannot create a team name with reserved words like www, admin, support, test, channel, etc'
+ />
+ </p>
</div>
</div>
@@ -248,7 +341,10 @@ export default class TeamSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableTeamListing'
>
- {'Enable Team Directory: '}
+ <FormattedMessage
+ id='admin.team.dirTitle'
+ defaultMessage='Enable Team Directory: '
+ />
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -260,7 +356,10 @@ export default class TeamSettings extends React.Component {
defaultChecked={this.props.config.TeamSettings.EnableTeamListing}
onChange={this.handleChange}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.team.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -270,9 +369,17 @@ export default class TeamSettings extends React.Component {
defaultChecked={!this.props.config.TeamSettings.EnableTeamListing}
onChange={this.handleChange}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.team.false'
+ defaultMessage='false'
+ />
</label>
- <p className='help-text'>{'When true, teams that are configured to show in team directory will show on main page inplace of creating a new team.'}</p>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.team.dirDesc'
+ defaultMessage='When true, teams that are configured to show in team directory will show on main page inplace of creating a new team.'
+ />
+ </p>
</div>
</div>
@@ -285,9 +392,12 @@ export default class TeamSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
- data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
+ data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
>
- {'Save'}
+ <FormattedMessage
+ id='admin.team.save'
+ defaultMessage='Save'
+ />
</button>
</div>
</div>
@@ -299,5 +409,8 @@ export default class TeamSettings extends React.Component {
}
TeamSettings.propTypes = {
+ intl: intlShape.isRequired,
config: React.PropTypes.object
};
+
+export default injectIntl(TeamSettings); \ No newline at end of file
diff --git a/web/react/components/admin_console/team_users.jsx b/web/react/components/admin_console/team_users.jsx
index 2d9657956..1177c9c56 100644
--- a/web/react/components/admin_console/team_users.jsx
+++ b/web/react/components/admin_console/team_users.jsx
@@ -6,6 +6,8 @@ import LoadingScreen from '../loading_screen.jsx';
import UserItem from './user_item.jsx';
import ResetPasswordModal from './reset_password_modal.jsx';
+import {FormattedMessage} from 'mm-intl';
+
export default class UserList extends React.Component {
constructor(props) {
super(props);
@@ -122,7 +124,15 @@ export default class UserList extends React.Component {
if (this.state.users == null) {
return (
<div className='wrapper--fixed'>
- <h3>{'Users for ' + this.props.team.name}</h3>
+ <h3>
+ <FormattedMessage
+ id='admin.userList.title'
+ defaultMessage='Users for {team}'
+ values={{
+ team: this.props.team.name
+ }}
+ />
+ </h3>
{serverError}
<LoadingScreen />
</div>
@@ -141,7 +151,16 @@ export default class UserList extends React.Component {
return (
<div className='wrapper--fixed'>
- <h3>{'Users for ' + this.props.team.name + ' (' + this.state.users.length + ')'}</h3>
+ <h3>
+ <FormattedMessage
+ id='admin.userList.title2'
+ defaultMessage='Users for {team} ({count})'
+ values={{
+ team: this.props.team.name,
+ count: this.state.users.length
+ }}
+ />
+ </h3>
{serverError}
<form
className='form-horizontal'
diff --git a/web/react/components/admin_console/user_item.jsx b/web/react/components/admin_console/user_item.jsx
index ef0b61460..59b4861e4 100644
--- a/web/react/components/admin_console/user_item.jsx
+++ b/web/react/components/admin_console/user_item.jsx
@@ -4,6 +4,8 @@
import * as Client from '../../utils/client.jsx';
import * as Utils from '../../utils/utils.jsx';
+import {FormattedMessage} from 'mm-intl';
+
export default class UserItem extends React.Component {
constructor(props) {
super(props);
@@ -109,12 +111,27 @@ export default class UserItem extends React.Component {
}
const user = this.props.user;
- let currentRoles = 'Member';
+ let currentRoles = (
+ <FormattedMessage
+ id='admin.user_item.member'
+ defaultMessage='Member'
+ />
+ );
if (user.roles.length > 0) {
if (Utils.isSystemAdmin(user.roles)) {
- currentRoles = 'System Admin';
+ currentRoles = (
+ <FormattedMessage
+ id='admin.user_item.sysAdmin'
+ defaultMessage='System Admin'
+ />
+ );
} else if (Utils.isAdmin(user.roles)) {
- currentRoles = 'Team Admin';
+ currentRoles = (
+ <FormattedMessage
+ id='admin.user_item.teamAdmin'
+ defaultMessage='Team Admin'
+ />
+ );
} else {
currentRoles = user.roles.charAt(0).toUpperCase() + user.roles.slice(1);
}
@@ -128,7 +145,12 @@ export default class UserItem extends React.Component {
let showMakeNotActive = user.roles !== 'system_admin';
if (user.delete_at > 0) {
- currentRoles = 'Inactive';
+ currentRoles = (
+ <FormattedMessage
+ id='admin.user_item.inactive'
+ defaultMessage='Inactive'
+ />
+ );
showMakeMember = false;
showMakeAdmin = false;
showMakeSystemAdmin = false;
@@ -145,7 +167,10 @@ export default class UserItem extends React.Component {
href='#'
onClick={this.handleMakeSystemAdmin}
>
- {'Make System Admin'}
+ <FormattedMessage
+ id='admin.user_item.makeSysAdmin'
+ defaultMessage='Make System Admin'
+ />
</a>
</li>
);
@@ -160,7 +185,10 @@ export default class UserItem extends React.Component {
href='#'
onClick={this.handleMakeAdmin}
>
- {'Make Team Admin'}
+ <FormattedMessage
+ id='admin.user_item.makeTeamAdmin'
+ defaultMessage='Make Team Admin'
+ />
</a>
</li>
);
@@ -175,7 +203,10 @@ export default class UserItem extends React.Component {
href='#'
onClick={this.handleMakeMember}
>
- {'Make Member'}
+ <FormattedMessage
+ id='admin.user_item.makeMember'
+ defaultMessage='Make Member'
+ />
</a>
</li>
);
@@ -190,7 +221,10 @@ export default class UserItem extends React.Component {
href='#'
onClick={this.handleMakeActive}
>
- {'Make Active'}
+ <FormattedMessage
+ id='admin.user_item.makeActive'
+ defaultMessage='Make Active'
+ />
</a>
</li>
);
@@ -205,7 +239,10 @@ export default class UserItem extends React.Component {
href='#'
onClick={this.handleMakeNotActive}
>
- {'Make Inactive'}
+ <FormattedMessage
+ id='admin.user_item.makeInactive'
+ defaultMessage='Make Inactive'
+ />
</a>
</li>
);
@@ -248,7 +285,10 @@ export default class UserItem extends React.Component {
href='#'
onClick={this.handleResetPassword}
>
- {'Reset Password'}
+ <FormattedMessage
+ id='admin.user_item.resetPwd'
+ defaultMessage='Reset Password'
+ />
</a>
</li>
</ul>
diff --git a/web/react/components/center_panel.jsx b/web/react/components/center_panel.jsx
index 7eef329c3..53dad1306 100644
--- a/web/react/components/center_panel.jsx
+++ b/web/react/components/center_panel.jsx
@@ -66,11 +66,9 @@ export default class CenterPanel extends React.Component {
createPost = (
<div
id='archive-link-home'
+ onClick={handleClick}
>
- <a
- href=''
- onClick={handleClick}
- >
+ <a href=''>
{'You are viewing the Archives. Click here to jump to recent messages. '}
{<i className='fa fa-arrow-down'></i>}
</a>
diff --git a/web/react/components/claim/claim_account.jsx b/web/react/components/claim/claim_account.jsx
index f38f558db..87026b762 100644
--- a/web/react/components/claim/claim_account.jsx
+++ b/web/react/components/claim/claim_account.jsx
@@ -4,6 +4,8 @@
import EmailToSSO from './email_to_sso.jsx';
import SSOToEmail from './sso_to_email.jsx';
+import {FormattedMessage} from 'mm-intl';
+
export default class ClaimAccount extends React.Component {
constructor(props) {
super(props);
@@ -13,7 +15,14 @@ export default class ClaimAccount extends React.Component {
render() {
let content;
if (this.props.email === '') {
- content = <p>{'No email specified.'}</p>;
+ content = (
+ <p>
+ <FormattedMessage
+ id='claim.account.noEmail'
+ defaultMessage='No email specified'
+ />
+ </p>
+ );
} else if (this.props.currentType === '' && this.props.newType !== '') {
content = (
<EmailToSSO
diff --git a/web/react/components/claim/email_to_sso.jsx b/web/react/components/claim/email_to_sso.jsx
index ac0cf876b..3d4b9e91f 100644
--- a/web/react/components/claim/email_to_sso.jsx
+++ b/web/react/components/claim/email_to_sso.jsx
@@ -4,7 +4,20 @@
import * as Utils from '../../utils/utils.jsx';
import * as Client from '../../utils/client.jsx';
-export default class EmailToSSO extends React.Component {
+import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl';
+
+const holders = defineMessages({
+ pwdError: {
+ id: 'claim.email_to_sso.pwdError',
+ defaultMessage: 'Please enter your password.'
+ },
+ pwd: {
+ id: 'claim.email_to_sso.pwd',
+ defaultMessage: 'Password'
+ }
+});
+
+class EmailToSSO extends React.Component {
constructor(props) {
super(props);
@@ -18,7 +31,7 @@ export default class EmailToSSO extends React.Component {
var password = ReactDOM.findDOMNode(this.refs.password).value.trim();
if (!password) {
- state.error = 'Please enter your password.';
+ state.error = this.props.intl.formatMessage(holders.pwdError);
this.setState(state);
return;
}
@@ -59,17 +72,42 @@ export default class EmailToSSO extends React.Component {
return (
<div className='col-sm-12'>
<div className='signup-team__container'>
- <h3>{'Switch Email/Password Account to ' + uiType}</h3>
+ <h3>
+ <FormattedMessage
+ id='claim.email_to_sso.title'
+ defaultMessage='Switch Email/Password Account to {uiType}'
+ values={{
+ uiType: uiType
+ }}
+ />
+ </h3>
<form onSubmit={this.submit}>
- <p>{'Upon claiming your account, you will only be able to login with ' + Utils.toTitleCase(this.props.type) + ' SSO.'}</p>
- <p>{'Enter the password for your ' + this.props.teamDisplayName + ' ' + global.window.mm_config.SiteName + ' account.'}</p>
+ <p>
+ <FormattedMessage
+ id='claim.email_to_sso.ssoType'
+ defaultMessage='Upon claiming your account, you will only be able to login with {type} SSO'
+ values={{
+ type: Utils.toTitleCase(this.props.type)
+ }}
+ />
+ </p>
+ <p>
+ <FormattedMessage
+ id='claim.email_to_sso.enterPwd'
+ defaultMessage='Enter the password for your {team} {site} account'
+ values={{
+ team: this.props.teamDisplayName,
+ site: global.window.mm_config.SiteName
+ }}
+ />
+ </p>
<div className={formClass}>
<input
type='password'
className='form-control'
name='password'
ref='password'
- placeholder='Password'
+ placeholder={this.props.intl.formatMessage(holders.pwd)}
spellCheck='false'
/>
</div>
@@ -78,7 +116,13 @@ export default class EmailToSSO extends React.Component {
type='submit'
className='btn btn-primary'
>
- {'Switch account to ' + uiType}
+ <FormattedMessage
+ id='claim.email_to_sso.switchTo'
+ defaultMessage='Switch account to {uiType}'
+ values={{
+ uiType: uiType
+ }}
+ />
</button>
</form>
</div>
@@ -90,8 +134,11 @@ export default class EmailToSSO extends React.Component {
EmailToSSO.defaultProps = {
};
EmailToSSO.propTypes = {
+ intl: intlShape.isRequired,
type: React.PropTypes.string.isRequired,
email: React.PropTypes.string.isRequired,
teamName: React.PropTypes.string.isRequired,
teamDisplayName: React.PropTypes.string.isRequired
};
+
+export default injectIntl(EmailToSSO); \ No newline at end of file
diff --git a/web/react/components/claim/sso_to_email.jsx b/web/react/components/claim/sso_to_email.jsx
index 0868b7f2f..73ff13cc9 100644
--- a/web/react/components/claim/sso_to_email.jsx
+++ b/web/react/components/claim/sso_to_email.jsx
@@ -4,7 +4,28 @@
import * as Utils from '../../utils/utils.jsx';
import * as Client from '../../utils/client.jsx';
-export default class SSOToEmail extends React.Component {
+import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl';
+
+const holders = defineMessages({
+ enterPwd: {
+ id: 'claim.sso_to_email.enterPwd',
+ defaultMessage: 'Please enter a password.'
+ },
+ pwdNotMatch: {
+ id: 'claim.sso_to_email.pwdNotMatch',
+ defaultMessage: 'Password do not match.'
+ },
+ newPwd: {
+ id: 'claim.sso_to_email.newPwd',
+ defaultMessage: 'New Password'
+ },
+ confirm: {
+ id: 'claim.sso_to_email.confirm',
+ defaultMessage: 'Confirm Password'
+ }
+});
+
+class SSOToEmail extends React.Component {
constructor(props) {
super(props);
@@ -13,19 +34,20 @@ export default class SSOToEmail extends React.Component {
this.state = {};
}
submit(e) {
+ const {formatMessage} = this.props.intl;
e.preventDefault();
const state = {};
const password = ReactDOM.findDOMNode(this.refs.password).value.trim();
if (!password) {
- state.error = 'Please enter a password.';
+ state.error = formatMessage(holders.enterPwd);
this.setState(state);
return;
}
const confirmPassword = ReactDOM.findDOMNode(this.refs.passwordconfirm).value.trim();
if (!confirmPassword || password !== confirmPassword) {
- state.error = 'Passwords do not match.';
+ state.error = formatMessage(holders.pwdNotMatch);
this.setState(state);
return;
}
@@ -50,6 +72,7 @@ export default class SSOToEmail extends React.Component {
);
}
render() {
+ const {formatMessage} = this.props.intl;
var error = null;
if (this.state.error) {
error = <div className='form-group has-error'><label className='control-label'>{this.state.error}</label></div>;
@@ -65,17 +88,39 @@ export default class SSOToEmail extends React.Component {
return (
<div className='col-sm-12'>
<div className='signup-team__container'>
- <h3>{'Switch ' + uiType + ' Account to Email'}</h3>
+ <h3>
+ <FormattedMessage
+ id='claim.sso_to_email.title'
+ defaultMessage='Switch {type} Account to Email'
+ values={{
+ type: uiType
+ }}
+ />
+ </h3>
<form onSubmit={this.submit}>
- <p>{'Upon changing your account type, you will only be able to login with your email and password.'}</p>
- <p>{'Enter a new password for your ' + this.props.teamDisplayName + ' ' + global.window.mm_config.SiteName + ' account.'}</p>
+ <p>
+ <FormattedMessage
+ id='claim.sso_to_email.description'
+ defaultMessage='Upon changing your account type, you will only be able to login with your email and password.'
+ />
+ </p>
+ <p>
+ <FormattedMessage
+ id='claim.sso_to_email_newPwd'
+ defaultMessage='Enter a new password for your {team} {site} account'
+ values={{
+ team: this.props.teamDisplayName,
+ site: global.window.mm_config.SiteName
+ }}
+ />
+ </p>
<div className={formClass}>
<input
type='password'
className='form-control'
name='password'
ref='password'
- placeholder='New Password'
+ placeholder={formatMessage(holders.newPwd)}
spellCheck='false'
/>
</div>
@@ -85,7 +130,7 @@ export default class SSOToEmail extends React.Component {
className='form-control'
name='passwordconfirm'
ref='passwordconfirm'
- placeholder='Confirm Password'
+ placeholder={formatMessage(holders.confirm)}
spellCheck='false'
/>
</div>
@@ -94,7 +139,13 @@ export default class SSOToEmail extends React.Component {
type='submit'
className='btn btn-primary'
>
- {'Switch ' + uiType + ' account to email and password'}
+ <FormattedMessage
+ id='claim.sso_to_email.switchTo'
+ defaultMessage='Switch {type} to email and password'
+ values={{
+ type: uiType
+ }}
+ />
</button>
</form>
</div>
@@ -106,8 +157,11 @@ export default class SSOToEmail extends React.Component {
SSOToEmail.defaultProps = {
};
SSOToEmail.propTypes = {
+ intl: intlShape.isRequired,
currentType: React.PropTypes.string.isRequired,
email: React.PropTypes.string.isRequired,
teamName: React.PropTypes.string.isRequired,
teamDisplayName: React.PropTypes.string.isRequired
};
+
+export default injectIntl(SSOToEmail); \ 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 70fe10eef..9f733c476 100644
--- a/web/react/components/new_channel_modal.jsx
+++ b/web/react/components/new_channel_modal.jsx
@@ -22,6 +22,11 @@ export default class NewChannelModal extends React.Component {
});
}
}
+ componentDidMount() {
+ if (Utils.isBrowserIE()) {
+ $('body').addClass('browser--IE');
+ }
+ }
handleSubmit(e) {
e.preventDefault();
diff --git a/web/react/components/suggestion/at_mention_provider.jsx b/web/react/components/suggestion/at_mention_provider.jsx
index e502c981d..50231ad15 100644
--- a/web/react/components/suggestion/at_mention_provider.jsx
+++ b/web/react/components/suggestion/at_mention_provider.jsx
@@ -5,6 +5,8 @@ import SuggestionStore from '../../stores/suggestion_store.jsx';
import UserStore from '../../stores/user_store.jsx';
import * as Utils from '../../utils/utils.jsx';
+import {FormattedMessage} from 'mm-intl';
+
const MaxUserSuggestions = 40;
class AtMentionSuggestion extends React.Component {
@@ -16,11 +18,21 @@ class AtMentionSuggestion extends React.Component {
let icon;
if (item.username === 'all') {
username = 'all';
- description = 'Notifies everyone in the team';
+ description = (
+ <FormattedMessage
+ id='suggestion.mention.all'
+ defaultMessage='Notifies everyone in the team'
+ />
+ );
icon = <i className='mention-img fa fa-users fa-2x' />;
} else if (item.username === 'channel') {
username = 'channel';
- description = 'Notifies everyone in the channel';
+ description = (
+ <FormattedMessage
+ id='suggestion.mention.channel'
+ defaultMessage='Notifies everyone in the channel'
+ />
+ );
icon = <i className='mention-img fa fa-users fa-2x' />;
} else {
username = item.username;
diff --git a/web/react/components/suggestion/search_suggestion_list.jsx b/web/react/components/suggestion/search_suggestion_list.jsx
index 3378a33a0..40f5d8777 100644
--- a/web/react/components/suggestion/search_suggestion_list.jsx
+++ b/web/react/components/suggestion/search_suggestion_list.jsx
@@ -3,7 +3,8 @@
import Constants from '../../utils/constants.jsx';
import SuggestionList from './suggestion_list.jsx';
-import * as Utils from '../../utils/utils.jsx';
+
+import {FormattedMessage} from 'mm-intl';
export default class SearchSuggestionList extends SuggestionList {
componentDidUpdate(prevProps, prevState) {
@@ -19,9 +20,19 @@ export default class SearchSuggestionList extends SuggestionList {
renderChannelDivider(type) {
let text;
if (type === Constants.OPEN_CHANNEL) {
- text = 'Public ' + Utils.getChannelTerm(type) + 's';
+ text = (
+ <FormattedMessage
+ id='suggestion.search.public'
+ defaultMessage='Public Channels'
+ />
+ );
} else {
- text = 'Private ' + Utils.getChannelTerm(type) + 's';
+ text = (
+ <FormattedMessage
+ id='suggestion.search.private'
+ defaultMessage='Public Groups'
+ />
+ );
}
return (
diff --git a/web/react/components/tutorial/tutorial_intro_screens.jsx b/web/react/components/tutorial/tutorial_intro_screens.jsx
index 7ab1e5512..78cfb7b60 100644
--- a/web/react/components/tutorial/tutorial_intro_screens.jsx
+++ b/web/react/components/tutorial/tutorial_intro_screens.jsx
@@ -9,6 +9,9 @@ import * as Utils from '../../utils/utils.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
import Constants from '../../utils/constants.jsx';
+
+import {FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
+
const Preferences = Constants.Preferences;
const NUM_SCREENS = 3;
@@ -61,10 +64,13 @@ export default class TutorialIntroScreens extends React.Component {
return (
<div>
- <h3>{'Welcome to:'}</h3>
- <h1>{'Mattermost'}</h1>
- <p>{'Your team communication all in one place, instantly searchable and available anywhere.'}</p>
- <p>{'Keep your team connected to help them achieve what matters most.'}</p>
+ <FormattedHTMLMessage
+ id='tutorial_intro.screenOne'
+ defaultMessage='<h3>Welcome to:</h3>
+ <h1>Mattermost</h1>
+ <p>Your team communication all in one place, instantly searchable and available anywhere</p>
+ <p>Keep your team connected to help them achieve what matters most.</p>'
+ />
{circles}
</div>
);
@@ -74,9 +80,12 @@ export default class TutorialIntroScreens extends React.Component {
return (
<div>
- <h3>{'How Mattermost works:'}</h3>
- <p>{'Communication happens in public discussion channels, private groups and direct messages.'}</p>
- <p>{'Everything is archived and searchable from any web-enabled desktop, laptop or phone.'}</p>
+ <FormattedHTMLMessage
+ id='tutorial_intro.screenTwo'
+ defaultMessage='<h3>How Mattermost works:</h3>
+ <p>Communication happens in public discussion channels, private groups and direct messages.</p>
+ <p>Everything is archived and searchable from any web-enabled desktop, laptop or phone.</p>'
+ />
{circles}
</div>
);
@@ -92,7 +101,10 @@ export default class TutorialIntroScreens extends React.Component {
data-toggle='modal'
data-target='#invite_member'
>
- {'Invite teammates'}
+ <FormattedMessage
+ id='tutorial_intro.invite'
+ defaultMessage='Invite teammates'
+ />
</a>
);
} else {
@@ -105,7 +117,10 @@ export default class TutorialIntroScreens extends React.Component {
data-title='Team Invite'
data-value={Utils.getWindowLocationOrigin() + '/signup_user_complete/?id=' + team.id}
>
- {'Invite teammates'}
+ <FormattedMessage
+ id='tutorial_intro.teamInvite'
+ defaultMessage='Team Invite'
+ />
</a>
);
}
@@ -116,7 +131,10 @@ export default class TutorialIntroScreens extends React.Component {
if (global.window.mm_config.SupportEmail) {
supportInfo = (
<p>
- {'Need anything, just email us at '}
+ <FormattedMessage
+ id='tutorial_intro.support'
+ defaultMessage='Need anything, just email us at '
+ />
<a
href={'mailto:' + global.window.mm_config.SupportEmail}
target='_blank'
@@ -130,13 +148,24 @@ export default class TutorialIntroScreens extends React.Component {
return (
<div>
- <h3>{'You’re all set'}</h3>
+ <h3>
+ <FormattedMessage
+ id='tutorial_intro.allSet'
+ defaultMessage='You’re all set'
+ />
+ </h3>
<p>
{inviteModalLink}
- {' when you’re ready.'}
+ <FormattedMessage
+ id='tutorial_intro.whenReady'
+ defaultMessage=' when you’re ready.'
+ />
</p>
{supportInfo}
- {'Click “Next” to enter Town Square. This is the first channel teammates see when they sign up. Use it for posting updates everyone needs to know.'}
+ <FormattedMessage
+ id='tutorial_intro.end'
+ defaultMessage='Click “Next” to enter Town Square. This is the first channel teammates see when they sign up. Use it for posting updates everyone needs to know.'
+ />
{circles}
</div>
);
@@ -186,14 +215,20 @@ export default class TutorialIntroScreens extends React.Component {
tabIndex='1'
onClick={this.handleNext}
>
- {'Next'}
+ <FormattedMessage
+ id='tutorial_intro.next'
+ defaultMessage='Next'
+ />
</button>
<a
className='tutorial-skip'
href='#'
onClick={this.skipTutorial}
>
- {'Skip tutorial'}
+ <FormattedMessage
+ id='tutorial_intro.skip'
+ defaultMessage='Skip tutorial'
+ />
</a>
</div>
</div>
diff --git a/web/react/components/tutorial/tutorial_tip.jsx b/web/react/components/tutorial/tutorial_tip.jsx
index 23daa4707..6bd7d89a4 100644
--- a/web/react/components/tutorial/tutorial_tip.jsx
+++ b/web/react/components/tutorial/tutorial_tip.jsx
@@ -6,6 +6,9 @@ import PreferenceStore from '../../stores/preference_store.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
import Constants from '../../utils/constants.jsx';
+
+import {FormattedMessage} from 'mm-intl';
+
const Preferences = Constants.Preferences;
const Overlay = ReactBootstrap.Overlay;
@@ -46,7 +49,17 @@ export default class TutorialTip extends React.Component {
AsyncClient.savePreferences([preference]);
}
render() {
- const buttonText = this.state.currentScreen === this.props.screens.length - 1 ? 'Okay' : 'Next';
+ const buttonText = this.state.currentScreen === this.props.screens.length - 1 ? (
+ <FormattedMessage
+ id='tutorial_tip.ok'
+ defaultMessage='Okay'
+ />
+ ) : (
+ <FormattedMessage
+ id='tutorial_tip.next'
+ defaultMessage='Next'
+ />
+ );
const dots = [];
if (this.props.screens.length > 1) {
@@ -111,12 +124,18 @@ export default class TutorialTip extends React.Component {
{buttonText}
</button>
<div className='tip-opt'>
- {'Seen this before? '}
+ <FormattedMessage
+ id='tutorial_tip.seen'
+ defaultMessage='Seen this before? '
+ />
<a
href='#'
onClick={this.skipTutorial}
>
- {'Opt out of these tips.'}
+ <FormattedMessage
+ id='tutorial_tip.out'
+ defaultMessage='Opt out of these tips.'
+ />
</a>
</div>
</div>
diff --git a/web/sass-files/sass/partials/_content.scss b/web/sass-files/sass/partials/_content.scss
index b54c97b41..fb2355da7 100644
--- a/web/sass-files/sass/partials/_content.scss
+++ b/web/sass-files/sass/partials/_content.scss
@@ -38,6 +38,7 @@
font-size: 13px;
.fa {
+ font-size: 11px;
@include opacity(0.7);
}
diff --git a/web/sass-files/sass/partials/_markdown.scss b/web/sass-files/sass/partials/_markdown.scss
index 9ad15f91a..7aa29d95d 100644
--- a/web/sass-files/sass/partials/_markdown.scss
+++ b/web/sass-files/sass/partials/_markdown.scss
@@ -43,7 +43,7 @@
@include opacity(0.2);
}
code {
- white-space: pre;
+ white-space: pre-line;
}
}
.markdown__table {
diff --git a/web/sass-files/sass/partials/_modal.scss b/web/sass-files/sass/partials/_modal.scss
index 7627f6a4c..b451adb75 100644
--- a/web/sass-files/sass/partials/_modal.scss
+++ b/web/sass-files/sass/partials/_modal.scss
@@ -10,6 +10,11 @@
.modal {
width: 100%;
color: #333;
+ body.browser--IE & {
+ .modal-dialog {
+ @include translateY(0);
+ }
+ }
&.image_modal {
.modal-backdrop.in {
@include opacity(0.7);
diff --git a/web/sass-files/sass/partials/_post.scss b/web/sass-files/sass/partials/_post.scss
index 34ff7e5a9..ef2366686 100644
--- a/web/sass-files/sass/partials/_post.scss
+++ b/web/sass-files/sass/partials/_post.scss
@@ -759,10 +759,18 @@ body.ios {
display: inline-block;
visibility: hidden;
+ &:focus {
+ outline: none;
+ }
+
&.icon--visible {
visibility: visible;
}
+ svg {
+ width: 17px;
+ }
+
.comment-icon {
display: inline-block;
top: 3px;
diff --git a/web/static/i18n/en.json b/web/static/i18n/en.json
index 56744ddac..ae302b86e 100644
--- a/web/static/i18n/en.json
+++ b/web/static/i18n/en.json
@@ -27,6 +27,16 @@
"admin.sidebar.teams": "TEAMS ({count})",
"admin.sidebar.other": "OTHER",
"admin.sidebar.logs": "Logs",
+ "admin.analytics.loading": "Loading...",
+ "admin.analytics.totalUsers": "Total Users",
+ "admin.analytics.publicChannels": "Public Channels",
+ "admin.analytics.privateGroups": "Private Groups",
+ "admin.analytics.totalPosts": "Total Posts",
+ "admin.analytics.meaningful": "Not enough data for a meaningful representation.",
+ "admin.analytics.activeUsers": "Active Users With Posts",
+ "admin.analytics.recentActive": "Recent Active Users",
+ "admin.analytics.newlyCreated": "Newly Created Users",
+ "admin.analytics.title": "Statistics for {title}",
"admin.email.notificationDisplayExample": "Ex: \"Mattermost Notification\", \"System\", \"No-Reply\"",
"admin.email.notificationEmailExample": "Ex: \"mattermost@yourcompany.com\", \"admin@yourcompany.com\"",
"admin.email.smtpUsernameExample": "Ex: \"admin@yourcompany.com\", \"AKIADTOVBGERKLCBV\"",
@@ -79,9 +89,346 @@
"admin.email.pushServerTitle": "Push Notification Server:",
"admin.email.pushServerDesc": "Location of Mattermost push notification service you can set up behind your firewall using https://github.com/mattermost/push-proxy. For testing you can use https://push-test.mattermost.com, which connects to the sample Mattermost iOS app in the public Apple AppStore. Please do not use test service for production deployments.",
"admin.email.save": "Save",
+ "admin.gitlab.clientIdExample": "Ex \"jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY\"",
+ "admin.gitlab.clientSecretExample": "Ex \"jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY\"",
+ "admin.gitlab.authExample": "Ex \"\"",
+ "admin.gitlab.tokenExample": "Ex \"\"",
+ "admin.gitlab.userExample": "Ex \"\"",
+ "admin.gitlab.saving": "Saving Config...",
+ "admin.gitlab.settingsTitle": "GitLab Settings",
+ "admin.gitlab.enableTitle": "Enable Sign Up With GitLab: ",
+ "admin.gitlab.true": "true",
+ "admin.gitlab.false": "false",
+ "admin.gitlab.enableDescription": "When true, Mattermost allows team creation and account signup using GitLab OAuth.",
+ "admin.gitlab.EnableHtmlDesc": "<ol><li>Log in to your GitLab account and go to Applications -> Profile Settings.</li><li>Enter Redirect URIs \"<your-mattermost-url>/login/gitlab/complete\" (example: http://localhost:8065/login/gitlab/complete) and \"<your-mattermost-url>/signup/gitlab/complete\". </li><li>Then use \"Secret\" and \"Id\" fields from GitLab to complete the options below.</li><li>Complete the Endpoint URLs below. </li></ol>",
+ "admin.gitlab.clientIdTitle": "Id:",
+ "admin.gitlab.clientIdDescription": "Obtain this value via the instructions above for logging into GitLab",
+ "admin.gitlab.clientSecretTitle": "Secret:",
+ "admin.gitab.clientSecretDescription": "Obtain this value via the instructions above for logging into GitLab.",
+ "admin.gitlab.authTitle": "Auth Endpoint:",
+ "admin.gitlab.authDescription": "Enter https://<your-gitlab-url>/oauth/authorize (example https://example.com:3000/oauth/authorize). Make sure you use HTTP or HTTPS in your URL depending on your server configuration.",
+ "admin.gitlab.tokenTitle": "Token Endpoint:",
+ "admin.gitlab.tokenDescription": "Enter https://<your-gitlab-url>/oauth/token. Make sure you use HTTP or HTTPS in your URL depending on your server configuration.",
+ "admin.gitlab.userTitle": "User API Endpoint:",
+ "admin.gitlab.userDescription": "Enter https://<your-gitlab-url>/api/v3/user. Make sure you use HTTP or HTTPS in your URL depending on your server configuration.",
+ "admin.gitlab.save": "Save",
+ "admin.image.storeDisabled": "Disable File Storage",
+ "admin.image.storeLocal": "Local File System",
+ "admin.image.storeAmazonS3": "Amazon S3",
+ "admin.image.localExample": "Ex \"./data/\"",
+ "admin.image.amazonS3IdExample": "Ex \"AKIADTOVBGERKLCBV\"",
+ "admin.image.amazonS3SecretExample": "Ex \"jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY\"",
+ "admin.image.amazonS3BucketExample": "Ex \"mattermost-media\"",
+ "admin.image.amazonS3RegionExample": "Ex \"us-east-1\"",
+ "admin.image.thumbWidthExample": "Ex \"120\"",
+ "admin.image.thumbHeightExample": "Ex \"100\"",
+ "admin.image.previewWidthExample": "Ex \"1024\"",
+ "admin.image.previewHeightExample": "Ex \"0\"",
+ "admin.image.profileWidthExample": "Ex \"1024\"",
+ "admin.image.profileHeightExample": "Ex \"0\"",
+ "admin.image.publicLinkExample": "Ex \"gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6\"",
+ "admin.image.saving": "Saving Config...",
+ "admin.image.fileSettings": "File Settings",
+ "admin.image.storeTitle": "Store Files In:",
+ "admin.image.localTitle": "Local Directory Location:",
+ "admin.image.localDescription": "Directory to which image files are written. If blank, will be set to ./data/.",
+ "admin.image.amazonS3IdTitle": "Amazon S3 Access Key Id:",
+ "admin.image.amazonS3IdDescription": "Obtain this credential from your Amazon EC2 administrator.",
+ "admin.image.amazonS3SecretTitle": "Amazon S3 Secret Access Key:",
+ "admin.image.amazonS3SecretDescription": "Obtain this credential from your Amazon EC2 administrator.",
+ "admin.image.amazonS3BucketTitle": "Amazon S3 Bucket:",
+ "admin.image.amazonS3BucketDescription": "Name you selected for your S3 bucket in AWS.",
+ "admin.image.amazonS3RegionTitle": "Amazon S3 Region:",
+ "admin.image.amazonS3RegionDescription": "AWS region you selected for creating your S3 bucket.",
+ "admin.image.thumbWidthTitle": "Thumbnail Width:",
+ "admin.image.thumbWidthDescription": "Width of thumbnails generated from uploaded images. Updating this value changes how thumbnail images render in future, but does not change images created in the past.",
+ "admin.image.thumbHeightTitle": "Thumbnail Height:",
+ "admin.image.thumbHeightDescription": "Height of thumbnails generated from uploaded images. Updating this value changes how thumbnail images render in future, but does not change images created in the past.",
+ "admin.image.previewWidthTitle": "Preview Width:",
+ "admin.image.previewWidthDescription": "Maximum width of preview image. Updating this value changes how preview images render in future, but does not change images created in the past.",
+ "admin.image.previewHeightTitle": "Preview Height:",
+ "admin.image.previewHeightDescription": "Maximum height of preview image (\"0\": Sets to auto-size). Updating this value changes how preview images render in future, but does not change images created in the past.",
+ "admin.image.profileWidthTitle": "Profile Width:",
+ "admin.image.profileWidthDescription": "Width of profile picture.",
+ "admin.image.profileHeightTitle": "Profile Height:",
+ "admin.image.profileHeightDescription": "Height of profile picture.",
+ "admin.image.shareTitle": "Share Public File Link: ",
+ "admin.image.true": "true",
+ "admin.image.false": "false",
+ "admin.image.shareDescription": "Allow users to share public links to files and images.",
+ "admin.image.publicLinkTitle": "Public Link Salt:",
+ "admin.image.publicLinkDescription": "32-character salt added to signing of public image links. Randomly generated on install. Click \"Re-Generate\" to create new salt.",
+ "admin.image.regenerate": "Re-Generate",
+ "admin.image.save": "Save",
+ "admin.ldap.serverEx": "Ex \"10.0.0.23\"",
+ "admin.ldap.portEx": "Ex \"389\"",
+ "admin.ldap.baseEx": "Ex \"dc=mydomain,dc=com\"",
+ "admin.ldap.firstnameAttrEx": "Ex \"givenName\"",
+ "admin.ldap.lastnameAttrEx": "Ex \"sn\"",
+ "admin.ldap.emailAttrEx": "Ex \"mail\"",
+ "admin.ldap.usernameAttrEx": "Ex \"sAMAccountName\"",
+ "admin.ldap.idAttrEx": "Ex \"sAMAccountName\"",
+ "admin.ldap.queryEx": "Ex \"60\"",
+ "admin.ldap.saving": "Saving Config...",
+ "admin.ldap.bannerHeading": "Note:",
+ "admin.ldap.bannerDesc": "If a user attribute changes on the LDAP server it will be updated the next time the user enters their credentials to log in to Mattermost. This includes if a user is made inactive or removed from an LDAP server. Synchronization with LDAP servers is planned in a future release.",
+ "admin.ldap.noLicense": "<h4 className=\"banner__heading\">Note:</h4><p>LDAP is an enterprise feature. Your current license does not support LDAP. Click <a href=\"http://mattermost.com\"target=\"_blank\">here</a> for information and pricing on enterprise licenses.</p>",
+ "admin.ldap.title": "LDAP Settings",
+ "admin.ldap.enableTitle": "Enable Login With LDAP:",
+ "admin.ldap.true": "true",
+ "admin.ldap.false": "false",
+ "admin.ldap.enableDesc": "When true, Mattermost allows login using LDAP",
+ "admin.ldap.serverTitle": "LDAP Server:",
+ "admin.ldap.serverDesc": "The domain or IP address of LDAP server.",
+ "admin.ldap.portTitle": "LDAP Port:",
+ "admin.ldap.portDesc": "The port Mattermost will use to connect to the LDAP server. Default is 389.",
+ "admin.ldap.baseTitle": "BaseDN:",
+ "admin.ldap.baseDesc": "The Base DN is the Distinguished Name of the location where Mattermost should start its search for users in the LDAP tree.",
+ "admin.ldap.bindUserTitle": "Bind Username:",
+ "admin.ldap.bindUserDesc": "The username used to perform the LDAP search. This should typically be an account created specifically for use with Mattermost. It should have access limited to read the portion of the LDAP tree specified in the BaseDN field.",
+ "admin.ldap.bindPwdTitle": "Bind Password:",
+ "admin.ldap.bindPwdDesc": "Password of the user given in \"Bind Username\".",
+ "admin.ldap.firstnameAttrTitle": "First Name Attrubute",
+ "admin.ldap.firstnameAttrDesc": "The attribute in the LDAP server that will be used to populate the first name of users in Mattermost.",
+ "admin.ldap.lastnameAttrTitle": "Last Name Attribute:",
+ "admin.ldap.lastnameAttrDesc": "The attribute in the LDAP server that will be used to populate the last name of users in Mattermost.",
+ "admin.ldap.emailAttrTitle": "Email Attribute:",
+ "admin.ldap.emailAttrDesc": "The attribute in the LDAP server that will be used to populate the email addresses of users in Mattermost.",
+ "admin.ldap.usernameAttrTitle": "Username Attribute:",
+ "admin.ldap.uernameAttrDesc": "The attribute in the LDAP server that will be used to populate the username field in Mattermost. This may be the same as the ID Attribute.",
+ "admin.ldap.idAttrTitle": "Id Attribute: ",
+ "admin.ldap.idAttrDesc": "The attribute in the LDAP server that will be used as a unique identifier in Mattermost. It should be an LDAP attribute with a value that does not change, such as username or uid. If a user’s Id Attribute changes, it will create a new Mattermost account unassociated with their old one. This is the value used to log in to Mattermost in the \"LDAP Username\" field on the sign in page. Normally this attribute is the same as the “Username Attribute” field above. If your team typically uses domain\\\\username to sign in to other services with LDAP, you may choose to put domain\\\\username in this field to maintain consistency between sites.",
+ "admin.ldap.queryTitle": "Query Timeout (seconds):",
+ "admin.ldap.queryDesc": "The timeout value for queries to the LDAP server. Increase if you are getting timeout errors caused by a slow LDAP server.",
+ "admin.ldap.save": "Save",
+ "admin.support.saving": "Saving Config...",
+ "admin.support.title": "Legal and Support Settings",
+ "admin.support.termsTitle": "Terms of Service link:",
+ "admin.support.termsDesc": "Link to Terms of Service available to users on desktop and on mobile. Leaving this blank will hide the option to display a notice.",
+ "admin.support.privacyTitle": "Privacy Policy link:",
+ "admin.support.privacyDesc": "Link to Privacy Policy available to users on desktop and on mobile. Leaving this blank will hide the option to display a notice.",
+ "admin.support.aboutTitle": "About link:",
+ "admin.support.aboutDesc": "Link to About page for more information on your Mattermost deployment, for example its purpose and audience within your organization. Defaults to Mattermost information page.",
+ "admin.support.helpTitle": "Help link:",
+ "admin.support.helpDesc": "Link to help documentation from team site main menu. Typically not changed unless your organization chooses to create custom documentation.",
+ "admin.support.problemTitle": "Report a Problem link:",
+ "admin.support.problemDesc": "Link to help documentation from team site main menu. By default this points to the peer-to-peer troubleshooting forum where users can search for, find and request help with technical issues.",
+ "admin.support.emailTitle": "Support email:",
+ "admin.support.emailHelp": "Email shown during tutorial for end users to ask support questions.",
+ "admin.support.save": "Save",
+ "admin.license.removing": "Removing License...",
+ "admin.license.uploading": "Uploading License...",
+ "admin.license.enterpriseEdition": "Mattermost Enterprise Edition. Designed for enterprise-scale communication.",
+ "admin.license.entrepriseType": "<div><p>This compiled release of Mattermost platform is provided under a <a href=\"http://mattermost.com\" target=\"_blank\">commercial license</a>\n from Mattermost, Inc. based on your subscription level and is subject to the <a href=\"{terms}\" target=\"_blank\">Terms of Service.</a></p>\n <p>Your subscription details are as follows:</p>\n Name: {name}<br />\n Company or organization name: {company}<br/>\n Number of users: {users}<br/>\n License issued: {issued}<br/>\n Start date of license: {start}<br/>\n Expiry date of license: {expires}<br/>\n LDAP: {ldap}<br/></div>",
+ "admin.license.keyRemove": "Remove Enterprise License and Downgrade Server",
+ "admin.licence.keyMigration": "If you’re migrating servers you may need to remove your license key from this server in order to install it on a new server. To start,\n <a href=\"http://mattermost.com\" target=\"_blank\">disable all Enterprise Edition features on this server</a>.\n This will enable the ability to remove the license key and downgrade this server from Enterprise Edition to Team Edition.",
+ "admin.license.teamEdition": "Mattermost Team Edition. Designed for teams from 5 to 50 users.",
+ "admin.license.teamType": "<span><p>This compiled release of Mattermost platform is offered under an MIT license.</p>\n <p>See MIT-COMPILED-LICENSE.txt in your root install directory for details. See NOTICES.txt for information about open source software used in this system.</p></span>",
+ "admin.license.upload": "Upload",
+ "admin.license.uploadDesc": "Upload a license key for Mattermost Enterprise Edition to upgrade this server. <a href=\"http://mattermost.com\" target=\"_blank\">Visit us online</a>\n to learn more about the benefits of Enterprise Edition or to purchase a key.",
+ "admin.license.title": "Edition and License",
+ "admin.license.edition": "Edition: ",
+ "admin.license.type": "License: ",
+ "admin.license.key": "License Key: ",
+ "admin.log.locationPlaceholder": "Enter your file location",
+ "admin.log.formatPlaceholder": "Enter your file format",
+ "admin.log.saving": "Saving Config...",
+ "admin.log.logSettings": "Log Settings",
+ "admin.log.consoleTitle": "Log To The Console: ",
+ "admin.log.true": "true",
+ "admin.log.false": "false",
+ "admin.log.consoleDescription": "Typically set to false in production. Developers may set this field to true to output log messages to console based on the console level option. If true, server writes messages to the standard output stream (stdout).",
+ "admin.log.levelTitle": "Console Log Level:",
+ "admin.log.levelDescription": "This setting determines the level of detail at which log events are written to the console. ERROR: Outputs only error messages. INFO: Outputs error messages and information around startup and initialization. DEBUG: Prints high detail for developers working on debugging issues.",
+ "admin.log.fileTitle": "Log To File: ",
+ "admin.log.fileDescription": "Typically set to true in production. When true, log files are written to the log file specified in file location field below.",
+ "admin.log.fileLevelTitle": "File Log Level:",
+ "admin.log.fileLevelDescription": "This setting determines the level of detail at which log events are written to the log file. ERROR: Outputs only error messages. INFO: Outputs error messages and information around startup and initialization. DEBUG: Prints high detail for developers working on debugging issues.",
+ "admin.log.locationTitle": "File Location:",
+ "admin.log.locationDescription": "File to which log files are written. If blank, will be set to ./logs/mattermost, which writes logs to mattermost.log. Log rotation is enabled and every 10,000 lines of log information is written to new files stored in the same directory, for example mattermost.2015-09-23.001, mattermost.2015-09-23.002, and so forth.",
+ "admin.log.formatTitle": "File Format:",
+ "admin.log.formatDescription": "Format of log message output. If blank will be set to \"[%D %T] [%L] %M\", where:",
+ "admin.log.formatTime": "Time (15:04:05 MST)",
+ "admin.log.formatDateLong": "Date (2006/01/02)",
+ "admin.log.formatDateShort": "Date (01/02/06)",
+ "admin.log.formatLevel": "Level (DEBG, INFO, EROR)",
+ "admin.log.formatSource": "Source",
+ "admin.log.formatMessage": "Message",
+ "admin.log.save": "Save",
+ "admin.logs.title": "Server Logs",
+ "admin.logs.reload": "Reload",
+ "admin.privacy.saving": "Saving Config...",
+ "admin.privacy.title": "Privacy Settings",
+ "admin.privacy.showEmailTitle": "Show Email Address: ",
+ "admin.privacy.true": "true",
+ "admin.privacy.false": "false",
+ "admin.privacy.showEmailDescription": "When false, hides email address of users from other users in the user interface, including team owners and team administrators. Used when system is set up for managing teams where some users choose to keep their contact information private.",
+ "admin.privacy.showFullNameTitle": "Show Full Name: ",
+ "admin.privacy.showFullNameDescription": "When false, hides full name of users from other users, including team owners and team administrators. Username is shown in place of full name.",
+ "admin.privacy.save": "Save",
+ "admin.rate.queriesExample": "Ex \"10\"",
+ "admin.rate.memoryExample": "Ex \"10000\"",
+ "admin.rate.httpHeaderExample": "Ex \"X-Real-IP\", \"X-Forwarded-For\"",
+ "admin.rate.saving": "Saving Config...",
+ "admin.rate.noteTitle": "Note:",
+ "admin.rate.noteDescription": "Changing properties in this section will require a server restart before taking effect.",
+ "admin.rate.title": "Rate Limit Settings",
+ "admin.rate.enableLimiterTitle": "Enable Rate Limiter: ",
+ "admin.rate.true": "true",
+ "admin.rate.false": "false",
+ "admin.rate.enableLimiterDescription": "When true, APIs are throttled at rates specified below.",
+ "admin.rate.queriesTitle": "Number Of Queries Per Second:",
+ "admin.rate.queriesDescription": "Throttles API at this number of requests per second.",
+ "admin.rate.memoryTitle": "Memory Store Size:",
+ "admin.rate.memoryDescription": "Maximum number of users sessions connected to the system as determined by \"Vary By Remote Address\" and \"Vary By Header\" settings below.",
+ "admin.rate.remoteTitle": "Vary By Remote Address: ",
+ "admin.rate.remoteDescription": "When true, rate limit API access by IP address.",
+ "admin.rate.httpHeaderTitle": "Vary By HTTP Header:",
+ "admin.rate.httpHeaderDescription": "When filled in, vary rate limiting by HTTP header field specified (e.g. when configuring NGINX set to \"X-Real-IP\", when configuring AmazonELB set to \"X-Forwarded-For\").",
+ "admin.rate.save": "Save",
+ "admin.reset_password.submit": "Please enter at least {chars} characters.",
+ "admin.reset_password.title": "Reset Password",
+ "admin.reset_password.newPassword": "New Password",
+ "admin.reset_password.close": "Close",
+ "admin.reset_password.select": "Select",
"admin.select_team.selectTeam": "Select Team",
"admin.select_team.close": "Close",
"admin.select_team.select": "Select",
+ "admin.service.listenExample": "Ex \":8065\"",
+ "admin.service.attemptExample": "Ex \"10\"",
+ "admin.service.segmentExample": "Ex \"g3fgGOXJAQ43QV7rAh6iwQCkV4cA1Gs\"",
+ "admin.service.googleExample": "Ex \"7rAh6iwQCkV4cA1Gsg3fgGOXJAQ43QV\"",
+ "admin.service.sessionDaysEx": "Ex \"30\"",
+ "admin.service.saving": "Saving Config...",
+ "admin.service.title": "Service Settings",
+ "admin.service.listenAddress": "Listen Address:",
+ "admin.service.listenDescription": "The address to which to bind and listen. Entering \":8065\" will bind to all interfaces or you can choose one like \"127.0.0.1:8065\". Changing this will require a server restart before taking effect.",
+ "admin.service.attemptTitle": "Maximum Login Attempts:",
+ "admin.service.attemptDescription": "Login attempts allowed before user is locked out and required to reset password via email.",
+ "admin.service.segmentTitle": "Segment Developer Key:",
+ "admin.service.segmentDescription": "For users running a SaaS services, sign up for a key at Segment.com to track metrics.",
+ "admin.service.googleTitle": "Google Developer Key:",
+ "admin.service.googleDescription": "Set this key to enable embedding of YouTube video previews based on hyperlinks appearing in messages or comments. Instructions to obtain a key available at\n <a href=\"https://www.youtube.com/watch?v=Im69kzhpR3I\" target=\"_blank\">https://www.youtube.com/watch?v=Im69kzhpR3I</a>.\n Leaving the field blank disables the automatic generation of YouTube video previews from links.",
+ "admin.service.webhooksTitle": "Enable Incoming Webhooks: ",
+ "admin.service.true": "true",
+ "admin.service.false": "false",
+ "admin.service.webhooksDescription": "When true, incoming webhooks will be allowed. To help combat phishing attacks, all posts from webhooks will be labelled by a BOT tag.",
+ "admin.service.outWebhooksTitle": "Enable Outgoing Webhooks: ",
+ "admin.service.outWebhooksDesc": "When true, outgoing webhooks will be allowed.",
+ "admin.service.overrideTitle": "Enable Overriding Usernames from Webhooks: ",
+ "admin.service.overrideDescription": "When true, webhooks will be allowed to change the username they are posting as. Note, combined with allowing icon overriding, this could open users up to phishing attacks.",
+ "admin.service.iconTitle": "Enable Overriding Icon from Webhooks: ",
+ "admin.service.iconDescription": "When true, webhooks will be allowed to change the icon they post with. Note, combined with allowing username overriding, this could open users up to phishing attacks.",
+ "admin.service.testingTitle": "Enable Testing: ",
+ "admin.service.testingDescription": "(Developer Option) When true, /loadtest slash command is enabled to load test accounts and test data. Changing this will require a server restart before taking effect.",
+ "admin.service.developerTitle": "Enable Developer Mode: ",
+ "admin.service.developerDesc": "(Developer Option) When true, extra information around errors will be displayed in the UI.",
+ "admin.service.securityTitle": "Enable Security Alerts: ",
+ "admin.service.securityDesc": "When true, System Administrators are notified by email if a relevant security fix alert has been announced in the last 12 hours. Requires email to be enabled.",
+ "admin.service.webSessionDays": "Session Length for Web in Days:",
+ "admin.service.webSessionDaysDesc": "The web session will expire after the number of days specified and will require a user to login again.",
+ "admin.service.mobileSessionDays": "Session Length for Mobile Device in Days:",
+ "admin.service.mobileSessionDaysDesc": "The native mobile session will expire after the number of days specified and will require a user to login again.",
+ "admin.service.ssoSessionDays": "Session Length for SSO in Days:",
+ "admin.service.ssoSessionDaysDesc": "The SSO session will expire after the number of days specified and will require a user to login again.",
+ "admin.service.sessionCache": "Session Cache in Minutes:",
+ "admin.service.sessionCacheDesc": "The number of minutes to cache a session in memory.",
+ "admin.service.save": "Save",
+ "admin.sql.warning": "Warning: re-generating this salt may cause some columns in the database to return empty results.",
+ "admin.sql.maxConnectionsExample": "Ex \"10\"",
+ "admin.sql.maxOpenExample": "Ex \"10\"",
+ "admin.sql.keyExample": "Ex \"gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6\"",
+ "admin.sql.saving": "Saving Config...",
+ "admin.sql.noteTitle": "Note:",
+ "admin.sql.noteDescription": "Changing properties in this section will require a server restart before taking effect.",
+ "admin.sql.title": "SQL Settings",
+ "admin.sql.driverName": "Driver Name:",
+ "admin.sql.dataSource": "Data Source:",
+ "admin.sql.replicas": "Data Source Replicas:",
+ "admin.sql.maxConnectionsTitle": "Maximum Idle Connections:",
+ "admin.sql.maxConnectionsDescription": "Maximum number of idle connections held open to the database.",
+ "admin.sql.maxOpenTitle": "Maximum Open Connections:",
+ "admin.sql.maxOpenDescription": "Maximum number of open connections held open to the database.",
+ "admin.sql.keyTitle": "At Rest Encrypt Key:",
+ "admin.sql.keyDescription": "32-character salt available to encrypt and decrypt sensitive fields in database.",
+ "admin.sql.regenerate": "Re-Generate",
+ "admin.sql.traceTitle": "Trace: ",
+ "admin.sql.true": "true",
+ "admin.sql.false": "false",
+ "admin.sql.traceDescription": "(Development Mode) When true, executing SQL statements are written to the log.",
+ "admin.sql.save": "Save",
+ "admin.system_analytics.totalPosts": "Total Posts",
+ "admin.system_analytics.activeUsers": "Active Users With Posts",
+ "admin.system_analytics.title": "the System",
+ "admin.team_analytics.totalPosts": "Total Posts",
+ "admin.team_analytics.activeUsers": "Active Users With Posts",
+ "admin.team.siteNameExample": "Ex \"Mattermost\"",
+ "admin.team.maxUsersExample": "Ex \"25\"",
+ "admin.team.restrictExample": "Ex \"corp.mattermost.com, mattermost.org\"",
+ "admin.team.saving": "Saving Config...",
+ "admin.team.title": "Team Settings",
+ "admin.team.siteNameTitle": "Site Name:",
+ "admin.team.siteNameDescription": "Name of service shown in login screens and UI.",
+ "admin.team.maxUsersTitle": "Max Users Per Team:",
+ "admin.team.maxUsersDescription": "Maximum total number of users per team, including both active and inactive users.",
+ "admin.team.teamCreationTitle": "Enable Team Creation: ",
+ "admin.team.true": "true",
+ "admin.team.false": "false",
+ "admin.team.teamCreationDescription": "When false, the ability to create teams is disabled. The create team button displays error when pressed.",
+ "admin.team.userCreationTitle": "Enable User Creation: ",
+ "admin.team.userCreationDescription": "When false, the ability to create accounts is disabled. The create account button displays error when pressed.",
+ "admin.team.restrictTitle": "Restrict Creation To Domains:",
+ "admin.team.restrictDescription": "Teams and user accounts can only be created from a specific domain (e.g. \"mattermost.org\") or list of comma-separated domains (e.g. \"corp.mattermost.com, mattermost.org\").",
+ "admin.team.restrictNameTitle": "Restrict Team Names: ",
+ "admin.team.restrictNameDesc": "When true, You cannot create a team name with reserved words like www, admin, support, test, channel, etc",
+ "admin.team.dirTitle": "Enable Team Directory: ",
+ "admin.team.dirDesc": "When true, teams that are configured to show in team directory will show on main page inplace of creating a new team.",
+ "admin.team.save": "Save",
+ "admin.userList.title": "Users for {team}",
+ "admin.userList.title2": "Users for {team} ({count})",
+ "admin.user_item.member": "Member",
+ "admin.user_item.sysAdmin": "System Admin",
+ "admin.user_item.teamAdmin": "Team Admin",
+ "admin.user_item.inactive": "Inactive",
+ "admin.user_item.makeSysAdmin": "Make System Admin",
+ "admin.user_item.makeTeamAdmin": "Make Team Admin",
+ "admin.user_item.makeMember": "Make Member",
+ "admin.user_item.makeActive": "Make Active",
+ "admin.user_item.makeInactive": "Make Inactive",
+ "admin.user_item.resetPwd": "Reset Password",
+ "claim.account.noEmail": "No email specified",
+ "claim.email_to_sso.pwdError": "Please enter your password.",
+ "claim.email_to_sso.pwd": "Password",
+ "claim.email_to_sso.title": "Switch Email/Password Account to {uiType}",
+ "claim.email_to_sso.ssoType": "Upon claiming your account, you will only be able to login with {type} SSO",
+ "claim.email_to_sso.enterPwd": "Enter the password for your {team} {site} account",
+ "claim.email_to_sso.switchTo": "Switch account to {uiType}",
+ "claim.sso_to_email.enterPwd": "Please enter a password.",
+ "claim.sso_to_email.pwdNotMatch": "Password do not match.",
+ "claim.sso_to_email.newPwd": "New Password",
+ "claim.sso_to_email.confirm": "Confirm Password",
+ "claim.sso_to_email.title": "Switch {type} Account to Email",
+ "claim.sso_to_email.description": "Upon changing your account type, you will only be able to login with your email and password.",
+ "claim.sso_to_email_newPwd": "Enter a new password for your {team} {site} account",
+ "claim.sso_to_email.switchTo": "Switch {type} to email and password",
"error_bar.preview_mode": "Preview Mode: Email notifications have not been configured",
- "loading_screen.loading": "Loading"
+ "loading_screen.loading": "Loading",
+ "suggestion.mention.all": "Notifies everyone in the team",
+ "suggestion.mention.channel": "Notifies everyone in the channel",
+ "suggestion.search.public": "Public Channels",
+ "suggestion.search.private": "Private Groups",
+ "tutorial_intro.screenOne": "<h3>Welcome to:</h3>\n <h1>Mattermost</h1>\n <p>Your team communication all in one place, instantly searchable and available anywhere</p>\n <p>Keep your team connected to help them achieve what matters most.</p>",
+ "tutorial_intro.screenTwo": "<h3>How Mattermost works:</h3>\n <p>Communication happens in public discussion channels, private groups and direct messages.</p>\n <p>Everything is archived and searchable from any web-enabled desktop, laptop or phone.</p>",
+ "tutorial_intro.invite": "Invite teammates",
+ "tutorial_intro.teamInvite": "Team Invite",
+ "tutorial_intro.support": "Need anything, just email us at ",
+ "tutorial_intro.allSet": "You’re all set",
+ "tutorial_intro.whenReady": " when you’re ready.",
+ "tutorial_intro.end": "Click “Next” to enter Town Square. This is the first channel teammates see when they sign up. Use it for posting updates everyone needs to know.",
+ "tutorial_intro.next": "Next",
+ "tutorial_intro.skip": "Skip tutorial",
+ "tutorial_tip.ok": "Okay",
+ "tutorial_tip.next": "Next",
+ "tutorial_tip.seen": "Seen this before? ",
+ "tutorial_tip.out": "Opt out of these tips."
} \ No newline at end of file
diff --git a/web/static/i18n/es.json b/web/static/i18n/es.json
index bc53a78b0..12f9b5fc5 100644
--- a/web/static/i18n/es.json
+++ b/web/static/i18n/es.json
@@ -1,4 +1,14 @@
{
+ "admin.analytics.activeUsers": "Usuarios Activos con Mensajes",
+ "admin.analytics.loading": "Cargando...",
+ "admin.analytics.meaningful": "No hay suficiente data para tener una representación significativa.",
+ "admin.analytics.newlyCreated": "Nuevos Usuarios Creados",
+ "admin.analytics.privateGroups": "Grupos Privados",
+ "admin.analytics.publicChannels": "Canales Públicos",
+ "admin.analytics.recentActive": "Usuarios Recientemente Activos",
+ "admin.analytics.title": "Estadísticas para {title}",
+ "admin.analytics.totalPosts": "Total de Mensajes",
+ "admin.analytics.totalUsers": "Total de Usuarios",
"admin.email.allowSignupDescription": "Cuando está en verdadero, Mattermost permite la creación de equipos y cuentas utilizando el correo electrónico y contraseña. Este valor debe estar en falso sólo cuando quieres limitar el inicio de sesión a través de servicios tipo OAuth o LDAP.",
"admin.email.allowSignupTitle": "Permitir inicio de sesión con correo:",
"admin.email.connectionSecurityNone": "Ninguno",
@@ -51,13 +61,240 @@
"admin.email.smtpUsernameTitle": "Usuario SMTP:",
"admin.email.testing": "Probando...",
"admin.email.true": "verdadero",
+ "admin.gitab.clientSecretDescription": "Utilizar este valor vía instrucciones suministradas anteriormente para iniciar sesión en GitLab.",
+ "admin.gitlab.EnableHtmlDesc": "<ol><li>Inicia sesión con tu cuenta en GitLab y dirigete a Applications -> Profile Settings.</li><li>Ingresa los URIs \"<tu-mattermost-url>/login/gitlab/complete\" (ejemplo: http://localhost:8065/login/gitlab/complete) y \"<tu-mattermost-url>/signup/gitlab/complete\". </li><li>Luego utiliza los valores de los campos \"Secret\" e \"Id\" de GitLab y completa las opciones que abajo se presentan.</li><li>Completa las dirección URLs abajo. </li></ol>",
+ "admin.gitlab.authDescription": "Ingresar <your-gitlab-url>/oauth/authorize (example http://localhost:3000/oauth/authorize). Asegurate que si utilizas HTTPS o HTTPS tus URLS sean correctas",
+ "admin.gitlab.authExample": "Ej \"\"",
+ "admin.gitlab.authTitle": "URL para autentificación:",
+ "admin.gitlab.clientIdDescription": "Utilizar este valor vía instrucciones suministradas anteriormente para iniciar sesión en GitLab.",
+ "admin.gitlab.clientIdExample": "Ej \"jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY\"",
+ "admin.gitlab.clientIdTitle": "Id:",
+ "admin.gitlab.clientSecretExample": "Ej \"jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY\"",
+ "admin.gitlab.clientSecretTitle": "Secreto:",
+ "admin.gitlab.enableDescription": "Cuando está asignado como verdadero, Mattermost permite la creación de equipos y cuentas utilizando el servicio de OAuth de GitLab. Para configurarlo, inicia sesión en GitLab con tu cuenta y dirigete a Applications -> Profile Settings. Ingresa los URIs de redireccionamiento \"<tu-mattermost-url>/login/gitlab/complete\" (ejemplo: http://localhost:8065/login/gitlab/complete) y \"<tu-mattermost-url>/signup/gitlab/complete\". Luego utiliza los campos de \"Secret\" y \"Id\" para completar las opciones de abajo.",
+ "admin.gitlab.enableTitle": "Enable Sign Up With GitLab: ",
+ "admin.gitlab.false": "falso",
+ "admin.gitlab.save": "Guardar",
+ "admin.gitlab.saving": "Guardando...",
+ "admin.gitlab.settingsTitle": "Configuración de GitLab",
+ "admin.gitlab.tokenDescription": "Ingresar <your-gitlab-url>/oauth/token. Asegurate que si utilizas HTTPS o HTTPS tus URLS sean correctas",
+ "admin.gitlab.tokenExample": "Ej \"\"",
+ "admin.gitlab.tokenTitle": "Url para obteción de Token:",
+ "admin.gitlab.true": "verdadero",
+ "admin.gitlab.userDescription": "Ingresar <tu-gitlab-url>/api/v3/user. Asegurate que si utilizas HTTPS o HTTPS tus URLS sean correctas",
+ "admin.gitlab.userExample": "Ej \"\"",
+ "admin.gitlab.userTitle": "URL para obtener datos de usuario:",
+ "admin.image.amazonS3BucketDescription": "Nombre que ha seleccionado para el bucket S3 en AWS.",
+ "admin.image.amazonS3BucketExample": "Ex \"mattermost-media\"",
+ "admin.image.amazonS3BucketTitle": "Amazon S3 Bucket:",
+ "admin.image.amazonS3IdDescription": "Obetener esta credencial del administrador de tu Amazon EC2",
+ "admin.image.amazonS3IdExample": "Ej \"AKIADTOVBGERKLCBV\"",
+ "admin.image.amazonS3IdTitle": "Llave de acceso Amazon S3:",
+ "admin.image.amazonS3RegionDescription": "Región que ha seleccionado en AWS para la creación de tu bucket S3.",
+ "admin.image.amazonS3RegionExample": "Ej \"us-east-1\"",
+ "admin.image.amazonS3RegionTitle": "Región de Amazon S3:",
+ "admin.image.amazonS3SecretDescription": "Obetener esta credencial del administrador de tu Amazon EC2.",
+ "admin.image.amazonS3SecretExample": "Ej \"jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY\"",
+ "admin.image.amazonS3SecretTitle": "Llave secreta de Amazon S3:",
+ "admin.image.false": "falso",
+ "admin.image.fileSettings": "Configuración de archivos",
+ "admin.image.localDescription": "Directorio al que se esriben los archivos de imágen. Si es vacio, se establecerá en ./data/.",
+ "admin.image.localExample": "Ej \"./dato/\"",
+ "admin.image.localTitle": "Directorio local de ubicación:",
+ "admin.image.previewHeightDescription": "Altura máxima para la vista previa de la imágen (\"0\": Establecer a tamaño-automático). Actualizando este valor los cambios de vista previa se hacen en el futuro, pero no cambia para imagenes creadas en el pasado.",
+ "admin.image.previewHeightExample": "Ej \"0\"",
+ "admin.image.previewHeightTitle": "Previsualzar alto:",
+ "admin.image.previewWidthDescription": "Ancho máximo para la vista previa de la imágen. Actualizando este valor los cambios de vista previa se hacen en el futuro, pero no cambia para imagenes creadas en el pasado.",
+ "admin.image.previewWidthExample": "Ej \"1024\"",
+ "admin.image.previewWidthTitle": "Previsualizar ancho:",
+ "admin.image.profileHeightDescription": "Alto de imagen de perfil.",
+ "admin.image.profileHeightExample": "Ej \"0\"",
+ "admin.image.profileHeightTitle": "Alto de perfil:",
+ "admin.image.profileWidthDescription": "Ancho de la imagen de perfil.",
+ "admin.image.profileWidthExample": "Ej \"1024\"",
+ "admin.image.profileWidthTitle": "Ancho de perfil:",
+ "admin.image.publicLinkDescription": "Salt de 32-characteres agregado para firmar los enlaces para las imagenes públicas. Aleatoriamente generados en la instalación. Pincha \"Regenerar\" para crear un nuevo salt.",
+ "admin.image.publicLinkExample": "Ej \"gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6\"",
+ "admin.image.publicLinkTitle": "Título del enlace público:",
+ "admin.image.regenerate": "Regenerar",
+ "admin.image.save": "Guardar",
+ "admin.image.saving": "Guardando...",
+ "admin.image.shareDescription": "Permitir a los usuarios compartir enlaces públicos para archivos e imágenes.",
+ "admin.image.shareTitle": "Compartir publicamente enlaces de archivos: ",
+ "admin.image.storeAmazonS3": "Amazon S3",
+ "admin.image.storeDisabled": "Deshabilitar almacenamiento de archivos",
+ "admin.image.storeLocal": "Sistema local de archivos",
+ "admin.image.storeTitle": "Almacenar archivos en:",
+ "admin.image.thumbHeightDescription": "Alto de imágen miniatura subida. Actualizando este valor la imagen miniatura cambia en el futuro, pero no cambia para imagenes creadas en el pasado.",
+ "admin.image.thumbHeightExample": "Ej \"100\"",
+ "admin.image.thumbHeightTitle": "Alto de imágen miniatura:",
+ "admin.image.thumbWidthDescription": "Ancho de imágen miniatura subida. Actualizando este valor la imagen miniatura cambia en el futuro, pero no cambia para imagenes creadas en el pasado.",
+ "admin.image.thumbWidthExample": "Ej \"120\"",
+ "admin.image.thumbWidthTitle": "Ancho de imágen miniatura:",
+ "admin.image.true": "verdadero",
+ "admin.ldap.bannerDesc": "Si el atributo de un usuario cambia en el servidor LDAP será actualizado la próxima vez que el usuario ingrese sus credenciales para iniciar sesión en Mattermost. Esto incluye si un usuario se inactiva o se remueve en el servidor LDAP. Sincronización con servidores LDAP está planificado para futuras versiones.",
+ "admin.ldap.bannerHeading": "Nota:",
+ "admin.ldap.baseDesc": "El DN Base es el Nombre Distinguido de la ubicación donde Mattermost debe comenzar a buscar a los usuarios en el árbol del LDAP.",
+ "admin.ldap.baseEx": "Ex \"dc=midominio,dc=com\"",
+ "admin.ldap.baseTitle": "DN Base:",
+ "admin.ldap.bindPwdDesc": "Contraseña del usuario asignado en \"Usuario de Enlace\".",
+ "admin.ldap.bindPwdTitle": "Contraseña de Enlace:",
+ "admin.ldap.bindUserDesc": "El usuario que realizará las busquedas LDAP. Normalmente este debería ser una cuenta específicamente creada para ser utilizada por Mattermost. Debería contat con acceso limitado para leer la porción del árbol LDAP especificada en el campo DN Base.",
+ "admin.ldap.bindUserTitle": "Usuario de Enlace:",
+ "admin.ldap.emailAttrDesc": "El atributo en el servidor LDAP que será utilizado para poblar la dirección de correo electrónico de los usuarios en Mattermost.",
+ "admin.ldap.emailAttrEx": "Ej \"mail\"",
+ "admin.ldap.emailAttrTitle": "Atributo de Correo Electrónico:",
+ "admin.ldap.enableDesc": "Cuando es verdadero, Mattermost permite realizar inicio de sesión utilizando LDAP",
+ "admin.ldap.enableTitle": "Habilitar inicio de sesión con LDAP:",
+ "admin.ldap.false": "falso",
+ "admin.ldap.firstnameAttrDesc": "El atributo en el servidor LDAP que será utilizado para poblar el nombre de los usuarios en Mattermost.",
+ "admin.ldap.firstnameAttrEx": "Ej \"givenName\"",
+ "admin.ldap.firstnameAttrTitle": "Atributo del Nombre",
+ "admin.ldap.idAttrDesc": "El atributo en el servidor LDAP que será utilizado para poblar el identificador único en Mattermost. Debe ser un atributo de LDAP que no cambie con el tiempo, como el nombre de usuario o el uid. Si el atributo del identificador cambia, se creará una nueva cuenta en Mattermost que no está asociada a la anterior. Este valor es utilizada para iniciar sesión en Mattermost en el campo \"Usuario LDAP\" en la página de inicio de sesión. Normalmente este atributo es el mismo que el campo “Atributo Usuario”. Si el equipo normalmente utiliza dominio\\\\usuario para iniciar sesión en otros servicios con LDAP, puedes elegir llenar este campo como dominio\\\\usuario para mantener consistencia entre los servicios.",
+ "admin.ldap.idAttrEx": "Ej \"sAMAccountName\"",
+ "admin.ldap.idAttrTitle": "Atributo Id: ",
+ "admin.ldap.lastnameAttrDesc": "El atributo en el servidor LDAP que será utilizado para poblar el apellido de los usuarios en Mattermost.",
+ "admin.ldap.lastnameAttrEx": "Ej \"sn\"",
+ "admin.ldap.lastnameAttrTitle": "Atributo Apellido:",
+ "admin.ldap.noLicense": "<h4 className=\"banner__heading\">Nota:</h4><p>LDAP es una característica de la edición enterprise. Tu licencia actual no soporta LDAP. Pincha <a href=\"http://mattermost.com\"target=\"_blank\">aquí</a> para información y precios de las licencias enterprise.</p>",
+ "admin.ldap.portDesc": "El puerto que Mattermost utilizará para conectarse al servidor LDAP. El predeterminado es 389.",
+ "admin.ldap.portEx": "Ej \"389\"",
+ "admin.ldap.portTitle": "Puerto LDAP:",
+ "admin.ldap.queryDesc": "El tiempo de espera para las consultas en el servidor LDAP. Aumenta este valor si estás obteniendo errores por falta de tiempo debido a un servidor de LDAP lento.",
+ "admin.ldap.queryEx": "Ej \"60\"",
+ "admin.ldap.queryTitle": "Tiempo de espera para las Consultas (segundos):",
+ "admin.ldap.save": "Guardar",
+ "admin.ldap.saving": "Guardando...",
+ "admin.ldap.serverDesc": "El dominio o dirección IP del servidor LDAP.",
+ "admin.ldap.serverEx": "Ej \"10.0.0.23\"",
+ "admin.ldap.serverTitle": "Servidor LDAP:",
+ "admin.ldap.title": "Configuración de LDAP",
+ "admin.ldap.true": "verdadero",
+ "admin.ldap.uernameAttrDesc": "El atributo en el servidor LDAP que se utilizará para poblar el nombre de usuario en Mattermost. Este puede ser igual al Attributo Id.",
+ "admin.ldap.usernameAttrEx": "Ej \"sAMAccountName\"",
+ "admin.ldap.usernameAttrTitle": "Atributo Usuario:",
+ "admin.licence.keyMigration": "Si estás migrando servidores es posible que necesites remover tu licencia de este servidor para poder instalarlo en un servidor nuevo. Para empezar,\n <a href=\"http://mattermost.com\" target=\"_blank\">deshabilita todas las características de la Edición Enterprise de este servidor</a>.\n Esta operación habilitará la opción para remover la licencia y degradar este servidor de la Edición Enterprise a la Edición Team.",
+ "admin.license.edition": "Edición: ",
+ "admin.license.enterpriseEdition": "Mattermost Edición Enterprise. Diseñada para comunicación de escala empresarial.",
+ "admin.license.entrepriseType": "<div><p>Esta versión compilada de la plataforma de Mattermost es proporcionada bajo una <a href=\"http://mattermost.com\" target=\"_blank\">licencia comercial</a>\n de Mattermost, Inc. basado en tu nivel de subscripción y sujeto a los <a href=\"{terms}\" target=\"_blank\">Términos del Servicio.</a></p>\n <p>Los detalles de tu subscripción son los siguientes:</p>\n Nombre: {name}<br />\n Nombre de compañia u organización: {company}<br/>\n Cantidad de usuarios: {users}<br/>\n Licencia emitida por: {issued}<br/>\n Inicio de la licencia: {start}<br/>\n Fecha de expiración: {expires}<br/>\n LDAP: {ldap}<br/></div>",
+ "admin.license.key": "Llave de la Licencia: ",
+ "admin.license.keyRemove": "Remover la Licencia Enterprise y Degradar el Servidor",
+ "admin.license.removing": "Removiendo Licencia...",
+ "admin.license.teamEdition": "Mattermost Edición Team. Diseñado para equipos desde 5 hasta 50 usuarios.",
+ "admin.license.teamType": "<span><p>Esta versión compilada de la plataforma de Mattermost es proporcionada bajo la licencia MIT.</p>\n <p>Lea MIT-COMPILED-LICENSE.txt en el directorio raíz de la instalación para más detalles. Lea NOTICES.txt para información sobre software libre utilizado en este sistema.</p></span>",
+ "admin.license.title": "Edición y Licencia",
+ "admin.license.type": "Licencia: ",
+ "admin.license.upload": "Subir",
+ "admin.license.uploadDesc": "Subir una llave de licencia de Mattermost Edición Enterprise para mejorar este servidor. <a href=\"http://mattermost.com\" target=\"_blank\">Visitanos en línea</a>\n para conocer más acerca de los beneficios de la Edición Enterprise or para comprar una licencia.",
+ "admin.license.uploading": "Subiendo Licencia...",
+ "admin.log.consoleDescription": "Normalmente asignado en falso en producción. Los desarolladores pueden configurar este campo en verdadero para ver de mensajes de consola basado en las opciones de nivel configuradas. Si es verdadera, el servidor escribirá los mensajes en una salida estandar (stdout).",
+ "admin.log.consoleTitle": "Mostrar registros en la consola: ",
+ "admin.log.false": "falso",
+ "admin.log.fileDescription": "Normalmente asignado en verdadero en producción. Cueando es verdadero, los archivos de registro son escritos en la ubicación especificada a continuación.",
+ "admin.log.fileLevelDescription": "Esta configuración determina el nivel de detalle con el cual los eventos serán escritos en el archivo de registro. ERROR: Sólo salida de mensajes de error. INFO: Salida de mensaje de error y información acerca de la partida e inicialización. DEBUG: Muestra un alto detalle para que los desarolladores que trabajan con eventos de depuración.",
+ "admin.log.fileLevelTitle": "Nivel registro:",
+ "admin.log.fileTitle": "Archivos de registro: ",
+ "admin.log.formatDateLong": "Fecha (2006/01/02)",
+ "admin.log.formatDateShort": "Fecha (01/02/06)",
+ "admin.log.formatDescription": "Formato del mensaje de registro de salida. Si es blanco se establecerá en \"[%D %T] [%L] %M\", donde:",
+ "admin.log.formatLevel": "Nivel (DEBG, INFO, EROR)",
+ "admin.log.formatMessage": "Mensaje",
+ "admin.log.formatPlaceholder": "Ingresar tu formato de archivo",
+ "admin.log.formatSource": "Fuente",
+ "admin.log.formatTime": "Hora (15:04:05 MST)",
+ "admin.log.formatTitle": "Formato de archivo:",
+ "admin.log.levelDescription": "Esta configuración determina el nivel de detalle con el cual los eventos serán escritos en la consola. ERROR: Sólo salida de mensajes de error. INFO: Salida de mensaje de error y información acerca de la partida e inicialización. DEBUG: Muestra un alto detalle para que los desarolladores que trabajan con eventos de depuración.",
+ "admin.log.levelTitle": "Nivel de log de consola:",
+ "admin.log.locationDescription": "Archivo en el cual se escribirán los registros. Si lo dejas en blanco, será asignado de forma predeterminada ./logs/mattermost, lo que escribirá los registros a mattermost.log. La rotación de los registros está habilitada y cada 10,000 lineas de registro se escriben en un nuevo archivo almacenado en el mismo directorio, por ejemplo mattermost.2015-09-23.001, mattermost.2015-09-23.002, y así sucesivamente.",
+ "admin.log.locationPlaceholder": "Ingresar locación de archivo",
+ "admin.log.locationTitle": "Ubicación de archivo:",
+ "admin.log.logSettings": "Configuración de registro",
+ "admin.log.save": "Guardar",
+ "admin.log.saving": "Guardando...",
+ "admin.log.true": "verdadero",
+ "admin.logs.reload": "Recargar",
+ "admin.logs.title": "Servidor de registros",
"admin.nav.help": "Ayuda",
"admin.nav.logout": "Cerrar sesión",
"admin.nav.report": "Reportar problema",
"admin.nav.switch": "Cambiar a {display_name}",
+ "admin.privacy.false": "falso",
+ "admin.privacy.save": "Guardar",
+ "admin.privacy.saving": "Guardando...",
+ "admin.privacy.showEmailDescription": "Cuando es falso, oculta la dirección de correo para otros usuarios en la interfaz de usuario, incluyendo a los dueños y administradores del grupo. Usado cuando el sistema es configurado para administrar grupos y donde algunos usuarios escogen mantener su información de contacto como privada.",
+ "admin.privacy.showEmailTitle": "Mostrar dirección de correo electrónico: ",
+ "admin.privacy.showFullNameDescription": "Cuando está asignado en falso, esconde el nombre completo de los usuarios para otros usuarios, incluyendo dueños de equipos y administradores de equipos. El nombre de usuario es mostrado en vez del nombre completo.",
+ "admin.privacy.showFullNameTitle": "Mostrar nombre completo: ",
+ "admin.privacy.title": "Configuraciones de privacidad",
+ "admin.privacy.true": "verdadero",
+ "admin.rate.enableLimiterDescription": "Cuando es verdadero, La APIs son reguladas a tasas especificadas a continuación.",
+ "admin.rate.enableLimiterTitle": "Habilitar el limitador de velocidad: ",
+ "admin.rate.false": "falso",
+ "admin.rate.httpHeaderDescription": "Al llenar este campo, se limita la velocidad según el encabezado HTTP especificado (e.j. cuando se configura con NGINX asigna \"X-Real-IP\", cuando se configura con AmazonELB asigna \"X-Forwarded-For\").",
+ "admin.rate.httpHeaderExample": "Ej \"X-Real-IP\", \"X-Forwarded-For\"",
+ "admin.rate.httpHeaderTitle": "Variar para encabezado HTTP:",
+ "admin.rate.memoryDescription": "Número máximo de sesiones de usuarios conectados en el sistema es determinado por \"Variar para dirección remota\" y \"Variar para encabezado HTTP\" en la configuración siguiente.",
+ "admin.rate.memoryExample": "Ej \"10000\"",
+ "admin.rate.memoryTitle": "Tamaño de memoria de almacenamiento:",
+ "admin.rate.noteDescription": "Cambiando propiedades en esta sección el servidor necesitará reiniciar antes de que los cambios tomen efecto.",
+ "admin.rate.noteTitle": "Nota:",
+ "admin.rate.queriesDescription": "Regulador de solicitudes API por sgundos.",
+ "admin.rate.queriesExample": "Ej \"10\"",
+ "admin.rate.queriesTitle": "Número de consultas por minuto:",
+ "admin.rate.remoteDescription": "Cuando es verdadero, límite de velocidad para el accedo a la API desde dirección IP.",
+ "admin.rate.remoteTitle": "Variar por direcciones remotas: ",
+ "admin.rate.save": "Guardar",
+ "admin.rate.saving": "Guardando...",
+ "admin.rate.title": "Configuración de velocidad",
+ "admin.rate.true": "verdadero",
+ "admin.reset_password.close": "Cerrar",
+ "admin.reset_password.newPassword": "Nueva contraseña",
+ "admin.reset_password.select": "Seleccionar",
+ "admin.reset_password.submit": "Por favor, introducir como mínimo 5 caracteres.",
+ "admin.reset_password.title": "Reiniciar Contraseña",
"admin.select_team.close": "Cerrar",
"admin.select_team.select": "Seleccionar",
"admin.select_team.selectTeam": "Seleccionar grupo",
+ "admin.service.attemptDescription": "Inicio de sesión permitidos antes que el usuario sea bloqueado y se requiera volver a configurar la contraseña vía correo electrónico.",
+ "admin.service.attemptExample": "Ej \"10\"",
+ "admin.service.attemptTitle": "Máximo de intentos de conexión:",
+ "admin.service.developerDesc": "(Opción de Desarrollador) Cuando está asignado en verdadero, información extra sobre errores se muestra en el UI.",
+ "admin.service.developerTitle": "Habilitar modo de Desarrollador: ",
+ "admin.service.false": "falso",
+ "admin.service.googleDescription": "Asigna una llave a este campo para habilitar la previsualización de videos de YouTube tomados de los enlaces que aparecen en los mensajes o comentarios. Las instrucciones de como obtener una llave está disponible en <a href=\"https://www.youtube.com/watch?v=Im69kzhpR3I\" target=\"_blank\">https://www.youtube.com/watch?v=Im69kzhpR3I</a>. Al dejar este campo en blanco deshabilita la generación de previsualizaciones de videos de YouTube desde los enlaces.",
+ "admin.service.googleExample": "Ej \"7rAh6iwQCkV4cA1Gsg3fgGOXJAQ43QV\"",
+ "admin.service.googleTitle": "Llave de desarrolador Google:",
+ "admin.service.iconDescription": "Cuando es verdadero, se le permitirá cambiar el icono del mensaje desde webhooks. Nota, en combinación con permitir el cambio de nombre de usuario, podría exponer a los usuarios a sufrir ataques de phishing.",
+ "admin.service.iconTitle": "Habilitar el cambio de icono desde los Webhooks: ",
+ "admin.service.listenAddress": "Dirección de escucha:",
+ "admin.service.listenDescription": "La dirección a la que se unirá y escuchará. Ingresar \":8065\" se podrá unir a todas las interfaces o podrá seleccionar una como ej: \"127.0.0.1:8065\". Cambiando este valor es necesario reiniciar el servidor.",
+ "admin.service.listenExample": "Ej \":8065\"",
+ "admin.service.mobileSessionDays": "Duración de la Sesión en Días para Dispositivos Moviles:",
+ "admin.service.mobileSessionDaysDesc": "La sesión nativa de los dispositivos moviles expirará luego de transcurrido el numero de días especificado y se solicitará al usuario que inicie sesión nuevamente.",
+ "admin.service.outWebhooksDesc": "Cuando es verdadero, los webhooks de salida serán permitidos.",
+ "admin.service.outWebhooksTitle": "Habilitar Webhooks de Salida: ",
+ "admin.service.overrideDescription": "Cuando es verdadero, se le permitirá cambiar el nombre de usuario desde webhooks. Nota, en conjunto con cambio de icono, podría exponer a los usuarios a sufrir ataques de phishing.",
+ "admin.service.overrideTitle": "Habilitar el cambio de nombres de usuario desde los Webhooks: ",
+ "admin.service.save": "Guardar",
+ "admin.service.saving": "Guardando....",
+ "admin.service.securityDesc": "Cuando es verdadero, Los Administradores del Sistema serán notificados por correo electrónico se han anunciado alertas de seguridad relevantes en las últimas 12 horas. Requiere que los correos estén habilitados.",
+ "admin.service.securityTitle": "Habilitar Alertas de Seguridad: ",
+ "admin.service.segmentDescription": "Para usuarios que corren en servicios SaaS, registarse en Segment.com para obtener su llave.",
+ "admin.service.segmentExample": "Ej \"g3fgGOXJAQ43QV7rAh6iwQCkV4cA1Gs\"",
+ "admin.service.segmentTitle": "Llave de segmento para desarollador:",
+ "admin.service.sessionCache": "Duración del Cache de la Sesión en Minutos:",
+ "admin.service.sessionCacheDesc": "La cantidad de minutes que el cache de la sesión se guardará en memoria.",
+ "admin.service.sessionDaysEx": "Ej \"30\"",
+ "admin.service.ssoSessionDays": "Duración de la Sesión en Días para SSO:",
+ "admin.service.ssoSessionDaysDesc": "Las sesión expirará lugo de transcurrido el numero de días especificado y se solicitará al usuario que inicie sesión nuevamente.",
+ "admin.service.testingDescription": "(Opción de desarollo) Cuando es verdadero, /pruebadecarga el comando slash es habilitado para cargar el nombre de la cuenta y probar la data. Cambiando esto será necesario reiniciar el servidor para que haga efecto.",
+ "admin.service.testingTitle": "Habilitar Pruebas: ",
+ "admin.service.title": "Configuracion de servicios",
+ "admin.service.true": "verdadero",
+ "admin.service.webSessionDays": "Duración de la Sesión en Días para Web:",
+ "admin.service.webSessionDaysDesc": "La sesión web expirará luego de transcurrido el número de días especificado y se solicitará al usuaio que inicie sesión nuevamente.",
+ "admin.service.webhooksDescription": "Cuando es verdadero, la entradas de webhooks será permitida. Para ayudar a combatir ataques phishing, todos los comentarios de webhooks serán marcados con una etiqueta BOT.",
+ "admin.service.webhooksTitle": "Habilitar Webhooks de Entrada: ",
"admin.sidebar.addTeamSidebar": "Agregar un equipo el menú lateral",
"admin.sidebar.email": "Configuración de correo",
"admin.sidebar.file": "Configuracion de archivos",
@@ -82,6 +319,116 @@
"admin.sidebar.users": "- Usuarios",
"admin.sidebar.view_statistics": "Ver Estadísticas",
"admin.sidebarHeader.systemConsole": "Consola de sistema",
+ "admin.sql.dataSource": "Origen de datos:",
+ "admin.sql.driverName": "Nombre de controlador:",
+ "admin.sql.false": "falso",
+ "admin.sql.keyDescription": "32-caracter disponible para encriptar y desincriptar campos sencible de la base de datos.",
+ "admin.sql.keyExample": "Ej \"gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6\"",
+ "admin.sql.keyTitle": "At Rest Encrypt Key:",
+ "admin.sql.maxConnectionsDescription": "Número máximo de conecciones inactivas que mantiene abierta la base de datos.",
+ "admin.sql.maxConnectionsExample": "Ej \"10\"",
+ "admin.sql.maxConnectionsTitle": "Maxímo de coneciones inactivas:",
+ "admin.sql.maxOpenDescription": "Número máximo de conexiones abiertas y retenidas en la base de datos.",
+ "admin.sql.maxOpenExample": "Ej \"10\"",
+ "admin.sql.maxOpenTitle": "Máximo de conexiones abiertas:",
+ "admin.sql.noteDescription": "Cambiando las propiedades de esta sección se requerirá reiniciar el servidor para que los cambios tomen efecto",
+ "admin.sql.noteTitle": "Nota:",
+ "admin.sql.regenerate": "Regenerar",
+ "admin.sql.replicas": "Origen de datos de réplica:",
+ "admin.sql.save": "Guardar",
+ "admin.sql.saving": "Guardando...",
+ "admin.sql.title": "Configuración de SQL",
+ "admin.sql.traceDescription": "(Modo desarrolador) Cuando es verdadero, la ejecución de sentencias SQL se escriben en el registro.",
+ "admin.sql.traceTitle": "Traza: ",
+ "admin.sql.true": "verdadero",
+ "admin.sql.warning": "Precaución: re-generando esto puede causar que algunas columnas de la base de datos retornen resultados vacíos.",
+ "admin.support.aboutDesc": "Enlace para la página de Acerca que contiene más información sobre Mattermost, por ejemplo el propósito y audiencia dentro de la organización. De forma predeterminada apunta a la página de información de Mattermost.",
+ "admin.support.aboutTitle": "Enlace de Acerca:",
+ "admin.support.emailHelp": "El correo electrónico mostrado durante el tutorial para que los usuarios puedan realizar preguntas de soporte.",
+ "admin.support.emailTitle": "Correo electrónico de Soporte:",
+ "admin.support.helpDesc": "Enlace con la documentación de ayuda para el equipo desde el menú principal. Normalmente no cambia a menos que tu organización decida crear una documentación personalizada.",
+ "admin.support.helpTitle": "Enlace de Ayuda:",
+ "admin.support.privacyDesc": "Enlace para las políticas de Privacidad disponible para los usuarios en versión de escritorio y movil. Al dejarlo en blanco esconderá la opción que muestra el aviso.",
+ "admin.support.privacyTitle": "Enlace de políticas de Privacidad:",
+ "admin.support.problemDesc": "Enlace con la documentación de ayuda para el equipo desde el menú principal. Como predeterminado esto apunta a un foro de ayuda donde los usuarios pueden buscar, encontrar y solicitar ayuda sobre temas técnicos.",
+ "admin.support.problemTitle": "Enlace de Reportar un Problema:",
+ "admin.support.save": "Guradar",
+ "admin.support.saving": "Guardando...",
+ "admin.support.termsDesc": "Enlace para los Terminos y Condiciones disponible para los usuarios en versión de escritorio y movil. Al dejarlo en blanco esconderá la opción que muestra el aviso.",
+ "admin.support.termsTitle": "Enlace de Terminos y Condiciones:",
+ "admin.support.title": "Configuración de Soporte",
+ "admin.system_analytics.activeUsers": "Usuarios Activos con Mensajes",
+ "admin.system_analytics.title": "el Sistema",
+ "admin.system_analytics.totalPosts": "Total de Mensajes",
+ "admin.team.dirDesc": "Cuando es verdadero, Los equipos que esten configurados para mostrarse en el directorio de equipos se mostrarán en vez de crear un nuevo equipo.",
+ "admin.team.dirTitle": "Habilitar Directorio de Equipos: ",
+ "admin.team.false": "falso",
+ "admin.team.maxUsersDescription": "Número máximo de usuarios por equipo, incluyendo usuarios activos e inactivos.",
+ "admin.team.maxUsersExample": "Ej \"25\"",
+ "admin.team.maxUsersTitle": "Máximo de usuarios por equipo:",
+ "admin.team.restrictDescription": "Equipos y las cuentas de usuario sólo pueden ser creadas para dominios especificos (ej. \"mattermost.org\") o una lista de dominios separado por comas (ej. \"corp.mattermost.com, mattermost.org\").",
+ "admin.team.restrictExample": "Ej \"corp.mattermost.com, mattermost.org\"",
+ "admin.team.restrictNameDesc": "Cuando es verdadero, No puedes crear equipos cuyo nombre tenga palabras reservadas como: www, admin, support, test, channel, etc",
+ "admin.team.restrictNameTitle": "Restringir Nombre de los Equipos: ",
+ "admin.team.restrictTitle": "Restringir la creación de dominios:",
+ "admin.team.save": "Guardar",
+ "admin.team.saving": "Guardando...",
+ "admin.team.siteNameDescription": "Nombre de servicios mostrados en pantalla login y UI.",
+ "admin.team.siteNameExample": "Ex \"Mattermost\"",
+ "admin.team.siteNameTitle": "Nombre de sitio:",
+ "admin.team.teamCreationDescription": "Cuando es falso, la posibilidad de crear equipos es deshabilitada. El botón crear equipo arrojará error cuando sea presionado.",
+ "admin.team.teamCreationTitle": "Habilitar Creación de Equipos: ",
+ "admin.team.title": "Configuración de equipo",
+ "admin.team.true": "Verdadero",
+ "admin.team.userCreationDescription": "Cuando es falso, a posibilidad de crear cuentas es deshabilitada. El botón crear cuentas arrojará error cuando sea presionado.",
+ "admin.team.userCreationTitle": "Habilitar Creación de Usuarios: ",
+ "admin.team_analytics.activeUsers": "Active Users With Posts",
+ "admin.team_analytics.totalPosts": "Total de Mensajes",
+ "admin.userList.title": "Usuarios para ",
+ "admin.userList.title2": "Usuarios para {team} ({count})",
+ "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.resetPwd": "Reiniciar Contraseña",
+ "admin.user_item.sysAdmin": "Admin de Sistema",
+ "admin.user_item.teamAdmin": "Admin de Equipo",
+ "claim.account.noEmail": "No se especifico un correo electrónico.",
+ "claim.email_to_sso.enterPwd": "Ingresa la contraseña para tu cuenta para {team} {site}",
+ "claim.email_to_sso.pwd": "Contraseña",
+ "claim.email_to_sso.pwdError": "Por favor introduce tu contraseña.",
+ "claim.email_to_sso.ssoType": "Al reclamar tu cuenta, sólo podrás iniciar sesión con {type} SSO",
+ "claim.email_to_sso.switchTo": "Cambiar cuenta a ",
+ "claim.email_to_sso.title": "Cambiar Cuenta de Correo/Contraseña a ",
+ "claim.sso_to_email.confirm": "Confirmar Contraseña",
+ "claim.sso_to_email.description": "Al cambiar el tipo de cuenta, sólo podrás iniciar sesión con tu correo electrónico y contraseña.",
+ "claim.sso_to_email.enterPwd": "Por favor ingresa una contraseña.",
+ "claim.sso_to_email.newPwd": "Nueva Contraseña",
+ "claim.sso_to_email.pwdNotMatch": "Las contraseñas no coinciden.",
+ "claim.sso_to_email.switchTo": "Cambiar {type} a correo electrónico y contraseña",
+ "claim.sso_to_email.title": "Cambiar la cuenta de {type} a Correo Electrónico",
+ "claim.sso_to_email_newPwd": "Ingresa una nueva contraseña para tu cuenta de {team} {site}",
"error_bar.preview_mode": "Modo de prueba: Las notificaciones por correo electrónico no han sido configuradas",
- "loading_screen.loading": "Cargando"
+ "loading_screen.loading": "Cargando",
+ "suggestion.mention.all": "Notifica a todas las personas en el equipo",
+ "suggestion.mention.channel": "Notifica a todas las personas en el canal",
+ "suggestion.search.private": "Grupos Privados",
+ "suggestion.search.public": "Canales Públicos",
+ "tutorial_intro.allSet": "Ya estás listo para comenzar",
+ "tutorial_intro.end": "Pincha “Siguiente” para entrar al Canal General. Este es el primer canal que ven tus compañeros cuando ingresan. Utilizalo para mandar mensajes que todos deben leer.",
+ "tutorial_intro.invite": "Invitar compañeros",
+ "tutorial_intro.next": "Seguir",
+ "tutorial_intro.screenOne": "<h3>Bienvenido a:</h3> <h1>Mattermost</h1> <p>Las comunicaciones de tu equipo en un solo lugar, con búsquedas instantáneas y disponible desde donde sea.</p> <p>Mantén a tu equipo conectado para ayudarlos a conseguir lo que realmente importa.</p>",
+ "tutorial_intro.screenTwo": "<h3>Cómo funciona Mattermost:</h3> <p>Las comunicaciones ocurren en los canales de discusión los cuales son públicos, o en grupos privados e incluso con mensajes privados.</p> <p>Todo lo que ocurre es archivado y se puede buscar en cualquier momento desde cualquier dispositivo con acceso a Mattermost.</p>",
+ "tutorial_intro.skip": "Saltar el tutorial",
+ "tutorial_intro.support": "Necesitas algo, escribemos a ",
+ "tutorial_intro.teamInvite": "Invitar a tu Equipo",
+ "tutorial_intro.whenReady": " cuando estés listo(a).",
+ "tutorial_tip.next": "Siguiente",
+ "tutorial_tip.ok": "Aceptar",
+ "tutorial_tip.out": "No optar por estos consejos.",
+ "tutorial_tip.seen": "¿Haz visto esto antes? "
} \ No newline at end of file