summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md61
-rw-r--r--api/team.go2
-rw-r--r--i18n/es.json8
-rw-r--r--web/react/components/admin_console/email_settings.jsx20
-rw-r--r--web/react/components/admin_console/ldap_settings.jsx2
-rw-r--r--web/react/components/audio_video_preview.jsx4
-rw-r--r--web/react/components/center_panel.jsx9
-rw-r--r--web/react/components/channel_loader.jsx52
-rw-r--r--web/react/components/create_post.jsx42
-rw-r--r--web/react/components/file_attachment.jsx16
-rw-r--r--web/react/components/file_info_preview.jsx19
-rw-r--r--web/react/components/login_username.jsx4
-rw-r--r--web/react/components/navbar.jsx89
-rw-r--r--web/react/components/post_attachment.jsx22
-rw-r--r--web/react/components/post_body.jsx47
-rw-r--r--web/react/components/post_focus_view.jsx9
-rw-r--r--web/react/components/post_info.jsx32
-rw-r--r--web/react/components/posts_view.jsx27
-rw-r--r--web/react/components/time_since.jsx20
-rw-r--r--web/react/components/user_settings/user_settings_display.jsx2
-rw-r--r--web/react/components/view_image.jsx28
-rw-r--r--web/react/components/view_image_popover_bar.jsx23
-rw-r--r--web/react/stores/post_store.jsx5
-rw-r--r--web/react/stores/socket_store.jsx21
-rw-r--r--web/react/utils/channel_intro_messages.jsx146
-rw-r--r--web/react/utils/locales/en.js16
-rw-r--r--web/react/utils/locales/es.js10
-rw-r--r--web/static/i18n/en.json184
-rw-r--r--web/static/i18n/es.json213
29 files changed, 801 insertions, 332 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 41a8f9375..e64f5a86c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,62 +1,3 @@
# Code Contribution Guidelines
-Thank you for your interest in contributing to Mattermost. This guide provides an overview of important information for contributors to know.
-
-## Choose a Ticket
-
-1. Review the list of [Good First Contribution](https://mattermost.atlassian.net/issues/?filter=10206) tickets listed in Jira
- - You are welcome to work on any ticket, even if it is assigned, so long as it is not yet marked "in progress"
- - (optional) Comment on the ticket that you're starting so no one else inadvertently duplicates your work
-
-2. These projects are intended to be a straight forward first pull requests from new contributors
- - If you don't find something appropriate for your interests, please see the full list of tickets [Accepting Pull Requests](https://mattermost.atlassian.net/issues/?filter=10101)
- - Also, feel free to fix bugs you find, or items in GitHub issues that the core team has approved, but not yet added to Jira
- - For feature ideas, please discuss on the [feature ideas forum](http://www.mattermost.org/feature-requests/) before beginning work
-
-3. If you have any questions at all about a ticket, there are several options to ask:
- 1. Start a topic in the [Mattermost forum](http://forum.mattermost.org/)
- 2. Join the [Mattermost core team discussion](https://pre-release.mattermost.com/signup_user_complete/?id=rcgiyftm7jyrxnma1osd8zswby) and post in the "Tickets" channel
-
-## Install Mattermost and set up a Fork
-
-1. Follow [developer setup instructions](https://github.com/mattermost/platform/blob/master/doc/developer/Setup.md) to install Mattermost
-
-2. Create a branch with <branch name> set to the ID of the ticket you're working on, for example ```PLT-394```, using command:
-
-```
-git checkout -b <branch name>
-```
-
-## Programming and Testing
-
-1. Please review the [Mattermost Style Guide](doc/developer/Style-Guide.md) prior to making changes
-
- To keep code clean and well structured, Mattermost uses ESLint to check that pull requests adhere to style guidelines for React. In addition all code is run through the official go formatter tool gofmt. Code will need to follow Mattermost's React style guidelines and the golang official style guide in order to pass the automated build tests when a pull request is submitted.
-
-2. Please make sure to thoroughly test your change before submitting a pull request
-
- For any changes to text processing, please run the text processing tests found in the [/tests](https://github.com/mattermost/platform/tree/master/doc/developer/tests) folder in GitHub.
-
- Please review the ["Fast, Obvious, Forgiving" experience design principles](http://www.mattermost.org/design-principles/) for Mattermost and check that your feature meets the criteria. Also, for any changes to user interface or help text, please read the changes out loud, as a quick and easy way to catch any inconsitencies
-
-3. For new server-side funcitonality, please include test cases that verify the code performs as you have intended
-
-
-## Submitting a Pull Request
-
-1. Please add yourself to the Mattermost [approved contributor list](https://docs.google.com/spreadsheets/d/1NTCeG-iL_VS9bFqtmHSfwETo5f-8MQ7oMDE5IUYJi_Y/pubhtml?gid=0&single=true) prior to submitting by completing the [contributor license agreement](http://www.mattermost.org/mattermost-contributor-agreement/).
-
-2. When you submit your pull request please make it against `master` and include the Ticket ID at the beginning of your pull request comment, followed by a colon
-
- - For example, for a ticket ID `PLT-394` start your comment with: `PLT-394:`. See [previously closed pull requests](https://github.com/mattermost/platform/pulls?q=is%3Apr+is%3Aclosed) for examples
- - All pull requests must have a ticket ID so the issue can be tracked and tested properly. If there is no existing ticket in Jira, please [file a bug in GitHub](http://www.mattermost.org/filing-issues/) or a [feature idea you're proposing to implement](http://www.mattermost.org/feature-requests/) so a Jira ticket can be created
-
-3. Please include a comment on the pull request describing the changes
-
- For new features visible in the UI, please make sure there are enough details explaining how the feature is expected to work. This will be used when testing and writing help documentation.
-
-4. Once submitted, your pull request will be checked via an automated build process and will be reviewed by at least two members of the Mattermost core team, who may either accept the PR or follow-up with feedback. It would then get merged into `master` for the next release
- 1. If the build fails, check the error log to narrow down the reason
- 2. Sometimes one of the multiple build tests will randomly fail due to issues in Travis CI so if you see just one build failure and no clear error message it may be a random issue. Add a comment so the reviewer for your change can re-run the build for you, or close the PR and re-submit and that typically clears the issue
-
-5. If you've included your mailing address in Step 1, you'll be receiving a [Limited Edition Mattermost Mug](http://forum.mattermost.org/t/limited-edition-mattermost-mugs/143) as a thank you gift after your first pull request has been accepted
+Please see the [Mattermost Contribution Guide](http://docs.mattermost.com/developer/contribution-guide.html) which describes the process for making code contributions across Mattermost projects.
diff --git a/api/team.go b/api/team.go
index 8b25e3316..6d59e94e9 100644
--- a/api/team.go
+++ b/api/team.go
@@ -66,7 +66,7 @@ func signupTeam(c *Context, w http.ResponseWriter, r *http.Request) {
bodyPage.Props["SiteURL"] = c.GetSiteURL()
bodyPage.Props["Title"] = c.T("api.templates.signup_team_body.title")
bodyPage.Props["Button"] = c.T("api.templates.signup_team_body.button")
- bodyPage.Html["Info"] = template.HTML(c.T("api.templates.signup_team_body.button",
+ bodyPage.Html["Info"] = template.HTML(c.T("api.templates.signup_team_body.info",
map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"]}))
props := make(map[string]string)
diff --git a/i18n/es.json b/i18n/es.json
index bd29c9860..9599fe879 100644
--- a/i18n/es.json
+++ b/i18n/es.json
@@ -3016,6 +3016,14 @@
"translation": "No se puede actualizar el campo de verificar correo"
},
{
+ "id": "store.sql_webhooks.analytics_incoming_count.app_error",
+ "translation": "No pudimos contar la cantidad de webhooks entrantes"
+ },
+ {
+ "id": "store.sql_webhooks.analytics_outgoing_count.app_error",
+ "translation": "No pudimos contar la cantidad de webhooks salientes"
+ },
+ {
"id": "store.sql_webhooks.delete_incoming.app_error",
"translation": "No pudimos eliminar el webhook"
},
diff --git a/web/react/components/admin_console/email_settings.jsx b/web/react/components/admin_console/email_settings.jsx
index 17f25a04c..435eff036 100644
--- a/web/react/components/admin_console/email_settings.jsx
+++ b/web/react/components/admin_console/email_settings.jsx
@@ -339,7 +339,10 @@ class EmailSettings extends React.Component {
defaultChecked={this.props.config.EmailSettings.EnableSignInWithEmail}
onChange={this.handleChange.bind(this, 'allowSignInWithEmail_true')}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.email.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -349,7 +352,10 @@ class EmailSettings extends React.Component {
defaultChecked={!this.props.config.EmailSettings.EnableSignInWithEmail}
onChange={this.handleChange.bind(this, 'allowSignInWithEmail_false')}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.email.false'
+ defaultMessage='false'
+ />
</label>
<p className='help-text'>
<FormattedMessage
@@ -380,7 +386,10 @@ class EmailSettings extends React.Component {
defaultChecked={this.props.config.EmailSettings.EnableSignInWithUsername}
onChange={this.handleChange.bind(this, 'allowSignInWithUsername_true')}
/>
- {'true'}
+ <FormattedMessage
+ id='admin.email.true'
+ defaultMessage='true'
+ />
</label>
<label className='radio-inline'>
<input
@@ -390,7 +399,10 @@ class EmailSettings extends React.Component {
defaultChecked={!this.props.config.EmailSettings.EnableSignInWithUsername}
onChange={this.handleChange.bind(this, 'allowSignInWithUsername_false')}
/>
- {'false'}
+ <FormattedMessage
+ id='admin.email.false'
+ defaultMessage='false'
+ />
</label>
<p className='help-text'>
<FormattedMessage
diff --git a/web/react/components/admin_console/ldap_settings.jsx b/web/react/components/admin_console/ldap_settings.jsx
index bc13b3bcd..535c264dd 100644
--- a/web/react/components/admin_console/ldap_settings.jsx
+++ b/web/react/components/admin_console/ldap_settings.jsx
@@ -164,7 +164,7 @@ class LdapSettings extends React.Component {
<div className='banner__content'>
<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>'
+ defaultMessage='<h4 class="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>
diff --git a/web/react/components/audio_video_preview.jsx b/web/react/components/audio_video_preview.jsx
index 7d00fbdaa..739c8c95e 100644
--- a/web/react/components/audio_video_preview.jsx
+++ b/web/react/components/audio_video_preview.jsx
@@ -75,6 +75,7 @@ export default class AudioVideoPreview extends React.Component {
filename={this.props.filename}
fileUrl={this.props.fileUrl}
fileInfo={this.props.fileInfo}
+ formatMessage={this.props.formatMessage}
/>
);
}
@@ -110,5 +111,6 @@ AudioVideoPreview.propTypes = {
filename: React.PropTypes.string.isRequired,
fileUrl: React.PropTypes.string.isRequired,
fileInfo: React.PropTypes.object.isRequired,
- maxHeight: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]).isRequired
+ maxHeight: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]).isRequired,
+ formatMessage: React.PropTypes.func.isRequired
};
diff --git a/web/react/components/center_panel.jsx b/web/react/components/center_panel.jsx
index 443ecefde..7d2be04d6 100644
--- a/web/react/components/center_panel.jsx
+++ b/web/react/components/center_panel.jsx
@@ -15,6 +15,8 @@ import UserStore from '../stores/user_store.jsx';
import * as Utils from '../utils/utils.jsx';
+import {FormattedMessage} from 'mm-intl';
+
import Constants from '../utils/constants.jsx';
const TutorialSteps = Constants.TutorialSteps;
const Preferences = Constants.Preferences;
@@ -69,8 +71,11 @@ export default class CenterPanel extends React.Component {
onClick={handleClick}
>
<a href=''>
- {'Click here to jump to recent messages. '}
- {<i className='fa fa-arrow-down'></i>}
+ <FormattedMessage
+ id='center_panel.recent'
+ defaultMessage='Click here to jump to recent messages. '
+ />
+ <i className='fa fa-arrow-down'></i>
</a>
</div>
);
diff --git a/web/react/components/channel_loader.jsx b/web/react/components/channel_loader.jsx
index cb1da90de..174c8c4e1 100644
--- a/web/react/components/channel_loader.jsx
+++ b/web/react/components/channel_loader.jsx
@@ -15,7 +15,40 @@ import PreferenceStore from '../stores/preference_store.jsx';
import * as Utils from '../utils/utils.jsx';
import Constants from '../utils/constants.jsx';
-export default class ChannelLoader extends React.Component {
+import {intlShape, injectIntl, defineMessages} from 'mm-intl';
+
+const holders = defineMessages({
+ socketError: {
+ id: 'channel_loader.socketError',
+ defaultMessage: 'Please check connection, Mattermost unreachable. If issue persists, ask administrator to check WebSocket port.'
+ },
+ someone: {
+ id: 'channel_loader.someone',
+ defaultMessage: 'Someone'
+ },
+ posted: {
+ id: 'channel_loader.posted',
+ defaultMessage: 'Posted'
+ },
+ uploadedImage: {
+ id: 'channel_loader.uploadedImage',
+ defaultMessage: ' uploaded an image'
+ },
+ uploadedFile: {
+ id: 'channel_loader.uploadedFile',
+ defaultMessage: ' uploaded a file'
+ },
+ something: {
+ id: 'channel_loader.something',
+ defaultMessage: ' did something new'
+ },
+ wrote: {
+ id: 'channel_loader.wrote',
+ defaultMessage: ' wrote: '
+ }
+});
+
+class ChannelLoader extends React.Component {
constructor(props) {
super(props);
@@ -23,6 +56,17 @@ export default class ChannelLoader extends React.Component {
this.onSocketChange = this.onSocketChange.bind(this);
+ const {formatMessage} = this.props.intl;
+ SocketStore.setTranslations({
+ socketError: formatMessage(holders.socketError),
+ someone: formatMessage(holders.someone),
+ posted: formatMessage(holders.posted),
+ uploadedImage: formatMessage(holders.uploadedImage),
+ uploadedFile: formatMessage(holders.uploadedFile),
+ something: formatMessage(holders.something),
+ wrote: formatMessage(holders.wrote)
+ });
+
this.state = {};
}
componentDidMount() {
@@ -136,3 +180,9 @@ export default class ChannelLoader extends React.Component {
return <div/>;
}
}
+
+ChannelLoader.propTypes = {
+ intl: intlShape.isRequired
+};
+
+export default injectIntl(ChannelLoader); \ No newline at end of file
diff --git a/web/react/components/create_post.jsx b/web/react/components/create_post.jsx
index de971c43f..ed672cd34 100644
--- a/web/react/components/create_post.jsx
+++ b/web/react/components/create_post.jsx
@@ -21,12 +21,33 @@ import SocketStore from '../stores/socket_store.jsx';
import Constants from '../utils/constants.jsx';
+import {intlShape, injectIntl, defineMessages, FormattedHTMLMessage} from 'mm-intl';
+
const Preferences = Constants.Preferences;
const TutorialSteps = Constants.TutorialSteps;
const ActionTypes = Constants.ActionTypes;
const KeyCodes = Constants.KeyCodes;
-export default class CreatePost extends React.Component {
+const holders = defineMessages({
+ comment: {
+ id: 'create_post.comment',
+ defaultMessage: 'Comment'
+ },
+ post: {
+ id: 'create_post.post',
+ defaultMessage: 'Post'
+ },
+ write: {
+ id: 'create_post.write',
+ defaultMessage: 'Write a message...'
+ },
+ deleteMsg: {
+ id: 'create_post.deleteMsg',
+ defaultMessage: '(message deleted)'
+ }
+});
+
+class CreatePost extends React.Component {
constructor(props) {
super(props);
@@ -49,6 +70,7 @@ export default class CreatePost extends React.Component {
this.sendMessage = this.sendMessage.bind(this);
PostStore.clearDraftUploads();
+ PostStore.deleteMessage(this.props.intl.formatMessage(holders.deleteMsg));
const draft = this.getCurrentDraft();
@@ -361,7 +383,8 @@ export default class CreatePost extends React.Component {
if (!lastPost) {
return;
}
- var type = (lastPost.root_id && lastPost.root_id.length > 0) ? 'Comment' : 'Post';
+ const {formatMessage} = this.props.intl;
+ var type = (lastPost.root_id && lastPost.root_id.length > 0) ? formatMessage(holders.comment) : formatMessage(holders.post);
AppDispatcher.handleViewAction({
type: ActionTypes.RECIEVED_EDIT_POST,
@@ -379,9 +402,10 @@ export default class CreatePost extends React.Component {
screens.push(
<div>
- <h4>{'Sending Messages'}</h4>
- <p>{'Type here to write a message and press '}<strong>{'Enter'}</strong>{' to post it.'}</p>
- <p>{'Click the '}<strong>{'Attachment'}</strong>{' button to upload an image or a file.'}</p>
+ <FormattedHTMLMessage
+ id='create_post.tutorialTip'
+ defaultMessage='<h4>Sending Messages</h4><p>Type here to write a message and press <strong>Enter</strong> to post it.</p><p>Click the <strong>Attachment</strong> button to upload an image or a file.</p>'
+ />
</div>
);
@@ -445,7 +469,7 @@ export default class CreatePost extends React.Component {
onKeyDown={this.handleKeyDown}
onHeightChange={this.resizePostHolder}
messageText={this.state.messageText}
- createMessage='Write a message...'
+ createMessage={this.props.intl.formatMessage(holders.write)}
channelId={this.state.channelId}
id='post_textbox'
ref='textbox'
@@ -482,3 +506,9 @@ export default class CreatePost extends React.Component {
);
}
}
+
+CreatePost.propTypes = {
+ intl: intlShape.isRequired
+};
+
+export default injectIntl(CreatePost); \ No newline at end of file
diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx
index eeb218bfe..776394828 100644
--- a/web/react/components/file_attachment.jsx
+++ b/web/react/components/file_attachment.jsx
@@ -5,7 +5,16 @@ import * as utils from '../utils/utils.jsx';
import * as Client from '../utils/client.jsx';
import Constants from '../utils/constants.jsx';
-export default class FileAttachment extends React.Component {
+import {intlShape, injectIntl, defineMessages} from 'mm-intl';
+
+const holders = defineMessages({
+ download: {
+ id: 'file_attachment.download',
+ defaultMessage: 'Download'
+ }
+});
+
+class FileAttachment extends React.Component {
constructor(props) {
super(props);
@@ -266,7 +275,7 @@ export default class FileAttachment extends React.Component {
href={fileUrl}
download={filenameString}
data-toggle='tooltip'
- title={'Download \"' + filenameString + '\"'}
+ title={this.props.intl.formatMessage(holders.download) + ' \"' + filenameString + '\"'}
className='post-image__name'
>
{trimmedFilename}
@@ -291,6 +300,7 @@ export default class FileAttachment extends React.Component {
}
FileAttachment.propTypes = {
+ intl: intlShape.isRequired,
// a list of file pathes displayed by the parent FileAttachmentList
filename: React.PropTypes.string.isRequired,
@@ -301,3 +311,5 @@ FileAttachment.propTypes = {
// handler for when the thumbnail is clicked passed the index above
handleImageClick: React.PropTypes.func
};
+
+export default injectIntl(FileAttachment); \ No newline at end of file
diff --git a/web/react/components/file_info_preview.jsx b/web/react/components/file_info_preview.jsx
index 45d89007f..1dac140c9 100644
--- a/web/react/components/file_info_preview.jsx
+++ b/web/react/components/file_info_preview.jsx
@@ -3,15 +3,28 @@
import * as Utils from '../utils/utils.jsx';
-export default function FileInfoPreview({filename, fileUrl, fileInfo}) {
+import {defineMessages} from 'mm-intl';
+
+const holders = defineMessages({
+ type: {
+ id: 'file_info_preview.type',
+ defaultMessage: 'File type '
+ },
+ size: {
+ id: 'file_info_preview.size',
+ defaultMessage: 'Size '
+ }
+});
+
+export default function FileInfoPreview({filename, fileUrl, fileInfo, formatMessage}) {
// non-image files include a section providing details about the file
const infoParts = [];
if (fileInfo.extension !== '') {
- infoParts.push('File type ' + fileInfo.extension.toUpperCase());
+ infoParts.push(formatMessage(holders.type) + fileInfo.extension.toUpperCase());
}
- infoParts.push('Size ' + Utils.fileSizeToString(fileInfo.size));
+ infoParts.push(formatMessage(holders.size) + Utils.fileSizeToString(fileInfo.size));
const infoString = infoParts.join(', ');
diff --git a/web/react/components/login_username.jsx b/web/react/components/login_username.jsx
index f787490fa..4bd9254c6 100644
--- a/web/react/components/login_username.jsx
+++ b/web/react/components/login_username.jsx
@@ -89,9 +89,9 @@ export default class LoginUsername extends React.Component {
}
},
(err) => {
- if (err.message === 'api.user.login.not_verified.app_error') {
+ if (err.id === 'api.user.login.not_verified.app_error') {
state.serverError = formatMessage(holders.verifyEmailError);
- } else if (err.message === 'store.sql_user.get_by_username.app_error') {
+ } else if (err.id === 'store.sql_user.get_by_username.app_error') {
state.serverError = formatMessage(holders.userNotFoundError);
} else {
state.serverError = err.message;
diff --git a/web/react/components/navbar.jsx b/web/react/components/navbar.jsx
index 7326a9ef8..8005678a2 100644
--- a/web/react/components/navbar.jsx
+++ b/web/react/components/navbar.jsx
@@ -24,6 +24,8 @@ import Constants from '../utils/constants.jsx';
const ActionTypes = Constants.ActionTypes;
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
+import {FormattedMessage} from 'mm-intl';
+
const Popover = ReactBootstrap.Popover;
const OverlayTrigger = ReactBootstrap.OverlayTrigger;
@@ -133,7 +135,10 @@ export default class Navbar extends React.Component {
dialogType={ChannelInfoModal}
dialogProps={{channel}}
>
- {'View Info'}
+ <FormattedMessage
+ id='navbar.viewInfo'
+ defaultMessage='View Info'
+ />
</ToggleModalButton>
</li>
);
@@ -145,7 +150,10 @@ export default class Navbar extends React.Component {
href='#'
onClick={this.showEditChannelHeaderModal}
>
- {'Set Channel Header...'}
+ <FormattedMessage
+ id='navbar.setHeader'
+ defaultMessage='Set Channel Header...'
+ />
</a>
</li>
);
@@ -159,7 +167,10 @@ export default class Navbar extends React.Component {
href='#'
onClick={() => this.setState({showEditChannelPurposeModal: true})}
>
- {'Set Channel Purpose...'}
+ <FormattedMessage
+ id='navbar.setPurpose'
+ defaultMessage='Set Channel Purpose...'
+ />
</a>
</li>
);
@@ -175,7 +186,10 @@ export default class Navbar extends React.Component {
dialogType={ChannelInviteModal}
dialogProps={{channel}}
>
- {'Add Members'}
+ <FormattedMessage
+ id='navbar.addMembers'
+ defaultMessage='Add Members'
+ />
</ToggleModalButton>
</li>
);
@@ -187,7 +201,10 @@ export default class Navbar extends React.Component {
href='#'
onClick={this.handleLeave}
>
- {'Leave Channel'}
+ <FormattedMessage
+ id='navbar.leave'
+ defaultMessage='Leave Channel'
+ />
</a>
</li>
);
@@ -205,7 +222,10 @@ export default class Navbar extends React.Component {
href='#'
onClick={() => this.setState({showMembersModal: true})}
>
- {'Manage Members'}
+ <FormattedMessage
+ id='navbar.manageMembers'
+ defaultMessage='Manage Members'
+ />
</a>
</li>
);
@@ -217,7 +237,10 @@ export default class Navbar extends React.Component {
dialogType={DeleteChannelModal}
dialogProps={{channel}}
>
- {'Delete Channel...'}
+ <FormattedMessage
+ id='navbar.delete'
+ defaultMessage='Delete Channel...'
+ />
</ToggleModalButton>
</li>
);
@@ -234,7 +257,10 @@ export default class Navbar extends React.Component {
data-name={channel.name}
data-channelid={channel.id}
>
- {'Rename Channel...'}
+ <FormattedMessage
+ id='navbar.rename'
+ defaultMessage='Rename Channel...'
+ />
</a>
</li>
);
@@ -249,7 +275,10 @@ export default class Navbar extends React.Component {
dialogType={ChannelNotificationsModal}
dialogProps={{channel}}
>
- {'Notification Preferences'}
+ <FormattedMessage
+ id='navbar.preferences'
+ defaultMessage='Notification Preferences'
+ />
</ToggleModalButton>
</li>
);
@@ -319,7 +348,12 @@ export default class Navbar extends React.Component {
data-toggle='collapse'
data-target='#navbar-collapse-1'
>
- <span className='sr-only'>{'Toggle sidebar'}</span>
+ <span className='sr-only'>
+ <FormattedMessage
+ id='navbar.toggle1'
+ defaultMessage='Toggle sidebar'
+ />
+ </span>
<span className='icon-bar'></span>
<span className='icon-bar'></span>
<span className='icon-bar'></span>
@@ -335,7 +369,12 @@ export default class Navbar extends React.Component {
data-target='#sidebar-nav'
onClick={this.toggleLeftSidebar}
>
- <span className='sr-only'>{'Toggle sidebar'}</span>
+ <span className='sr-only'>
+ <FormattedMessage
+ id='navbar.toggle2'
+ defaultMessage='Toggle sidebar'
+ />
+ </span>
<span className='icon-bar'></span>
<span className='icon-bar'></span>
<span className='icon-bar'></span>
@@ -405,6 +444,17 @@ export default class Navbar extends React.Component {
}
if (channel.header.length === 0) {
+ const link = (
+ <a
+ href='#'
+ onClick={this.showEditChannelHeaderModal}
+ >
+ <FormattedMessage
+ id='navbar.click'
+ defaultMessage='Click here'
+ />
+ </a>
+ );
popoverContent = (
<Popover
bsStyle='info'
@@ -412,15 +462,14 @@ export default class Navbar extends React.Component {
id='header-popover'
>
<div>
- {'No channel header yet.'}
- <br/>
- <a
- href='#'
- onClick={this.showEditChannelHeaderModal}
- >
- {'Click here'}
- </a>
- {' to add one.'}
+ <FormattedMessage
+ id='navbar.noHeader'
+ defaultMessage='No channel header yet.{newline}{link} to add one.'
+ values={{
+ newline: (<br/>),
+ link: (link)
+ }}
+ />
</div>
</Popover>
);
diff --git a/web/react/components/post_attachment.jsx b/web/react/components/post_attachment.jsx
index 676bc91af..2eedfb7c1 100644
--- a/web/react/components/post_attachment.jsx
+++ b/web/react/components/post_attachment.jsx
@@ -3,7 +3,20 @@
import * as TextFormatting from '../utils/text_formatting.jsx';
-export default class PostAttachment extends React.Component {
+import {intlShape, injectIntl, defineMessages} from 'mm-intl';
+
+const holders = defineMessages({
+ collapse: {
+ id: 'post_attachment.collapse',
+ defaultMessage: '▲ collapse text'
+ },
+ more: {
+ id: 'post_attachment.more',
+ defaultMessage: '▼ read more'
+ }
+});
+
+class PostAttachment extends React.Component {
constructor(props) {
super(props);
@@ -28,7 +41,7 @@ export default class PostAttachment extends React.Component {
getInitState() {
const shouldCollapse = this.shouldCollapse();
const text = TextFormatting.formatText(this.props.attachment.text || '');
- const uncollapsedText = text + (shouldCollapse ? '<a class="attachment-link-more" href="#">▲ collapse text</a>' : '');
+ const uncollapsedText = text + (shouldCollapse ? `<a class="attachment-link-more" href="#">${this.props.intl.formatMessage(holders.collapse)}</a>` : '');
const collapsedText = shouldCollapse ? this.getCollapsedText() : text;
return {
@@ -62,7 +75,7 @@ export default class PostAttachment extends React.Component {
text = text.substr(0, 700);
}
- return TextFormatting.formatText(text) + '<a class="attachment-link-more" href="#">▼ read more</a>';
+ return TextFormatting.formatText(text) + `<a class="attachment-link-more" href="#">${this.props.intl.formatMessage(holders.more)}</a>`;
}
getFieldsTable() {
@@ -292,5 +305,8 @@ export default class PostAttachment extends React.Component {
}
PostAttachment.propTypes = {
+ intl: intlShape.isRequired,
attachment: React.PropTypes.object.isRequired
};
+
+export default injectIntl(PostAttachment);
diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx
index b1657f0eb..16f8528b2 100644
--- a/web/react/components/post_body.jsx
+++ b/web/react/components/post_body.jsx
@@ -14,7 +14,20 @@ import YoutubeVideo from './youtube_video.jsx';
import providers from './providers.json';
-export default class PostBody extends React.Component {
+import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl';
+
+const holders = defineMessages({
+ plusOne: {
+ id: 'post_body.plusOne',
+ defaultMessage: ' plus 1 other file'
+ },
+ plusMore: {
+ id: 'post_body.plusMore',
+ defaultMessage: ' plus {count} other files'
+ }
+});
+
+class PostBody extends React.Component {
constructor(props) {
super(props);
@@ -187,6 +200,7 @@ export default class PostBody extends React.Component {
}
render() {
+ const {formatMessage} = this.props.intl;
const post = this.props.post;
const filenames = this.props.post.filenames;
const parentPost = this.props.parentPost;
@@ -208,10 +222,12 @@ export default class PostBody extends React.Component {
username = parentPost.props.override_username;
}
- if (username.slice(-1) === 's') {
- apostrophe = '\'';
- } else {
- apostrophe = '\'s';
+ if (global.window.mm_locale === 'en') {
+ if (username.slice(-1) === 's') {
+ apostrophe = '\'';
+ } else {
+ apostrophe = '\'s';
+ }
}
name = (
<a
@@ -230,16 +246,23 @@ export default class PostBody extends React.Component {
message = parentPost.filenames[0].split('/').pop();
if (parentPost.filenames.length === 2) {
- message += ' plus 1 other file';
+ message += formatMessage(holders.plusOne);
} else if (parentPost.filenames.length > 2) {
- message += ` plus ${parentPost.filenames.length - 1} other files`;
+ message += formatMessage(holders.plusMore, {count: (parentPost.filenames.length - 1)});
}
}
comment = (
<div className='post__link'>
<span>
- {'Commented on '}{name}{apostrophe}{' message: '}
+ <FormattedMessage
+ id='post_body.commentedOn'
+ defaultMessage='Commented on {name}{apostrophe} message: '
+ values={{
+ name: (name),
+ apostrophe: apostrophe
+ }}
+ />
<a
className='theme'
onClick={this.props.handleCommentClick}
@@ -260,7 +283,10 @@ export default class PostBody extends React.Component {
href='#'
onClick={this.props.retryPost}
>
- {'Retry'}
+ <FormattedMessage
+ id='post_body.retry'
+ defaultMessage='Retry'
+ />
</a>
);
} else if (post.state === Constants.POST_LOADING) {
@@ -313,8 +339,11 @@ export default class PostBody extends React.Component {
}
PostBody.propTypes = {
+ intl: intlShape.isRequired,
post: React.PropTypes.object.isRequired,
parentPost: React.PropTypes.object,
retryPost: React.PropTypes.func.isRequired,
handleCommentClick: React.PropTypes.func.isRequired
};
+
+export default injectIntl(PostBody); \ No newline at end of file
diff --git a/web/react/components/post_focus_view.jsx b/web/react/components/post_focus_view.jsx
index adcd78839..b9b6acd5f 100644
--- a/web/react/components/post_focus_view.jsx
+++ b/web/react/components/post_focus_view.jsx
@@ -7,6 +7,8 @@ import PostStore from '../stores/post_store.jsx';
import ChannelStore from '../stores/channel_store.jsx';
import * as EventHelpers from '../dispatcher/event_helpers.jsx';
+import {FormattedMessage} from 'mm-intl';
+
export default class PostFocusView extends React.Component {
constructor(props) {
super(props);
@@ -73,7 +75,12 @@ export default class PostFocusView extends React.Component {
getIntroMessage() {
return (
<div className='channel-intro'>
- <h4 className='channel-intro__title'>{'Beginning of Channel Archives'}</h4>
+ <h4 className='channel-intro__title'>
+ <FormattedMessage
+ id='post_focus_view.beginning'
+ defaultMessage='Beginning of Channel Archives'
+ />
+ </h4>
</div>
);
}
diff --git a/web/react/components/post_info.jsx b/web/react/components/post_info.jsx
index 0fb9d7f4a..ddb393520 100644
--- a/web/react/components/post_info.jsx
+++ b/web/react/components/post_info.jsx
@@ -9,6 +9,8 @@ import * as EventHelpers from '../dispatcher/event_helpers.jsx';
import Constants from '../utils/constants.jsx';
+import {FormattedMessage} from 'mm-intl';
+
const Overlay = ReactBootstrap.Overlay;
const Popover = ReactBootstrap.Popover;
@@ -53,7 +55,10 @@ export default class PostInfo extends React.Component {
href='#'
onClick={this.props.handleCommentClick}
>
- {'Reply'}
+ <FormattedMessage
+ id='post_info.reply'
+ defaultMessage='Reply'
+ />
</a>
</li>
);
@@ -68,7 +73,10 @@ export default class PostInfo extends React.Component {
href='#'
onClick={(e) => this.setState({target: e.target, show: !this.state.show})}
>
- {'Permalink'}
+ <FormattedMessage
+ id='post_info.permalink'
+ defaultMessage='Permalink'
+ />
</a>
</li>
);
@@ -84,7 +92,10 @@ export default class PostInfo extends React.Component {
role='menuitem'
onClick={() => EventHelpers.showDeletePostModal(post, dataComments)}
>
- {'Delete'}
+ <FormattedMessage
+ id='post_info.del'
+ defaultMessage='Delete'
+ />
</a>
</li>
);
@@ -108,7 +119,10 @@ export default class PostInfo extends React.Component {
data-channelid={post.channel_id}
data-comments={dataComments}
>
- {'Edit'}
+ <FormattedMessage
+ id='post_info.edit'
+ defaultMessage='Edit'
+ />
</a>
</li>
);
@@ -183,7 +197,15 @@ export default class PostInfo extends React.Component {
var dropdown = this.createDropdown();
const permalink = TeamStore.getCurrentTeamUrl() + '/pl/' + post.id;
- const copyButtonText = this.state.copiedLink ? (<div>{'Copy '}<i className='fa fa-check'/></div>) : 'Copy';
+ const copyButtonText = this.state.copiedLink ? (
+ <div>
+ <FormattedMessage
+ id='post_info.copy'
+ defaultMessage='Copy '
+ />
+ <i className='fa fa-check'/></div>
+ ) : (<FormattedMessage id='post_info.copy' />);
+
const permalinkOverlay = (
<Popover
id='permalink-overlay'
diff --git a/web/react/components/posts_view.jsx b/web/react/components/posts_view.jsx
index 856403af5..f108ace2e 100644
--- a/web/react/components/posts_view.jsx
+++ b/web/react/components/posts_view.jsx
@@ -8,6 +8,9 @@ import * as Utils from '../utils/utils.jsx';
import Post from './post.jsx';
import Constants from '../utils/constants.jsx';
import DelayedAction from '../utils/delayed_action.jsx';
+
+import {FormattedDate, FormattedMessage} from 'mm-intl';
+
const Preferences = Constants.Preferences;
export default class PostsView extends React.Component {
@@ -250,7 +253,15 @@ export default class PostsView extends React.Component {
className='date-separator'
>
<hr className='separator__hr' />
- <div className='separator__text'>{currentPostDay.toDateString()}</div>
+ <div className='separator__text'>
+ <FormattedDate
+ value={currentPostDay}
+ weekday='short'
+ month='short'
+ day='2-digit'
+ year='numeric'
+ />
+ </div>
</div>
);
}
@@ -276,7 +287,12 @@ export default class PostsView extends React.Component {
<hr
className='separator__hr'
/>
- <div className='separator__text'>{'New Messages'}</div>
+ <div className='separator__text'>
+ <FormattedMessage
+ id='posts_view.newMsg'
+ defaultMessage='New Messages'
+ />
+ </div>
</div>
);
}
@@ -420,7 +436,10 @@ export default class PostsView extends React.Component {
href='#'
onClick={this.loadMorePostsTop}
>
- {'Load more messages'}
+ <FormattedMessage
+ id='posts_view.loadMore'
+ defaultMessage='Load more messages'
+ />
</a>
);
} else {
@@ -436,7 +455,7 @@ export default class PostsView extends React.Component {
href='#'
onClick={this.loadMorePostsBottom}
>
- {'Load more messages'}
+ <FormattedMessage id='posts_view.loadMore' />
</a>
);
} else {
diff --git a/web/react/components/time_since.jsx b/web/react/components/time_since.jsx
index 0b549b1e6..ba8dbffcc 100644
--- a/web/react/components/time_since.jsx
+++ b/web/react/components/time_since.jsx
@@ -2,7 +2,8 @@
// See License.txt for license information.
import Constants from '../utils/constants.jsx';
-import * as Utils from '../utils/utils.jsx';
+
+import {FormattedRelative, FormattedDate} from 'mm-intl';
var Tooltip = ReactBootstrap.Tooltip;
var OverlayTrigger = ReactBootstrap.OverlayTrigger;
@@ -20,20 +21,25 @@ export default class TimeSince extends React.Component {
clearInterval(this.intervalId);
}
render() {
- const displayDate = Utils.displayDate(this.props.eventTime);
- const displayTime = Utils.displayTime(this.props.eventTime);
-
if (this.props.sameUser) {
return (
<time className='post__time'>
- {Utils.displayTime(this.props.eventTime)}
+ <FormattedRelative value={this.props.eventTime} />
</time>
);
}
const tooltip = (
<Tooltip id={'time-since-tooltip-' + this.props.eventTime}>
- {displayDate + ' at ' + displayTime}
+ <FormattedDate
+ value={this.props.eventTime}
+ month='long'
+ day='numeric'
+ year='numeric'
+ hour12={true}
+ hour='numeric'
+ minute='2-digit'
+ />
</Tooltip>
);
@@ -44,7 +50,7 @@ export default class TimeSince extends React.Component {
overlay={tooltip}
>
<time className='post__time'>
- {Utils.displayDateTime(this.props.eventTime)}
+ <FormattedRelative value={this.props.eventTime} />
</time>
</OverlayTrigger>
);
diff --git a/web/react/components/user_settings/user_settings_display.jsx b/web/react/components/user_settings/user_settings_display.jsx
index 3b2a2065b..776bde442 100644
--- a/web/react/components/user_settings/user_settings_display.jsx
+++ b/web/react/components/user_settings/user_settings_display.jsx
@@ -297,7 +297,7 @@ class UserSettingsDisplay extends React.Component {
if (this.state.nameFormat === 'username') {
describe = formatMessage(holders.showUsername);
} else if (this.state.nameFormat === 'full_name') {
- describe = formatMessage(holders.showFullName);
+ describe = formatMessage(holders.showFullname);
} else {
describe = formatMessage(holders.showNickname);
}
diff --git a/web/react/components/view_image.jsx b/web/react/components/view_image.jsx
index d11f8a21c..90885e495 100644
--- a/web/react/components/view_image.jsx
+++ b/web/react/components/view_image.jsx
@@ -9,10 +9,20 @@ import Constants from '../utils/constants.jsx';
import FileInfoPreview from './file_info_preview.jsx';
import FileStore from '../stores/file_store.jsx';
import ViewImagePopoverBar from './view_image_popover_bar.jsx';
+
+import {intlShape, injectIntl, defineMessages} from 'mm-intl';
+
const Modal = ReactBootstrap.Modal;
const KeyCodes = Constants.KeyCodes;
-export default class ViewImageModal extends React.Component {
+const holders = defineMessages({
+ loading: {
+ id: 'view_image.loading',
+ defaultMessage: 'Loading '
+ }
+});
+
+class ViewImageModal extends React.Component {
constructor(props) {
super(props);
@@ -235,6 +245,7 @@ export default class ViewImageModal extends React.Component {
fileUrl={fileUrl}
fileInfo={this.state.fileInfo}
maxHeight={this.state.imgHeight}
+ formatMessage={this.props.intl.formatMessage}
/>
);
} else {
@@ -243,6 +254,7 @@ export default class ViewImageModal extends React.Component {
filename={filename}
fileUrl={fileUrl}
fileInfo={fileInfo}
+ formatMessage={this.props.intl.formatMessage}
/>
);
}
@@ -250,7 +262,12 @@ export default class ViewImageModal extends React.Component {
// display a progress indicator when the preview for an image is still loading
const progress = Math.floor(this.state.progress[this.state.imgId]);
- content = <LoadingImagePreview progress={progress} />;
+ content = (
+ <LoadingImagePreview
+ progress={progress}
+ loading={this.props.intl.formatMessage(holders.loading)}
+ />
+ );
}
let leftArrow = null;
@@ -335,6 +352,7 @@ ViewImageModal.defaultProps = {
startId: 0
};
ViewImageModal.propTypes = {
+ intl: intlShape.isRequired,
show: React.PropTypes.bool.isRequired,
onModalDismissed: React.PropTypes.func.isRequired,
filenames: React.PropTypes.array,
@@ -344,12 +362,12 @@ ViewImageModal.propTypes = {
startId: React.PropTypes.number
};
-function LoadingImagePreview({progress}) {
+function LoadingImagePreview({progress, loading}) {
let progressView = null;
if (progress) {
progressView = (
<span className='loader-percent'>
- {'Loading ' + progress + '%'}
+ {loading + progress + '%'}
</span>
);
}
@@ -386,3 +404,5 @@ function ImagePreview({filename, fileUrl, fileInfo, maxHeight}) {
</a>
);
}
+
+export default injectIntl(ViewImageModal); \ No newline at end of file
diff --git a/web/react/components/view_image_popover_bar.jsx b/web/react/components/view_image_popover_bar.jsx
index 1287f4fba..97671b845 100644
--- a/web/react/components/view_image_popover_bar.jsx
+++ b/web/react/components/view_image_popover_bar.jsx
@@ -1,6 +1,8 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
+import {FormattedMessage} from 'mm-intl';
+
export default class ViewImagePopoverBar extends React.Component {
constructor(props) {
super(props);
@@ -16,7 +18,10 @@ export default class ViewImagePopoverBar extends React.Component {
data-title='Public Image'
onClick={this.props.getPublicLink}
>
- {'Get Public Link'}
+ <FormattedMessage
+ id='view_image_popover.publicLink'
+ defaultMessage='Get Public Link'
+ />
</a>
<span className='text'>{' | '}</span>
</div>
@@ -33,7 +38,16 @@ export default class ViewImagePopoverBar extends React.Component {
ref='imageFooter'
className={footerClass}
>
- <span className='pull-left text'>{'File ' + (this.props.fileId + 1) + ' of ' + this.props.totalFiles}</span>
+ <span className='pull-left text'>
+ <FormattedMessage
+ id='view_image_popover.file'
+ defaultMessage='File {count} of {total}'
+ values={{
+ count: (this.props.fileId + 1),
+ total: this.props.totalFiles
+ }}
+ />
+ </span>
<div className='image-links'>
{publicLink}
<a
@@ -41,7 +55,10 @@ export default class ViewImagePopoverBar extends React.Component {
download={this.props.filename}
className='text'
>
- {'Download'}
+ <FormattedMessage
+ id='view_image_popover.download'
+ defaultMessage='Download'
+ />
</a>
</div>
</div>
diff --git a/web/react/stores/post_store.jsx b/web/react/stores/post_store.jsx
index 7abadf2b1..08ffef822 100644
--- a/web/react/stores/post_store.jsx
+++ b/web/react/stores/post_store.jsx
@@ -446,7 +446,7 @@ class PostStoreClass extends EventEmitter {
posts = {};
}
- post.message = '(message deleted)';
+ post.message = this.delete_message;
post.state = Constants.POST_DELETED;
post.filenames = [];
@@ -581,6 +581,9 @@ class PostStoreClass extends EventEmitter {
return commentCount;
}
+ deleteMessage(msg) {
+ this.delete_message = msg;
+ }
}
var PostStore = new PostStoreClass();
diff --git a/web/react/stores/socket_store.jsx b/web/react/stores/socket_store.jsx
index 736b0ca27..744c2c8e5 100644
--- a/web/react/stores/socket_store.jsx
+++ b/web/react/stores/socket_store.jsx
@@ -86,7 +86,7 @@ class SocketStoreClass extends EventEmitter {
this.failCount = this.failCount + 1;
- ErrorStore.storeLastError({connErrorCount: this.failCount, message: 'Please check connection, Mattermost unreachable. If issue persists, ask administrator to check WebSocket port.'});
+ ErrorStore.storeLastError({connErrorCount: this.failCount, message: this.translations.socketError});
ErrorStore.emitChange();
};
@@ -109,7 +109,7 @@ class SocketStoreClass extends EventEmitter {
handleMessage(msg) {
switch (msg.action) {
case SocketEvents.POSTED:
- handleNewPostEvent(msg);
+ handleNewPostEvent(msg, this.translations);
break;
case SocketEvents.POST_EDITED:
@@ -151,9 +151,12 @@ class SocketStoreClass extends EventEmitter {
this.initialize();
}
}
+ setTranslations(messages) {
+ this.translations = messages;
+ }
}
-function handleNewPostEvent(msg) {
+function handleNewPostEvent(msg, translations) {
// Store post
const post = JSON.parse(msg.props.post);
EventHelpers.emitPostRecievedEvent(post);
@@ -192,14 +195,14 @@ function handleNewPostEvent(msg) {
return;
}
- let username = 'Someone';
+ let username = translations.someone;
if (post.props.override_username && global.window.mm_config.EnablePostUsernameOverride === 'true') {
username = post.props.override_username;
} else if (UserStore.hasProfile(msg.user_id)) {
username = UserStore.getProfile(msg.user_id).username;
}
- let title = 'Posted';
+ let title = translations.posted;
if (channel) {
title = channel.display_name;
}
@@ -211,14 +214,14 @@ function handleNewPostEvent(msg) {
if (notifyText.length === 0) {
if (msgProps.image) {
- Utils.notifyMe(title, username + ' uploaded an image', channel);
+ Utils.notifyMe(title, username + translations.uploadedImage, channel);
} else if (msgProps.otherFile) {
- Utils.notifyMe(title, username + ' uploaded a file', channel);
+ Utils.notifyMe(title, username + translations.uploadedFile, channel);
} else {
- Utils.notifyMe(title, username + ' did something new', channel);
+ Utils.notifyMe(title, username + translations.something, channel);
}
} else {
- Utils.notifyMe(title, username + ' wrote: ' + notifyText, channel);
+ Utils.notifyMe(title, username + translations.wrote + notifyText, channel);
}
if (!user.notify_props || user.notify_props.desktop_sound === 'true') {
Utils.ding();
diff --git a/web/react/utils/channel_intro_messages.jsx b/web/react/utils/channel_intro_messages.jsx
index 9685f94b0..69e08f143 100644
--- a/web/react/utils/channel_intro_messages.jsx
+++ b/web/react/utils/channel_intro_messages.jsx
@@ -11,6 +11,8 @@ import Constants from '../utils/constants.jsx';
import TeamStore from '../stores/team_store.jsx';
import * as EventHelpers from '../dispatcher/event_helpers.jsx';
+import {FormattedMessage, FormattedHTMLMessage, FormattedDate} from 'mm-intl';
+
export function createChannelIntroMessage(channel) {
if (channel.type === 'D') {
return createDMIntroMessage(channel);
@@ -48,8 +50,13 @@ export function createDMIntroMessage(channel) {
</strong>
</div>
<p className='channel-intro-text'>
- {'This is the start of your direct message history with ' + teammateName + '.'}<br/>
- {'Direct messages and files shared here are not shown to people outside this area.'}
+ <FormattedHTMLMessage
+ id='intro_messages.DM'
+ defaultMessage='This is the start of your direct message history with {teammate}.<br />Direct messages and files shared here are not shown to people outside this area.'
+ values={{
+ teammate: teammateName
+ }}
+ />
</p>
{createSetHeaderButton(channel)}
</div>
@@ -58,7 +65,12 @@ export function createDMIntroMessage(channel) {
return (
<div className='channel-intro'>
- <p className='channel-intro-text'>{'This is the start of your direct message history with this teammate. Direct messages and files shared here are not shown to people outside this area.'}</p>
+ <p className='channel-intro-text'>
+ <FormattedMessage
+ id='intro_messages.teammate'
+ defaultMessage='This is the start of your direct message history with this teammate. Direct messages and files shared here are not shown to people outside this area.'
+ />
+ </p>
</div>
);
}
@@ -66,11 +78,13 @@ export function createDMIntroMessage(channel) {
export function createOffTopicIntroMessage(channel) {
return (
<div className='channel-intro'>
- <h4 className='channel-intro__title'>{'Beginning of ' + channel.display_name}</h4>
- <p className='channel-intro__content'>
- {'This is the start of ' + channel.display_name + ', a channel for non-work-related conversations.'}
- <br/>
- </p>
+ <FormattedHTMLMessage
+ id='intro_messages.offTopic'
+ defaultMessage='<h4 class="channel-intro__title">Beginning of {display_name}</h4><p class="channel-intro__content">This is the start of {display_name}, a channel for non-work-related conversations.<br/></p>'
+ values={{
+ display_name: channel.display_name
+ }}
+ />
{createSetHeaderButton(channel)}
{createInviteChannelMemberButton(channel, 'channel')}
</div>
@@ -87,7 +101,11 @@ export function createDefaultIntroMessage(channel) {
href='#'
onClick={EventHelpers.showInviteMemberModal}
>
- <i className='fa fa-user-plus'></i>{'Invite others to this team'}
+ <i className='fa fa-user-plus'></i>
+ <FormattedMessage
+ id='intro_messages.inviteOthers'
+ defaultMessage='Invite others to this team'
+ />
</a>
);
} else {
@@ -97,19 +115,24 @@ export function createDefaultIntroMessage(channel) {
href='#'
onClick={EventHelpers.showGetTeamInviteLinkModal}
>
- <i className='fa fa-user-plus'></i>{'Invite others to this team'}
+ <i className='fa fa-user-plus'></i>
+ <FormattedMessage
+ id='intro_messages.inviteOthers'
+ defaultMessage='Invite others to this team'
+ />
</a>
);
}
return (
<div className='channel-intro'>
- <h4 className='channel-intro__title'>{'Beginning of ' + channel.display_name}</h4>
- <p className='channel-intro__content'>
- <strong>{'Welcome to ' + channel.display_name + '!'}</strong>
- <br/><br/>
- {'This is the first channel teammates see when they sign up - use it for posting updates everyone needs to know.'}
- </p>
+ <FormattedHTMLMessage
+ id='intro_messages.default'
+ defaultMessage="<h4 class='channel-intro__title'>Beginning of {display_name}</h4><p class='channel-intro__content'><strong>Welcome to {display_name}!'</strong><br/><br/>This is the first channel teammates see when they sign up - use it for posting updates everyone needs to know.</p>"
+ values={{
+ display_name: channel.display_name
+ }}
+ />
{inviteModalLink}
{createSetHeaderButton(channel)}
<br/>
@@ -124,33 +147,83 @@ export function createStandardIntroMessage(channel) {
var uiType;
var memberMessage;
if (channel.type === 'P') {
- uiType = 'private group';
- memberMessage = ' Only invited members can see this private group.';
+ uiType = (
+ <FormattedMessage
+ id='intro_messages.group'
+ defaultMessage='private group'
+ />
+ );
+ memberMessage = (
+ <FormattedMessage
+ id='intro_messages.onlyInvited'
+ defaultMessage=' Only invited members can see this private group.'
+ />
+ );
} else {
- uiType = 'channel';
- memberMessage = ' Any member can join and read this channel.';
+ uiType = (
+ <FormattedMessage
+ id='intro_messages.channel'
+ defaultMessage='channel'
+ />
+ );
+ memberMessage = (
+ <FormattedMessage
+ id='intro_messages.anyMember'
+ defaultMessage=' Any member can join and read this channel.'
+ />
+ );
}
+ const date = (
+ <FormattedDate
+ value={channel.create_at}
+ month='long'
+ day='2-digit'
+ year='numeric'
+ />
+ );
+
var createMessage;
if (creatorName === '') {
- createMessage = 'This is the start of the ' + uiName + ' ' + uiType + ', created on ' + Utils.displayDate(channel.create_at) + '.';
+ createMessage = (
+ <FormattedMessage
+ id='intro_messages.noCreator'
+ defaultMessage='This is the start of the {name} {type}, created on {date}.'
+ values={{
+ name: (uiName),
+ type: (uiType),
+ date: (date)
+ }}
+ />
+ );
} else {
createMessage = (
<span>
- {'This is the start of the '}
- <strong>{uiName}</strong>
- {' '}
- {uiType}{', created by '}
- <strong>{creatorName}</strong>
- {' on '}
- <strong>{Utils.displayDate(channel.create_at)}</strong>
+ <FormattedHTMLMessage
+ id='intro_messages.creator'
+ defaultMessage='This is the start of the <strong>{name}</strong> {type}, created by <strong>{creator}</strong> on <strong>{date}</strong>'
+ values={{
+ name: (uiName),
+ type: (uiType),
+ date: (date),
+ creator: creatorName
+ }}
+ />
</span>
);
}
return (
<div className='channel-intro'>
- <h4 className='channel-intro__title'>{'Beginning of ' + uiName}</h4>
+ <h4 className='channel-intro__title'>
+ <FormattedMessage
+ id='intro_messages.beginning'
+ defaultMessage='Beginning of {name}'
+ values={{
+ name: (uiName)
+ }}
+ />
+ </h4>
<p className='channel-intro__content'>
{createMessage}
{memberMessage}
@@ -169,7 +242,14 @@ function createInviteChannelMemberButton(channel, uiType) {
dialogType={ChannelInviteModal}
dialogProps={{channel}}
>
- <i className='fa fa-user-plus'></i>{'Invite others to this ' + uiType}
+ <i className='fa fa-user-plus'></i>
+ <FormattedMessage
+ id='intro_messages.invite'
+ defaultMessage='Invite others to this {type}'
+ values={{
+ type: (uiType)
+ }}
+ />
</ToggleModalButton>
);
}
@@ -181,7 +261,11 @@ function createSetHeaderButton(channel) {
dialogType={EditChannelHeaderModal}
dialogProps={{channel}}
>
- <i className='fa fa-pencil'></i>{'Set a header'}
+ <i className='fa fa-pencil'></i>
+ <FormattedMessage
+ id='intro_messages.setHeader'
+ defaultMessage='Set a Header'
+ />
</ToggleModalButton>
);
}
diff --git a/web/react/utils/locales/en.js b/web/react/utils/locales/en.js
deleted file mode 100644
index 08d41225a..000000000
--- a/web/react/utils/locales/en.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// GENERATED FILE
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports["default"] = [{ "locale": "en", "pluralRuleFunction": function pluralRuleFunction(n, ord) {
- var s = String(n).split("."),
- v0 = !s[1],
- t0 = Number(s[0]) == n,
- n10 = t0 && s[0].slice(-1),
- n100 = t0 && s[0].slice(-2);if (ord) return n10 == 1 && n100 != 11 ? "one" : n10 == 2 && n100 != 12 ? "two" : n10 == 3 && n100 != 13 ? "few" : "other";return n == 1 && v0 ? "one" : "other";
-}, "fields": { "year": { "displayName": "Year", "relative": { "0": "this year", "1": "next year", "-1": "last year" }, "relativeTime": { "future": { "one": "in {0} year", "other": "in {0} years" }, "past": { "one": "{0} year ago", "other": "{0} years ago" } } }, "month": { "displayName": "Month", "relative": { "0": "this month", "1": "next month", "-1": "last month" }, "relativeTime": { "future": { "one": "in {0} month", "other": "in {0} months" }, "past": { "one": "{0} month ago", "other": "{0} months ago" } } }, "day": { "displayName": "Day", "relative": { "0": "today", "1": "tomorrow", "-1": "yesterday" }, "relativeTime": { "future": { "one": "in {0} day", "other": "in {0} days" }, "past": { "one": "{0} day ago", "other": "{0} days ago" } } }, "hour": { "displayName": "Hour", "relativeTime": { "future": { "one": "in {0} hour", "other": "in {0} hours" }, "past": { "one": "{0} hour ago", "other": "{0} hours ago" } } }, "minute": { "displayName": "Minute", "relativeTime": { "future": { "one": "in {0} minute", "other": "in {0} minutes" }, "past": { "one": "{0} minute ago", "other": "{0} minutes ago" } } }, "second": { "displayName": "Second", "relative": { "0": "now" }, "relativeTime": { "future": { "one": "in {0} second", "other": "in {0} seconds" }, "past": { "one": "{0} second ago", "other": "{0} seconds ago" } } } } }, { "locale": "en-001", "parentLocale": "en" }, { "locale": "en-150", "parentLocale": "en-GB" }, { "locale": "en-GB", "parentLocale": "en-001" }, { "locale": "en-AG", "parentLocale": "en-001" }, { "locale": "en-AI", "parentLocale": "en-001" }, { "locale": "en-AS", "parentLocale": "en" }, { "locale": "en-AU", "parentLocale": "en-GB", "fields": { "year": { "displayName": "Year", "relative": { "0": "This year", "1": "Next year", "-1": "Last year" }, "relativeTime": { "future": { "one": "in {0} year", "other": "in {0} years" }, "past": { "one": "{0} year ago", "other": "{0} years ago" } } }, "month": { "displayName": "Month", "relative": { "0": "This month", "1": "Next month", "-1": "Last month" }, "relativeTime": { "future": { "one": "in {0} month", "other": "in {0} months" }, "past": { "one": "{0} month ago", "other": "{0} months ago" } } }, "day": { "displayName": "Day", "relative": { "0": "today", "1": "tomorrow", "-1": "yesterday" }, "relativeTime": { "future": { "one": "in {0} day", "other": "in {0} days" }, "past": { "one": "{0} day ago", "other": "{0} days ago" } } }, "hour": { "displayName": "Hour", "relativeTime": { "future": { "one": "in {0} hour", "other": "in {0} hours" }, "past": { "one": "{0} hour ago", "other": "{0} hours ago" } } }, "minute": { "displayName": "Minute", "relativeTime": { "future": { "one": "in {0} minute", "other": "in {0} minutes" }, "past": { "one": "{0} minute ago", "other": "{0} minutes ago" } } }, "second": { "displayName": "Second", "relative": { "0": "now" }, "relativeTime": { "future": { "one": "in {0} second", "other": "in {0} seconds" }, "past": { "one": "{0} second ago", "other": "{0} seconds ago" } } } } }, { "locale": "en-BB", "parentLocale": "en-001" }, { "locale": "en-BE", "parentLocale": "en-GB" }, { "locale": "en-BM", "parentLocale": "en-001" }, { "locale": "en-BS", "parentLocale": "en-001" }, { "locale": "en-BW", "parentLocale": "en-001" }, { "locale": "en-BZ", "parentLocale": "en-001" }, { "locale": "en-CA", "parentLocale": "en" }, { "locale": "en-CC", "parentLocale": "en-001" }, { "locale": "en-CK", "parentLocale": "en-001" }, { "locale": "en-CM", "parentLocale": "en-001" }, { "locale": "en-CX", "parentLocale": "en-001" }, { "locale": "en-DG", "parentLocale": "en-GB" }, { "locale": "en-DM", "parentLocale": "en-001" }, { "locale": "en-Dsrt", "pluralRuleFunction": function pluralRuleFunction(n, ord) {
- if (ord) return "other";return "other";
-}, "fields": { "year": { "displayName": "Year", "relative": { "0": "this year", "1": "next year", "-1": "last year" }, "relativeTime": { "future": { "other": "+{0} y" }, "past": { "other": "-{0} y" } } }, "month": { "displayName": "Month", "relative": { "0": "this month", "1": "next month", "-1": "last month" }, "relativeTime": { "future": { "other": "+{0} m" }, "past": { "other": "-{0} m" } } }, "day": { "displayName": "Day", "relative": { "0": "today", "1": "tomorrow", "-1": "yesterday" }, "relativeTime": { "future": { "other": "+{0} d" }, "past": { "other": "-{0} d" } } }, "hour": { "displayName": "Hour", "relativeTime": { "future": { "other": "+{0} h" }, "past": { "other": "-{0} h" } } }, "minute": { "displayName": "Minute", "relativeTime": { "future": { "other": "+{0} min" }, "past": { "other": "-{0} min" } } }, "second": { "displayName": "Second", "relative": { "0": "now" }, "relativeTime": { "future": { "other": "+{0} s" }, "past": { "other": "-{0} s" } } } } }, { "locale": "en-ER", "parentLocale": "en-001" }, { "locale": "en-FJ", "parentLocale": "en-001" }, { "locale": "en-FK", "parentLocale": "en-GB" }, { "locale": "en-FM", "parentLocale": "en-001" }, { "locale": "en-GD", "parentLocale": "en-001" }, { "locale": "en-GG", "parentLocale": "en-GB" }, { "locale": "en-GH", "parentLocale": "en-001" }, { "locale": "en-GI", "parentLocale": "en-GB" }, { "locale": "en-GM", "parentLocale": "en-001" }, { "locale": "en-GU", "parentLocale": "en" }, { "locale": "en-GY", "parentLocale": "en-001" }, { "locale": "en-HK", "parentLocale": "en-GB" }, { "locale": "en-IE", "parentLocale": "en-GB" }, { "locale": "en-IM", "parentLocale": "en-GB" }, { "locale": "en-IN", "parentLocale": "en-GB" }, { "locale": "en-IO", "parentLocale": "en-GB" }, { "locale": "en-JE", "parentLocale": "en-GB" }, { "locale": "en-JM", "parentLocale": "en-001" }, { "locale": "en-KE", "parentLocale": "en-001" }, { "locale": "en-KI", "parentLocale": "en-001" }, { "locale": "en-KN", "parentLocale": "en-001" }, { "locale": "en-KY", "parentLocale": "en-001" }, { "locale": "en-LC", "parentLocale": "en-001" }, { "locale": "en-LR", "parentLocale": "en-001" }, { "locale": "en-LS", "parentLocale": "en-001" }, { "locale": "en-MG", "parentLocale": "en-001" }, { "locale": "en-MH", "parentLocale": "en" }, { "locale": "en-MO", "parentLocale": "en-GB" }, { "locale": "en-MP", "parentLocale": "en" }, { "locale": "en-MS", "parentLocale": "en-001" }, { "locale": "en-MT", "parentLocale": "en-GB" }, { "locale": "en-MU", "parentLocale": "en-001" }, { "locale": "en-MW", "parentLocale": "en-001" }, { "locale": "en-MY", "parentLocale": "en-001" }, { "locale": "en-NA", "parentLocale": "en-001" }, { "locale": "en-NF", "parentLocale": "en-001" }, { "locale": "en-NG", "parentLocale": "en-001" }, { "locale": "en-NR", "parentLocale": "en-001" }, { "locale": "en-NU", "parentLocale": "en-001" }, { "locale": "en-NZ", "parentLocale": "en-GB" }, { "locale": "en-PG", "parentLocale": "en-001" }, { "locale": "en-PH", "parentLocale": "en-001" }, { "locale": "en-PK", "parentLocale": "en-GB" }, { "locale": "en-PN", "parentLocale": "en-001" }, { "locale": "en-PR", "parentLocale": "en" }, { "locale": "en-PW", "parentLocale": "en-001" }, { "locale": "en-RW", "parentLocale": "en-001" }, { "locale": "en-SB", "parentLocale": "en-001" }, { "locale": "en-SC", "parentLocale": "en-001" }, { "locale": "en-SD", "parentLocale": "en-001" }, { "locale": "en-SG", "parentLocale": "en-GB" }, { "locale": "en-SH", "parentLocale": "en-GB" }, { "locale": "en-SL", "parentLocale": "en-001" }, { "locale": "en-SS", "parentLocale": "en-001" }, { "locale": "en-SX", "parentLocale": "en-001" }, { "locale": "en-SZ", "parentLocale": "en-001" }, { "locale": "en-TC", "parentLocale": "en-001" }, { "locale": "en-TK", "parentLocale": "en-001" }, { "locale": "en-TO", "parentLocale": "en-001" }, { "locale": "en-TT", "parentLocale": "en-001" }, { "locale": "en-TV", "parentLocale": "en-001" }, { "locale": "en-TZ", "parentLocale": "en-001" }, { "locale": "en-UG", "parentLocale": "en-001" }, { "locale": "en-UM", "parentLocale": "en" }, { "locale": "en-US", "parentLocale": "en" }, { "locale": "en-US-POSIX", "parentLocale": "en-US" }, { "locale": "en-VC", "parentLocale": "en-001" }, { "locale": "en-VG", "parentLocale": "en-GB" }, { "locale": "en-VI", "parentLocale": "en" }, { "locale": "en-VU", "parentLocale": "en-001" }, { "locale": "en-WS", "parentLocale": "en-001" }, { "locale": "en-ZA", "parentLocale": "en-001" }, { "locale": "en-ZM", "parentLocale": "en-001" }, { "locale": "en-ZW", "parentLocale": "en-001" }];
-module.exports = exports["default"]; \ No newline at end of file
diff --git a/web/react/utils/locales/es.js b/web/react/utils/locales/es.js
deleted file mode 100644
index 8591950ca..000000000
--- a/web/react/utils/locales/es.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// GENERATED FILE
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports["default"] = [{ "locale": "es", "pluralRuleFunction": function pluralRuleFunction(n, ord) {
- if (ord) return "other";return n == 1 ? "one" : "other";
-}, "fields": { "year": { "displayName": "Año", "relative": { "0": "este año", "1": "el próximo año", "-1": "el año pasado" }, "relativeTime": { "future": { "one": "dentro de {0} año", "other": "dentro de {0} años" }, "past": { "one": "hace {0} año", "other": "hace {0} años" } } }, "month": { "displayName": "Mes", "relative": { "0": "este mes", "1": "el próximo mes", "-1": "el mes pasado" }, "relativeTime": { "future": { "one": "dentro de {0} mes", "other": "dentro de {0} meses" }, "past": { "one": "hace {0} mes", "other": "hace {0} meses" } } }, "day": { "displayName": "Día", "relative": { "0": "hoy", "1": "mañana", "2": "pasado mañana", "-1": "ayer", "-2": "antes de ayer" }, "relativeTime": { "future": { "one": "dentro de {0} día", "other": "dentro de {0} días" }, "past": { "one": "hace {0} día", "other": "hace {0} días" } } }, "hour": { "displayName": "Hora", "relativeTime": { "future": { "one": "dentro de {0} hora", "other": "dentro de {0} horas" }, "past": { "one": "hace {0} hora", "other": "hace {0} horas" } } }, "minute": { "displayName": "Minuto", "relativeTime": { "future": { "one": "dentro de {0} minuto", "other": "dentro de {0} minutos" }, "past": { "one": "hace {0} minuto", "other": "hace {0} minutos" } } }, "second": { "displayName": "Segundo", "relative": { "0": "ahora" }, "relativeTime": { "future": { "one": "dentro de {0} segundo", "other": "dentro de {0} segundos" }, "past": { "one": "hace {0} segundo", "other": "hace {0} segundos" } } } } }, { "locale": "es-419", "parentLocale": "es", "fields": { "year": { "displayName": "Año", "relative": { "0": "Este año", "1": "Año próximo", "-1": "Año pasado" }, "relativeTime": { "future": { "one": "En {0} año", "other": "En {0} años" }, "past": { "one": "hace {0} año", "other": "hace {0} años" } } }, "month": { "displayName": "Mes", "relative": { "0": "Este mes", "1": "Mes próximo", "-1": "El mes pasado" }, "relativeTime": { "future": { "one": "En {0} mes", "other": "En {0} meses" }, "past": { "one": "hace {0} mes", "other": "hace {0} meses" } } }, "day": { "displayName": "Día", "relative": { "0": "hoy", "1": "mañana", "2": "pasado mañana", "-1": "ayer", "-2": "antes de ayer" }, "relativeTime": { "future": { "one": "En {0} día", "other": "En {0} días" }, "past": { "one": "hace {0} día", "other": "hace {0} días" } } }, "hour": { "displayName": "Hora", "relativeTime": { "future": { "one": "En {0} hora", "other": "En {0} horas" }, "past": { "one": "hace {0} hora", "other": "hace {0} horas" } } }, "minute": { "displayName": "Minuto", "relativeTime": { "future": { "one": "En {0} minuto", "other": "En {0} minutos" }, "past": { "one": "hace {0} minuto", "other": "hace {0} minutos" } } }, "second": { "displayName": "Segundo", "relative": { "0": "ahora" }, "relativeTime": { "future": { "one": "En {0} segundo", "other": "En {0} segundos" }, "past": { "one": "hace {0} segundo", "other": "hace {0} segundos" } } } } }, { "locale": "es-AR", "parentLocale": "es-419" }, { "locale": "es-BO", "parentLocale": "es-419" }, { "locale": "es-CL", "parentLocale": "es-419" }, { "locale": "es-CO", "parentLocale": "es-419" }, { "locale": "es-CR", "parentLocale": "es-419" }, { "locale": "es-CU", "parentLocale": "es-419" }, { "locale": "es-DO", "parentLocale": "es-419" }, { "locale": "es-EA", "parentLocale": "es" }, { "locale": "es-EC", "parentLocale": "es-419" }, { "locale": "es-ES", "parentLocale": "es" }, { "locale": "es-GQ", "parentLocale": "es" }, { "locale": "es-GT", "parentLocale": "es-419" }, { "locale": "es-HN", "parentLocale": "es-419" }, { "locale": "es-IC", "parentLocale": "es" }, { "locale": "es-MX", "parentLocale": "es-419", "fields": { "year": { "displayName": "Año", "relative": { "0": "este año", "1": "el año próximo", "-1": "el año pasado" }, "relativeTime": { "future": { "one": "En {0} año", "other": "En {0} años" }, "past": { "one": "hace {0} año", "other": "hace {0} años" } } }, "month": { "displayName": "Mes", "relative": { "0": "este mes", "1": "el mes próximo", "-1": "el mes pasado" }, "relativeTime": { "future": { "one": "en {0} mes", "other": "en {0} meses" }, "past": { "one": "hace {0} mes", "other": "hace {0} meses" } } }, "day": { "displayName": "Día", "relative": { "0": "hoy", "1": "mañana", "2": "pasado mañana", "-1": "ayer", "-2": "antes de ayer" }, "relativeTime": { "future": { "one": "En {0} día", "other": "En {0} días" }, "past": { "one": "hace {0} día", "other": "hace {0} días" } } }, "hour": { "displayName": "Hora", "relativeTime": { "future": { "one": "En {0} hora", "other": "En {0} horas" }, "past": { "one": "hace {0} hora", "other": "hace {0} horas" } } }, "minute": { "displayName": "Minuto", "relativeTime": { "future": { "one": "En {0} minuto", "other": "En {0} minutos" }, "past": { "one": "hace {0} minuto", "other": "hace {0} minutos" } } }, "second": { "displayName": "Segundo", "relative": { "0": "ahora" }, "relativeTime": { "future": { "one": "En {0} segundo", "other": "En {0} segundos" }, "past": { "one": "hace {0} segundo", "other": "hace {0} segundos" } } } } }, { "locale": "es-NI", "parentLocale": "es-419" }, { "locale": "es-PA", "parentLocale": "es-419" }, { "locale": "es-PE", "parentLocale": "es-419" }, { "locale": "es-PH", "parentLocale": "es" }, { "locale": "es-PR", "parentLocale": "es-419" }, { "locale": "es-PY", "parentLocale": "es-419" }, { "locale": "es-SV", "parentLocale": "es-419" }, { "locale": "es-US", "parentLocale": "es-419" }, { "locale": "es-UY", "parentLocale": "es-419" }, { "locale": "es-VE", "parentLocale": "es-419" }];
-module.exports = exports["default"]; \ No newline at end of file
diff --git a/web/static/i18n/en.json b/web/static/i18n/en.json
index 890e7188d..aaffc6ea7 100644
--- a/web/static/i18n/en.json
+++ b/web/static/i18n/en.json
@@ -8,54 +8,6 @@
"about.date": "Build Date:",
"about.hash": "Build Hash:",
"about.close": "Close",
- "audit_table.sessionRevoked": "The session with id {sessionId} was revoked",
- "audit_table.channelCreated": "Created the {channelName} channel/group",
- "audit_table.establishedDM": "Established a direct message channel with {username}",
- "audit_table.nameUpdated": "Updated the {channelName} channel/group name",
- "audit_table.headerUpdated": "Updated the {channelName} channel/group header",
- "audit_table.channelDeleted": "Deleted the channel/group with the URL {url}",
- "audit_table.userAdded": "Added {username} to the {channelName} channel/group",
- "audit_table.userRemoved": "Removed {username} to the {channelName} channel/group",
- "audit_table.attemptedRegisterApp": "Attempted to register a new OAuth Application with ID {id}",
- "audit_table.attemptedAllowOAuthAccess": "Attempted to allow a new OAuth service access",
- "audit_table.successfullOAuthAccess": "Successfully gave a new OAuth service access",
- "audit_table.failedOAuthAccess": "Failed to allow a new OAuth service access - the redirect URI did not match the previously registered callback",
- "audit_table.attemptedOAuthToken": "Attempted to get an OAuth access token",
- "audit_table.successfullOAuthToken": "Successfully added a new OAuth service",
- "audit_table.oauthTokenFailed": "Failed to get an OAuth access token - {token}",
- "audit_table.attemptedLogin": "Attempted to login",
- "audit_table.successfullLogin": "Successfully logged in",
- "audit_table.failedLogin": "FAILED login attempt",
- "audit_table.updatePicture": "Updated your profile picture",
- "audit_table.updateGeneral": "Updated the general settings of your account",
- "audit_table.attemptedPassword": "Attempted to change password",
- "audit_table.successfullPassword": "Successfully changed password",
- "audit_table.failedPassword": "Failed to change password - tried to update user password who was logged in through oauth",
- "audit_table.updatedRol": "Updated user role(s) to ",
- "audit_table.member": "member",
- "audit_table.accountActive": "Account made active",
- "audit_table.accountInactive": "Account made inactive",
- "audit_table.by": " by {username}",
- "audit_table.byAdmin": " by an admin",
- "audit_table.sentEmail": "Sent an email to {email} to reset your password",
- "audit_table.attemptedReset": "Attempted to reset password",
- "audit_table.successfullReset": "Successfully reset password",
- "audit_table.updateGlobalNotifications": "Updated your global notification settings",
- "audit_table.attemptedWebhookCreate": "Attempted to create a webhook",
- "audit_table.successfullWebhookCreate": "Successfully created a webhook",
- "audit_table.failedWebhookCreate": "Failed to create a webhook - bad channel permissions",
- "audit_table.attemptedWebhookDelete": "Attempted to delete a webhook",
- "audit_table.successfullWebhookDelete": "Successfully deleted a webhook",
- "audit_table.failedWebhookDelete": "Failed to delete a webhook - inappropriate conditions",
- "audit_table.logout": "Logged out of your account",
- "audit_table.verified": "Sucessfully verified your email address",
- "audit_table.revokedAll": "Revoked all current sessions for the team",
- "audit_table.loginAttempt": " (Login attempt)",
- "audit_table.loginFailure": " (Login failure)",
- "audit_table.moreInfo": "More info",
- "audit_table.ip": "IP: {ip}",
- "audit_table.session": "Session ID: {id}",
- "audit_table.userId": "User ID",
"access_history.title": "Access History",
"activity_log_modal.iphoneNativeApp": "iPhone Native App",
"activity_log_modal.androidNativeApp": "Android Native App",
@@ -81,6 +33,7 @@
"admin.sidebar.statistics": "- Statistics",
"admin.sidebar.ldap": "LDAP Settings",
"admin.sidebar.license": "Edition and License",
+ "admin.sidebar.audits": "Audits",
"admin.sidebar.reports": "SITE REPORTS",
"admin.sidebar.view_statistics": "View Statistics",
"admin.sidebar.settings": "SETTINGS",
@@ -97,8 +50,6 @@
"admin.sidebar.teams": "TEAMS ({count})",
"admin.sidebar.other": "OTHER",
"admin.sidebar.logs": "Logs",
- "admin.sidebar.audits": "Audits",
- "admin.analytics.loading": "Loading...",
"admin.analytics.totalUsers": "Total Users",
"admin.analytics.publicChannels": "Public Channels",
"admin.analytics.privateGroups": "Private Groups",
@@ -110,11 +61,14 @@
"admin.analytics.channelTypes": "Channel Types",
"admin.analytics.textPosts": "Posts with Text-only",
"admin.analytics.postTypes": "Posts, Files and Hashtags",
+ "admin.analytics.loading": "Loading...",
"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.audits.title": "Server Audits",
+ "admin.audits.reload": "Reload",
"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\"",
@@ -254,7 +208,7 @@
"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.noLicense": "<h4 class=\"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",
@@ -339,8 +293,6 @@
"admin.log.save": "Save",
"admin.logs.title": "Server Logs",
"admin.logs.reload": "Reload",
- "admin.audits.title": "Server Audits",
- "admin.audits.reload": "Reload",
"admin.privacy.saving": "Saving Config...",
"admin.privacy.title": "Privacy Settings",
"admin.privacy.showEmailTitle": "Show Email Address: ",
@@ -484,11 +436,60 @@
"admin.user_item.makeActive": "Make Active",
"admin.user_item.makeInactive": "Make Inactive",
"admin.user_item.resetPwd": "Reset Password",
+ "audit_table.sessionRevoked": "The session with id {sessionId} was revoked",
+ "audit_table.channelCreated": "Created the {channelName} channel/group",
+ "audit_table.establishedDM": "Established a direct message channel with {username}",
+ "audit_table.nameUpdated": "Updated the {channelName} channel/group name",
+ "audit_table.headerUpdated": "Updated the {channelName} channel/group header",
+ "audit_table.channelDeleted": "Deleted the channel/group with the URL {url}",
+ "audit_table.userAdded": "Added {username} to the {channelName} channel/group",
+ "audit_table.userRemoved": "Removed {username} to the {channelName} channel/group",
+ "audit_table.attemptedRegisterApp": "Attempted to register a new OAuth Application with ID {id}",
+ "audit_table.attemptedAllowOAuthAccess": "Attempted to allow a new OAuth service access",
+ "audit_table.successfullOAuthAccess": "Successfully gave a new OAuth service access",
+ "audit_table.failedOAuthAccess": "Failed to allow a new OAuth service access - the redirect URI did not match the previously registered callback",
+ "audit_table.attemptedOAuthToken": "Attempted to get an OAuth access token",
+ "audit_table.successfullOAuthToken": "Successfully added a new OAuth service",
+ "audit_table.oauthTokenFailed": "Failed to get an OAuth access token - {token}",
+ "audit_table.attemptedLogin": "Attempted to login",
+ "audit_table.successfullLogin": "Successfully logged in",
+ "audit_table.failedLogin": "FAILED login attempt",
+ "audit_table.updatePicture": "Updated your profile picture",
+ "audit_table.updateGeneral": "Updated the general settings of your account",
+ "audit_table.attemptedPassword": "Attempted to change password",
+ "audit_table.successfullPassword": "Successfully changed password",
+ "audit_table.failedPassword": "Failed to change password - tried to update user password who was logged in through oauth",
+ "audit_table.updatedRol": "Updated user role(s) to ",
+ "audit_table.member": "member",
+ "audit_table.accountActive": "Account made active",
+ "audit_table.accountInactive": "Account made inactive",
+ "audit_table.by": " by {username}",
+ "audit_table.byAdmin": " by an admin",
+ "audit_table.sentEmail": "Sent an email to {email} to reset your password",
+ "audit_table.attemptedReset": "Attempted to reset password",
+ "audit_table.successfullReset": "Successfully reset password",
+ "audit_table.updateGlobalNotifications": "Updated your global notification settings",
+ "audit_table.attemptedWebhookCreate": "Attempted to create a webhook",
+ "audit_table.successfullWebhookCreate": "Successfully created a webhook",
+ "audit_table.failedWebhookCreate": "Failed to create a webhook - bad channel permissions",
+ "audit_table.attemptedWebhookDelete": "Attempted to delete a webhook",
+ "audit_table.successfullWebhookDelete": "Successfully deleted a webhook",
+ "audit_table.failedWebhookDelete": "Failed to delete a webhook - inappropriate conditions",
+ "audit_table.logout": "Logged out of your account",
+ "audit_table.verified": "Sucessfully verified your email address",
+ "audit_table.revokedAll": "Revoked all current sessions for the team",
+ "audit_table.loginAttempt": " (Login attempt)",
+ "audit_table.loginFailure": " (Login failure)",
+ "audit_table.userId": "User ID",
+ "audit_table.moreInfo": "More info",
+ "audit_table.ip": "IP: {ip}",
+ "audit_table.session": "Session ID: {id}",
"authorize.title": "An application would like to connect to your {teamName} account",
"authorize.app": "The app <strong>{appName}</strong> would like the ability to access and modify your basic information.",
"authorize.access": "Allow <strong>{appName}</strong> access?",
"authorize.deny": "Deny",
"authorize.allow": "Allow",
+ "center_panel.recent": "Click here to jump to recent messages. ",
"change_url.longer": "Must be longer than two characters",
"change_url.startWithLetter": "Must start with a letter or number",
"change_url.endWithLetter": "Must end with a letter or number",
@@ -516,6 +517,13 @@
"channel_info.close": "Close",
"channel_invite.addNewMembers": "Add New Members to ",
"channel_invite.close": "Close",
+ "channel_loader.socketError": "Please check connection, Mattermost unreachable. If issue persists, ask administrator to check WebSocket port.",
+ "channel_loader.someone": "Someone",
+ "channel_loader.posted": "Posted",
+ "channel_loader.uploadedImage": " uploaded an image",
+ "channel_loader.uploadedFile": " uploaded a file",
+ "channel_loader.something": " did something new",
+ "channel_loader.wrote": " wrote: ",
"channel_memebers_modal.members": " Members",
"channel_members_modal.addNew": " Add New Members",
"channel_members_modal.close": "Close",
@@ -551,6 +559,11 @@
"create_comment.commentTitle": "Comment",
"create_comment.file": "File uploading",
"create_comment.files": "Files uploading",
+ "create_post.comment": "Comment",
+ "create_post.post": "Post",
+ "create_post.write": "Write a message...",
+ "create_post.deleteMsg": "(message deleted)",
+ "create_post.tutorialTip": "<h4>Sending Messages</h4><p>Type here to write a message and press <strong>Enter</strong> to post it.</p><p>Click the <strong>Attachment</strong> button to upload an image or a file.</p>",
"delete_channel.channel": "channel",
"delete_channel.group": "group",
"delete_channel.confirm": "Confirm DELETE Channel",
@@ -588,6 +601,9 @@
"email_verify.resend": "Resend Email",
"email_verify.sent": " Verification email sent.",
"error_bar.preview_mode": "Preview Mode: Email notifications have not been configured",
+ "file_attachment.download": "Download",
+ "file_info_preview.type": "File type ",
+ "file_info_preview.size": "Size ",
"upload_overlay.info": "Drop a file to upload it.",
"file_upload.limited": "Uploads limited to {count} files maximum. Please use additional posts for more files.",
"file_upload.filesAbove": "Files above {max}MB could not be uploaded: {filenames}",
@@ -630,6 +646,12 @@
"login_email.email": "Email",
"login_email.pwd": "Password",
"login_email.signin": "Sign in",
+ "login_ldap.badTeam": "Bad team name",
+ "login_ldap.idlReq": "An LDAP ID is required",
+ "login_ldap.pwdReq": "An LDAP password is required",
+ "login_ldap.username": "LDAP Username",
+ "login_ldap.pwd": "LDAP Password",
+ "login_ldap.signin": "Sign in",
"login_username.badTeam": "Bad team name",
"login_username.usernameReq": "A username is required",
"login_username.pwdReq": "A password is required",
@@ -638,12 +660,6 @@
"login_username.username": "Username",
"login_username.pwd": "Password",
"login_username.signin": "Sign in",
- "login_ldap.badTeam": "Bad team name",
- "login_ldap.idlReq": "An LDAP ID is required",
- "login_ldap.pwdReq": "An LDAP password is required",
- "login_ldap.username": "LDAP Username",
- "login_ldap.pwd": "LDAP Password",
- "login_ldap.signin": "Sign in",
"login.gitlab": "with GitLab",
"login.google": "with Google Apps",
"login.changed": " Sign-in method changed successfully",
@@ -697,6 +713,19 @@
"navbar_dropdown.accountSettings": "Account Settings",
"navbar_dropdown.logout": "Logout",
"navbar_dropdown.about": "About Mattermost",
+ "navbar.viewInfo": "View Info",
+ "navbar.setHeader": "Set Channel Header...",
+ "navbar.setPurpose": "Set Channel Purpose...",
+ "navbar.addMembers": "Add Members",
+ "navbar.leave": "Leave Channel",
+ "navbar.manageMembers": "Manage Members",
+ "navbar.delete": "Delete Channel...",
+ "navbar.rename": "Rename Channel...",
+ "navbar.preferences": "Notification Preferences",
+ "navbar.toggle1": "Toggle sidebar",
+ "navbar.toggle2": "Toggle sidebar",
+ "navbar.click": "Click here",
+ "navbar.noHeader": "No channel header yet.{newline}{link} to add one.",
"channel_flow.invalidName": "Invalid Channel Name",
"channel_flow.alreadyExist": "A channel with that URL already exists",
"channel_flow.channel": "Channel",
@@ -737,9 +766,23 @@
"password_send.reset": "Reset my password",
"members_popover.msg": "Message",
"members_popover.title": "Members",
+ "post_attachment.collapse": "▲ collapse text",
+ "post_attachment.more": "▼ read more",
+ "post_body.plusOne": " plus 1 other file",
+ "post_body.plusMore": " plus {count} other files",
+ "post_body.commentedOn": "Commented on {name}{apostrophe} message: ",
+ "post_body.retry": "Retry",
"post_delete.notPosted": "Comment could not be posted",
"post_delete.someone": "Someone deleted the message on which you tried to post a comment.",
"post_delete.okay": "Okay",
+ "post_focus_view.beginning": "Beginning of Channel Archives",
+ "post_info.reply": "Reply",
+ "post_info.permalink": "Permalink",
+ "post_info.del": "Delete",
+ "post_info.edit": "Edit",
+ "post_info.copy": "Copy ",
+ "posts_view.newMsg": "New Messages",
+ "posts_view.loadMore": "Load more messages",
"register_app.required": "Required",
"register_app.optional": "Optional",
"register_app.nameError": "Application name must be filled in.",
@@ -841,6 +884,7 @@
"signup_user_completed.usernameLength": "Username must begin with a letter, and contain between {min} to {max} lowercase characters made up of numbers, letters, and the symbols '.', '-' and '_'.",
"signup_user_completed.passwordLength": "Please enter at least {min} characters",
"signup_user_completed.expired": "You've already completed the signup process for this invitation or this invitation has expired.",
+ "signup_user_completed.emailHelp": "Valid email required for sign-up",
"signup_user_completed.userHelp": "Username must begin with a letter, and contain between {min} to {max} lowercase characters made up of numbers, letters, and the symbols '.', '-' and '_'",
"signup_user_completed.emailIs": "Your email address is <strong>{email}</strong>. You'll use this address to sign in to {siteName}.",
"signup_user_completed.whatis": "What's your email address?",
@@ -1157,5 +1201,23 @@
"user.settings.security.gitlab": "GitLab SSO",
"user.settings.security.title": "Security Settings",
"user.settings.security.viewHistory": "View Access History",
- "user.settings.security.logoutActiveSessions": "View and Logout of Active Sessions"
-}
+ "user.settings.security.logoutActiveSessions": "View and Logout of Active Sessions",
+ "view_image_popover.publicLink": "Get Public Link",
+ "view_image_popover.file": "File {count} of {total}",
+ "view_image_popover.download": "Download",
+ "view_image.loading": "Loading ",
+ "intro_messages.DM": "This is the start of your direct message history with {teammate}.<br />Direct messages and files shared here are not shown to people outside this area.",
+ "intro_messages.teammate": "This is the start of your direct message history with this teammate. Direct messages and files shared here are not shown to people outside this area.",
+ "intro_messages.offTopic": "<h4 class=\"channel-intro__title\">Beginning of {display_name}</h4><p class=\"channel-intro__content\">This is the start of {display_name}, a channel for non-work-related conversations.<br/></p>",
+ "intro_messages.inviteOthers": "Invite others to this team",
+ "intro_messages.default": "<h4 class='channel-intro__title'>Beginning of {display_name}</h4><p class='channel-intro__content'><strong>Welcome to {display_name}!'</strong><br/><br/>This is the first channel teammates see when they sign up - use it for posting updates everyone needs to know.</p>",
+ "intro_messages.group": "private group",
+ "intro_messages.onlyInvited": " Only invited members can see this private group.",
+ "intro_messages.channel": "channel",
+ "intro_messages.anyMember": " Any member can join and read this channel.",
+ "intro_messages.noCreator": "This is the start of the {name} {type}, created on {date}.",
+ "intro_messages.creator": "This is the start of the <strong>{name}</strong> {type}, created by <strong>{creator}</strong> on <strong>{date}</strong>",
+ "intro_messages.beginning": "Beginning of {name}",
+ "intro_messages.invite": "Invite others to this {type}",
+ "intro_messages.setHeader": "Set a Header"
+} \ No newline at end of file
diff --git a/web/static/i18n/es.json b/web/static/i18n/es.json
index 92f3ba2ea..981e1f06f 100644
--- a/web/static/i18n/es.json
+++ b/web/static/i18n/es.json
@@ -8,54 +8,7 @@
"about.teamEdtion": "Edición Team",
"about.title": "Acerca de Mattermost",
"about.version": "Versión:",
- "access_history.accountActive": "La cuenta se ha activado",
- "access_history.accountInactive": "La cuenta se ha desactivado",
- "access_history.attemptedAllowOAuthAccess": "Intento para permitir acceso a un nuevo servicio de OAuth",
- "access_history.attemptedLogin": "Intento de inicio de sesión",
- "access_history.attemptedOAuthToken": "Intento de obtener un token de acceso de OAuth",
- "access_history.attemptedPassword": "Intento de cambio de contraseña",
- "access_history.attemptedRegisterApp": "Intento de registrar una nueva aplicación OAuth con el ID {id}",
- "access_history.attemptedReset": "Intento de reestablecer al contraseña",
- "access_history.attemptedWebhookCreate": "Intento de creación de un webhook",
- "access_history.attemptedWebhookDelete": "Intento de eliminación de un webhook",
- "access_history.by": " por {username}",
- "access_history.byAdmin": " por un admin",
- "access_history.channelCreated": "Creado el canal/grupo {channelName}",
- "access_history.channelDeleted": "Eliminado el canal/grupo con el URL {url}",
- "access_history.establishedDM": "Establecido un canal de mensajes directos con {username}",
- "access_history.failedLogin": "Intento de inicio de sesión FALLIDO",
- "access_history.failedOAuthAccess": "Fallo al permitir acceso a un nuevo servicio de OAuth - la URI de redirección no concuerda con la previamente registrada",
- "access_history.failedPassword": "Fallo al cambiar la contraseña - se trató de actualizar la contraseña de un usuario que ingresó por medio de un servicio de OAuth",
- "access_history.failedWebhookCreate": "Falló la creación del webhook - permisos inadecuados del canal",
- "access_history.failedWebhookDelete": "Falló la eliminación del webhook - condiciones inapropiadas",
- "access_history.headerUpdated": "Actualizado el cancabezado del canal/grupo {channelName}",
- "access_history.ip": "IP: {ip}",
- "access_history.loginAttempt": " (intento de inicio de sesión)",
- "access_history.loginFailure": " (Fallo de inicio de sesión)",
- "access_history.logout": "Cerrada la sesión de tu cuenta",
- "access_history.member": "miembro",
- "access_history.moreInfo": "Más información",
- "access_history.nameUpdated": "Actualizado el nombre del canal/grupo {channelName}",
- "access_history.oauthTokenFailed": "Fallo al obtener un token de acceso de OAuth - {token}",
- "access_history.revokedAll": "Revocadas todas las sesiones actuales para el equipo",
- "access_history.sentEmail": "Enviado un correo electrónico a {email} para restablecer tu contraseña",
- "access_history.session": "Sesión ID: {id}",
- "access_history.sessionRevoked": "La sesión con el id {sessionId} fue revocada",
- "access_history.successfullLogin": "Inicio de sesión con éxito",
- "access_history.successfullOAuthAccess": "Se asignó un nuevo servicio de OAuth con éxito",
- "access_history.successfullOAuthToken": "Se agregó un nuevo servicio de OAuth con éxito",
- "access_history.successfullPassword": "La contraseña se cambió satisfactoriamente",
- "access_history.successfullReset": "La contraseña fue reestablecida con éxito",
- "access_history.successfullWebhookCreate": "Creación del webhook con éxito",
- "access_history.successfullWebhookDelete": "Eliminación del webhook con éxito",
"access_history.title": "Historial de Acceso",
- "access_history.updateGeneral": "Actualizada la configuración general de tu cuenta",
- "access_history.updateGlobalNotifications": "Actualizada la configuración global de tus notificaciones",
- "access_history.updatePicture": "Actualizada tu imagén de perfil",
- "access_history.updatedRol": "Actualizado rol(es) de usuario a ",
- "access_history.userAdded": "Agregado {username} al canal/grupo {channelName}",
- "access_history.userRemoved": "Removido {username} del canal/grupo {channelName}",
- "access_history.verified": "Se verificó tu dirección de correo electrónico con éxito",
"activity_log.activeSessions": "Sesiones Activas",
"activity_log.browser": "Navegador: {browser}",
"activity_log.firstTime": "Primera actividad: {date}, {time}",
@@ -69,17 +22,30 @@
"activity_log_modal.androidNativeApp": "Android App Nativa",
"activity_log_modal.iphoneNativeApp": "iPhone App Nativa",
"admin.analytics.activeUsers": "Usuarios Activos con Mensajes",
+ "admin.analytics.channelTypes": "Tipos de Canales",
"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.postTypes": "Mesajes, Archivos y Hashtags",
"admin.analytics.privateGroups": "Grupos Privados",
"admin.analytics.publicChannels": "Canales Públicos",
"admin.analytics.recentActive": "Usuarios Recientemente Activos",
+ "admin.analytics.textPosts": "Mensajes de sólo Texto",
"admin.analytics.title": "Estadísticas para {title}",
+ "admin.analytics.totalFilePosts": "Mensajes con Archivos",
+ "admin.analytics.totalHashtagPosts": "Mensajes con Hashtags",
+ "admin.analytics.totalIncomingWebhooks": "Webhooks de Entrada",
+ "admin.analytics.totalOutgoingWebhooks": "Webhooks de Salida",
"admin.analytics.totalPosts": "Total de Mensajes",
"admin.analytics.totalUsers": "Total de Usuarios",
+ "admin.audits.reload": "Recargar",
+ "admin.audits.title": "Auditorías del Servidor",
+ "admin.email.allowEmailSignInDescription": "Cuando es verdadero, Mattermost permite a los usuarios iniciar sesión utilizando el correo electrónico y contraseña.",
+ "admin.email.allowEmailSignInTitle": "Permitir inicio de sesión con Correo electrónico: ",
"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.allowSignupTitle": "Permitir registro con correo electrónico:",
+ "admin.email.allowUsernameSignInDescription": "Cuando es verdadero, Mattermost permite a los usuarios iniciar sesión con el nombre de usuario y contraseña. Esta opción normalmente se utiliza cuando la verificación de correo electrónico está deshabilitada.",
+ "admin.email.allowUsernameSignInTitle": "Permitir inicio de sesión con Nombre de usuario: ",
"admin.email.connectionSecurityNone": "Ninguno",
"admin.email.connectionSecurityNoneDescription": "Mattermost enviará los correos electrónicos sobre conexiones no seguras.",
"admin.email.connectionSecurityStart": "STARTTLS",
@@ -365,6 +331,7 @@
"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.audits": "Auditorías",
"admin.sidebar.email": "Configuración de correo",
"admin.sidebar.file": "Configuracion de archivos",
"admin.sidebar.gitlab": "Configuración de GitLab",
@@ -469,11 +436,60 @@
"admin.user_item.resetPwd": "Reiniciar Contraseña",
"admin.user_item.sysAdmin": "Admin de Sistema",
"admin.user_item.teamAdmin": "Admin de Equipo",
+ "audit_table.accountActive": "Cuentas activadas",
+ "audit_table.accountInactive": "Cuentas desactivadas",
+ "audit_table.attemptedAllowOAuthAccess": "Intento de permitir acceso a un nuevo servicio OAuth",
+ "audit_table.attemptedLogin": "Intento de inicio de sesión",
+ "audit_table.attemptedOAuthToken": "Intento de obtener un token de acceso con OAuth",
+ "audit_table.attemptedPassword": "Intento de cambio de contraseña",
+ "audit_table.attemptedRegisterApp": "Intento de registrar una nueva aplicación OAuth con ID {id}",
+ "audit_table.attemptedReset": "Intento de restablecer contraseña",
+ "audit_table.attemptedWebhookCreate": "Intento de crear un webhook",
+ "audit_table.attemptedWebhookDelete": "Intento de eliminar un webhook",
+ "audit_table.by": " por {username}",
+ "audit_table.byAdmin": " por un admin",
+ "audit_table.channelCreated": "Creado el canal/grupo {channelName}",
+ "audit_table.channelDeleted": "Borrado el canal/grupo con el URL {url}",
+ "audit_table.establishedDM": "Establecido un canal de mensajes directos con {username}",
+ "audit_table.failedLogin": "intento de inicio de sesión FALLIDO",
+ "audit_table.failedOAuthAccess": "Falla al permitir acceso al nuevo servicio de OAuth - El URI de redirección no coincide con el previamente registrado",
+ "audit_table.failedPassword": "Falla al cambiar la contraseña - intento de actualizar la contraseña del usuario que está autenticado a través de oauth",
+ "audit_table.failedWebhookCreate": "Falla al crear un webhook - no tiene permisos en el canal",
+ "audit_table.failedWebhookDelete": "Falla al borrar un webhook - condiciones inapropiadas",
+ "audit_table.headerUpdated": "Actualizado el encabezado del canal/grupo {channelName}",
+ "audit_table.ip": "IP: {ip}",
+ "audit_table.loginAttempt": " (intento de inicio de sesión)",
+ "audit_table.loginFailure": " (inicio de sesión fallido)",
+ "audit_table.logout": "Cerrada la sesión de tu cuenta",
+ "audit_table.member": "miembro",
+ "audit_table.moreInfo": "Más Info",
+ "audit_table.nameUpdated": "Actualizado el nombre del canal/grupo {channelName}",
+ "audit_table.oauthTokenFailed": "Falla al obtener un token de acceso de OAuth - {token}",
+ "audit_table.revokedAll": "Revocadas todas las sesiones actuales del equipo",
+ "audit_table.sentEmail": "Correo electrónico enviado a {email} para restablecer tu contraseña",
+ "audit_table.session": "ID de Sesión: {id}",
+ "audit_table.sessionRevoked": "La sesión con id {sessionId} fue revocada",
+ "audit_table.successfullLogin": "Inicio de sesión satisfactorio",
+ "audit_table.successfullOAuthAccess": "Se entrego acceso al nuevo servicio de OAuth satisfactoriamente",
+ "audit_table.successfullOAuthToken": "Se agregó el nuevo servicio de OAuth satisfactoriamente",
+ "audit_table.successfullPassword": "Cambio de contraseña satisfactorio",
+ "audit_table.successfullReset": "Contraseña restablecida satisfactoriamente",
+ "audit_table.successfullWebhookCreate": "Creado un webhook satisfactoriamente",
+ "audit_table.successfullWebhookDelete": "Borrado un webhook satisfactoriamente",
+ "audit_table.updateGeneral": "Actulizada la configuración general de tu cuenta",
+ "audit_table.updateGlobalNotifications": "Actualizada la configuración global de tus notificaciones",
+ "audit_table.updatePicture": "Actualizada tu imagen de perfil",
+ "audit_table.updatedRol": "Rol(es) de usuario actualizado(s) a ",
+ "audit_table.userAdded": "Agregado {username} al canal/grupo {channelName}",
+ "audit_table.userId": "ID de Usuario",
+ "audit_table.userRemoved": "Removido {username} del canal/grupo {channelName}",
+ "audit_table.verified": "Verificada la dirección de correo electrónico satisfacoriamente",
"authorize.access": "¿Permitir acceso a {appName}?",
"authorize.allow": "Permitir",
"authorize.app": "La app {appName} quiere tener la abilidad de accesar y modificar tu información básica.",
"authorize.deny": "Denegar",
"authorize.title": "Una aplicación quiere conectarse con tu cuenta de {teamName}",
+ "center_panel.recent": "Pincha aquí para ir a los mensajes más recientes. ",
"chanel_header.addMembers": "Agregar Miembros",
"change_url.close": "Cerrar",
"change_url.endWithLetter": "Debe terminar con una letra o número",
@@ -490,14 +506,14 @@
"channel_flow.invalidName": "Nombre de Canal Inválido",
"channel_flow.set_url_title": "Asignar URL de {term}",
"channel_header.channel": "Canal",
- "channel_header.channelHeader": "Encabezado del Canal...",
- "channel_header.delete": "Eliminar {term}...",
+ "channel_header.channelHeader": "Asignar Encabezado del Canal...",
+ "channel_header.delete": "Borrar {term}...",
"channel_header.group": "Grupo",
- "channel_header.leave": "Abondanar {term}",
+ "channel_header.leave": "Abandonar ",
"channel_header.manageMembers": "Administrar Miembros",
"channel_header.notificationPreferences": "Preferencias de Notificación",
"channel_header.recentMentions": "Menciones recientes",
- "channel_header.rename": "Renombrar {term}...",
+ "channel_header.rename": "Renombrar ",
"channel_header.setHeader": "Encabezado del {term}...",
"channel_header.setPurpose": "Propósito del {term}...",
"channel_header.viewInfo": "Ver Info",
@@ -509,6 +525,13 @@
"channel_info.url": "URL del Canal:",
"channel_invite.addNewMembers": "Agregar nuevos Miembros a ",
"channel_invite.close": "Cerrar",
+ "channel_loader.posted": "Publicó",
+ "channel_loader.socketError": "No se puede conectar con Mattermost, por favor revise su conexión. Si el problema persiste, solicite a un administrador que revise el puerto del WebSocket.",
+ "channel_loader.someone": "Alguien",
+ "channel_loader.something": " hizo algo nuevo",
+ "channel_loader.uploadedFile": " subió un archivo",
+ "channel_loader.uploadedImage": " subió una imagen",
+ "channel_loader.wrote": " escribió: ",
"channel_members_modal.addNew": " Agregar nuevos Miembros",
"channel_members_modal.close": "Cerrar",
"channel_memebers_modal.members": " Miembros",
@@ -530,12 +553,12 @@
"channel_modal.purpose": "Propósito",
"channel_notifications.allActivity": "Para toda actividad",
"channel_notifications.allUnread": "Para todos los mensajes sin leer",
- "channel_notifications.globalDefault": "Predeterminado global ({notifyLevel})",
+ "channel_notifications.globalDefault": "Predeterminada",
"channel_notifications.markUnread": "Marcar Canal como No Leido",
"channel_notifications.never": "Nunca",
"channel_notifications.onlyMentions": "Sólo para menciones",
"channel_notifications.override": "Seleccionar una opción diferente a \"Predeterminada\" anulará las configuraciones globales de notificación. Las notificaciones de Escritorio están disponibles para Firefox, Safari, y Chrome.",
- "channel_notifications.preferences": "Preferencias de Notificación de ",
+ "channel_notifications.preferences": "Preferencias de Notificación para ",
"channel_notifications.sendDesktop": "Enviar notificaciones de escritorio",
"channel_notifications.unreadInfo": "El nombre del canal está en negritas en la barra lateral cuando hay mensajes sin leer. Al elegir \"Sólo para menciones\" sólo lo dejará en negritas cuando seas mencionado.",
"choose_auth_page.emailCreate": "Crea un nuevo equipo con tu cuenta de correo",
@@ -548,8 +571,8 @@
"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.email_to_sso.switchTo": "Cambiar cuenta a {uiType}",
+ "claim.email_to_sso.title": "Cambiar Cuenta de Correo/Contraseña a {uiType}",
"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.",
@@ -565,18 +588,23 @@
"create_comment.commentTitle": "Comentario",
"create_comment.file": "Subiendo archivo",
"create_comment.files": "Subiendo archivos",
+ "create_post.comment": "Comentario",
+ "create_post.deleteMsg": "(mensaje eliminado)",
+ "create_post.post": "Mensaje",
+ "create_post.tutorialTip": "<h4>Enviar Mensajes</h4> <p>Escribe aquí para redactar un mensaje y presiona <strong>Retorno</strong> para enviarlo.</p><p>Pincha el botón de <strong>Adjuntar</strong> para subir una imagen o archivo.</p>",
+ "create_post.write": "Escribe un mensaje...",
"delete_channel.cancel": "Cancelar",
"delete_channel.channel": "canal",
- "delete_channel.confirm": "Confirmar la ELIMINACIÓN del Canal",
- "delete_channel.del": "Eliminar",
+ "delete_channel.confirm": "Confirmar BORRAR Canal",
+ "delete_channel.del": "Borrar",
"delete_channel.group": "grupo",
- "delete_channel.question": "¿Estás seguro de querer eliminar el {term} {display_name}?",
+ "delete_channel.question": "¿Estás seguro de querer borrar el ",
"delete_post.cancel": "Cancelar",
"delete_post.comment": "Comentario",
"delete_post.confirm": "Confirmar Eliminación del {term}",
- "delete_post.del": "Eliminar",
+ "delete_post.del": "Borrar",
"delete_post.post": "Mensaje",
- "delete_post.question": "¿Estás seguro(a) de querer eliminar este {term}?",
+ "delete_post.question": "¿Estás seguro(a) de querer borrar este {term}?",
"delete_post.warning": "Este mensaje tiene {count} comentario(s).",
"edit_channel_header_modal.cancel": "Cancelar",
"edit_channel_header_modal.description": "Edita el texto que aparece al lado del nombre del canal en el encabezado del canal.",
@@ -606,6 +634,9 @@
"email_verify.verified": "{siteName} Correo electrónico verificado",
"email_verify.verifiedBody": "<p>Tu correo electrónico ha sido verificado!! Pincha <a href={url}>aquí</a> para iniciar sesión.</p>",
"error_bar.preview_mode": "Modo de prueba: Las notificaciones por correo electrónico no han sido configuradas",
+ "file_attachment.download": "Descargar",
+ "file_info_preview.size": "Tamaño ",
+ "file_info_preview.type": "Tipo de archivo ",
"file_upload.fileAbove": "No se puede subir un archivo que pesa más de {max}MB: {filename}",
"file_upload.filesAbove": "No se pueden subir archivos de más de {max}MB: {filenames}",
"file_upload.limited": "Se pueden subir un máximo de {count} archivos. Por favor envía otros mensajes para adjuntar más archivos.",
@@ -639,7 +670,22 @@
"get_link.close": "Cerrar",
"get_link.copy": "Copiar Enlace",
"get_team_invite_link_modal.help": "Enviar a los compañeros de equipo el enlace que se muestra a continuación para permitirles registrarse a este equipo.",
+ "get_team_invite_link_modal.helpDisabled": "La creación de usuario ha sido deshabilitada para tu equipo. Por favor solicita más detalles a tu administrador de equipo.",
"get_team_invite_link_modal.title": "Enlace de Invitación al Equipo",
+ "intro_messages.DM": "Este es el inicio de tu historial de mensajes directos con {teammate}.<br />Los mensajes directos y archivos que se comparten aquí no son mostrados a personas fuera de esta área.",
+ "intro_messages.anyMember": " Cualquier miembro se puede unir y leer este canal.",
+ "intro_messages.beginning": "Inicio de {name}",
+ "intro_messages.channel": "canal",
+ "intro_messages.creator": "Este es el inicio del {type} <strong>{name}</strong>, creado por <strong>{creator}</strong> el <strong>{date}</strong>",
+ "intro_messages.default": "<h4 class='channel-intro__title'>Inicio de {display_name}</h4><p class='channel-intro__content'><strong>¡Bienvenido a {display_name}!</strong><br/><br/>Este es el primer canal que ven tus compañeros cuando se registran - utilizalo para colocar mensajes que todos deberían leer.</p>",
+ "intro_messages.group": "grupo privado",
+ "intro_messages.invite": "Invita a otros a este {type}",
+ "intro_messages.inviteOthers": "Invita a otros a este equipo",
+ "intro_messages.noCreator": "Este es el inicio del {type} {name}, creado el {date}.",
+ "intro_messages.offTopic": "<h4 class=\"channel-intro__title\">Inicio de {display_name}</h4><p class=\"channel-intro__content\">Este es el inicio de {display_name}, un canal para tener conversaciones no relacionadas trabajo.<br/></p>",
+ "intro_messages.onlyInvited": " Sólo miembros invitados pueden ver este grupo privado.",
+ "intro_messages.setHeader": "Asignar un Encabezado",
+ "intro_messages.teammate": "Este es el inicio de tu historial de mensajes directos con este compañero. Los mensajes directos y archivos que se comparten aquí no son mostrados a personas fuera de esta área.",
"invite_member.addAnother": "Agregar otro",
"invite_member.autoJoin": "Las personas invitadas se unirán automáticamente al canal <strong>{channel}</strong>.",
"invite_member.cancel": "Cancelar",
@@ -656,7 +702,6 @@
"invite_member.send": "Enviar Invitaciones",
"invite_member.send2": "Enviar Invitaciones",
"invite_member.sending": " Enviando",
- "invite_member.teamInvite": "Invitación de Equipo",
"invite_member.teamInviteLink": "También puedes invitar personas usando el {link}.",
"loading_screen.loading": "Cargando",
"login.changed": " Cambiado el método de inicio de sesión satisfactoriamente",
@@ -683,6 +728,14 @@
"login_ldap.pwdReq": "La contraseña LDAP es obligatoria",
"login_ldap.signin": "Entrar",
"login_ldap.username": "Usuario LDAP",
+ "login_username.badTeam": "Mal nombre de equipo",
+ "login_username.pwd": "Contraseña",
+ "login_username.pwdReq": "La contraseña es obligatoria",
+ "login_username.signin": "Ingresar",
+ "login_username.userNotFoundError": "No encontramos una cuenta existente que coincida con tu nombre de usuario en este equipo.",
+ "login_username.username": "Nombre de usuario",
+ "login_username.usernameReq": "El nombre de usuario es obligatorio",
+ "login_username.verifyEmailError": "Por favor válida tu dirección de correo electrónico. Te hemos enviado un correo, revisa tu bandeja de entrada.",
"member_item.add": " Agregar",
"member_item.makeAdmin": "Convertir en Admin de Equipo",
"member_item.member": "Miembro",
@@ -714,6 +767,19 @@
"msg_typing.areTyping": "{users} y {last} están escribiendo...",
"msg_typing.isTyping": "{user} está escribiendo...",
"msg_typing.someone": "Alguien",
+ "navbar.addMembers": "Agregar Miembros",
+ "navbar.click": "Pincha aquí",
+ "navbar.delete": "Borrar Canal...",
+ "navbar.leave": "Abandonar Canal",
+ "navbar.manageMembers": "Administrar Miembros",
+ "navbar.noHeader": "Todavía no hay un encabezado.{newline}{link} para agregar uno.",
+ "navbar.preferences": "Preferencias de Notificación",
+ "navbar.rename": "Renombrar Canal...",
+ "navbar.setHeader": "Asignar Encabezado del Canal...",
+ "navbar.setPurpose": "Asignar Propósito del Canal...",
+ "navbar.toggle1": "Mostrar Barra",
+ "navbar.toggle2": "Esconder Barra",
+ "navbar.viewInfo": "Ver Info",
"navbar_dropdown.about": "Acerca de Mattermost",
"navbar_dropdown.accountSettings": "Configurar Cuenta",
"navbar_dropdown.console": "Consola de Sistema",
@@ -740,9 +806,23 @@
"password_send.link": "<p>Se ha enviado un enlace para restablecer la contraseña a <b>{email}</b> para tu equipo <b>{teamDisplayName}</b> en {hostname}.</p>",
"password_send.reset": "Restablecer mi contraseña",
"password_send.title": "Restablecer Contraseña",
+ "post_attachment.collapse": "▲ colapsar texto",
+ "post_attachment.more": "▼ leer más",
+ "post_body.commentedOn": "Comentó el mensaje de {name}{apostrophe}: ",
+ "post_body.plusMore": " más {count} otros archivos",
+ "post_body.plusOne": " más 1 archivo",
+ "post_body.retry": "Reintentar",
"post_delete.notPosted": "No se pudo enviar el comentario",
"post_delete.okay": "Ok",
"post_delete.someone": "Alguien borró el mensaje que querías comentar.",
+ "post_focus_view.beginning": "Inicio de los Archivos del Canal",
+ "post_info.copy": "Copiar ",
+ "post_info.del": "Borrar",
+ "post_info.edit": "Editar",
+ "post_info.permalink": "Enlace permanente",
+ "post_info.reply": "Responder",
+ "posts_view.loadMore": "Cargar más mensajes",
+ "posts_view.newMsg": "Nuevos Mensajes",
"register_app.callback": "Callback URL",
"register_app.callbackError": "Al menos un callback URL debe ser ingresado.",
"register_app.cancel": "Cancelar",
@@ -841,6 +921,7 @@
"signup_user_completed.choosePwd": "Escoge tu contraseña",
"signup_user_completed.chooseUser": "Escoge tu nombre de usuario",
"signup_user_completed.create": "Crea una Cuenta",
+ "signup_user_completed.emailHelp": "Para registrarte es necesario un correo electrónico válido",
"signup_user_completed.emailIs": "Tu dirección de correo electrónico es <strong>{email}</strong>. Utiliza está dirección para ingresar a {siteName}.",
"signup_user_completed.expired": "Ya haz completado el proceso de registro para esta invitación, o esta invitación ya ha expirado.",
"signup_user_completed.gitlab": "con GitLab",
@@ -1134,5 +1215,9 @@
"user.settings.security.switchGoogle": "Cambiar para utilizar Google SSO",
"user.settings.security.title": "Configuración de Seguridad",
"user.settings.security.viewHistory": "Visualizar historial de acceso",
- "user_profile.notShared": "Correo no compartido"
-}
+ "user_profile.notShared": "Correo no compartido",
+ "view_image.loading": "Cargando ",
+ "view_image_popover.download": "Descargar",
+ "view_image_popover.file": "Archivo {count} de {total}",
+ "view_image_popover.publicLink": "Obtener Enlace Público"
+} \ No newline at end of file