diff options
Diffstat (limited to 'web/react')
23 files changed, 518 insertions, 145 deletions
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 712d6885f..15571ad93 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() { @@ -126,3 +170,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 76f63d4b3..20892898e 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(); @@ -356,7 +378,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, @@ -374,9 +397,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> ); @@ -440,7 +464,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' @@ -477,3 +501,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/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 |