summaryrefslogtreecommitdiffstats
path: root/web/react
diff options
context:
space:
mode:
authorElias Nahum <nahumhbl@gmail.com>2016-02-01 17:23:45 -0300
committerElias Nahum <nahumhbl@gmail.com>2016-02-01 17:23:45 -0300
commit3f91bc2df2c6f9d8437f258233609e9801b7f8f6 (patch)
tree3721db61cb0c052fba9c100c000ab64297c81f51 /web/react
parent9fe4c0603e8b98570d4a9ab1c6bd3d69b321c36c (diff)
downloadchat-3f91bc2df2c6f9d8437f258233609e9801b7f8f6.tar.gz
chat-3f91bc2df2c6f9d8437f258233609e9801b7f8f6.tar.bz2
chat-3f91bc2df2c6f9d8437f258233609e9801b7f8f6.zip
PLT-7: Refactoring frontend (chunk 9)
- sidebar right & rhs
Diffstat (limited to 'web/react')
-rw-r--r--web/react/components/create_comment.jsx52
-rw-r--r--web/react/components/file_upload.jsx32
-rw-r--r--web/react/components/file_upload_overlay.jsx9
-rw-r--r--web/react/components/msg_typing.jsx42
-rw-r--r--web/react/components/rhs_comment.jsx41
-rw-r--r--web/react/components/rhs_header_post.jsx11
-rw-r--r--web/react/components/rhs_root_post.jsx29
-rw-r--r--web/react/components/search_bar.jsx39
-rw-r--r--web/react/components/search_results.jsx32
-rw-r--r--web/react/components/search_results_header.jsx17
-rw-r--r--web/react/components/search_results_item.jsx24
-rw-r--r--web/react/components/sidebar_right_menu.jsx68
-rw-r--r--web/react/components/textbox.jsx20
-rw-r--r--web/react/components/user_profile.jsx8
14 files changed, 350 insertions, 74 deletions
diff --git a/web/react/components/create_comment.jsx b/web/react/components/create_comment.jsx
index aa7ab6a7b..1b552838a 100644
--- a/web/react/components/create_comment.jsx
+++ b/web/react/components/create_comment.jsx
@@ -16,10 +16,32 @@ import FilePreview from './file_preview.jsx';
import * as Utils from '../utils/utils.jsx';
import Constants from '../utils/constants.jsx';
+
+import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl';
+
const ActionTypes = Constants.ActionTypes;
const KeyCodes = Constants.KeyCodes;
-export default class CreateComment extends React.Component {
+const holders = defineMessages({
+ commentLength: {
+ id: 'create_comment.commentLength',
+ defaultMessage: 'Comment length must be less than {max} characters.'
+ },
+ comment: {
+ id: 'create_comment.comment',
+ defaultMessage: 'Add Comment'
+ },
+ addComment: {
+ id: 'create_comment.addComment',
+ defaultMessage: 'Add a comment...'
+ },
+ commentTitle: {
+ id: 'create_comment.commentTitle',
+ defaultMessage: 'Comment'
+ }
+});
+
+class CreateComment extends React.Component {
constructor(props) {
super(props);
@@ -93,7 +115,7 @@ export default class CreateComment extends React.Component {
}
if (post.message.length > Constants.CHARACTER_LIMIT) {
- this.setState({postError: `Comment length must be less than ${Constants.CHARACTER_LIMIT} characters.`});
+ this.setState({postError: this.props.intl.formatMessage(holders.commentLength, {max: Constants.CHARACTER_LIMIT})});
return;
}
@@ -189,7 +211,7 @@ export default class CreateComment extends React.Component {
AppDispatcher.handleViewAction({
type: ActionTypes.RECIEVED_EDIT_POST,
refocusId: '#reply_textbox',
- title: 'Comment',
+ title: this.props.intl.formatMessage(holders.commentTitle),
message: lastPost.message,
postId: lastPost.id,
channelId: lastPost.channel_id,
@@ -305,14 +327,23 @@ export default class CreateComment extends React.Component {
let uploadsInProgressText = null;
if (this.state.uploadsInProgress.length > 0) {
uploadsInProgressText = (
- <span
- className='pull-right post-right-comments-upload-in-progress'
- >
- {this.state.uploadsInProgress.length === 1 ? 'File uploading' : 'Files uploading'}
+ <span className='pull-right post-right-comments-upload-in-progress'>
+ {this.state.uploadsInProgress.length === 1 ? (
+ <FormattedMessage
+ id='create_comment.file'
+ defaultMessage='File uploading'
+ />
+ ) : (
+ <FormattedMessage
+ id='create_comment.files'
+ defaultMessage='Files uploading'
+ />
+ )}
</span>
);
}
+ const {formatMessage} = this.props.intl;
return (
<form onSubmit={this.handleSubmit}>
<div className='post-create'>
@@ -326,7 +357,7 @@ export default class CreateComment extends React.Component {
onKeyPress={this.commentMsgKeyPress}
onKeyDown={this.handleKeyDown}
messageText={this.state.messageText}
- createMessage='Add a comment...'
+ createMessage={formatMessage(holders.addComment)}
initialText=''
supportsCommands={false}
id='reply_textbox'
@@ -351,7 +382,7 @@ export default class CreateComment extends React.Component {
<input
type='button'
className='btn btn-primary comment-btn pull-right'
- value='Add Comment'
+ value={formatMessage(holders.comment)}
onClick={this.handleSubmit}
/>
{uploadsInProgressText}
@@ -366,6 +397,9 @@ export default class CreateComment extends React.Component {
}
CreateComment.propTypes = {
+ intl: intlShape.isRequired,
channelId: React.PropTypes.string.isRequired,
rootId: React.PropTypes.string.isRequired
};
+
+export default injectIntl(CreateComment); \ No newline at end of file
diff --git a/web/react/components/file_upload.jsx b/web/react/components/file_upload.jsx
index 7e6cc2942..2f9146193 100644
--- a/web/react/components/file_upload.jsx
+++ b/web/react/components/file_upload.jsx
@@ -6,7 +6,24 @@ import Constants from '../utils/constants.jsx';
import ChannelStore from '../stores/channel_store.jsx';
import * as Utils from '../utils/utils.jsx';
-export default class FileUpload extends React.Component {
+import {intlShape, injectIntl, defineMessages} from 'mm-intl';
+
+const holders = defineMessages({
+ limited: {
+ id: 'file_upload.limited',
+ defaultMessage: 'Uploads limited to {count} files maximum. Please use additional posts for more files.'
+ },
+ filesAbove: {
+ id: 'file_upload.filesAbove',
+ defaultMessage: 'Files above {max}MB could not be uploaded: {filenames}'
+ },
+ fileAbove: {
+ id: 'file_upload.fileAbove',
+ defaultMessage: 'File above {max}MB could not be uploaded: {filename}'
+ }
+});
+
+class FileUpload extends React.Component {
constructor(props) {
super(props);
@@ -74,14 +91,15 @@ export default class FileUpload extends React.Component {
numUploads += 1;
}
+ const {formatMessage} = this.props.intl;
if (files.length > uploadsRemaining) {
- this.props.onUploadError(`Uploads limited to ${Constants.MAX_UPLOAD_FILES} files maximum. Please use additional posts for more files.`);
+ this.props.onUploadError(formatMessage(holders.limited, {count: Constants.MAX_UPLOAD_FILES}));
} else if (tooLargeFiles.length > 1) {
var tooLargeFilenames = tooLargeFiles.map((file) => file.name).join(', ');
- this.props.onUploadError(`Files above ${Constants.MAX_FILE_SIZE / 1000000}MB could not be uploaded: ${tooLargeFilenames}`);
+ this.props.onUploadError(formatMessage(holders.filesAbove, {max: (Constants.MAX_FILE_SIZE / 1000000), files: tooLargeFilenames}));
} else if (tooLargeFiles.length > 0) {
- this.props.onUploadError(`File above ${Constants.MAX_FILE_SIZE / 1000000}MB could not be uploaded: ${tooLargeFiles[0].name}`);
+ this.props.onUploadError(formatMessage(holders.fileAbove, {max: (Constants.MAX_FILE_SIZE / 1000000), file: tooLargeFiles[0].name}));
}
}
@@ -106,6 +124,7 @@ export default class FileUpload extends React.Component {
componentDidMount() {
var inputDiv = ReactDOM.findDOMNode(this.refs.input);
var self = this;
+ const {formatMessage} = this.props.intl;
if (this.props.postType === 'post') {
$('.row.main').dragster({
@@ -184,7 +203,7 @@ export default class FileUpload extends React.Component {
var numToUpload = Math.min(Constants.MAX_UPLOAD_FILES - self.props.getFileCount(ChannelStore.getCurrentId()), numItems);
if (numItems > numToUpload) {
- self.props.onUploadError('Uploads limited to ' + Constants.MAX_UPLOAD_FILES + ' files maximum. Please use additional posts for more files.');
+ self.props.onUploadError(formatMessage(holders.limited, {count: Constants.MAX_UPLOAD_FILES}));
}
for (var i = 0; i < items.length && i < numToUpload; i++) {
@@ -296,6 +315,7 @@ export default class FileUpload extends React.Component {
}
FileUpload.propTypes = {
+ intl: intlShape.isRequired,
onUploadError: React.PropTypes.func,
getFileCount: React.PropTypes.func,
onFileUpload: React.PropTypes.func,
@@ -304,3 +324,5 @@ FileUpload.propTypes = {
channelId: React.PropTypes.string,
postType: React.PropTypes.string
};
+
+export default injectIntl(FileUpload); \ No newline at end of file
diff --git a/web/react/components/file_upload_overlay.jsx b/web/react/components/file_upload_overlay.jsx
index dbba00022..497d5aee2 100644
--- a/web/react/components/file_upload_overlay.jsx
+++ b/web/react/components/file_upload_overlay.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 FileUploadOverlay extends React.Component {
render() {
var overlayClass = 'file-overlay hidden';
@@ -19,7 +21,12 @@ export default class FileUploadOverlay extends React.Component {
src='/static/images/filesOverlay.png'
alt='Files'
/>
- <span><i className='fa fa-upload'></i>{'Drop a file to upload it.'}</span>
+ <span><i className='fa fa-upload'></i>
+ <FormattedMessage
+ id='upload_overlay.info'
+ defaultMessage='Drop a file to upload it.'
+ />
+ </span>
<img
className='overlay__logo'
src='/static/images/logoWhite.png'
diff --git a/web/react/components/msg_typing.jsx b/web/react/components/msg_typing.jsx
index 35a832875..b95b06260 100644
--- a/web/react/components/msg_typing.jsx
+++ b/web/react/components/msg_typing.jsx
@@ -5,9 +5,19 @@ import SocketStore from '../stores/socket_store.jsx';
import UserStore from '../stores/user_store.jsx';
import Constants from '../utils/constants.jsx';
+
+import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl';
+
const SocketEvents = Constants.SocketEvents;
-export default class MsgTyping extends React.Component {
+const holders = defineMessages({
+ someone: {
+ id: 'msg_typing.someone',
+ defaultMessage: 'Someone'
+ }
+});
+
+class MsgTyping extends React.Component {
constructor(props) {
super(props);
@@ -44,10 +54,10 @@ export default class MsgTyping extends React.Component {
}
onChange(msg) {
- let username = 'Someone';
+ let username = this.props.intl.formatMessage(holders.someone);
if (msg.action === SocketEvents.TYPING &&
- this.props.channelId === msg.channel_id &&
- this.props.parentId === msg.props.parent_id) {
+ this.props.channelId === msg.channel_id &&
+ this.props.parentId === msg.props.parent_id) {
if (UserStore.hasProfile(msg.user_id)) {
username = UserStore.getProfile(msg.user_id).username;
}
@@ -80,11 +90,28 @@ export default class MsgTyping extends React.Component {
text = '';
break;
case 1:
- text = users[0] + ' is typing...';
+ text = (
+ <FormattedMessage
+ id='msg_typing.isTyping'
+ defaultMessage='{user} is typing...'
+ values={{
+ user: users[0]
+ }}
+ />
+ );
break;
default: {
const last = users.pop();
- text = users.join(', ') + ' and ' + last + ' are typing...';
+ text = (
+ <FormattedMessage
+ id='msg_typing.areTyping'
+ defaultMessage='{users} and {last} are typing...'
+ vaues={{
+ users: users.join(', '),
+ last: last
+ }}
+ />
+ );
break;
}
}
@@ -100,6 +127,9 @@ export default class MsgTyping extends React.Component {
}
MsgTyping.propTypes = {
+ intl: intlShape.isRequired,
channelId: React.PropTypes.string,
parentId: React.PropTypes.string
};
+
+export default injectIntl(MsgTyping); \ No newline at end of file
diff --git a/web/react/components/rhs_comment.jsx b/web/react/components/rhs_comment.jsx
index 7aae5177e..1dd8354d7 100644
--- a/web/react/components/rhs_comment.jsx
+++ b/web/react/components/rhs_comment.jsx
@@ -16,7 +16,16 @@ import * as TextFormatting from '../utils/text_formatting.jsx';
import twemoji from 'twemoji';
import * as EventHelpers from '../dispatcher/event_helpers.jsx';
-export default class RhsComment extends React.Component {
+import {intlShape, injectIntl, defineMessages, FormattedMessage, FormattedDate} from 'mm-intl';
+
+const holders = defineMessages({
+ comment: {
+ id: 'rhs_comment.comment',
+ defaultMessage: 'Comment'
+ }
+});
+
+class RhsComment extends React.Component {
constructor(props) {
super(props);
@@ -95,12 +104,15 @@ export default class RhsComment extends React.Component {
data-toggle='modal'
data-target='#edit_post'
data-refocusid='#reply_textbox'
- data-title='Comment'
+ data-title={this.props.intl.formatMessage(holders.comment)}
data-message={post.message}
data-postid={post.id}
data-channelid={post.channel_id}
>
- {'Edit'}
+ <FormattedMessage
+ id='rhs_comment.edit'
+ defaultMessage='Edit'
+ />
</a>
</li>
);
@@ -117,7 +129,10 @@ export default class RhsComment extends React.Component {
role='menuitem'
onClick={() => EventHelpers.showDeletePostModal(post, 0)}
>
- {'Delete'}
+ <FormattedMessage
+ id='rhs_comment.del'
+ defaultMessage='Delete'
+ />
</a>
</li>
);
@@ -165,7 +180,10 @@ export default class RhsComment extends React.Component {
href='#'
onClick={this.retryComment}
>
- {'Retry'}
+ <FormattedMessage
+ id='rhs_comment.retry'
+ defaultMessage='Retry'
+ />
</a>
);
} else if (post.state === Constants.POST_LOADING) {
@@ -208,7 +226,15 @@ export default class RhsComment extends React.Component {
</li>
<li className='col'>
<time className='post__time'>
- {Utils.displayCommentDateTime(post.create_at)}
+ <FormattedDate
+ value={post.create_at}
+ day='numeric'
+ month='long'
+ year='numeric'
+ hour12='true'
+ hour='2-digit'
+ minute='2-digit'
+ />
</time>
</li>
<li className='col col__reply'>
@@ -237,5 +263,8 @@ RhsComment.defaultProps = {
post: null
};
RhsComment.propTypes = {
+ intl: intlShape.isRequired,
post: React.PropTypes.object
};
+
+export default injectIntl(RhsComment); \ No newline at end of file
diff --git a/web/react/components/rhs_header_post.jsx b/web/react/components/rhs_header_post.jsx
index 990b33eb5..d56ba76f8 100644
--- a/web/react/components/rhs_header_post.jsx
+++ b/web/react/components/rhs_header_post.jsx
@@ -3,6 +3,9 @@
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
import Constants from '../utils/constants.jsx';
+
+import {FormattedMessage} from 'mm-intl';
+
const ActionTypes = Constants.ActionTypes;
export default class RhsHeaderPost extends React.Component {
@@ -58,7 +61,13 @@ export default class RhsHeaderPost extends React.Component {
return (
<div className='sidebar--right__header'>
- <span className='sidebar--right__title'>{back}Message Details</span>
+ <span className='sidebar--right__title'>
+ {back}
+ <FormattedMessage
+ id='rhs_header.details'
+ defaultMessage='Message Details'
+ />
+ </span>
<button
type='button'
className='sidebar--right__close'
diff --git a/web/react/components/rhs_root_post.jsx b/web/react/components/rhs_root_post.jsx
index cd7f6766c..bc772aaa5 100644
--- a/web/react/components/rhs_root_post.jsx
+++ b/web/react/components/rhs_root_post.jsx
@@ -14,6 +14,8 @@ import * as EventHelpers from '../dispatcher/event_helpers.jsx';
import Constants from '../utils/constants.jsx';
+import {FormattedMessage, FormattedDate} from 'mm-intl';
+
export default class RhsRootPost extends React.Component {
constructor(props) {
super(props);
@@ -68,7 +70,12 @@ export default class RhsRootPost extends React.Component {
var channelName;
if (channel) {
if (channel.type === 'D') {
- channelName = 'Direct Message';
+ channelName = (
+ <FormattedMessage
+ id='rhs_root.direct'
+ defaultMessage='Direct Message'
+ />
+ );
} else {
channelName = channel.display_name;
}
@@ -93,7 +100,10 @@ export default class RhsRootPost extends React.Component {
data-postid={post.id}
data-channelid={post.channel_id}
>
- {'Edit'}
+ <FormattedMessage
+ id='rhs_root.edit'
+ defaultMessage='Edit'
+ />
</a>
</li>
);
@@ -110,7 +120,10 @@ export default class RhsRootPost extends React.Component {
role='menuitem'
onClick={() => EventHelpers.showDeletePostModal(post, this.props.commentCount)}
>
- {'Delete'}
+ <FormattedMessage
+ id='rhs_root.del'
+ defaultMessage='Delete'
+ />
</a>
</li>
);
@@ -205,7 +218,15 @@ export default class RhsRootPost extends React.Component {
{botIndicator}
<li className='col'>
<time className='post__time'>
- {utils.displayCommentDateTime(post.create_at)}
+ <FormattedDate
+ value={post.create_at}
+ day='numeric'
+ month='long'
+ year='numeric'
+ hour12='true'
+ hour='2-digit'
+ minute='2-digit'
+ />
</time>
</li>
<li className='col col__reply'>
diff --git a/web/react/components/search_bar.jsx b/web/react/components/search_bar.jsx
index 77c9e39b9..35d7e9514 100644
--- a/web/react/components/search_bar.jsx
+++ b/web/react/components/search_bar.jsx
@@ -11,10 +11,20 @@ import SearchSuggestionList from './suggestion/search_suggestion_list.jsx';
import SearchUserProvider from './suggestion/search_user_provider.jsx';
import * as utils from '../utils/utils.jsx';
import Constants from '../utils/constants.jsx';
+
+import {intlShape, injectIntl, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
+
var ActionTypes = Constants.ActionTypes;
var Popover = ReactBootstrap.Popover;
-export default class SearchBar extends React.Component {
+const holders = defineMessages({
+ search: {
+ id: 'search_bar.search',
+ defaultMessage: 'Search'
+ }
+});
+
+class SearchBar extends React.Component {
constructor() {
super();
this.mounted = false;
@@ -147,7 +157,10 @@ export default class SearchBar extends React.Component {
className='search__clear'
onClick={this.clearFocus}
>
- {'Cancel'}
+ <FormattedMessage
+ id='search_bar.cancel'
+ defaultMessage='Cancel'
+ />
</span>
<form
role='form'
@@ -160,7 +173,7 @@ export default class SearchBar extends React.Component {
<SuggestionBox
ref='search'
className='form-control search-bar'
- placeholder='Search'
+ placeholder={this.props.intl.formatMessage(holders.search)}
value={this.state.searchTerm}
onFocus={this.handleUserFocus}
onBlur={this.handleUserBlur}
@@ -174,18 +187,20 @@ export default class SearchBar extends React.Component {
placement='bottom'
className={helpClass}
>
- <h4>{'Search Options'}</h4>
- <ul>
- <li>
- <span>{'Use '}</span><b>{'"quotation marks"'}</b><span>{' to search for phrases'}</span>
- </li>
- <li>
- <span>{'Use '}</span><b>{'from:'}</b><span>{' to find posts from specific users and '}</span><b>{'in:'}</b><span>{' to find posts in specific channels'}</span>
- </li>
- </ul>
+ <FormattedHTMLMessage
+ id='search_bar.usage'
+ defaultMessage='<h4>Search Options</h4><ul><li><span>Use </span><b>"quotation marks"</b><span> to search for phrases</span></li><li><span>Use </span><b>from:</b><span> to find posts from specific users and </span><b>in:</b><span> to find posts in specific channels</span></li></ul>'
+ />
</Popover>
</form>
</div>
);
}
}
+
+SearchBar.propTypes = {
+ intl: intlShape.isRequired
+};
+
+export default injectIntl(SearchBar);
+
diff --git a/web/react/components/search_results.jsx b/web/react/components/search_results.jsx
index 141181701..9dcc99061 100644
--- a/web/react/components/search_results.jsx
+++ b/web/react/components/search_results.jsx
@@ -8,6 +8,8 @@ import * as Utils from '../utils/utils.jsx';
import SearchResultsHeader from './search_results_header.jsx';
import SearchResultsItem from './search_results_item.jsx';
+import {FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
+
function getStateFromStores() {
return {results: SearchStore.getSearchResults()};
}
@@ -83,25 +85,29 @@ export default class SearchResults extends React.Component {
if (!searchTerm && noResults) {
ctls = (
<div className='sidebar--right__subheader'>
- <ul>
- <li>
- {'Use '}<b>{'"quotation marks"'}</b>{' to search for phrases'}
- </li>
- <li>
- {'Use '}<b>{'from:'}</b>{' to find posts from specific users and '}<b>{'in:'}</b>{' to find posts in specific channels'}
- </li>
- </ul>
+ <FormattedHTMLMessage
+ id='search_results.usage'
+ defaultMessage='<ul><li>Use <b>"quotation marks"</b> to search for phrases</li><li>Use <b>from:</b> to find posts from specific users and <b>in:</b> to find posts in specific channels</li></ul>'
+ />
</div>
);
} else if (noResults) {
ctls =
(
<div className='sidebar--right__subheader'>
- <h4>{'NO RESULTS'}</h4>
- <ul>
- <li>{'If you\'re searching a partial phrase (ex. searching "rea", looking for "reach" or "reaction"), append a * to your search term'}</li>
- <li>{'Due to the volume of results, two letter searches and common words like "this", "a" and "is" won\'t appear in search results'}</li>
- </ul>
+ <h4>
+ <FormattedMessage
+ id='search_results.noResults'
+ defaultMessage='NO RESULTS'
+ />
+ </h4>
+ <FormattedHTMLMessage
+ id='search_results.because'
+ defaultMessage='<ul>
+ <li>If you&#39;re searching a partial phrase (ex. searching "rea", looking for "reach" or "reaction"), append a * to your search term</li>
+ <li>Due to the volume of results, two letter searches and common words like "this", "a" and "is" won&#39;t appear in search results</li>
+ </ul>'
+ />
</div>
);
} else {
diff --git a/web/react/components/search_results_header.jsx b/web/react/components/search_results_header.jsx
index 581976494..45f56f65a 100644
--- a/web/react/components/search_results_header.jsx
+++ b/web/react/components/search_results_header.jsx
@@ -3,6 +3,9 @@
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
import Constants from '../utils/constants.jsx';
+
+import {FormattedMessage} from 'mm-intl';
+
var ActionTypes = Constants.ActionTypes;
export default class SearchResultsHeader extends React.Component {
@@ -34,10 +37,20 @@ export default class SearchResultsHeader extends React.Component {
}
render() {
- var title = 'Search Results';
+ var title = (
+ <FormattedMessage
+ id='search_header.results'
+ defaultMessage='Search Results'
+ />
+ );
if (this.props.isMentionSearch) {
- title = 'Recent Mentions';
+ title = (
+ <FormattedMessage
+ id='search_header.title2'
+ defaultMessage='Recent Mentions'
+ />
+ );
}
return (
diff --git a/web/react/components/search_results_item.jsx b/web/react/components/search_results_item.jsx
index e4f83eb1c..a0b252d25 100644
--- a/web/react/components/search_results_item.jsx
+++ b/web/react/components/search_results_item.jsx
@@ -10,6 +10,8 @@ import * as TextFormatting from '../utils/text_formatting.jsx';
import Constants from '../utils/constants.jsx';
+import {FormattedMessage, FormattedDate} from 'mm-intl';
+
export default class SearchResultsItem extends React.Component {
constructor(props) {
super(props);
@@ -42,7 +44,12 @@ export default class SearchResultsItem extends React.Component {
if (channel) {
channelName = channel.display_name;
if (channel.type === 'D') {
- channelName = 'Direct Message';
+ channelName = (
+ <FormattedMessage
+ id='search_item.direct'
+ defaultMessage='Direct Message'
+ />
+ );
}
}
@@ -69,7 +76,15 @@ export default class SearchResultsItem extends React.Component {
<li className='col__name'><strong><UserProfile userId={this.props.post.user_id} /></strong></li>
<li className='col'>
<time className='search-item-time'>
- {utils.displayDate(this.props.post.create_at) + ' ' + utils.displayTime(this.props.post.create_at)}
+ <FormattedDate
+ value={this.props.post.create_at}
+ day='numeric'
+ month='long'
+ year='numeric'
+ hour12='true'
+ hour='2-digit'
+ minute='2-digit'
+ />
</time>
</li>
<li>
@@ -78,7 +93,10 @@ export default class SearchResultsItem extends React.Component {
className='search-item__jump'
onClick={this.handleClick}
>
- {'Jump'}
+ <FormattedMessage
+ id='search_item.jump'
+ defaultMessage='Jump'
+ />
</a>
</li>
<li>
diff --git a/web/react/components/sidebar_right_menu.jsx b/web/react/components/sidebar_right_menu.jsx
index 20c2bf696..4d714e9f1 100644
--- a/web/react/components/sidebar_right_menu.jsx
+++ b/web/react/components/sidebar_right_menu.jsx
@@ -9,6 +9,8 @@ import * as client from '../utils/client.jsx';
import * as EventHelpers from '../dispatcher/event_helpers.jsx';
import * as utils from '../utils/utils.jsx';
+import {FormattedMessage} from 'mm-intl';
+
export default class SidebarRightMenu extends React.Component {
componentDidMount() {
$('.sidebar--left .dropdown-menu').perfectScrollbar();
@@ -49,7 +51,11 @@ export default class SidebarRightMenu extends React.Component {
href='#'
onClick={EventHelpers.showInviteMemberModal}
>
- <i className='fa fa-user'></i>{'Invite New Member'}
+ <i className='fa fa-user'></i>
+ <FormattedMessage
+ id='sidebar_right_menu.inviteNew'
+ defaultMessage='Invite New Member'
+ />
</a>
</li>
);
@@ -61,7 +67,11 @@ export default class SidebarRightMenu extends React.Component {
href='#'
onClick={EventHelpers.showGetTeamInviteLinkModal}
>
- <i className='glyphicon glyphicon-link'></i>{'Get Team Invite Link'}
+ <i className='glyphicon glyphicon-link'></i>
+ <FormattedMessage
+ id='sidebar_right_menu.teamLink'
+ defaultMessage='Get Team Invite Link'
+ />
</a>
</li>
);
@@ -75,13 +85,23 @@ export default class SidebarRightMenu extends React.Component {
href='#'
data-toggle='modal'
data-target='#team_settings'
- ><i className='fa fa-globe'></i>{'Team Settings'}</a>
+ >
+ <i className='fa fa-globe'></i>
+ <FormattedMessage
+ id='sidebar_right_menu.teamSettings'
+ defaultMessage='Team Settings'
+ />
+ </a>
</li>
);
manageLink = (
<li>
<ToggleModalButton dialogType={TeamMembersModal}>
- <i className='fa fa-users'></i>{'Manage Members'}
+ <i className='fa fa-users'></i>
+ <FormattedMessage
+ id='sidebar_right_menu.manageMembers'
+ defaultMessage='Manage Members'
+ />
</ToggleModalButton>
</li>
);
@@ -93,7 +113,12 @@ export default class SidebarRightMenu extends React.Component {
<a
href={'/admin_console?' + utils.getSessionIndex()}
>
- <i className='fa fa-wrench'></i>{'System Console'}</a>
+ <i className='fa fa-wrench'></i>
+ <FormattedMessage
+ id='sidebar_right_menu.console'
+ defaultMessage='System Console'
+ />
+ </a>
</li>
);
}
@@ -114,7 +139,14 @@ export default class SidebarRightMenu extends React.Component {
<a
target='_blank'
href={global.window.mm_config.HelpLink}
- ><i className='fa fa-question'></i>{'Help'}</a></li>
+ >
+ <i className='fa fa-question'></i>
+ <FormattedMessage
+ id='sidebar_right_menu.help'
+ defaultMessage='Help'
+ />
+ </a>
+ </li>
);
}
@@ -125,7 +157,14 @@ export default class SidebarRightMenu extends React.Component {
<a
target='_blank'
href={global.window.mm_config.ReportAProblemLink}
- ><i className='fa fa-phone'></i>{'Report a Problem'}</a></li>
+ >
+ <i className='fa fa-phone'></i>
+ <FormattedMessage
+ id='sidebar_right_menu.report'
+ defaultMessage='Report a Problem'
+ />
+ </a>
+ </li>
);
}
return (
@@ -144,7 +183,11 @@ export default class SidebarRightMenu extends React.Component {
href='#'
onClick={() => this.setState({showUserSettingsModal: true})}
>
- <i className='fa fa-cog'></i>{'Account Settings'}
+ <i className='fa fa-cog'></i>
+ <FormattedMessage
+ id='sidebar_right_menu.accountSettings'
+ defaultMessage='Account Settings'
+ />
</a>
</li>
{teamSettingsLink}
@@ -156,7 +199,14 @@ export default class SidebarRightMenu extends React.Component {
<a
href='#'
onClick={this.handleLogoutClick}
- ><i className='fa fa-sign-out'></i>{'Logout'}</a></li>
+ >
+ <i className='fa fa-sign-out'></i>
+ <FormattedMessage
+ id='sidebar_right_menu.logout'
+ defaultMessage='Logout'
+ />
+ </a>
+ </li>
<li className='divider'></li>
{helpLink}
{reportLink}
diff --git a/web/react/components/textbox.jsx b/web/react/components/textbox.jsx
index 62c0d5218..bb383aca1 100644
--- a/web/react/components/textbox.jsx
+++ b/web/react/components/textbox.jsx
@@ -11,6 +11,9 @@ import ErrorStore from '../stores/error_store.jsx';
import * as TextFormatting from '../utils/text_formatting.jsx';
import * as Utils from '../utils/utils.jsx';
import Constants from '../utils/constants.jsx';
+
+import {FormattedMessage} from 'mm-intl';
+
const PreReleaseFeatures = Constants.PRE_RELEASE_FEATURES;
export default class Textbox extends React.Component {
@@ -143,7 +146,17 @@ export default class Textbox extends React.Component {
onClick={this.showPreview}
className='textbox-preview-link'
>
- {this.state.preview ? 'Edit message' : 'Preview'}
+ {this.state.preview ? (
+ <FormattedMessage
+ id='textbox.edit'
+ defaultMessage='Edit message'
+ />
+ ) : (
+ <FormattedMessage
+ id='textbox.preview'
+ defaultMessage='Preview'
+ />
+ )}
</a>
);
}
@@ -184,7 +197,10 @@ export default class Textbox extends React.Component {
onClick={this.showHelp}
className='textbox-help-link'
>
- {'Help'}
+ <FormattedMessage
+ id='textbox.help'
+ defaultMessage='Help'
+ />
</a>
</div>
);
diff --git a/web/react/components/user_profile.jsx b/web/react/components/user_profile.jsx
index 385cd0f52..1e393cfe9 100644
--- a/web/react/components/user_profile.jsx
+++ b/web/react/components/user_profile.jsx
@@ -3,6 +3,9 @@
import * as Utils from '../utils/utils.jsx';
import UserStore from '../stores/user_store.jsx';
+
+import {FormattedMessage} from 'mm-intl';
+
var Popover = ReactBootstrap.Popover;
var OverlayTrigger = ReactBootstrap.OverlayTrigger;
@@ -87,7 +90,10 @@ export default class UserProfile extends React.Component {
className='text-nowrap'
key='user-popover-no-email'
>
- {'Email not shared'}
+ <FormattedMessage
+ id='user_profile.notShared'
+ defaultMessage='Email not shared'
+ />
</div>
);
} else {