more components updated and translated
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
// Flattens messages extracted via the React Intl Babel plugin. An error will be
|
// 1.Flattens messages extracted via the React Intl Babel plugin. An error will be
|
||||||
// thrown if there are messages with the same `id`. The result is a file containing
|
// thrown if there are messages with the same `id`. The result is a file containing
|
||||||
// `id: message` pairs in "en" locale.
|
// `id: message` pairs in "en" locale.
|
||||||
|
//
|
||||||
|
// 2. Takes all translations and groups them into a single file.
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var globSync = require('glob').sync;
|
var globSync = require('glob').sync;
|
||||||
@@ -9,7 +10,10 @@ var mkdirpSync = require('mkdirp').sync;
|
|||||||
|
|
||||||
const MESSAGES_PATTERN = './src/i18n/src/**/*.json';
|
const MESSAGES_PATTERN = './src/i18n/src/**/*.json';
|
||||||
const LANG_DIR = './src/i18n/';
|
const LANG_DIR = './src/i18n/';
|
||||||
|
const LANG_PATTERN = './src/i18n/*.json';
|
||||||
|
const FINAL_FILE = './src/messages.json';
|
||||||
|
|
||||||
|
// Read message files generated by react-intl-babel-plugin.
|
||||||
let messages = globSync(MESSAGES_PATTERN)
|
let messages = globSync(MESSAGES_PATTERN)
|
||||||
.map((filename) => fs.readFileSync(filename, 'utf8'))
|
.map((filename) => fs.readFileSync(filename, 'utf8'))
|
||||||
.map((file) => JSON.parse(file))
|
.map((file) => JSON.parse(file))
|
||||||
@@ -24,6 +28,22 @@ let messages = globSync(MESSAGES_PATTERN)
|
|||||||
return collection;
|
return collection;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
|
// Write English translation.
|
||||||
let filename = path.join(LANG_DIR, 'en.json');
|
let filename = path.join(LANG_DIR, 'en.json');
|
||||||
mkdirpSync(path.dirname(filename));
|
mkdirpSync(path.dirname(filename));
|
||||||
fs.writeFileSync(filename, JSON.stringify(messages, null, 2));
|
fs.writeFileSync(filename, JSON.stringify(messages, null, 2));
|
||||||
|
|
||||||
|
// Read all translations.
|
||||||
|
messages = globSync(LANG_PATTERN)
|
||||||
|
.map((filename) => {
|
||||||
|
const parts = filename.split('/');
|
||||||
|
const locale = parts[parts.length - 1].split('.json')[0];
|
||||||
|
return { [locale]: JSON.parse(fs.readFileSync(filename, 'utf8')) };
|
||||||
|
})
|
||||||
|
.reduce((collection, descriptors) => {
|
||||||
|
return { ...collection, ...descriptors };
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
// Write file with all translations combined.
|
||||||
|
mkdirpSync(path.dirname(FINAL_FILE));
|
||||||
|
fs.writeFileSync(FINAL_FILE, JSON.stringify(messages, null, 2));
|
||||||
|
|||||||
+8
-3
@@ -2,12 +2,12 @@
|
|||||||
"contacts_not_found": "You have no chats<br />¯\\\\_(ツ)_/¯",
|
"contacts_not_found": "You have no chats<br />¯\\\\_(ツ)_/¯",
|
||||||
"full_name_prompt": "Full name, e.g. John Doe",
|
"full_name_prompt": "Full name, e.g. John Doe",
|
||||||
"email_prompt": "Email, e.g. jdoe@example.com",
|
"email_prompt": "Email, e.g. jdoe@example.com",
|
||||||
"sign_up_button": "Sign up",
|
"button_sign_up": "Sign up",
|
||||||
"login_prompt": "Login",
|
"login_prompt": "Login",
|
||||||
"password_prompt": "Password",
|
"password_prompt": "Password",
|
||||||
"stay_logged_in": "Stay logged in",
|
"stay_logged_in": "Stay logged in",
|
||||||
"forgot_password_link": "Forgot password?",
|
"forgot_password_link": "Forgot password?",
|
||||||
"sign_in_button": "Sign in",
|
"button_sign_in": "Sign in",
|
||||||
"label_client": "Client:",
|
"label_client": "Client:",
|
||||||
"label_server": "Server:",
|
"label_server": "Server:",
|
||||||
"online_now": "online now",
|
"online_now": "online now",
|
||||||
@@ -15,6 +15,9 @@
|
|||||||
"title_not_found": "Not found",
|
"title_not_found": "Not found",
|
||||||
"unnamed_topic": "Unnamed",
|
"unnamed_topic": "Unnamed",
|
||||||
"messages_not_readable": "no access to messages",
|
"messages_not_readable": "no access to messages",
|
||||||
|
"tabtitle_find_user": "find",
|
||||||
|
"tabtitle_new_group": "new group",
|
||||||
|
"tabtitle_group_by_id": "by id",
|
||||||
"label_server_to_use": "Server to use:",
|
"label_server_to_use": "Server to use:",
|
||||||
"label_wire_transport": "Wire transport:",
|
"label_wire_transport": "Wire transport:",
|
||||||
"button_update": "Update",
|
"button_update": "Update",
|
||||||
@@ -24,5 +27,7 @@
|
|||||||
"sidepanel_title_edit_account": "Edit Account",
|
"sidepanel_title_edit_account": "Edit Account",
|
||||||
"sidepanel_title_newtpk": "Start New Chat",
|
"sidepanel_title_newtpk": "Start New Chat",
|
||||||
"sidepanel_title_cred": "Confirm Credentials",
|
"sidepanel_title_cred": "Confirm Credentials",
|
||||||
"sidepanel_title_reset": "Reset Password"
|
"sidepanel_title_reset": "Reset Password",
|
||||||
|
"tags_not_found": "No tags defined. Add some.",
|
||||||
|
"tags_editor_no_tags": "Add some tags"
|
||||||
}
|
}
|
||||||
+5
-2
@@ -2,12 +2,12 @@
|
|||||||
"contacts_not_found": "Чатов нет<br />¯\\\\_(ツ)_/¯",
|
"contacts_not_found": "Чатов нет<br />¯\\\\_(ツ)_/¯",
|
||||||
"full_name_prompt": "Полное имя, напр. Иван Петров",
|
"full_name_prompt": "Полное имя, напр. Иван Петров",
|
||||||
"email_prompt": "Email, напр. ivan@example.com",
|
"email_prompt": "Email, напр. ivan@example.com",
|
||||||
"sign_up_button": "Создать счет",
|
"button_sign_up": "Создать счет",
|
||||||
"login_prompt": "Логин",
|
"login_prompt": "Логин",
|
||||||
"password_prompt": "Пароль",
|
"password_prompt": "Пароль",
|
||||||
"stay_logged_in": "Запомнить",
|
"stay_logged_in": "Запомнить",
|
||||||
"forgot_password_link": "Напомнить пароль",
|
"forgot_password_link": "Напомнить пароль",
|
||||||
"sign_in_button": "Войти",
|
"button_sign_in": "Войти",
|
||||||
"label_client": "Клиент:",
|
"label_client": "Клиент:",
|
||||||
"label_server": "Сервер:",
|
"label_server": "Сервер:",
|
||||||
"online_now": "онлайн",
|
"online_now": "онлайн",
|
||||||
@@ -15,6 +15,9 @@
|
|||||||
"title_not_found": "Не найден",
|
"title_not_found": "Не найден",
|
||||||
"unnamed_topic": "Без названия",
|
"unnamed_topic": "Без названия",
|
||||||
"messages_not_readable": "нет доступа к сообщениям",
|
"messages_not_readable": "нет доступа к сообщениям",
|
||||||
|
"tabtitle_find_user": "найти",
|
||||||
|
"tabtitle_new_group": "создать",
|
||||||
|
"tabtitle_group_by_id": "по id",
|
||||||
"label_server_to_use": "Использовать сервер:",
|
"label_server_to_use": "Использовать сервер:",
|
||||||
"label_wire_transport": "Соединение:",
|
"label_wire_transport": "Соединение:",
|
||||||
"button_update": "Применить",
|
"button_update": "Применить",
|
||||||
|
|||||||
+10
-3
@@ -6,8 +6,7 @@ import ReactDOM from 'react-dom';
|
|||||||
import { IntlProvider, addLocaleData } from 'react-intl';
|
import { IntlProvider, addLocaleData } from 'react-intl';
|
||||||
import ruData from 'react-intl/locale-data/ru';
|
import ruData from 'react-intl/locale-data/ru';
|
||||||
addLocaleData(ruData);
|
addLocaleData(ruData);
|
||||||
import en from './i18n/en.json';
|
import allMessages from './messages.json';
|
||||||
import ru from './i18n/ru.json';
|
|
||||||
|
|
||||||
import TinodeWeb from './views/tinode-web.jsx';
|
import TinodeWeb from './views/tinode-web.jsx';
|
||||||
|
|
||||||
@@ -19,8 +18,16 @@ const language = (params && params.hl) ||
|
|||||||
navigator.language ||
|
navigator.language ||
|
||||||
navigator.userLanguage;
|
navigator.userLanguage;
|
||||||
|
|
||||||
|
const baseLanguage = language.toLowerCase().split(/[-_]+/)[0];
|
||||||
|
|
||||||
|
// Try full locale, try locale without region code, fallback to 'en'
|
||||||
|
const messages =
|
||||||
|
allMessages[language] ||
|
||||||
|
allMessages[baseLanguage] ||
|
||||||
|
allMessages.en;
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<IntlProvider locale={language} messages={en} >
|
<IntlProvider locale={language} messages={messages} >
|
||||||
<TinodeWeb />
|
<TinodeWeb />
|
||||||
</IntlProvider>,
|
</IntlProvider>,
|
||||||
document.getElementById('mountPoint')
|
document.getElementById('mountPoint')
|
||||||
|
|||||||
+5
-3
@@ -1,5 +1,7 @@
|
|||||||
|
// Odds and ends
|
||||||
|
|
||||||
// Make shortcut icon appear with a green dot + show unread count in title.
|
// Make shortcut icon appear with a green dot + show unread count in title.
|
||||||
function updateFavicon(count) {
|
export function updateFavicon(count) {
|
||||||
var oldIcon = document.getElementById('shortcut-icon');
|
var oldIcon = document.getElementById('shortcut-icon');
|
||||||
if (oldIcon) {
|
if (oldIcon) {
|
||||||
var head = document.head || document.getElementsByTagName('head')[0];
|
var head = document.head || document.getElementsByTagName('head')[0];
|
||||||
@@ -15,7 +17,7 @@ function updateFavicon(count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create VCard which represents topic 'public' info
|
// Create VCard which represents topic 'public' info
|
||||||
function vcard(fn, imageDataUrl) {
|
export function vcard(fn, imageDataUrl) {
|
||||||
var card = null;
|
var card = null;
|
||||||
|
|
||||||
if ((fn && fn.trim()) || imageDataUrl) {
|
if ((fn && fn.trim()) || imageDataUrl) {
|
||||||
@@ -35,7 +37,7 @@ function vcard(fn, imageDataUrl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Deep-shallow compare two arrays: shallow compare each element.
|
// Deep-shallow compare two arrays: shallow compare each element.
|
||||||
function arrayEqual(a, b) {
|
export function arrayEqual(a, b) {
|
||||||
// Compare lengths first.
|
// Compare lengths first.
|
||||||
if (a.length != b.length) {
|
if (a.length != b.length) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
/* ContactsView holds all contacts-related stuff */
|
/* ContactsView holds all contacts-related stuff */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
import ContactList from '../widgets/contact-list.jsx';
|
import ContactList from '../widgets/contact-list.jsx';
|
||||||
|
|
||||||
|
import { updateFavicon } from '../lib/utils.js';
|
||||||
|
|
||||||
// Panel titles for translation.
|
// Panel titles for translation.
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
'contacts_not_found': {
|
'contacts_not_found': {
|
||||||
@@ -13,7 +15,7 @@ const messages = defineMessages({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default class ContactsView extends React.Component {
|
class ContactsView extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@@ -37,7 +39,7 @@ export default class ContactsView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {formatMessage} = this.props.intl;
|
const {formatHTMLMessage} = this.props.intl;
|
||||||
return (
|
return (
|
||||||
<ContactList
|
<ContactList
|
||||||
connected={this.props.connected}
|
connected={this.props.connected}
|
||||||
@@ -52,3 +54,5 @@ export default class ContactsView extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default injectIntl(ContactsView);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import CheckBox from '../widgets/checkbox.jsx';
|
|||||||
import VisiblePassword from '../widgets/visible-password.jsx';
|
import VisiblePassword from '../widgets/visible-password.jsx';
|
||||||
|
|
||||||
import LocalStorageUtil from '../lib/local-storage.js';
|
import LocalStorageUtil from '../lib/local-storage.js';
|
||||||
import vcard from '../lib/utils.js';
|
import { vcard } from '../lib/utils.js';
|
||||||
|
|
||||||
export default class CreateAccountView extends React.PureComponent {
|
export default class CreateAccountView extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -115,7 +115,7 @@ export default class CreateAccountView extends React.PureComponent {
|
|||||||
</div>
|
</div>
|
||||||
<div className="dialog-buttons">
|
<div className="dialog-buttons">
|
||||||
<button className={submitClasses} type="submit">
|
<button className={submitClasses} type="submit">
|
||||||
<FormattedMessage id="sign_up_button" defaultMessage="Sign up"
|
<FormattedMessage id="button_sign_up" defaultMessage="Sign up"
|
||||||
description="Create account button [Sign Up]" />
|
description="Create account button [Sign Up]" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ export default class LoginView extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
<div className="dialog-buttons">
|
<div className="dialog-buttons">
|
||||||
<button className={submitClasses} type="submit">
|
<button className={submitClasses} type="submit">
|
||||||
<FormattedMessage id="sign_in_button" defaultMessage="Sign in"
|
<FormattedMessage id="button_sign_in" defaultMessage="Sign in"
|
||||||
description="Button [Sign In]" />
|
description="Button [Sign In]" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
/* Create new topic and invite users or send an invite */
|
/* Create new topic and invite users or send an invite */
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import ContactList from '../widgets/contact-list.jsx';
|
import ContactList from '../widgets/contact-list.jsx';
|
||||||
import NewTopicById from '../widgets/new-topic-by-id.jsx';
|
import NewTopicById from '../widgets/new-topic-by-id.jsx';
|
||||||
import NewTopicGroup from '../widgets/new-topic-group.jsx';
|
import NewTopicGroup from '../widgets/new-topic-group.jsx';
|
||||||
import SearchContacts from '../widgets/search-contacts.jsx';
|
import SearchContacts from '../widgets/search-contacts.jsx';
|
||||||
|
|
||||||
|
import HashNavigation from '../lib/navigation.js';
|
||||||
|
|
||||||
export default class NewTopicView extends React.Component {
|
export default class NewTopicView extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@@ -34,24 +37,24 @@ export default class NewTopicView extends React.Component {
|
|||||||
|
|
||||||
handleTabClick(e) {
|
handleTabClick(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
navigateTo(addUrlParam(window.location.hash, 'tab', e.currentTarget.dataset.id));
|
HashNavigation.navigateTo(HashNavigation.addUrlParam(window.location.hash, 'tab', e.currentTarget.dataset.id));
|
||||||
this.setState({tabSelected: e.currentTarget.dataset.id});
|
this.setState({tabSelected: e.currentTarget.dataset.id});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleContactSelected(sel) {
|
handleContactSelected(sel) {
|
||||||
if (this.state.tabSelected === 'p2p') {
|
if (this.state.tabSelected === 'p2p') {
|
||||||
navigateTo(removeUrlParam(window.location.hash, 'tab'));
|
HashNavigation.navigateTo(HashNavigation.removeUrlParam(window.location.hash, 'tab'));
|
||||||
this.props.onCreateTopic(sel, undefined);
|
this.props.onCreateTopic(sel, undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleNewGroupSubmit(name, dataUrl, priv, tags) {
|
handleNewGroupSubmit(name, dataUrl, priv, tags) {
|
||||||
navigateTo(removeUrlParam(window.location.hash, 'tab'));
|
HashNavigation.navigateTo(HashNavigation.removeUrlParam(window.location.hash, 'tab'));
|
||||||
this.props.onCreateTopic(undefined, vcard(name, dataUrl), priv, tags);
|
this.props.onCreateTopic(undefined, vcard(name, dataUrl), priv, tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleGroupByID(topicName) {
|
handleGroupByID(topicName) {
|
||||||
navigateTo(removeUrlParam(window.location.hash, 'tab'));
|
HashNavigation.navigateTo(HashNavigation.removeUrlParam(window.location.hash, 'tab'));
|
||||||
this.props.onCreateTopic(topicName);
|
this.props.onCreateTopic(topicName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,13 +63,22 @@ export default class NewTopicView extends React.Component {
|
|||||||
<div className="flex-column">
|
<div className="flex-column">
|
||||||
<ul className="tabbar">
|
<ul className="tabbar">
|
||||||
<li className={this.state.tabSelected === "p2p" ? "active" : null}>
|
<li className={this.state.tabSelected === "p2p" ? "active" : null}>
|
||||||
<a href="javascript:;" data-id="p2p" onClick={this.handleTabClick}>find</a>
|
<a href="javascript:;" data-id="p2p" onClick={this.handleTabClick}>
|
||||||
|
<FormattedMessage id="tabtitle_find_user" defaultMessage="find"
|
||||||
|
description="Tab title Find" />
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li className={this.state.tabSelected === "grp" ? "active" : null}>
|
<li className={this.state.tabSelected === "grp" ? "active" : null}>
|
||||||
<a href="javascript:;" data-id="grp" onClick={this.handleTabClick}>new group</a>
|
<a href="javascript:;" data-id="grp" onClick={this.handleTabClick}>
|
||||||
|
<FormattedMessage id="tabtitle_new_group" defaultMessage="new group"
|
||||||
|
description="Tab title New Group" />
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li className={this.state.tabSelected === "byid" ? "active" : null}>
|
<li className={this.state.tabSelected === "byid" ? "active" : null}>
|
||||||
<a href="javascript:;" data-id="byid" onClick={this.handleTabClick}>by id</a>
|
<a href="javascript:;" data-id="byid" onClick={this.handleTabClick}>
|
||||||
|
<FormattedMessage id="tabtitle_group_by_id" defaultMessage="by id"
|
||||||
|
description="Tab title Find topic by ID" />
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
{this.state.tabSelected === 'grp' ?
|
{this.state.tabSelected === 'grp' ?
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import MessagesView from './messages-view.jsx';
|
|||||||
import SidepanelView from './sidepanel-view.jsx';
|
import SidepanelView from './sidepanel-view.jsx';
|
||||||
|
|
||||||
import { API_KEY, APP_NAME, MEDIA_BREAKPOINT, RECEIVED_DELAY } from '../config.js';
|
import { API_KEY, APP_NAME, MEDIA_BREAKPOINT, RECEIVED_DELAY } from '../config.js';
|
||||||
|
import { makeImageUrl } from '../lib/blob-helpers.js';
|
||||||
import { isLocalHost, isSecureConnection } from '../lib/host-name.js';
|
import { isLocalHost, isSecureConnection } from '../lib/host-name.js';
|
||||||
import LocalStorageUtil from '../lib/local-storage.js';
|
import LocalStorageUtil from '../lib/local-storage.js';
|
||||||
import HashNavigation from '../lib/navigation.js';
|
import HashNavigation from '../lib/navigation.js';
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import React from 'react';
|
|||||||
|
|
||||||
import Contact from './contact.jsx';
|
import Contact from './contact.jsx';
|
||||||
|
|
||||||
|
import { makeImageUrl } from '../lib/blob-helpers.js';
|
||||||
|
|
||||||
/* ContactList: component for showing a list of contacts,
|
/* ContactList: component for showing a list of contacts,
|
||||||
* such as a list of group members in a group chat */
|
* such as a list of group members in a group chat */
|
||||||
export default class ContactList extends React.Component {
|
export default class ContactList extends React.Component {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import React from 'react';
|
|||||||
|
|
||||||
import Tinode from 'tinode-sdk';
|
import Tinode from 'tinode-sdk';
|
||||||
|
|
||||||
|
import { stringHash } from '../lib/strformat.js';
|
||||||
|
|
||||||
export default class LetterTile extends React.PureComponent {
|
export default class LetterTile extends React.PureComponent {
|
||||||
render() {
|
render() {
|
||||||
let avatar;
|
let avatar;
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
// TagManager: edit topic or user tags.
|
// TagManager: edit topic or user tags.
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import ChipInput from './chip-input.jsx';
|
import ChipInput from './chip-input.jsx';
|
||||||
|
|
||||||
|
import { arrayEqual } from '../lib/utils.js';
|
||||||
|
|
||||||
export default class TagManager extends React.Component {
|
export default class TagManager extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@@ -10,8 +13,7 @@ export default class TagManager extends React.Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
tags: this.props.tags,
|
tags: this.props.tags,
|
||||||
tagInput: '',
|
tagInput: '',
|
||||||
activated: this.props.activated,
|
activated: this.props.activated
|
||||||
noTagsMessage: "Add some tags"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.handleShowTagManager = this.handleShowTagManager.bind(this);
|
this.handleShowTagManager = this.handleShowTagManager.bind(this);
|
||||||
@@ -99,7 +101,9 @@ export default class TagManager extends React.Component {
|
|||||||
tags.push(<span className="badge" key={tags.length}>{tag}</span>);
|
tags.push(<span className="badge" key={tags.length}>{tag}</span>);
|
||||||
});
|
});
|
||||||
if (tags.length == 0) {
|
if (tags.length == 0) {
|
||||||
tags = <i>No tags defined. Add some.</i>;
|
tags = (<i>
|
||||||
|
<FormattedMessage id="tags_not_found" defaultMessage="No tags defined. Add some." description="" />
|
||||||
|
</i>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
@@ -109,26 +113,34 @@ export default class TagManager extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
{this.state.activated ?
|
{this.state.activated ?
|
||||||
<div>
|
<div>
|
||||||
<ChipInput
|
<FormattedMessage id="tags_editor_no_tags" defaultMessage="Add some tags"
|
||||||
|
description="Tag editor prompt when no tags are found.">{
|
||||||
|
(add_tags_prompt) => <ChipInput
|
||||||
chips={tags}
|
chips={tags}
|
||||||
avatarDisabled={true}
|
avatarDisabled={true}
|
||||||
prompt={this.state.noTagsMessage}
|
prompt={add_tags_prompt}
|
||||||
onEnter={this.handleAddTag}
|
onEnter={this.handleAddTag}
|
||||||
onFocusLost={this.handleAddTag}
|
onFocusLost={this.handleAddTag}
|
||||||
onCancel={this.handleCancel}
|
onCancel={this.handleCancel}
|
||||||
onChipRemoved={this.handleRemoveTag}
|
onChipRemoved={this.handleRemoveTag}
|
||||||
filterFunc={this.handleTagInput} />
|
filterFunc={this.handleTagInput} />
|
||||||
|
}</FormattedMessage>
|
||||||
{this.props.onSubmit || this.props.onCancel ?
|
{this.props.onSubmit || this.props.onCancel ?
|
||||||
<div id="tag-manager-buttons" className="panel-form-row">
|
<div id="tag-manager-buttons" className="panel-form-row">
|
||||||
<button className="blue" onClick={this.handleSubmit}>OK</button>
|
<button className="blue" onClick={this.handleSubmit}>
|
||||||
<button className="white" onClick={this.handleCancel}>Cancel</button>
|
<FormattedMessage id="button_ok" defautMessage="OK" description="Confirmation button [OK]" />
|
||||||
|
</button>
|
||||||
|
<button className="white" onClick={this.handleCancel}>
|
||||||
|
<FormattedMessage id="button_cancel" defautMessage="Cancel" description="Rejection button [Cancel]" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
: null}
|
: null}
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
<div>
|
<div>
|
||||||
<a href="javascript:;" className="flat-button" onClick={this.handleShowTagManager}>
|
<a href="javascript:;" className="flat-button" onClick={this.handleShowTagManager}>
|
||||||
<i className="material-icons">edit</i> Manage tags
|
<i className="material-icons">edit</i> <FormattedMessage id="title_manage_tags" defautMessage="Manage tags"
|
||||||
|
description="Section title in TagManager" />
|
||||||
</a>
|
</a>
|
||||||
<span>{tags}</span>
|
<span>{tags}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+36
-34
File diff suppressed because one or more lines are too long
+6
-6
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user