Commit 11cd6b83 authored by JC Brand's avatar JC Brand

Fixes #2193.

Translations called at the top of template files don't apply, since the
trnaslations aren't yet fetched at that point.
parent 3e8b3f73
...@@ -1544,7 +1544,7 @@ Object.assign(converse, { ...@@ -1544,7 +1544,7 @@ Object.assign(converse, {
/^converse\?loglevel=(debug|info|warn|error|fatal)$/, 'loglevel', /^converse\?loglevel=(debug|info|warn|error|fatal)$/, 'loglevel',
l => log.setLogLevel(l) l => log.setLogLevel(l)
); );
initLocale(); await initLocale();
_converse.connfeedback = new _converse.ConnectionFeedback(); _converse.connfeedback = new _converse.ConnectionFeedback();
/* When reloading the page: /* When reloading the page:
......
...@@ -4,21 +4,23 @@ import { __ } from '@converse/headless/i18n'; ...@@ -4,21 +4,23 @@ import { __ } from '@converse/headless/i18n';
import { modal_header_close_button } from "./buttons" import { modal_header_close_button } from "./buttons"
import xss from "xss/dist/xss"; import xss from "xss/dist/xss";
const i18n_join = __('Join');
const i18n_enter = __('Enter a new Groupchat');
const i18n_nickname = __('Nickname');
const i18n_required_field = __('This field is required');
const nickname_input = (o) => {
const nickname_input = (o) => html` const i18n_nickname = __('Nickname');
const i18n_required_field = __('This field is required');
return html`
<div class="form-group" > <div class="form-group" >
<label for="nickname">${i18n_nickname}:</label> <label for="nickname">${i18n_nickname}:</label>
<input type="text" title="${i18n_required_field}" required="required" name="nickname" value="${o.nick || ''}" class="form-control"/> <input type="text" title="${i18n_required_field}" required="required" name="nickname" value="${o.nick || ''}" class="form-control"/>
</div> </div>
`; `;
}
export default (o) => html` export default (o) => {
const i18n_join = __('Join');
const i18n_enter = __('Enter a new Groupchat');
return html`
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
...@@ -40,4 +42,5 @@ export default (o) => html` ...@@ -40,4 +42,5 @@ export default (o) => html`
</div> </div>
</div> </div>
</div> </div>
`; `;
}
...@@ -2,15 +2,15 @@ import { html } from "lit-html"; ...@@ -2,15 +2,15 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n'; import { __ } from '@converse/headless/i18n';
import { modal_header_close_button } from "./buttons" import { modal_header_close_button } from "./buttons"
const i18n_contact_placeholder = __('name@example.org');
const i18n_add = __('Add');
const i18n_error_message = __('Please enter a valid XMPP address');
const i18n_new_contact = __('Add a Contact');
const i18n_xmpp_address = __('XMPP Address');
const i18n_nickname = __('Nickname');
export default (o) => {
export default (o) => html` const i18n_contact_placeholder = __('name@example.org');
const i18n_add = __('Add');
const i18n_error_message = __('Please enter a valid XMPP address');
const i18n_new_contact = __('Add a Contact');
const i18n_xmpp_address = __('XMPP Address');
const i18n_nickname = __('Nickname');
return html`
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
...@@ -49,4 +49,5 @@ export default (o) => html` ...@@ -49,4 +49,5 @@ export default (o) => html`
</form> </form>
</div> </div>
</div> </div>
`; `;
}
...@@ -2,13 +2,10 @@ import { html } from "lit-html"; ...@@ -2,13 +2,10 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n'; import { __ } from '@converse/headless/i18n';
const desc_bookmarks = __('Click to toggle the bookmarks list'); const bookmark_item = (o) => {
const info_remove_bookmark = __('Unbookmark this groupchat'); const info_remove_bookmark = __('Unbookmark this groupchat');
const label_bookmarks = __('Bookmarks'); const open_title = __('Click to open this groupchat');
const open_title = __('Click to open this groupchat'); return html`
const bookmark_item = (o) => html`
<div class="list-item controlbox-padded room-item available-chatroom d-flex flex-row ${ (o.is_hidden(o.bm)) ? 'hidden' : ''}" data-room-jid="${o.bm.get('jid')}"> <div class="list-item controlbox-padded room-item available-chatroom d-flex flex-row ${ (o.is_hidden(o.bm)) ? 'hidden' : ''}" data-room-jid="${o.bm.get('jid')}">
<a class="list-item-link open-room w-100" data-room-jid="${o.bm.get('jid')}" <a class="list-item-link open-room w-100" data-room-jid="${o.bm.get('jid')}"
title="${open_title}" title="${open_title}"
...@@ -20,9 +17,13 @@ const bookmark_item = (o) => html` ...@@ -20,9 +17,13 @@ const bookmark_item = (o) => html`
title="${info_remove_bookmark}" title="${info_remove_bookmark}"
@click=${o.removeBookmark}></a> @click=${o.removeBookmark}></a>
</div> </div>
`; `;
}
export default (o) => html` export default (o) => {
const desc_bookmarks = __('Click to toggle the bookmarks list');
const label_bookmarks = __('Bookmarks');
return html`
<div class="list-container list-container--bookmarks ${ !o.hidden && 'hidden' || '' }"> <div class="list-container list-container--bookmarks ${ !o.hidden && 'hidden' || '' }">
<a class="list-toggle bookmarks-toggle controlbox-padded" <a class="list-toggle bookmarks-toggle controlbox-padded"
title="${desc_bookmarks}" title="${desc_bookmarks}"
...@@ -34,4 +35,5 @@ export default (o) => html` ...@@ -34,4 +35,5 @@ export default (o) => html`
${ o.bookmarks.map(bm => bookmark_item(Object.assign({bm}, o))) } ${ o.bookmarks.map(bm => bookmark_item(Object.assign({bm}, o))) }
</div> </div>
</div> </div>
`; `;
}
import { __ } from '@converse/headless/i18n'; import { __ } from '@converse/headless/i18n';
import { html } from "lit-html"; import { html } from "lit-html";
const i18n_close = __('Close');
export const modal_close_button = html`<button type="button" class="btn btn-secondary" data-dismiss="modal">${i18n_close}</button>`; export const modal_close_button = html`<button type="button" class="btn btn-secondary" data-dismiss="modal">${__('Close')}</button>`;
export const modal_header_close_button = html`<button type="button" class="close" data-dismiss="modal" aria-label="${i18n_close}"><span aria-hidden="true">×</span></button>`; export const modal_header_close_button = html`<button type="button" class="close" data-dismiss="modal" aria-label="${__('Close')}"><span aria-hidden="true">×</span></button>`;
...@@ -3,10 +3,8 @@ import { __ } from '@converse/headless/i18n'; ...@@ -3,10 +3,8 @@ import { __ } from '@converse/headless/i18n';
import { renderAvatar } from './../templates/directives/avatar'; import { renderAvatar } from './../templates/directives/avatar';
const i18n_new_messages = __('New messages');
export default (o) => { export default (o) => {
const i18n_new_messages = __('New messages');
return html` return html`
${ o.is_first_unread ? html`<div class="message date-separator"><hr class="separator"><span class="separator-text">${ i18n_new_messages }</span></div>` : '' } ${ o.is_first_unread ? html`<div class="message date-separator"><hr class="separator"><span class="separator-text">${ i18n_new_messages }</span></div>` : '' }
<div class="message chat-msg ${ o.getExtraMessageClasses() }" <div class="message chat-msg ${ o.getExtraMessageClasses() }"
......
...@@ -3,19 +3,17 @@ import { __ } from '@converse/headless/i18n'; ...@@ -3,19 +3,17 @@ import { __ } from '@converse/headless/i18n';
import { until } from 'lit-html/directives/until.js'; import { until } from 'lit-html/directives/until.js';
import avatar from "./avatar.js"; import avatar from "./avatar.js";
const i18n_profile = __('The User\'s Profile Image');
const avatar_data = { export default (o) => {
const i18n_profile = __('The User\'s Profile Image');
const avatar_data = {
'alt_text': i18n_profile, 'alt_text': i18n_profile,
'extra_classes': '', 'extra_classes': '',
'height': 40, 'height': 40,
'width': 40, 'width': 40,
} }
const tpl_standalone_btns = (o) => o.standalone_btns.reverse().map(b => until(b, ''));
const tpl_standalone_btns = (o) => o.standalone_btns.reverse().map(b => until(b, ''));
export default (o) => {
return html` return html`
<div class="chatbox-title ${ o.status ? '' : "chatbox-title--no-desc"}"> <div class="chatbox-title ${ o.status ? '' : "chatbox-title--no-desc"}">
<div class="chatbox-title--row"> <div class="chatbox-title--row">
......
...@@ -5,47 +5,48 @@ import { unsafeHTML } from 'lit-html/directives/unsafe-html.js'; ...@@ -5,47 +5,48 @@ import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
import xss from "xss/dist/xss"; import xss from "xss/dist/xss";
const i18n_address = __('Groupchat address (JID)'); const subject = (o) => {
const i18n_archiving = __('Message archiving'); const i18n_topic = __('Topic');
const i18n_archiving_help = __('Messages are archived on the server'); const i18n_topic_author = __('Topic author');
const i18n_desc = __('Description'); return html`
const i18n_features = __('Features');
const i18n_hidden = __('Hidden');
const i18n_hidden_help = __('This groupchat is not publicly searchable');
const i18n_members_help = __('This groupchat is restricted to members only');
const i18n_members_only = __('Members only');
const i18n_moderated = __('Moderated');
const i18n_moderated_help = __('Participants entering this groupchat need to request permission to write');
const i18n_name = __('Name');
const i18n_no_pass_help = __('This groupchat does not require a password upon entry');
const i18n_no_password_required = __('No password required');
const i18n_not_anonymous = __('Not anonymous');
const i18n_not_anonymous_help = __('All other groupchat participants can see your XMPP address');
const i18n_not_moderated = __('Not moderated');
const i18n_not_moderated_help = __('Participants entering this groupchat can write right away');
const i18n_online_users = __('Online users');
const i18n_open = __('Open');
const i18n_open_help = __('Anyone can join this groupchat');
const i18n_password_help = __('This groupchat requires a password before entry');
const i18n_password_protected = __('Password protected');
const i18n_persistent = __('Persistent');
const i18n_persistent_help = __('This groupchat persists even if it\'s unoccupied');
const i18n_public = __('Public');
const i18n_semi_anon = __('Semi-anonymous');
const i18n_semi_anon_help = __('Only moderators can see your XMPP address');
const i18n_temporary = __('Temporary');
const i18n_temporary_help = __('This groupchat will disappear once the last person leaves');
const i18n_topic = __('Topic');
const i18n_topic_author = __('Topic author');
const subject = (o) => html`
<p class="room-info"><strong>${i18n_topic}</strong>: ${unsafeHTML(xss.filterXSS(o.subject.text, {'whiteList': {}}))}</p> <p class="room-info"><strong>${i18n_topic}</strong>: ${unsafeHTML(xss.filterXSS(o.subject.text, {'whiteList': {}}))}</p>
<p class="room-info"><strong>${i18n_topic_author}</strong>: ${o.subject && o.subject.author}</p> <p class="room-info"><strong>${i18n_topic_author}</strong>: ${o.subject && o.subject.author}</p>
`; `;
}
export default (o) => html` export default (o) => {
const i18n_address = __('Groupchat address (JID)');
const i18n_archiving = __('Message archiving');
const i18n_archiving_help = __('Messages are archived on the server');
const i18n_desc = __('Description');
const i18n_features = __('Features');
const i18n_hidden = __('Hidden');
const i18n_hidden_help = __('This groupchat is not publicly searchable');
const i18n_members_help = __('This groupchat is restricted to members only');
const i18n_members_only = __('Members only');
const i18n_moderated = __('Moderated');
const i18n_moderated_help = __('Participants entering this groupchat need to request permission to write');
const i18n_name = __('Name');
const i18n_no_pass_help = __('This groupchat does not require a password upon entry');
const i18n_no_password_required = __('No password required');
const i18n_not_anonymous = __('Not anonymous');
const i18n_not_anonymous_help = __('All other groupchat participants can see your XMPP address');
const i18n_not_moderated = __('Not moderated');
const i18n_not_moderated_help = __('Participants entering this groupchat can write right away');
const i18n_online_users = __('Online users');
const i18n_open = __('Open');
const i18n_open_help = __('Anyone can join this groupchat');
const i18n_password_help = __('This groupchat requires a password before entry');
const i18n_password_protected = __('Password protected');
const i18n_persistent = __('Persistent');
const i18n_persistent_help = __('This groupchat persists even if it\'s unoccupied');
const i18n_public = __('Public');
const i18n_semi_anon = __('Semi-anonymous');
const i18n_semi_anon_help = __('Only moderators can see your XMPP address');
const i18n_temporary = __('Temporary');
const i18n_temporary_help = __('This groupchat will disappear once the last person leaves');
return html`
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
...@@ -84,4 +85,5 @@ export default (o) => html` ...@@ -84,4 +85,5 @@ export default (o) => html`
<div class="modal-footer">${modal_close_button}</div> <div class="modal-footer">${modal_close_button}</div>
</div> </div>
</div> </div>
`; `;
}
...@@ -5,14 +5,14 @@ import { until } from 'lit-html/directives/until.js'; ...@@ -5,14 +5,14 @@ import { until } from 'lit-html/directives/until.js';
import { converse } from "@converse/headless/converse-core"; import { converse } from "@converse/headless/converse-core";
const u = converse.env.utils; const u = converse.env.utils;
const i18n_hide_topic = __('Hide the groupchat topic');
const i18n_bookmarked = __('This groupchat is bookmarked');
const tpl_standalone_btns = (o) => o.standalone_btns.reverse().map(b => until(b, '')); const tpl_standalone_btns = (o) => o.standalone_btns.reverse().map(b => until(b, ''));
export default (o) => { export default (o) => {
const i18n_hide_topic = __('Hide the groupchat topic');
const i18n_bookmarked = __('This groupchat is bookmarked');
const subject = o.subject ? u.addHyperlinks(o.subject.text) : ''; const subject = o.subject ? u.addHyperlinks(o.subject.text) : '';
const show_subject = (subject && !o.subject_hidden); const show_subject = (subject && !o.subject_hidden);
return html` return html`
......
...@@ -4,10 +4,6 @@ import { html } from "lit-html"; ...@@ -4,10 +4,6 @@ import { html } from "lit-html";
const u = converse.env.utils; const u = converse.env.utils;
const i18n_search = __('Search');
const i18n_search_results = __('Search results');
const skintones = ['tone1', 'tone2', 'tone3', 'tone4', 'tone5'];
const emoji_category = (o) => { const emoji_category = (o) => {
return html` return html`
...@@ -37,14 +33,17 @@ const emoji_item = (o) => { ...@@ -37,14 +33,17 @@ const emoji_item = (o) => {
`; `;
} }
export const tpl_search_results = (o) => html` export const tpl_search_results = (o) => {
const i18n_search_results = __('Search results');
return html`
<span ?hidden=${!o.query} class="emoji-lists__container emojis-lists__container--search"> <span ?hidden=${!o.query} class="emoji-lists__container emojis-lists__container--search">
<a id="emoji-picker-search-results" class="emoji-category__heading">${i18n_search_results}</a> <a id="emoji-picker-search-results" class="emoji-category__heading">${i18n_search_results}</a>
<ul class="emoji-picker"> <ul class="emoji-picker">
${ o.search_results.map(emoji => emoji_item(Object.assign({emoji}, o))) } ${ o.search_results.map(emoji => emoji_item(Object.assign({emoji}, o))) }
</ul> </ul>
</span> </span>
`; `;
}
const emojis_for_category = (o) => { const emojis_for_category = (o) => {
return html` return html`
...@@ -72,6 +71,8 @@ const skintone_emoji = (o) => { ...@@ -72,6 +71,8 @@ const skintone_emoji = (o) => {
export const tpl_emoji_picker = (o) => { export const tpl_emoji_picker = (o) => {
const i18n_search = __('Search');
const skintones = ['tone1', 'tone2', 'tone3', 'tone4', 'tone5'];
return html` return html`
<div class="emoji-picker__header"> <div class="emoji-picker__header">
<input class="form-control emoji-search" name="emoji-search" placeholder="${i18n_search}" <input class="form-control emoji-search" name="emoji-search" placeholder="${i18n_search}"
......
...@@ -2,10 +2,10 @@ import { __ } from '@converse/headless/i18n'; ...@@ -2,10 +2,10 @@ import { __ } from '@converse/headless/i18n';
import { html } from "lit-html"; import { html } from "lit-html";
import { renderAvatar } from './../templates/directives/avatar'; import { renderAvatar } from './../templates/directives/avatar';
const i18n_uploading = __('Uploading file:')
export default (o) => {
export default (o) => html` const i18n_uploading = __('Uploading file:')
return html`
<div class="message chat-msg" data-isodate="${o.time}" data-msgid="${o.msgid}"> <div class="message chat-msg" data-isodate="${o.time}" data-msgid="${o.msgid}">
${ renderAvatar(this) } ${ renderAvatar(this) }
<div class="chat-msg__content"> <div class="chat-msg__content">
...@@ -13,4 +13,5 @@ export default (o) => html` ...@@ -13,4 +13,5 @@ export default (o) => html`
<progress value="${o.progress}"/> <progress value="${o.progress}"/>
</div> </div>
</div> </div>
`; `;
}
import { html } from "lit-html"; import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
const tpl_headline_box = (o) => html` const tpl_headline_box = (o) => html`
<div class="list-item controlbox-padded d-flex flex-row" <div class="list-item controlbox-padded d-flex flex-row"
......
import { html } from "lit-html"; import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
import tpl_headline_list from "templates/headline_list.js"; import tpl_headline_list from "templates/headline_list.js";
......
...@@ -3,14 +3,11 @@ import { __ } from '@converse/headless/i18n'; ...@@ -3,14 +3,11 @@ import { __ } from '@converse/headless/i18n';
import { modal_close_button, modal_header_close_button } from "./buttons" import { modal_close_button, modal_header_close_button } from "./buttons"
const i18n_image = __('Image: ');
export default (o) => html` export default (o) => html`
<div class="modal-dialog fit-content" role="document"> <div class="modal-dialog fit-content" role="document">
<div class="modal-content fit-content"> <div class="modal-content fit-content">
<div class="modal-header"> <div class="modal-header">
<h4 class="modal-title" id="message-versions-modal-label">${i18n_image}<a target="_blank" rel="noopener" href="${o.src}">${o.src}</a></h4> <h4 class="modal-title" id="message-versions-modal-label">${__('Image: ')}<a target="_blank" rel="noopener" href="${o.src}">${o.src}</a></h4>
${modal_header_close_button} ${modal_header_close_button}
</div> </div>
<div class="modal-body fit-content"> <div class="modal-body fit-content">
......
...@@ -4,13 +4,11 @@ import { repeat } from 'lit-html/directives/repeat.js'; ...@@ -4,13 +4,11 @@ import { repeat } from 'lit-html/directives/repeat.js';
import { modal_close_button, modal_header_close_button } from "./buttons" import { modal_close_button, modal_header_close_button } from "./buttons"
import spinner from "./spinner.js"; import spinner from "./spinner.js";
const i18n_info_title = __('Show more information on this groupchat');
const i18n_list_chatrooms = __('Query for Groupchats');
const i18n_open_title = __('Click to open this groupchat');
const i18n_query = __('Show groupchats');
const i18n_server_address = __('Server address');
const form = (o) => html` const form = (o) => {
const i18n_query = __('Show groupchats');
const i18n_server_address = __('Server address');
return html`
<form class="converse-form list-chatrooms" <form class="converse-form list-chatrooms"
@submit=${o.submitForm}> @submit=${o.submitForm}>
<div class="form-group"> <div class="form-group">
...@@ -25,10 +23,14 @@ const form = (o) => html` ...@@ -25,10 +23,14 @@ const form = (o) => html`
</div> </div>
<input type="submit" class="btn btn-primary" name="list" value="${i18n_query}"/> <input type="submit" class="btn btn-primary" name="list" value="${i18n_query}"/>
</form> </form>
`; `;
}
const tpl_item = (o, item) => html` const tpl_item = (o, item) => {
const i18n_info_title = __('Show more information on this groupchat');
const i18n_open_title = __('Click to open this groupchat');
return html`
<li class="room-item list-group-item"> <li class="room-item list-group-item">
<div class="available-chatroom d-flex flex-row"> <div class="available-chatroom d-flex flex-row">
<a class="open-room available-room w-100" <a class="open-room available-room w-100"
...@@ -44,10 +46,13 @@ const tpl_item = (o, item) => html` ...@@ -44,10 +46,13 @@ const tpl_item = (o, item) => html`
href="#"></a> href="#"></a>
</div> </div>
</li> </li>
`; `;
}
export default (o) => html` export default (o) => {
const i18n_list_chatrooms = __('Query for Groupchats');
return html`
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
...@@ -66,4 +71,5 @@ export default (o) => html` ...@@ -66,4 +71,5 @@ export default (o) => html`
<div class="modal-footer">${modal_close_button}</div> <div class="modal-footer">${modal_close_button}</div>
</div> </div>
</div> </div>
`; `;
}
...@@ -2,22 +2,15 @@ import { html } from "lit-html"; ...@@ -2,22 +2,15 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n'; import { __ } from '@converse/headless/i18n';
import tpl_spinner from './spinner.js'; import tpl_spinner from './spinner.js';
const i18n_anon_login = __('Click here to log in anonymously');
const i18n_disconnected = __('Disconnected'); const trust_checkbox = (o) => {
const i18n_login = __('Log in'); const i18n_hint_trusted = __(
const i18n_hint_no_account = __("Don't have a chat account?");
const i18n_password = __('Password');
const i18n_trusted = __('This is a trusted device');
const i18n_xmpp_address = __("XMPP Address");
const i18n_create_account = __("Create an account");
const i18n_hint_trusted = __(
'To improve performance, we cache your data in this browser. '+ 'To improve performance, we cache your data in this browser. '+
'Uncheck this box if this is a public computer or if you want your data to be deleted when you log out. '+ 'Uncheck this box if this is a public computer or if you want your data to be deleted when you log out. '+
'It\'s important that you explicitly log out, otherwise not all cached data might be deleted. '+ 'It\'s important that you explicitly log out, otherwise not all cached data might be deleted. '+
'Please note, when using an untrusted device, OMEMO encryption is NOT available.') 'Please note, when using an untrusted device, OMEMO encryption is NOT available.')
const i18n_trusted = __('This is a trusted device');
return html`
const trust_checkbox = (o) => html`
<div class="form-group form-check login-trusted"> <div class="form-group form-check login-trusted">
<input id="converse-login-trusted" type="checkbox" class="form-check-input" name="trusted" ?checked=${o._converse.config.get('trusted')}> <input id="converse-login-trusted" type="checkbox" class="form-check-input" name="trusted" ?checked=${o._converse.config.get('trusted')}>
<label for="converse-login-trusted" class="form-check-label login-trusted__desc">${i18n_trusted}</label> <label for="converse-login-trusted" class="form-check-label login-trusted__desc">${i18n_trusted}</label>
...@@ -25,21 +18,29 @@ const trust_checkbox = (o) => html` ...@@ -25,21 +18,29 @@ const trust_checkbox = (o) => html`
data-title="Trusted device?" data-title="Trusted device?"
data-content="${i18n_hint_trusted}"></i> data-content="${i18n_hint_trusted}"></i>
</div> </div>
`; `;
}
const password_input = () => html` const password_input = () => {
const i18n_password = __('Password');
return html`
<div class="form-group"> <div class="form-group">
<label for="converse-login-password">${i18n_password}</label> <label for="converse-login-password">${i18n_password}</label>
<input id="converse-login-password" class="form-control" required="required" type="password" name="password" placeholder="${i18n_password}"/> <input id="converse-login-password" class="form-control" required="required" type="password" name="password" placeholder="${i18n_password}"/>
</div> </div>
`; `;
}
const register_link = () => html` const register_link = () => {
const i18n_create_account = __("Create an account");
const i18n_hint_no_account = __("Don't have a chat account?");
return html`
<fieldset class="switch-form"> <fieldset class="switch-form">
<p>${i18n_hint_no_account}</p> <p>${i18n_hint_no_account}</p>
<p><a class="register-account toggle-register-login" href="#converse/register">${i18n_create_account}</a></p> <p><a class="register-account toggle-register-login" href="#converse/register">${i18n_create_account}</a></p>
</fieldset> </fieldset>
`; `;
}
const show_register_link = (o) => { const show_register_link = (o) => {
const _converse = o._converse; const _converse = o._converse;
...@@ -49,7 +50,10 @@ const show_register_link = (o) => { ...@@ -49,7 +50,10 @@ const show_register_link = (o) => {
} }
const auth_fields = (o) => html` const auth_fields = (o) => {
const i18n_login = __('Log in');
const i18n_xmpp_address = __("XMPP Address");
return html`
<div class="form-group"> <div class="form-group">
<label for="converse-login-jid">${i18n_xmpp_address}:</label> <label for="converse-login-jid">${i18n_xmpp_address}:</label>
<input id="converse-login-jid" class="form-control" required="required" type="text" name="jid" placeholder="${o.placeholder_username}"/> <input id="converse-login-jid" class="form-control" required="required" type="text" name="jid" placeholder="${o.placeholder_username}"/>
...@@ -60,14 +64,19 @@ const auth_fields = (o) => html` ...@@ -60,14 +64,19 @@ const auth_fields = (o) => html`
<input class="btn btn-primary" type="submit" value="${i18n_login}"/> <input class="btn btn-primary" type="submit" value="${i18n_login}"/>
</fieldset> </fieldset>
${ show_register_link(o) ? register_link(o) : '' } ${ show_register_link(o) ? register_link(o) : '' }
`; `;
}
const form_fields = (o) => html` const form_fields = (o) => {
const i18n_disconnected = __('Disconnected');
const i18n_anon_login = __('Click here to log in anonymously');
return html`
${ (o.authentication == o.LOGIN || o.authentication == o.EXTERNAL) ? auth_fields(o) : '' } ${ (o.authentication == o.LOGIN || o.authentication == o.EXTERNAL) ? auth_fields(o) : '' }
${ o.authentication == o.ANONYMOUS ? html`<input class="btn btn-primary login-anon" type="submit" value="${i18n_anon_login}">` : '' } ${ o.authentication == o.ANONYMOUS ? html`<input class="btn btn-primary login-anon" type="submit" value="${i18n_anon_login}">` : '' }
${ o.authentication == o.PREBIND ? html`<p>${i18n_disconnected}</p>` : '' } ${ o.authentication == o.PREBIND ? html`<p>${i18n_disconnected}</p>` : '' }
`; `;
}
export default (o) => html` export default (o) => html`
......
...@@ -4,14 +4,11 @@ import dayjs from 'dayjs'; ...@@ -4,14 +4,11 @@ import dayjs from 'dayjs';
import { modal_close_button, modal_header_close_button } from "./buttons" import { modal_close_button, modal_header_close_button } from "./buttons"
const i18n_message_versions = __('Message versions');
export default (o) => html` export default (o) => html`
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h4 class="modal-title" id="message-versions-modal-label">${i18n_message_versions}</h4> <h4 class="modal-title" id="message-versions-modal-label">${__('Message versions')}</h4>
${modal_header_close_button} ${modal_header_close_button}
</div> </div>
<div class="modal-body"> <div class="modal-body">
......
...@@ -4,32 +4,6 @@ import spinner from "./spinner.js"; ...@@ -4,32 +4,6 @@ import spinner from "./spinner.js";
import { modal_header_close_button } from "./buttons" import { modal_header_close_button } from "./buttons"
const i18n_affiliation = __('Affiliation');
const i18n_change_affiliation = __('Change affiliation');
const i18n_change_role = __('Change role');
const i18n_moderator_tools = __('Moderator Tools');
const i18n_new_affiliation = __('New affiliation');
const i18n_new_role = __('New Role');
const i18n_no_users_with_aff = __('No users with that affiliation found.')
const i18n_no_users_with_role = __('No users with that role found.');
const i18n_reason = __('Reason');
const i18n_filter = __('Type here to filter the search results');
const i18n_role = __('Role');
const i18n_show_users = __('Show users');
const i18n_helptext_role = __(
"Roles are assigned to users to grant or deny them certain abilities in a multi-user chat. "+
"They're assigned either explicitly or implicitly as part of an affiliation. "+
"A role that's not due to an affiliation, is only valid for the duration of the user's session."
);
const i18n_helptext_affiliation = __(
"An affiliation is a long-lived entitlement which typically implies a certain role and which "+
"grants privileges and responsibilities. For example admins and owners automatically have the "+
"moderator role."
);
function getRoleHelpText (role) { function getRoleHelpText (role) {
if (role === 'moderator') { if (role === 'moderator') {
return __("Moderators are privileged users who can change the roles of other users (except those with admin or owner affiliations."); return __("Moderators are privileged users who can change the roles of other users (except those with admin or owner affiliations.");
...@@ -65,7 +39,11 @@ const affiliation_option = (o) => html` ...@@ -65,7 +39,11 @@ const affiliation_option = (o) => html`
`; `;
const tpl_set_role_form = (o) => html` const tpl_set_role_form = (o) => {
const i18n_change_role = __('Change role');
const i18n_new_role = __('New Role');
const i18n_reason = __('Reason');
return html`
<form class="role-form hidden" @submit=${o.assignRole}> <form class="role-form hidden" @submit=${o.assignRole}>
<div class="form-group"> <div class="form-group">
<input type="hidden" name="jid" value="${o.item.jid}"/> <input type="hidden" name="jid" value="${o.item.jid}"/>
...@@ -87,7 +65,8 @@ const tpl_set_role_form = (o) => html` ...@@ -87,7 +65,8 @@ const tpl_set_role_form = (o) => html`
<input type="submit" class="btn btn-primary" value="${i18n_change_role}"/> <input type="submit" class="btn btn-primary" value="${i18n_change_role}"/>
</div> </div>
</form> </form>
`; `;
}
const role_list_item = (o) => html` const role_list_item = (o) => html`
...@@ -108,7 +87,11 @@ const role_list_item = (o) => html` ...@@ -108,7 +87,11 @@ const role_list_item = (o) => html`
`; `;
const tpl_set_affiliation_form = (o) => html` const tpl_set_affiliation_form = (o) => {
const i18n_change_affiliation = __('Change affiliation');
const i18n_new_affiliation = __('New affiliation');
const i18n_reason = __('Reason');
return html`
<form class="affiliation-form hidden" @submit=${o.assignAffiliation}> <form class="affiliation-form hidden" @submit=${o.assignAffiliation}>
<div class="form-group"> <div class="form-group">
<input type="hidden" name="jid" value="${o.item.jid}"/> <input type="hidden" name="jid" value="${o.item.jid}"/>
...@@ -130,7 +113,8 @@ const tpl_set_affiliation_form = (o) => html` ...@@ -130,7 +113,8 @@ const tpl_set_affiliation_form = (o) => html`
<input type="submit" class="btn btn-primary" name="change" value="${i18n_change_affiliation}"/> <input type="submit" class="btn btn-primary" name="change" value="${i18n_change_affiliation}"/>
</div> </div>
</form> </form>
`; `;
}
const affiliation_list_item = (o) => html` const affiliation_list_item = (o) => html`
...@@ -164,6 +148,23 @@ const tpl_navigation = (o) => html` ...@@ -164,6 +148,23 @@ const tpl_navigation = (o) => html`
export default (o) => { export default (o) => {
const i18n_affiliation = __('Affiliation');
const i18n_moderator_tools = __('Moderator Tools');
const i18n_no_users_with_aff = __('No users with that affiliation found.')
const i18n_no_users_with_role = __('No users with that role found.');
const i18n_filter = __('Type here to filter the search results');
const i18n_role = __('Role');
const i18n_show_users = __('Show users');
const i18n_helptext_role = __(
"Roles are assigned to users to grant or deny them certain abilities in a multi-user chat. "+
"They're assigned either explicitly or implicitly as part of an affiliation. "+
"A role that's not due to an affiliation, is only valid for the duration of the user's session."
);
const i18n_helptext_affiliation = __(
"An affiliation is a long-lived entitlement which typically implies a certain role and which "+
"grants privileges and responsibilities. For example admins and owners automatically have the "+
"moderator role."
);
const show_both_tabs = o.queryable_roles.length && o.queryable_affiliations.length; const show_both_tabs = o.queryable_roles.length && o.queryable_affiliations.length;
return html` return html`
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
......
import { html } from "lit-html"; import { html } from "lit-html";
import { __ } from '@converse/headless/i18n'; import { __ } from '@converse/headless/i18n';
const i18n_heading = __('Bookmark this groupchat');
const i18n_autojoin = __('Would you like this groupchat to be automatically joined upon startup?');
const i18n_cancel = __('Cancel');
const i18n_name = __('The name for this bookmark:');
const i18n_nick = __('What should your nickname for this groupchat be?');
const i18n_submit = __('Save');
export default (o) => {
export default (o) => html` const i18n_heading = __('Bookmark this groupchat');
const i18n_autojoin = __('Would you like this groupchat to be automatically joined upon startup?');
const i18n_cancel = __('Cancel');
const i18n_name = __('The name for this bookmark:');
const i18n_nick = __('What should your nickname for this groupchat be?');
const i18n_submit = __('Save');
return html`
<form class="converse-form chatroom-form" @submit=${o.onSubmit}> <form class="converse-form chatroom-form" @submit=${o.onSubmit}>
<legend>${i18n_heading}</legend> <legend>${i18n_heading}</legend>
<fieldset class="form-group"> <fieldset class="form-group">
...@@ -29,4 +29,5 @@ export default (o) => html` ...@@ -29,4 +29,5 @@ export default (o) => html`
<input class="btn btn-secondary button-cancel" type="button" value="${i18n_cancel}" @click=${o.onCancel}> <input class="btn btn-secondary button-cancel" type="button" value="${i18n_cancel}" @click=${o.onCancel}>
</fieldset> </fieldset>
</form> </form>
`; `;
}
...@@ -2,10 +2,10 @@ import { html } from "lit-html"; ...@@ -2,10 +2,10 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n'; import { __ } from '@converse/headless/i18n';
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js'; import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
const i18n_save = __('Save'); export default (o) => {
const i18n_cancel = __('Cancel'); const i18n_save = __('Save');
const i18n_cancel = __('Cancel');
export default (o) => html` return html`
<form class="converse-form chatroom-form" autocomplete="off" @submit=${o.submitConfigForm}> <form class="converse-form chatroom-form" autocomplete="off" @submit=${o.submitConfigForm}>
<fieldset class="form-group"> <fieldset class="form-group">
<legend>${o.title}</legend> <legend>${o.title}</legend>
...@@ -18,4 +18,5 @@ export default (o) => html` ...@@ -18,4 +18,5 @@ export default (o) => html`
<input type="button" class="btn btn-secondary button-cancel" value="${i18n_cancel}" @click=${o.closeConfigForm}> <input type="button" class="btn btn-secondary button-cancel" value="${i18n_cancel}" @click=${o.closeConfigForm}>
</fieldset> </fieldset>
</form> </form>
`; `;
}
...@@ -2,15 +2,15 @@ import { html } from "lit-html"; ...@@ -2,15 +2,15 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n'; import { __ } from '@converse/headless/i18n';
import { modal_header_close_button } from "./buttons" import { modal_header_close_button } from "./buttons"
const i18n_invite = __('Invite');
const i18n_invite_heading = __('Invite someone to this groupchat');
const i18n_jid_placeholder = __('user@example.org');
const i18n_error_message = __('Please enter a valid XMPP address');
const i18n_invite_label = __('XMPP Address');
const i18n_reason = __('Optional reason for the invitation');
export default (o) => {
export default (o) => html` const i18n_invite = __('Invite');
const i18n_invite_heading = __('Invite someone to this groupchat');
const i18n_jid_placeholder = __('user@example.org');
const i18n_error_message = __('Please enter a valid XMPP address');
const i18n_invite_label = __('XMPP Address');
const i18n_reason = __('Optional reason for the invitation');
return html`
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
...@@ -45,4 +45,5 @@ export default (o) => html` ...@@ -45,4 +45,5 @@ export default (o) => html`
</div> </div>
</div> </div>
</div> </div>
`; `;
}
import { html } from "lit-html"; import { html } from "lit-html";
import { __ } from '@converse/headless/i18n'; import { __ } from '@converse/headless/i18n';
const i18n_heading = __('This groupchat requires a password');
const i18n_password = __('Password: ');
const i18n_submit = __('Submit');
export default (o) => {
export default (o) => html` const i18n_heading = __('This groupchat requires a password');
const i18n_password = __('Password: ');
const i18n_submit = __('Submit');
return html`
<form class="converse-form chatroom-form converse-centered-form" @submit=${o.submitPassword}> <form class="converse-form chatroom-form converse-centered-form" @submit=${o.submitPassword}>
<fieldset class="form-group"> <fieldset class="form-group">
<label>${i18n_heading}</label> <label>${i18n_heading}</label>
...@@ -22,4 +22,5 @@ export default (o) => html` ...@@ -22,4 +22,5 @@ export default (o) => html`
<input class="btn btn-primary" type="submit" value="${i18n_submit}"/> <input class="btn btn-primary" type="submit" value="${i18n_submit}"/>
</fieldset> </fieldset>
</form> </form>
`; `;
}
...@@ -13,11 +13,11 @@ const PRETTY_CHAT_STATUS = { ...@@ -13,11 +13,11 @@ const PRETTY_CHAT_STATUS = {
'online': 'Online' 'online': 'Online'
}; };
const i18n_occupant_hint = (occupant) => __('Click to mention %1$s in your message.', occupant.get('nick'))
const i18n_participants = __('Participants');
export default (o) => {
export default (o) => html` const i18n_occupant_hint = (occupant) => __('Click to mention %1$s in your message.', occupant.get('nick'))
const i18n_participants = __('Participants');
return html`
<div class="occupants-header"> <div class="occupants-header">
<i class="hide-occupants fa fa-times"></i> <i class="hide-occupants fa fa-times"></i>
<div class="occupants-header--title"> <div class="occupants-header--title">
...@@ -36,4 +36,5 @@ export default (o) => html` ...@@ -36,4 +36,5 @@ export default (o) => html`
); );
}) } }) }
</ul> </ul>
`; `;
}
...@@ -2,16 +2,10 @@ import { html } from "lit-html"; ...@@ -2,16 +2,10 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n'; import { __ } from '@converse/headless/i18n';
const i18n_moderator_hint = __('This user is a moderator.');
const i18n_participant_hint = __('This user can send messages in this groupchat.');
const i18n_visitor_hint = __('This user can NOT send messages in this groupchat.')
const i18n_owner = __('Owner');
const i18n_admin = __('Admin');
const i18n_member = __('Member');
const i18n_moderator = __('Moderator');
const i18n_visitor = __('Visitor');
const occupant_title = (o) => { const occupant_title = (o) => {
const i18n_moderator_hint = __('This user is a moderator.');
const i18n_participant_hint = __('This user can send messages in this groupchat.');
const i18n_visitor_hint = __('This user can NOT send messages in this groupchat.')
if (o.role === "moderator") { if (o.role === "moderator") {
return `${o.jid} ${i18n_moderator_hint} ${o.hint_occupant}`; return `${o.jid} ${i18n_moderator_hint} ${o.hint_occupant}`;
} else if (o.role === "participant") { } else if (o.role === "participant") {
...@@ -24,7 +18,13 @@ const occupant_title = (o) => { ...@@ -24,7 +18,13 @@ const occupant_title = (o) => {
} }
export default (o) => html` export default (o) => {
const i18n_owner = __('Owner');
const i18n_admin = __('Admin');
const i18n_member = __('Member');
const i18n_moderator = __('Moderator');
const i18n_visitor = __('Visitor');
return html`
<li class="occupant" id="${o.id}" title="${occupant_title(o)}"> <li class="occupant" id="${o.id}" title="${occupant_title(o)}">
<div class="row no-gutters"> <div class="row no-gutters">
<div class="col-auto"> <div class="col-auto">
...@@ -42,4 +42,5 @@ export default (o) => html` ...@@ -42,4 +42,5 @@ export default (o) => html`
</div> </div>
</div> </div>
</li> </li>
`; `;
}
...@@ -2,12 +2,11 @@ import { __ } from '@converse/headless/i18n'; ...@@ -2,12 +2,11 @@ import { __ } from '@converse/headless/i18n';
import { api } from "@converse/headless/converse-core"; import { api } from "@converse/headless/converse-core";
import { html } from "lit-html"; import { html } from "lit-html";
const i18n_logout = __('Log out');
const i18n_change_status = __('Click to change your chat status');
const i18n_details = __('Show details about this chat client');
export default (o) => { export default (o) => {
const i18n_logout = __('Log out');
const i18n_change_status = __('Click to change your chat status');
const i18n_details = __('Show details about this chat client');
const show_settings_button = api.settings.get('show_client_info') || api.settings.get('allow_adhoc_commands'); const show_settings_button = api.settings.get('show_client_info') || api.settings.get('allow_adhoc_commands');
return html` return html`
<div class="userinfo controlbox-padded"> <div class="userinfo controlbox-padded">
......
...@@ -7,42 +7,13 @@ import { modal_header_close_button } from "./buttons"; ...@@ -7,42 +7,13 @@ import { modal_header_close_button } from "./buttons";
const u = converse.env.utils; const u = converse.env.utils;
const heading_profile = __('Your Profile');
const i18n_fingerprint_checkbox_label = __('Checkbox for selecting the following fingerprint');
const i18n_device_without_fingerprint = __('Device without a fingerprint');
const i18n_email = __('Email');
const i18n_fingerprint = __("This device's OMEMO fingerprint");
const i18n_fullname = __('Full Name');
const i18n_generate = __('Generate new keys and fingerprint');
const i18n_jid = __('XMPP Address (JID)');
const i18n_nickname = __('Nickname');
const i18n_other_devices = __('Other OMEMO-enabled devices');
const i18n_other_devices_label = __('Checkbox to select fingerprints of all other OMEMO devices');
const i18n_remove_devices = __('Remove checked devices and close');
const i18n_role = __('Role');
const i18n_save = __('Save and close');
const i18n_select_all = __('Select all');
const i18n_role_help = __('Use commas to separate multiple roles. Your roles are shown next to your name on your chat messages.');
const i18n_url = __('URL');
const i18n_omemo = __('OMEMO');
const i18n_profile = __('Profile');
const navigation = html`
<ul class="nav nav-pills justify-content-center">
<li role="presentation" class="nav-item">
<a class="nav-link active" id="profile-tab" href="#profile-tabpanel" aria-controls="profile-tabpanel" role="tab" data-toggle="tab">${i18n_profile}</a>
</li>
<li role="presentation" class="nav-item">
<a class="nav-link" id="omemo-tab" href="#omemo-tabpanel" aria-controls="omemo-tabpanel" role="tab" data-toggle="tab">${i18n_omemo}</a>
</li>
</ul>`;
const fingerprint = (o) => html` const fingerprint = (o) => html`
<span class="fingerprint">${u.formatFingerprint(o.view.current_device.get('bundle').fingerprint)}</span>`; <span class="fingerprint">${u.formatFingerprint(o.view.current_device.get('bundle').fingerprint)}</span>`;
const device_with_fingerprint = (o) => html` const device_with_fingerprint = (o) => {
const i18n_fingerprint_checkbox_label = __('Checkbox for selecting the following fingerprint');
return html`
<li class="fingerprint-removal-item list-group-item nopadding"> <li class="fingerprint-removal-item list-group-item nopadding">
<label> <label>
<input type="checkbox" value="${o.device.get('id')}" <input type="checkbox" value="${o.device.get('id')}"
...@@ -50,10 +21,14 @@ const device_with_fingerprint = (o) => html` ...@@ -50,10 +21,14 @@ const device_with_fingerprint = (o) => html`
<span class="fingerprint">${u.formatFingerprint(o.device.get('bundle').fingerprint)}</span> <span class="fingerprint">${u.formatFingerprint(o.device.get('bundle').fingerprint)}</span>
</label> </label>
</li> </li>
`; `;
}
const device_without_fingerprint = (o) => html` const device_without_fingerprint = (o) => {
const i18n_device_without_fingerprint = __('Device without a fingerprint');
const i18n_fingerprint_checkbox_label = __('Checkbox for selecting the following device');
return html`
<li class="fingerprint-removal-item list-group-item nopadding"> <li class="fingerprint-removal-item list-group-item nopadding">
<label> <label>
<input type="checkbox" value="${o.device.get('id')}" <input type="checkbox" value="${o.device.get('id')}"
...@@ -61,7 +36,8 @@ const device_without_fingerprint = (o) => html` ...@@ -61,7 +36,8 @@ const device_without_fingerprint = (o) => html`
<span>${i18n_device_without_fingerprint}</span> <span>${i18n_device_without_fingerprint}</span>
</label> </label>
</li> </li>
`; `;
}
const device_item = (o) => html` const device_item = (o) => html`
...@@ -69,7 +45,12 @@ const device_item = (o) => html` ...@@ -69,7 +45,12 @@ const device_item = (o) => html`
`; `;
const device_list = (o) => html` const device_list = (o) => {
const i18n_other_devices = __('Other OMEMO-enabled devices');
const i18n_other_devices_label = __('Checkbox to select fingerprints of all other OMEMO devices');
const i18n_remove_devices = __('Remove checked devices and close');
const i18n_select_all = __('Select all');
return html`
<ul class="list-group fingerprints"> <ul class="list-group fingerprints">
<li class="list-group-item nopadding active"> <li class="list-group-item nopadding active">
<label> <label>
...@@ -80,10 +61,14 @@ const device_list = (o) => html` ...@@ -80,10 +61,14 @@ const device_list = (o) => html`
${ o.view.other_devices.map(device => device_item(Object.assign({device}, o))) } ${ o.view.other_devices.map(device => device_item(Object.assign({device}, o))) }
</ul> </ul>
<div class="form-group"><button type="submit" class="save-form btn btn-primary">${i18n_remove_devices}</button></div> <div class="form-group"><button type="submit" class="save-form btn btn-primary">${i18n_remove_devices}</button></div>
`; `;
}
const omemo_page = (o) => html` const omemo_page = (o) => {
const i18n_fingerprint = __("This device's OMEMO fingerprint");
const i18n_generate = __('Generate new keys and fingerprint');
return html`
<div class="tab-pane" id="omemo-tabpanel" role="tabpanel" aria-labelledby="omemo-tab"> <div class="tab-pane" id="omemo-tabpanel" role="tabpanel" aria-labelledby="omemo-tab">
<form class="converse-form fingerprint-removal"> <form class="converse-form fingerprint-removal">
<ul class="list-group fingerprints"> <ul class="list-group fingerprints">
...@@ -98,9 +83,34 @@ const omemo_page = (o) => html` ...@@ -98,9 +83,34 @@ const omemo_page = (o) => html`
${ o.view.other_devices.length ? device_list(o) : '' } ${ o.view.other_devices.length ? device_list(o) : '' }
</form> </form>
</div>`; </div>`;
}
export default (o) => {
const heading_profile = __('Your Profile');
const i18n_email = __('Email');
const i18n_fullname = __('Full Name');
const i18n_jid = __('XMPP Address (JID)');
const i18n_nickname = __('Nickname');
const i18n_role = __('Role');
const i18n_save = __('Save and close');
const i18n_role_help = __('Use commas to separate multiple roles. Your roles are shown next to your name on your chat messages.');
const i18n_url = __('URL');
const i18n_omemo = __('OMEMO');
const i18n_profile = __('Profile');
const navigation = html`
<ul class="nav nav-pills justify-content-center">
<li role="presentation" class="nav-item">
<a class="nav-link active" id="profile-tab" href="#profile-tabpanel" aria-controls="profile-tabpanel" role="tab" data-toggle="tab">${i18n_profile}</a>
</li>
<li role="presentation" class="nav-item">
<a class="nav-link" id="omemo-tab" href="#omemo-tabpanel" aria-controls="omemo-tabpanel" role="tab" data-toggle="tab">${i18n_omemo}</a>
</li>
</ul>`;
export default (o) => html` return html`
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
...@@ -156,4 +166,5 @@ export default (o) => html` ...@@ -156,4 +166,5 @@ export default (o) => html`
</div> </div>
</div> </div>
</div> </div>
`; `;
}
...@@ -2,10 +2,6 @@ import { html } from "lit-html"; ...@@ -2,10 +2,6 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n'; import { __ } from '@converse/headless/i18n';
const i18n_cancel = __('Cancel');
const i18n_ok = __('OK');
const tpl_field = (f) => html` const tpl_field = (f) => html`
<div class="form-group"> <div class="form-group">
<label> <label>
...@@ -37,8 +33,8 @@ export default (o) => html` ...@@ -37,8 +33,8 @@ export default (o) => html`
</div> </div>
${ o.fields.map(f => tpl_field(f)) } ${ o.fields.map(f => tpl_field(f)) }
<div class="form-group"> <div class="form-group">
<button type="submit" class="btn btn-primary">${i18n_ok}</button> <button type="submit" class="btn btn-primary">${__('OK')}</button>
<input type="button" class="btn btn-secondary" data-dismiss="modal" value="${i18n_cancel}"/> <input type="button" class="btn btn-secondary" data-dismiss="modal" value="${__('Cancel')}"/>
</div> </div>
</form> </form>
</div> </div>
......
...@@ -2,20 +2,9 @@ import { html } from "lit-html"; ...@@ -2,20 +2,9 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n'; import { __ } from '@converse/headless/i18n';
const i18n_desc_rooms = __('Click to toggle the list of open groupchats');
const i18n_add_bookmark = __('Bookmark this groupchat');
const i18n_leave_room = __('Leave this groupchat');
const i18n_remove_bookmark = __('Unbookmark this groupchat');
const i18n_title = __('Show more information on this groupchat');
const i18n_open = __('Click to open this groupchat');
// Note to translators, "Open Groupchats" refers to groupchats that are open, NOT a command.
const i18n_rooms = __('Open Groupchats');
const unread_indicator = (o) => html`<span class="list-item-badge badge badge--muc msgs-indicator">${ o.room.get('num_unread') }</span>`;
const bookmark = (o) => { const bookmark = (o) => {
const i18n_add_bookmark = __('Bookmark this groupchat');
const i18n_remove_bookmark = __('Unbookmark this groupchat');
if (o.bookmarked) { if (o.bookmarked) {
return html` return html`
<a class="list-item-action fa fa-bookmark remove-bookmark button-on" <a class="list-item-action fa fa-bookmark remove-bookmark button-on"
...@@ -34,21 +23,24 @@ const bookmark = (o) => { ...@@ -34,21 +23,24 @@ const bookmark = (o) => {
} }
const room_item = (o) => html` const room_item = (o) => {
const i18n_leave_room = __('Leave this groupchat');
const unread_indicator = (o) => html`<span class="list-item-badge badge badge--muc msgs-indicator">${ o.room.get('num_unread') }</span>`;
return html`
<div class="list-item controlbox-padded available-chatroom d-flex flex-row ${ o.currently_open(o.room) ? 'open' : '' } ${ o.room.get('num_unread_general') ? 'unread-msgs' : '' }" <div class="list-item controlbox-padded available-chatroom d-flex flex-row ${ o.currently_open(o.room) ? 'open' : '' } ${ o.room.get('num_unread_general') ? 'unread-msgs' : '' }"
data-room-jid="${o.room.get('jid')}"> data-room-jid="${o.room.get('jid')}">
${ o.room.get('num_unread') ? unread_indicator(o) : '' } ${ o.room.get('num_unread') ? unread_indicator(o) : '' }
<a class="list-item-link open-room available-room w-100" <a class="list-item-link open-room available-room w-100"
data-room-jid="${o.room.get('jid')}" data-room-jid="${o.room.get('jid')}"
title="${i18n_open}" title="${__('Click to open this groupchat')}"
@click=${o.openRoom}>${o.room.getDisplayName()}</a> @click=${o.openRoom}>${o.room.getDisplayName()}</a>
${ o.allow_bookmarks ? bookmark(o) : '' } ${ o.allow_bookmarks ? bookmark(o) : '' }
<a class="list-item-action room-info fa fa-info-circle" <a class="list-item-action room-info fa fa-info-circle"
data-room-jid="${o.room.get('jid')}" data-room-jid="${o.room.get('jid')}"
title="${i18n_title}" title="${__('Show more information on this groupchat')}"
@click=${o.showRoomDetailsModal}></a> @click=${o.showRoomDetailsModal}></a>
<a class="list-item-action fa fa-sign-out-alt close-room" <a class="list-item-action fa fa-sign-out-alt close-room"
...@@ -56,15 +48,17 @@ const room_item = (o) => html` ...@@ -56,15 +48,17 @@ const room_item = (o) => html`
data-room-name="${o.room.getDisplayName()}" data-room-name="${o.room.getDisplayName()}"
title="${i18n_leave_room}" title="${i18n_leave_room}"
@click=${o.closeRoom}></a> @click=${o.closeRoom}></a>
</div> </div>`;
`; }
export default (o) => html` export default (o) => {
const i18n_desc_rooms = __('Click to toggle the list of open groupchats');
return html`
<div class="list-container list-container--openrooms ${ o.rooms.length ? '' : 'hidden' }"> <div class="list-container list-container--openrooms ${ o.rooms.length ? '' : 'hidden' }">
<a class="list-toggle open-rooms-toggle controlbox-padded" title="${i18n_desc_rooms}" @click=${o.toggleRoomsList}> <a class="list-toggle open-rooms-toggle controlbox-padded" title="${i18n_desc_rooms}" @click=${o.toggleRoomsList}>
<span class="fa ${ (o.toggle_state === o._converse.OPENED) ? 'fa-caret-down' : 'fa-caret-right' }"></span> ${i18n_rooms}</a> <span class="fa ${ (o.toggle_state === o._converse.OPENED) ? 'fa-caret-down' : 'fa-caret-right' }"></span> ${__('Open Groupchats')}</a>
<div class="items-list rooms-list open-rooms-list ${ o.collapsed && 'collapsed' }"> <div class="items-list rooms-list open-rooms-list ${ o.collapsed && 'collapsed' }">
${ o.rooms.map(room => room_item(Object.assign({room}, o))) } ${ o.rooms.map(room => room_item(Object.assign({room}, o))) }
</div> </div>
</div> </div>`;
`; }
...@@ -2,10 +2,7 @@ import { html } from "lit-html"; ...@@ -2,10 +2,7 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n'; import { __ } from '@converse/headless/i18n';
const i18n_minimized = __('Minimized')
export default (o) => html` export default (o) => html`
${o.num_minimized} ${i18n_minimized} ${o.num_minimized} ${__('Minimized')}
<span class="unread-message-count ${!o.num_unread ? 'unread-message-count-hidden' : ''}" href="#">${o.num_unread}</span> <span class="unread-message-count ${!o.num_unread ? 'unread-message-count-hidden' : ''}" href="#">${o.num_unread}</span>
`; `;
...@@ -2,10 +2,9 @@ import { html } from "lit-html"; ...@@ -2,10 +2,9 @@ import { html } from "lit-html";
import { __ } from '@converse/headless/i18n'; import { __ } from '@converse/headless/i18n';
const i18n_tooltip = __('Click to restore this chat'); export default (o) => {
const i18n_tooltip = __('Click to restore this chat');
return html`
export default (o) => html`
<div class="chat-head-${o.type} chat-head row no-gutters"> <div class="chat-head-${o.type} chat-head row no-gutters">
<a class="restore-chat w-100 align-self-center" title="${i18n_tooltip}"> <a class="restore-chat w-100 align-self-center" title="${i18n_tooltip}">
${o.num_unread ? html`<span class="message-count badge badge-light">${o.num_unread}</span>` : '' } ${o.num_unread ? html`<span class="message-count badge badge-light">${o.num_unread}</span>` : '' }
...@@ -13,3 +12,4 @@ export default (o) => html` ...@@ -13,3 +12,4 @@ export default (o) => html`
</a> </a>
<a class="chatbox-btn close-chatbox-button fa fa-times"></a> <a class="chatbox-btn close-chatbox-button fa fa-times"></a>
</div>`; </div>`;
}
...@@ -4,27 +4,9 @@ import avatar from "./avatar.js"; ...@@ -4,27 +4,9 @@ import avatar from "./avatar.js";
import { modal_close_button, modal_header_close_button } from "./buttons" import { modal_close_button, modal_header_close_button } from "./buttons"
const i18n_address = __('XMPP Address');
const i18n_email = __('Email');
const i18n_fingerprints = __('OMEMO Fingerprints');
const i18n_full_name = __('Full Name');
const i18n_nickname = __('Nickname');
const i18n_profile = __('The User\'s Profile Image');
const i18n_refresh = __('Refresh');
const i18n_role = __('Role');
const i18n_url = __('URL');
const i18n_remove_contact = __('Remove as contact');
const i18n_trusted = __('Trusted');
const i18n_untrusted = __('Untrusted');
const i18n_no_devices = __("No OMEMO-enabled devices found");
const avatar_data = {
'alt_text': i18n_profile,
'extra_classes': 'mb-3'
}
const device_fingerprint = (o) => { const device_fingerprint = (o) => {
const i18n_trusted = __('Trusted');
const i18n_untrusted = __('Untrusted');
if (o.device.get('bundle') && o.device.get('bundle').fingerprint) { if (o.device.get('bundle') && o.device.get('bundle').fingerprint) {
return html` return html`
<li class="list-group-item"> <li class="list-group-item">
...@@ -48,6 +30,8 @@ const device_fingerprint = (o) => { ...@@ -48,6 +30,8 @@ const device_fingerprint = (o) => {
const fingerprints = (o) => { const fingerprints = (o) => {
const i18n_fingerprints = __('OMEMO Fingerprints');
const i18n_no_devices = __("No OMEMO-enabled devices found");
const devices = o.view.devicelist.devices; const devices = o.view.devicelist.devices;
return html` return html`
<hr/> <hr/>
...@@ -61,6 +45,7 @@ const fingerprints = (o) => { ...@@ -61,6 +45,7 @@ const fingerprints = (o) => {
} }
const remove_button = (o) => { const remove_button = (o) => {
const i18n_remove_contact = __('Remove as contact');
return html` return html`
<button type="button" @click="${o.removeContact}" class="btn btn-danger remove-contact"> <button type="button" @click="${o.removeContact}" class="btn btn-danger remove-contact">
<i class="far fa-trash-alt"></i>${i18n_remove_contact} <i class="far fa-trash-alt"></i>${i18n_remove_contact}
...@@ -69,7 +54,21 @@ const remove_button = (o) => { ...@@ -69,7 +54,21 @@ const remove_button = (o) => {
} }
export default (o) => html` export default (o) => {
const i18n_address = __('XMPP Address');
const i18n_email = __('Email');
const i18n_full_name = __('Full Name');
const i18n_nickname = __('Nickname');
const i18n_profile = __('The User\'s Profile Image');
const i18n_refresh = __('Refresh');
const i18n_role = __('Role');
const i18n_url = __('URL');
const avatar_data = {
'alt_text': i18n_profile,
'extra_classes': 'mb-3'
}
return html`
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
...@@ -95,4 +94,5 @@ export default (o) => html` ...@@ -95,4 +94,5 @@ export default (o) => html`
</div> </div>
</div> </div>
</div> </div>
`; `;
}
...@@ -7,24 +7,10 @@ import { modal_header_close_button } from "./buttons" ...@@ -7,24 +7,10 @@ import { modal_header_close_button } from "./buttons"
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js'; import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
const i18n_modal_title = __('Settings'); const tpl_navigation = (o) => {
const i18n_about = __('About'); const i18n_about = __('About');
const i18n_commands = __('Commands'); const i18n_commands = __('Commands');
return html`
const first_subtitle = __(
'%1$s Open Source %2$s XMPP chat client brought to you by %3$s Opkode %2$s',
'<a target="_blank" rel="nofollow" href="https://conversejs.org">',
'</a>',
'<a target="_blank" rel="nofollow" href="https://opkode.com">'
);
const second_subtitle = __(
'%1$s Translate %2$s it into your own language',
'<a target="_blank" rel="nofollow" href="https://hosted.weblate.org/projects/conversejs/#languages">',
'</a>'
);
const tpl_navigation = (o) => html`
<ul class="nav nav-pills justify-content-center"> <ul class="nav nav-pills justify-content-center">
<li role="presentation" class="nav-item"> <li role="presentation" class="nav-item">
<a class="nav-link active" id="about-tab" href="#about-tabpanel" aria-controls="about-tabpanel" role="tab" data-toggle="tab" @click=${o.switchTab}>${i18n_about}</a> <a class="nav-link active" id="about-tab" href="#about-tabpanel" aria-controls="about-tabpanel" role="tab" data-toggle="tab" @click=${o.switchTab}>${i18n_about}</a>
...@@ -33,10 +19,24 @@ const tpl_navigation = (o) => html` ...@@ -33,10 +19,24 @@ const tpl_navigation = (o) => html`
<a class="nav-link" id="commands-tab" href="#commands-tabpanel" aria-controls="commands-tabpanel" role="tab" data-toggle="tab" @click=${o.switchTab}>${i18n_commands}</a> <a class="nav-link" id="commands-tab" href="#commands-tabpanel" aria-controls="commands-tabpanel" role="tab" data-toggle="tab" @click=${o.switchTab}>${i18n_commands}</a>
</li> </li>
</ul> </ul>
`; `;
}
export default (o) => { export default (o) => {
const i18n_modal_title = __('Settings');
const first_subtitle = __(
'%1$s Open Source %2$s XMPP chat client brought to you by %3$s Opkode %2$s',
'<a target="_blank" rel="nofollow" href="https://conversejs.org">',
'</a>',
'<a target="_blank" rel="nofollow" href="https://opkode.com">'
);
const second_subtitle = __(
'%1$s Translate %2$s it into your own language',
'<a target="_blank" rel="nofollow" href="https://hosted.weblate.org/projects/conversejs/#languages">',
'</a>'
);
const show_client_info = api.settings.get('show_client_info'); const show_client_info = api.settings.get('show_client_info');
const allow_adhoc_commands = api.settings.get('allow_adhoc_commands'); const allow_adhoc_commands = api.settings.get('allow_adhoc_commands');
const show_both_tabs = show_client_info && allow_adhoc_commands; const show_both_tabs = show_client_info && allow_adhoc_commands;
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
modtools_disable_assign: ['owner', 'moderator', 'participant', 'visitor'], modtools_disable_assign: ['owner', 'moderator', 'participant', 'visitor'],
modtools_disable_query: ['moderator', 'participant', 'visitor'], modtools_disable_query: ['moderator', 'participant', 'visitor'],
enable_smacks: true, enable_smacks: true,
i18n: 'en', i18n: 'af',
// connection_options: { 'worker': '/dist/shared-connection-worker.js' }, // connection_options: { 'worker': '/dist/shared-connection-worker.js' },
message_archiving: 'always', message_archiving: 'always',
muc_domain: 'conference.chat.example.org', muc_domain: 'conference.chat.example.org',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment