all components are translated now

This commit is contained in:
or-else
2018-10-30 15:56:36 +03:00
parent 954b0079a4
commit 8c4e0e9068
20 changed files with 263 additions and 95 deletions
+4 -5
View File
@@ -2,17 +2,16 @@ import React from 'react';
/* Contact's labels: [you], [muted], [blocked], etc */
// FIXME: this class is unused.
export default class ContactBadges_UNUSED_REMOVE extends React.PureComponent {
export default class ContactBadges extends React.PureComponent {
render() {
let badges = null;
if (this.props.badges && this.props.badges.length > 0) {
badges = [];
this.props.badges.map(function(b) {
var style = 'badge' + (b.color ? ' ' + b.color : '');
// Badge names are expected to be unique, so using the name as the key.
badges.push(<span className={style} key={b.name}>{b.name}</span>);
let style = 'badge' + (b.color ? ' ' + b.color : '');
badges.push(<span className={style} key={b.key || b.name}>{b.name}</span>);
});
}
return badges;
return <span>{badges}</span>;
}
};
+22 -7
View File
@@ -1,12 +1,26 @@
// ContactList: component for showing a list of contacts,
// such as a list of group members in a group chat.
import React from 'react';
import { defineMessages, injectIntl } from 'react-intl';
import Contact from './contact.jsx';
import { makeImageUrl } from '../lib/blob-helpers.js';
/* ContactList: component for showing a list of contacts,
* such as a list of group members in a group chat */
export default class ContactList extends React.Component {
const messages = defineMessages({
badge_you: {
id: 'badge_you',
defaultMessage: 'you',
description: 'Badge for indicating the current user'
},
badge_owner: {
id: 'badge_owner',
defaultMessage: 'owner',
description: 'Badge for indicating the owner'
}
});
class ContactList extends React.Component {
render() {
var contactNodes = [];
var showCheckmark = Array.isArray(this.props.topicSelected);
@@ -34,14 +48,14 @@ export default class ContactList extends React.Component {
var badges = [];
if (this.props.showMode) {
if (key === this.props.myUserId) {
badges.push({name: "you", color: 'green'});
badges.push({name: formatMessage(messages.badge_you), color: 'green'});
}
if (c.acs && c.acs.isOwner()) {
badges.push({name: "owner"});
badges.push({name: formatMessage(messages.badge_owner), color: 'blue'});
}
}
var comment = Array.isArray(c.private) ?
c.private.join(', ') : (c.private ? c.private.comment : null);
c.private.join(',') : (c.private ? c.private.comment : null);
contactNodes.push(
<Contact
@@ -79,4 +93,5 @@ export default class ContactList extends React.Component {
);
}
};
/* END ContactList */
export default injectIntl(ContactList);
+4 -11
View File
@@ -3,6 +3,7 @@ import React from 'react';
import { FormattedMessage } from 'react-intl';
import LetterTile from './letter-tile.jsx';
import ContactBadges from './contact-badges.jsx';
import UnreadBadge from './unread-badge.jsx';
export default class Contact extends React.Component {
@@ -37,17 +38,9 @@ export default class Contact extends React.Component {
}
let online = this.props.now ? 'online' : 'offline';
let avatar = this.props.avatar ? this.props.avatar : true;
let badges = [];
if (this.props.badges && this.props.badges.length > 0) {
let count = 0;
this.props.badges.map(function(b) {
let style = 'badge' + (b.color ? ' ' + b.color : '');
badges.push(<span className={style} key={count}>{b.name}</span>);
count ++;
});
}
let badges = this.props.badges.slice();
if (this.props.showMode && this.props.acs) {
badges.push(<span className="badge" key="mode">{this.props.acs.getMode()}</span>);
badges.push({name: this.props.acs.getMode(), key: 'mode'});
}
return (
@@ -68,7 +61,7 @@ export default class Contact extends React.Component {
{this.props.unread > 0 ? <UnreadBadge count={this.props.unread} /> : null}
</div>
{this.props.comment ? <div className="contact-comment">{this.props.comment}</div> : null}
<span>{badges}</span>
<ContactBadges badges={badges} />
</div>
{this.props.showContextMenu ?
<span className="menuTrigger">
+8 -4
View File
@@ -1,6 +1,6 @@
// File uload/download progress indicator with a cancel inside.
import React from 'react';
/* File uload/download progress indicator with a cancel inside */
import { FormattedMessage } from 'react-intl';
export default class FileProgress extends React.PureComponent {
render() {
@@ -8,9 +8,13 @@ export default class FileProgress extends React.PureComponent {
<div className="uploader">
<div><span style={{width: (this.props.progress * 100) + "%"}}></span></div>
{this.props.progress < 0.999 ?
<a href="javascript:;" onClick={this.props.onCancel}><i className="material-icons">close</i> cancel</a>
<a href="javascript:;" onClick={this.props.onCancel}>
<i className="material-icons">close</i> <FormattedMessage id="action_cancel"
defaultMessage="cancel" description="Call to action [cancel]" />
</a>
:
<span>finishing...</span>
<FormattedMessage id="upload_finishing" defaultMessage="finishing..."
description="Notification that upload is finishing" />
}
</div>
);
+21 -5
View File
@@ -5,6 +5,19 @@ import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
import ChipInput from './chip-input.jsx';
import ContactList from './contact-list.jsx';
const messages = defineMessages({
no_contacts: {
id: 'no_contacts',
defaultMessage: 'You have no contacts :-(',
description: 'Shown in ContactsView when the user has no contacts'
},
contacts_not_found: {
id: 'contacts_not_found_short',
defaultMessage: "No contacts match '{query}'",
description: 'Shown in ContactsView when search returned no results'
}
});
class GroupManager extends React.Component {
constructor(props) {
super(props);
@@ -13,7 +26,7 @@ class GroupManager extends React.Component {
members: props.members,
index: GroupManager.indexMembers(props.members),
contactFilter: '',
noContactsMessage: "You have no contacts :-(",
noContactsMessage: props.intl.formatMessage(messages.no_contacts),
selectedContacts: GroupManager.selectedContacts(props.members)
};
@@ -86,8 +99,8 @@ class GroupManager extends React.Component {
handleContactFilter(val) {
const {formatMessage} = this.props.intl;
const msg = !val ?
"You have no contacts :-(" :
"No contacts match '" + val + "'";
formatMessage(messages.no_contacts) :
formatMessage(messages.contacts_not_found, {query: val});
this.setState({contactFilter: val, noContactsMessage: msg});
}
@@ -135,7 +148,7 @@ class GroupManager extends React.Component {
<div id="group-manager">
<div className="panel-form-row">
<label className="small">
<FormattedMessage id="title_group_members" defaultMessage="Group members" description="Section title" />
<FormattedMessage id="title_group_members" defaultMessage="Group Members" description="Section title" />
</label>
</div>
<div className="panel-form-row">
@@ -147,7 +160,10 @@ class GroupManager extends React.Component {
onChipRemoved={this.handleMemberRemoved} />
</div>
<div className="panel-form-row">
<label className="small">All contacts</label>
<label className="small">
<FormattedMessage id="title_all_contacts" defaultMessage="All Contacts"
description="Section title [All Contacts]" />
</label>
</div>
<ContactList
contacts={this.props.contacts}
+23 -6
View File
@@ -1,6 +1,15 @@
import React from 'react';
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
export default class NewTopicById extends React.PureComponent {
const messages = defineMessages({
invalid_id: {
id: 'error_invalid_id',
defaultMessage: 'Invalid ID',
description: 'Error message'
}
});
class NewTopicById extends React.PureComponent {
constructor(props) {
super(props);
@@ -30,7 +39,7 @@ export default class NewTopicById extends React.PureComponent {
if (name.length > 3 && (name.substr(0, 3) == 'usr' || name.substr(0, 3) == 'grp')) {
this.props.onSubmit(name);
} else {
this.props.onError("Invalid ID", 'err');
this.props.onError(this.props.intl.formatMessage(messages.invalid_id), 'err');
}
}
}
@@ -39,14 +48,22 @@ export default class NewTopicById extends React.PureComponent {
return (
<div className="panel-form">
<div className="panel-form-row">
<input type="text" placeholder="Group or User ID"
value={this.state.groupId} onChange={this.handleChange}
onKeyPress={this.handleKeyPress} required />
<FormattedMessage id="group_user_id_prompt" defaultMessage="Group or User ID"
description="Prompt for entering user or group ID">{
(prompt) => <input type="text" placeholder={prompt}
value={this.state.groupId} onChange={this.handleChange}
onKeyPress={this.handleKeyPress} required />
}</FormattedMessage>
</div>
<div className="dialog-buttons">
<button className="blue" onClick={this.handleSubmit}>Subscribe</button>
<button className="blue" onClick={this.handleSubmit}>
<FormattedMessage id="button_subscribe" defaultMessage="Subscribe"
description="Button [Subscribe]" />
</button>
</div>
</div>
);
}
};
export default injectIntl(NewTopicById);
+27 -12
View File
@@ -1,4 +1,5 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import AvatarUpload from './avatar-upload.jsx';
import TagManager from './tag-manager.jsx';
@@ -56,25 +57,39 @@ export default class NewTopicGroup extends React.PureComponent {
<form className="panel-form" onSubmit={this.handleSubmit}>
<div className="panel-form-row">
<div className="panel-form-column">
<label className="small" htmlFor="new-topic-fn">Group name</label>
<input type="text" id="new-topic-fn" placeholder="Freeform name of the group"
value={this.state.fn} onChange={this.handleFnChange} autoFocus required />
<label className="small" htmlFor="new-topic-fn">
<FormattedMessage id="label_topic_name" />
</label>
<FormattedMessage id="topic_name_editing_placeholder" defaultMessage="Freeform name of the group"
description="Prompt for entering topic name">{
(placeholder) => <input type="text" id="new-topic-fn" placeholder={placeholder}
value={this.state.fn} onChange={this.handleFnChange} autoFocus required />
}</FormattedMessage>
<br />
<label className="small" htmlFor="new-topic-priv">Private comment</label>
<input type="text" id="new-topic-priv" placeholder="Visible to you only"
value={this.state.private} onChange={this.handlePrivateChange} />
<label className="small" htmlFor="new-topic-priv">
<FormattedMessage id="label_private" />
</label>
<FormattedMessage id="private_editing_placeholder">{
(placeholder) => <input type="text" id="new-topic-priv" placeholder={placeholder}
value={this.state.private} onChange={this.handlePrivateChange} />
}</FormattedMessage>
</div>
<AvatarUpload
onError={this.props.onError}
onImageChanged={this.handleImageChanged} />
</div>
<TagManager
tags={this.state.tags}
activated={true}
onTagsChanged={this.handleTagsChanged}
title="Optional tags (search and discovery)" />
<FormattedMessage id="title_tag_manager">{
(title) => <TagManager
tags={this.state.tags}
activated={true}
onTagsChanged={this.handleTagsChanged}
title={title} />
}</FormattedMessage>
<div className="dialog-buttons">
<button className={submitClasses}>Create</button>
<button className={submitClasses}>
<FormattedMessage id="button_create" defaultMessage="Create"
description="Button [Create]" />
</button>
</div>
</form>
);
+1
View File
@@ -4,6 +4,7 @@ import { FormattedMessage } from 'react-intl';
import ChipInput from './chip-input.jsx';
import { MIN_TAG_LENGTH } from '../config.js';
import { arrayEqual } from '../lib/utils.js';
export default class TagManager extends React.Component {