Merge pull request #1056 from jitsi/translations-update
Translations update
This commit is contained in:
commit
221f6d1d68
|
@ -195,11 +195,7 @@ function maybeRedirectToWelcomePage(showThankYou) {
|
||||||
|
|
||||||
if (showThankYou) {
|
if (showThankYou) {
|
||||||
APP.UI.messageHandler.openMessageDialog(
|
APP.UI.messageHandler.openMessageDialog(
|
||||||
null, null, null,
|
null, "dialog.thankYou", {appName:interfaceConfig.APP_NAME});
|
||||||
APP.translation.translateString(
|
|
||||||
"dialog.thankYou", {appName:interfaceConfig.APP_NAME}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.enableWelcomePage) {
|
if (!config.enableWelcomePage) {
|
||||||
|
@ -1045,21 +1041,20 @@ export default {
|
||||||
// TrackErrors.GENERAL
|
// TrackErrors.GENERAL
|
||||||
// and any other
|
// and any other
|
||||||
let dialogTxt;
|
let dialogTxt;
|
||||||
let dialogTitle;
|
let dialogTitleKey;
|
||||||
|
|
||||||
if (err.name === TrackErrors.PERMISSION_DENIED) {
|
if (err.name === TrackErrors.PERMISSION_DENIED) {
|
||||||
dialogTxt = APP.translation.generateTranslationHTML(
|
dialogTxt = APP.translation.generateTranslationHTML(
|
||||||
"dialog.screenSharingPermissionDeniedError");
|
"dialog.screenSharingPermissionDeniedError");
|
||||||
dialogTitle = APP.translation.generateTranslationHTML(
|
dialogTitleKey = "dialog.error";
|
||||||
"dialog.error");
|
|
||||||
} else {
|
} else {
|
||||||
dialogTxt = APP.translation.generateTranslationHTML(
|
dialogTxt = APP.translation.generateTranslationHTML(
|
||||||
"dialog.failtoinstall");
|
"dialog.failtoinstall");
|
||||||
dialogTitle = APP.translation.generateTranslationHTML(
|
dialogTitleKey = "dialog.permissionDenied";
|
||||||
"dialog.permissionDenied");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
APP.UI.messageHandler.openDialog(dialogTitle, dialogTxt, false);
|
APP.UI.messageHandler.openDialog(
|
||||||
|
dialogTitleKey, dialogTxt, false);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
createLocalTracks({ devices: ['video'] }).then(
|
createLocalTracks({ devices: ['video'] }).then(
|
||||||
|
|
|
@ -105,7 +105,7 @@
|
||||||
<div id="subject" class="hide"></div>
|
<div id="subject" class="hide"></div>
|
||||||
|
|
||||||
<div id="extendedToolbar" class="toolbar">
|
<div id="extendedToolbar" class="toolbar">
|
||||||
<a class="button" id="toolbar_button_profile" data-container="body" data-placement="right" data-i18n="[content]toolbar.profile" content="Edit your profile">
|
<a class="button" id="toolbar_button_profile" data-container="body" data-placement="right" data-i18n="[content]toolbar.profile">
|
||||||
<img id="avatar" src="images/avatar2.png"/>
|
<img id="avatar" src="images/avatar2.png"/>
|
||||||
</a>
|
</a>
|
||||||
<a class="button icon-contactList" id="toolbar_contact_list" shortcut="contactlistpopover">
|
<a class="button icon-contactList" id="toolbar_contact_list" shortcut="contactlistpopover">
|
||||||
|
@ -138,11 +138,11 @@
|
||||||
<div class="title" data-i18n="profile.title"></div>
|
<div class="title" data-i18n="profile.title"></div>
|
||||||
<div class="sideToolbarBlock first">
|
<div class="sideToolbarBlock first">
|
||||||
<label class="first" data-i18n="profile.setDisplayNameLabel"></label>
|
<label class="first" data-i18n="profile.setDisplayNameLabel"></label>
|
||||||
<input type="text" id="setDisplayName" data-i18n="[placeholder]settings.name" placeholder="Name">
|
<input type="text" id="setDisplayName" data-i18n="[placeholder]settings.name">
|
||||||
</div>
|
</div>
|
||||||
<div class="sideToolbarBlock">
|
<div class="sideToolbarBlock">
|
||||||
<label data-i18n="profile.setEmailLabel"></label>
|
<label data-i18n="profile.setEmailLabel"></label>
|
||||||
<input type="text" id="setEmail" placeholder="Enter e-mail">
|
<input data-i18n="[placeholder]profile.setEmailInput" type="text" id="setEmail">
|
||||||
</div>
|
</div>
|
||||||
<div class="sideToolbarBlock auth_container" id="authenticationContainer">
|
<div class="sideToolbarBlock auth_container" id="authenticationContainer">
|
||||||
<p data-i18n="toolbar.authenticate"></p>
|
<p data-i18n="toolbar.authenticate"></p>
|
||||||
|
@ -175,7 +175,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="contacts_container" class="sideToolbarContainer__inner">
|
<div id="contacts_container" class="sideToolbarContainer__inner">
|
||||||
<div class="title" data-i18n="contactlist"></div>
|
<div class="title" data-i18n="contactlist" data-i18n-options='{"pcount":"1"}'></div>
|
||||||
<ul id="contacts"></ul>
|
<ul id="contacts"></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="settings_container" class="sideToolbarContainer__inner">
|
<div id="settings_container" class="sideToolbarContainer__inner">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"contactlist": "Participants",
|
"contactlist": "Participants (__pcount__)",
|
||||||
"addParticipants": "Add Participants",
|
"addParticipants": "Add Participants",
|
||||||
"roomLocked": "Callers must enter a password",
|
"roomLocked": "Callers must enter a password",
|
||||||
"roomUnlocked": "Anyone with the link can join",
|
"roomUnlocked": "Anyone with the link can join",
|
||||||
|
@ -99,6 +99,7 @@
|
||||||
"cameraDisabled": "Camera is not available",
|
"cameraDisabled": "Camera is not available",
|
||||||
"micDisabled": "Microphone is not available",
|
"micDisabled": "Microphone is not available",
|
||||||
"filmstrip": "Show / hide videos",
|
"filmstrip": "Show / hide videos",
|
||||||
|
"profile": "Edit your profile",
|
||||||
"raiseHand": "Raise hand to speak"
|
"raiseHand": "Raise hand to speak"
|
||||||
},
|
},
|
||||||
"bottomtoolbar": {
|
"bottomtoolbar": {
|
||||||
|
@ -135,7 +136,8 @@
|
||||||
"profile": {
|
"profile": {
|
||||||
"title": "Profile",
|
"title": "Profile",
|
||||||
"setDisplayNameLabel": "Set your display name",
|
"setDisplayNameLabel": "Set your display name",
|
||||||
"setEmailLabel": "Set your gravatar email"
|
"setEmailLabel": "Set your gravatar email",
|
||||||
|
"setEmailInput": "Enter e-mail"
|
||||||
},
|
},
|
||||||
"videothumbnail":
|
"videothumbnail":
|
||||||
{
|
{
|
||||||
|
@ -342,7 +344,7 @@
|
||||||
"ATTACHED": "Attached",
|
"ATTACHED": "Attached",
|
||||||
"FETCH_SESSION_ID": "Obtaining session-id...",
|
"FETCH_SESSION_ID": "Obtaining session-id...",
|
||||||
"GOT_SESSION_ID": "Obtaining session-id... Done",
|
"GOT_SESSION_ID": "Obtaining session-id... Done",
|
||||||
"GET_SESSION_ID_ERROR": "Get session-id error: ",
|
"GET_SESSION_ID_ERROR": "Get session-id error: __code__",
|
||||||
"USER_CONNECTION_INTERRUPTED": "__displayName__ is having connectivity issues..."
|
"USER_CONNECTION_INTERRUPTED": "__displayName__ is having connectivity issues..."
|
||||||
},
|
},
|
||||||
"recording":
|
"recording":
|
||||||
|
|
|
@ -41,7 +41,6 @@ You can add translatable text in the HTML:
|
||||||
|
|
||||||
**Note:** If you dynamically add HTML elements don't forget to call APP.translation.translateElement(jquery_selector) to translate the text initially.
|
**Note:** If you dynamically add HTML elements don't forget to call APP.translation.translateElement(jquery_selector) to translate the text initially.
|
||||||
|
|
||||||
* **via Javascript string** - call APP.translation.translateString(key, options). You can use that method to get the translated string in Javascript and then attach it in the HTML.
|
|
||||||
|
|
||||||
```
|
```
|
||||||
APP.translation.translateString("dialog.OK") // returns the value for the key of the current language file. "OK" for example.
|
APP.translation.translateString("dialog.OK") // returns the value for the key of the current language file. "OK" for example.
|
||||||
|
@ -50,7 +49,6 @@ You can add translatable text in the HTML:
|
||||||
For the available values of ``options`` parameter for the above methods of translation module see [i18next documentation](http://i18next.com/pages/doc_features).
|
For the available values of ``options`` parameter for the above methods of translation module see [i18next documentation](http://i18next.com/pages/doc_features).
|
||||||
|
|
||||||
**Note:** It is useful to add attributes in the HTML for persistent HTML elements because when the language is changed the text will be automatically translated.
|
**Note:** It is useful to add attributes in the HTML for persistent HTML elements because when the language is changed the text will be automatically translated.
|
||||||
Otherwise you should call ``APP.translation.translateString`` and manually change the text every time the language is changed.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -75,17 +75,13 @@ JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP.microphone[TrackErrors.NO_DATA_FROM_SOURCE]
|
||||||
*/
|
*/
|
||||||
function promptDisplayName() {
|
function promptDisplayName() {
|
||||||
let labelKey = 'dialog.enterDisplayName';
|
let labelKey = 'dialog.enterDisplayName';
|
||||||
let labelStr = APP.translation.translateString(labelKey);
|
|
||||||
let titleStr
|
|
||||||
= APP.translation.translateString('dialog.displayNameRequired');
|
|
||||||
let defaultNickMsg = APP.translation.translateString("defaultNickname");
|
|
||||||
let message = (
|
let message = (
|
||||||
`<div class="input-control">
|
`<div class="input-control">
|
||||||
<label class="input-control__label">${labelStr}</label>
|
<label data-i18n="${labelKey}" class="input-control__label"></label>
|
||||||
<input name="displayName" type="text"
|
<input name="displayName" type="text"
|
||||||
data-i18n="[placeholder]defaultNickname"
|
data-i18n="[placeholder]defaultNickname"
|
||||||
class="input-control__input"
|
class="input-control__input"
|
||||||
placeholder="${defaultNickMsg}" autofocus>
|
autofocus>
|
||||||
</div>`
|
</div>`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -94,7 +90,7 @@ function promptDisplayName() {
|
||||||
let buttons = {Ok:true};
|
let buttons = {Ok:true};
|
||||||
|
|
||||||
let dialog = messageHandler.openDialog(
|
let dialog = messageHandler.openDialog(
|
||||||
titleStr,
|
'dialog.displayNameRequired',
|
||||||
message,
|
message,
|
||||||
true,
|
true,
|
||||||
buttons,
|
buttons,
|
||||||
|
@ -167,11 +163,10 @@ UI.notifyGracefulShutdown = function () {
|
||||||
* Notify user that reservation error happened.
|
* Notify user that reservation error happened.
|
||||||
*/
|
*/
|
||||||
UI.notifyReservationError = function (code, msg) {
|
UI.notifyReservationError = function (code, msg) {
|
||||||
var title = APP.translation.generateTranslationHTML(
|
|
||||||
"dialog.reservationError");
|
|
||||||
var message = APP.translation.generateTranslationHTML(
|
var message = APP.translation.generateTranslationHTML(
|
||||||
"dialog.reservationErrorMsg", {code: code, msg: msg});
|
"dialog.reservationErrorMsg", {code: code, msg: msg});
|
||||||
messageHandler.openDialog(title, message, true, {}, () => false);
|
messageHandler.openDialog(
|
||||||
|
"dialog.reservationError", message, true, {}, () => false);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -190,9 +185,8 @@ UI.notifyKicked = function () {
|
||||||
UI.notifyConferenceDestroyed = function (reason) {
|
UI.notifyConferenceDestroyed = function (reason) {
|
||||||
//FIXME: use Session Terminated from translation, but
|
//FIXME: use Session Terminated from translation, but
|
||||||
// 'reason' text comes from XMPP packet and is not translated
|
// 'reason' text comes from XMPP packet and is not translated
|
||||||
const title
|
messageHandler.openDialog(
|
||||||
= APP.translation.generateTranslationHTML("dialog.sessTerminated");
|
"dialog.sessTerminated", reason, true, {}, () => false);
|
||||||
messageHandler.openDialog(title, reason, true, {}, () => false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -750,8 +744,6 @@ UI.connectionIndicatorShowMore = function(id) {
|
||||||
// FIXME check if someone user this
|
// FIXME check if someone user this
|
||||||
UI.showLoginPopup = function(callback) {
|
UI.showLoginPopup = function(callback) {
|
||||||
console.log('password is required');
|
console.log('password is required');
|
||||||
let titleKey = "dialog.passwordRequired";
|
|
||||||
let titleString = APP.translation.translateString(titleKey);
|
|
||||||
|
|
||||||
let message = (
|
let message = (
|
||||||
`<input name="username" type="text"
|
`<input name="username" type="text"
|
||||||
|
@ -770,8 +762,7 @@ UI.showLoginPopup = function(callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
messageHandler.openTwoButtonDialog({
|
messageHandler.openTwoButtonDialog({
|
||||||
titleKey,
|
titleKey : "dialog.passwordRequired",
|
||||||
titleString,
|
|
||||||
msgString: message,
|
msgString: message,
|
||||||
leftButtonKey: 'dialog.Ok',
|
leftButtonKey: 'dialog.Ok',
|
||||||
submitFunction,
|
submitFunction,
|
||||||
|
@ -904,9 +895,6 @@ UI.setUserAvatarUrl = function (id, url) {
|
||||||
* @param {string} stropheErrorMsg raw Strophe error message
|
* @param {string} stropheErrorMsg raw Strophe error message
|
||||||
*/
|
*/
|
||||||
UI.notifyConnectionFailed = function (stropheErrorMsg) {
|
UI.notifyConnectionFailed = function (stropheErrorMsg) {
|
||||||
var title = APP.translation.generateTranslationHTML(
|
|
||||||
"dialog.error");
|
|
||||||
|
|
||||||
var message;
|
var message;
|
||||||
if (stropheErrorMsg) {
|
if (stropheErrorMsg) {
|
||||||
message = APP.translation.generateTranslationHTML(
|
message = APP.translation.generateTranslationHTML(
|
||||||
|
@ -916,7 +904,7 @@ UI.notifyConnectionFailed = function (stropheErrorMsg) {
|
||||||
"dialog.connectError");
|
"dialog.connectError");
|
||||||
}
|
}
|
||||||
|
|
||||||
messageHandler.openDialog(title, message, true, {}, () => false);
|
messageHandler.openDialog("dialog.error", message, true, {}, () => false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -924,13 +912,10 @@ UI.notifyConnectionFailed = function (stropheErrorMsg) {
|
||||||
* Notify user that maximum users limit has been reached.
|
* Notify user that maximum users limit has been reached.
|
||||||
*/
|
*/
|
||||||
UI.notifyMaxUsersLimitReached = function () {
|
UI.notifyMaxUsersLimitReached = function () {
|
||||||
var title = APP.translation.generateTranslationHTML(
|
|
||||||
"dialog.error");
|
|
||||||
|
|
||||||
var message = APP.translation.generateTranslationHTML(
|
var message = APP.translation.generateTranslationHTML(
|
||||||
"dialog.maxUsersLimitReached");
|
"dialog.maxUsersLimitReached");
|
||||||
|
|
||||||
messageHandler.openDialog(title, message, true, {}, () => false);
|
messageHandler.openDialog("dialog.error", message, true, {}, () => false);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1191,10 +1176,8 @@ UI.getLargeVideo = function () {
|
||||||
UI.showExtensionRequiredDialog = function (url) {
|
UI.showExtensionRequiredDialog = function (url) {
|
||||||
messageHandler.openMessageDialog(
|
messageHandler.openMessageDialog(
|
||||||
"dialog.extensionRequired",
|
"dialog.extensionRequired",
|
||||||
null,
|
"dialog.firefoxExtensionPrompt",
|
||||||
null,
|
{url: url});
|
||||||
APP.translation.generateTranslationHTML(
|
|
||||||
"dialog.firefoxExtensionPrompt", {url: url}));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1216,9 +1199,7 @@ UI.showExtensionExternalInstallationDialog = function (url) {
|
||||||
|
|
||||||
messageHandler.openTwoButtonDialog({
|
messageHandler.openTwoButtonDialog({
|
||||||
titleKey: 'dialog.externalInstallationTitle',
|
titleKey: 'dialog.externalInstallationTitle',
|
||||||
titleString: '',
|
|
||||||
msgKey: 'dialog.externalInstallationMsg',
|
msgKey: 'dialog.externalInstallationMsg',
|
||||||
msgString: '',
|
|
||||||
leftButtonKey: 'dialog.goToStore',
|
leftButtonKey: 'dialog.goToStore',
|
||||||
submitFunction,
|
submitFunction,
|
||||||
loadedFunction: $.noop,
|
loadedFunction: $.noop,
|
||||||
|
@ -1263,8 +1244,6 @@ UI.showDeviceErrorDialog = function (micError, cameraError) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let title = getTitleKey();
|
|
||||||
let titleMsg = `<span data-i18n="${title}"></span>`;
|
|
||||||
let cameraJitsiTrackErrorMsg = cameraError
|
let cameraJitsiTrackErrorMsg = cameraError
|
||||||
? JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP.camera[cameraError.name]
|
? JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP.camera[cameraError.name]
|
||||||
: undefined;
|
: undefined;
|
||||||
|
@ -1318,7 +1297,7 @@ UI.showDeviceErrorDialog = function (micError, cameraError) {
|
||||||
deviceErrorDialog && deviceErrorDialog.close();
|
deviceErrorDialog && deviceErrorDialog.close();
|
||||||
|
|
||||||
deviceErrorDialog = messageHandler.openDialog(
|
deviceErrorDialog = messageHandler.openDialog(
|
||||||
titleMsg,
|
getTitleKey(),
|
||||||
message,
|
message,
|
||||||
false,
|
false,
|
||||||
{Ok: true},
|
{Ok: true},
|
||||||
|
@ -1342,8 +1321,6 @@ UI.showDeviceErrorDialog = function (micError, cameraError) {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
APP.translation.translateElement($(".jqibox"));
|
|
||||||
|
|
||||||
function getTitleKey() {
|
function getTitleKey() {
|
||||||
let title = "dialog.error";
|
let title = "dialog.error";
|
||||||
|
|
||||||
|
@ -1369,9 +1346,7 @@ UI.showTrackNotWorkingDialog = function (stream) {
|
||||||
messageHandler.openMessageDialog(
|
messageHandler.openMessageDialog(
|
||||||
"dialog.error",
|
"dialog.error",
|
||||||
stream.isAudioTrack()? "dialog.micNotSendingData" :
|
stream.isAudioTrack()? "dialog.micNotSendingData" :
|
||||||
"dialog.cameraNotSendingData",
|
"dialog.cameraNotSendingData");
|
||||||
null,
|
|
||||||
null);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
UI.updateDevicesAvailability = function (id, devices) {
|
UI.updateDevicesAvailability = function (id, devices) {
|
||||||
|
@ -1483,12 +1458,11 @@ UI.hideUserMediaPermissionsGuidanceOverlay = function () {
|
||||||
*/
|
*/
|
||||||
UI.toggleKeyboardShortcutsPanel = function() {
|
UI.toggleKeyboardShortcutsPanel = function() {
|
||||||
if (!messageHandler.isDialogOpened()) {
|
if (!messageHandler.isDialogOpened()) {
|
||||||
let titleKey = 'keyboardShortcuts.keyboardShortcuts';
|
|
||||||
let title = APP.translation.translateString(titleKey);
|
|
||||||
let msg = $('#keyboard-shortcuts').html();
|
let msg = $('#keyboard-shortcuts').html();
|
||||||
let buttons = { Close: true };
|
let buttons = { Close: true };
|
||||||
|
|
||||||
messageHandler.openDialog(title, msg, true, buttons);
|
messageHandler.openDialog(
|
||||||
|
'keyboardShortcuts.keyboardShortcuts', msg, true, buttons);
|
||||||
} else {
|
} else {
|
||||||
messageHandler.closeDialog();
|
messageHandler.closeDialog();
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,16 +146,13 @@ function doXmppAuth (room, lockPassword) {
|
||||||
room.getName(), APP.conference._getConferenceOptions()
|
room.getName(), APP.conference._getConferenceOptions()
|
||||||
);
|
);
|
||||||
|
|
||||||
loginDialog.displayConnectionStatus(
|
loginDialog.displayConnectionStatus('connection.FETCH_SESSION_ID');
|
||||||
APP.translation.translateString('connection.FETCH_SESSION_ID')
|
|
||||||
);
|
|
||||||
|
|
||||||
newRoom.room.moderator.authenticate().then(function () {
|
newRoom.room.moderator.authenticate().then(function () {
|
||||||
connection.disconnect();
|
connection.disconnect();
|
||||||
|
|
||||||
loginDialog.displayConnectionStatus(
|
loginDialog.displayConnectionStatus(
|
||||||
APP.translation.translateString('connection.GOT_SESSION_ID')
|
'connection.GOT_SESSION_ID');
|
||||||
);
|
|
||||||
|
|
||||||
// authenticate conference on the fly
|
// authenticate conference on the fly
|
||||||
room.join(lockPassword);
|
room.join(lockPassword);
|
||||||
|
@ -166,11 +163,8 @@ function doXmppAuth (room, lockPassword) {
|
||||||
|
|
||||||
console.error('Auth on the fly failed', error);
|
console.error('Auth on the fly failed', error);
|
||||||
|
|
||||||
let errorMsg = APP.translation.translateString(
|
loginDialog.displayError(
|
||||||
'connection.GET_SESSION_ID_ERROR'
|
'connection.GET_SESSION_ID_ERROR', {code: code});
|
||||||
);
|
|
||||||
|
|
||||||
loginDialog.displayError(errorMsg + code);
|
|
||||||
});
|
});
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
loginDialog.displayError(err);
|
loginDialog.displayError(err);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global APP, config */
|
/* global $, APP, config */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build html for "password required" dialog.
|
* Build html for "password required" dialog.
|
||||||
|
@ -15,8 +15,7 @@ function getPasswordInputHtml() {
|
||||||
placeholder=${placeholder} autofocus>
|
placeholder=${placeholder} autofocus>
|
||||||
<input name="password" type="password"
|
<input name="password" type="password"
|
||||||
class="input-control__input"
|
class="input-control__input"
|
||||||
data-i18n="[placeholder]dialog.userPassword"
|
data-i18n="[placeholder]dialog.userPassword">`;
|
||||||
placeholder="user password">`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,7 +66,7 @@ function LoginDialog(successCallback, cancelCallback) {
|
||||||
value: true
|
value: true
|
||||||
}];
|
}];
|
||||||
let finishedButtons = [{
|
let finishedButtons = [{
|
||||||
title: APP.translation.translateString('dialog.retry'),
|
title: APP.translation.generateTranslationHTML('dialog.retry'),
|
||||||
value: 'retry'
|
value: 'retry'
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
@ -79,7 +78,7 @@ function LoginDialog(successCallback, cancelCallback) {
|
||||||
|
|
||||||
const states = {
|
const states = {
|
||||||
login: {
|
login: {
|
||||||
title: APP.translation.translateString('dialog.passwordRequired'),
|
titleKey: 'dialog.passwordRequired',
|
||||||
html: getPasswordInputHtml(),
|
html: getPasswordInputHtml(),
|
||||||
buttons: loginButtons,
|
buttons: loginButtons,
|
||||||
focus: ':input:first',
|
focus: ':input:first',
|
||||||
|
@ -99,13 +98,13 @@ function LoginDialog(successCallback, cancelCallback) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
connecting: {
|
connecting: {
|
||||||
title: APP.translation.translateString('dialog.connecting'),
|
titleKey: 'dialog.connecting',
|
||||||
html: '<div id="connectionStatus"></div>',
|
html: '<div id="connectionStatus"></div>',
|
||||||
buttons: [],
|
buttons: [],
|
||||||
defaultButton: 0
|
defaultButton: 0
|
||||||
},
|
},
|
||||||
finished: {
|
finished: {
|
||||||
title: APP.translation.translateString('dialog.error'),
|
titleKey: 'dialog.error',
|
||||||
html: '<div id="errorMessage"></div>',
|
html: '<div id="errorMessage"></div>',
|
||||||
buttons: finishedButtons,
|
buttons: finishedButtons,
|
||||||
defaultButton: 0,
|
defaultButton: 0,
|
||||||
|
@ -128,27 +127,31 @@ function LoginDialog(successCallback, cancelCallback) {
|
||||||
/**
|
/**
|
||||||
* Displays error message in 'finished' state which allows either to cancel
|
* Displays error message in 'finished' state which allows either to cancel
|
||||||
* or retry.
|
* or retry.
|
||||||
* @param message the final message to be displayed.
|
* @param messageKey the key to the message to be displayed.
|
||||||
|
* @param options the options to the error message (optional)
|
||||||
*/
|
*/
|
||||||
this.displayError = function (message) {
|
this.displayError = function (messageKey, options) {
|
||||||
|
|
||||||
let finishedState = connDialog.getState('finished');
|
let finishedState = connDialog.getState('finished');
|
||||||
|
|
||||||
let errorMessageElem = finishedState.find('#errorMessage');
|
let errorMessageElem = finishedState.find('#errorMessage');
|
||||||
errorMessageElem.text(message);
|
errorMessageElem.attr("data-i18n", messageKey);
|
||||||
|
|
||||||
|
APP.translation.translateElement($(errorMessageElem), options);
|
||||||
|
|
||||||
connDialog.goToState('finished');
|
connDialog.goToState('finished');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show message as connection status.
|
* Show message as connection status.
|
||||||
* @param {string} message
|
* @param {string} messageKey the key to the message
|
||||||
*/
|
*/
|
||||||
this.displayConnectionStatus = function (message) {
|
this.displayConnectionStatus = function (messageKey) {
|
||||||
let connectingState = connDialog.getState('connecting');
|
let connectingState = connDialog.getState('connecting');
|
||||||
|
|
||||||
let connectionStatus = connectingState.find('#connectionStatus');
|
let connectionStatus = connectingState.find('#connectionStatus');
|
||||||
connectionStatus.text(message);
|
connectionStatus.attr("data-i18n", messageKey);
|
||||||
|
APP.translation.translateElement($(connectionStatus));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -202,9 +205,6 @@ export default {
|
||||||
* @returns dialog
|
* @returns dialog
|
||||||
*/
|
*/
|
||||||
showAuthRequiredDialog: function (roomName, onAuthNow) {
|
showAuthRequiredDialog: function (roomName, onAuthNow) {
|
||||||
var title = APP.translation.generateTranslationHTML(
|
|
||||||
"dialog.WaitingForHost"
|
|
||||||
);
|
|
||||||
var msg = APP.translation.generateTranslationHTML(
|
var msg = APP.translation.generateTranslationHTML(
|
||||||
"dialog.WaitForHostMsg", {room: roomName}
|
"dialog.WaitForHostMsg", {room: roomName}
|
||||||
);
|
);
|
||||||
|
@ -215,7 +215,7 @@ export default {
|
||||||
var buttons = [{title: buttonTxt, value: "authNow"}];
|
var buttons = [{title: buttonTxt, value: "authNow"}];
|
||||||
|
|
||||||
return APP.UI.messageHandler.openDialog(
|
return APP.UI.messageHandler.openDialog(
|
||||||
title,
|
"dialog.WaitingForHost",
|
||||||
msg,
|
msg,
|
||||||
true,
|
true,
|
||||||
buttons,
|
buttons,
|
||||||
|
|
|
@ -35,7 +35,6 @@ function toggleStars(starCount) {
|
||||||
* @returns {string} the contructed html string
|
* @returns {string} the contructed html string
|
||||||
*/
|
*/
|
||||||
function createRateFeedbackHTML() {
|
function createRateFeedbackHTML() {
|
||||||
let feedbackHelp = APP.translation.translateString('dialog.feedbackHelp');
|
|
||||||
|
|
||||||
let starClassName = (interfaceConfig.ENABLE_FEEDBACK_ANIMATION)
|
let starClassName = (interfaceConfig.ENABLE_FEEDBACK_ANIMATION)
|
||||||
? "icon-star-full shake-rotate"
|
? "icon-star-full shake-rotate"
|
||||||
|
@ -68,7 +67,7 @@ function createRateFeedbackHTML() {
|
||||||
</div>
|
</div>
|
||||||
<div class="details">
|
<div class="details">
|
||||||
<textarea id="feedbackTextArea" class="input-control__input"
|
<textarea id="feedbackTextArea" class="input-control__input"
|
||||||
placeholder="${ feedbackHelp }"></textarea>
|
data-i18n="[placeholder]dialog.feedbackHelp"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</form>`;
|
</form>`;
|
||||||
}
|
}
|
||||||
|
@ -147,10 +146,10 @@ export default class Dialog {
|
||||||
this.submitted = false;
|
this.submitted = false;
|
||||||
this.onCloseCallback = function() {};
|
this.onCloseCallback = function() {};
|
||||||
|
|
||||||
this.setDefoulOptions();
|
this.setDefaultOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
setDefoulOptions() {
|
setDefaultOptions() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this.options = {
|
this.options = {
|
||||||
|
|
|
@ -8,12 +8,10 @@ import UIUtil from '../util/UIUtil';
|
||||||
*/
|
*/
|
||||||
export default function askForPassword () {
|
export default function askForPassword () {
|
||||||
let titleKey = "dialog.passwordRequired";
|
let titleKey = "dialog.passwordRequired";
|
||||||
let passMsg = APP.translation.translateString("dialog.password");
|
|
||||||
let msgString = `
|
let msgString = `
|
||||||
<input name="lockKey" type="text"
|
<input name="lockKey" type="text"
|
||||||
data-i18n="[placeholder]dialog.password"
|
data-i18n="[placeholder]dialog.password"
|
||||||
placeholder="${passMsg}" autofocus>
|
autofocus>`;
|
||||||
`;
|
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
APP.UI.messageHandler.openTwoButtonDialog({
|
APP.UI.messageHandler.openTwoButtonDialog({
|
||||||
titleKey,
|
titleKey,
|
||||||
|
|
|
@ -191,8 +191,10 @@ class Invite {
|
||||||
* @param isLocked
|
* @param isLocked
|
||||||
*/
|
*/
|
||||||
setLockedFromElsewhere(isLocked) {
|
setLockedFromElsewhere(isLocked) {
|
||||||
let oldLockState = this.roomLocker.lockedElsewhere;
|
// isLocked can be 1, true or false
|
||||||
if (oldLockState !== isLocked) {
|
let newLockState = (isLocked === 1) || isLocked;
|
||||||
|
let oldLockState = this.roomLocker.isLocked;
|
||||||
|
if (oldLockState !== newLockState) {
|
||||||
this.roomLocker.lockedElsewhere = isLocked;
|
this.roomLocker.lockedElsewhere = isLocked;
|
||||||
APP.UI.emitEvent(UIEvents.TOGGLE_ROOM_LOCK);
|
APP.UI.emitEvent(UIEvents.TOGGLE_ROOM_LOCK);
|
||||||
this.updateView();
|
this.updateView();
|
||||||
|
|
|
@ -15,20 +15,15 @@ const States = {
|
||||||
*/
|
*/
|
||||||
export default class InviteDialogView {
|
export default class InviteDialogView {
|
||||||
constructor(model) {
|
constructor(model) {
|
||||||
let InviteAttributesKey = 'inviteUrlDefaultMsg';
|
|
||||||
let title = APP.translation.translateString(InviteAttributesKey);
|
|
||||||
|
|
||||||
this.unlockHint = "unlockHint";
|
this.unlockHint = "unlockHint";
|
||||||
this.lockHint = "lockHint";
|
this.lockHint = "lockHint";
|
||||||
this.model = model;
|
this.model = model;
|
||||||
|
|
||||||
if (this.model.inviteUrl === null) {
|
if (this.model.inviteUrl === null) {
|
||||||
this.inviteAttributes = (
|
this.inviteAttributes = `data-i18n="[value]inviteUrlDefaultMsg"`;
|
||||||
`data-i18n="[value]inviteUrlDefaultMsg" value="${title}"`
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
let encodedInviteUrl = this.model.getEncodedInviteUrl();
|
this.inviteAttributes
|
||||||
this.inviteAttributes = `value="${encodedInviteUrl}"`;
|
= `value="${this.model.getEncodedInviteUrl()}"`;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initDialog();
|
this.initDialog();
|
||||||
|
@ -43,11 +38,7 @@ export default class InviteDialogView {
|
||||||
dialog.submitFunction = this.submitFunction.bind(this);
|
dialog.submitFunction = this.submitFunction.bind(this);
|
||||||
dialog.loadedFunction = this.loadedFunction.bind(this);
|
dialog.loadedFunction = this.loadedFunction.bind(this);
|
||||||
|
|
||||||
let titleKey = "dialog.shareLink";
|
dialog.titleKey = "dialog.shareLink";
|
||||||
let titleString = APP.translation.generateTranslationHTML(titleKey);
|
|
||||||
|
|
||||||
dialog.titleKey = titleKey;
|
|
||||||
dialog.titleString = titleString;
|
|
||||||
this.dialog = dialog;
|
this.dialog = dialog;
|
||||||
|
|
||||||
this.dialog.states = this.getStates();
|
this.dialog.states = this.getStates();
|
||||||
|
@ -101,21 +92,20 @@ export default class InviteDialogView {
|
||||||
*/
|
*/
|
||||||
getStates() {
|
getStates() {
|
||||||
let {
|
let {
|
||||||
titleString
|
titleKey
|
||||||
} = this.dialog;
|
} = this.dialog;
|
||||||
let doneKey = 'dialog.done';
|
let doneMsg = APP.translation.generateTranslationHTML('dialog.done');
|
||||||
let doneMsg = APP.translation.translateString(doneKey);
|
|
||||||
let states = {};
|
let states = {};
|
||||||
let buttons = {};
|
let buttons = {};
|
||||||
buttons[`${doneMsg}`] = true;
|
buttons[`${doneMsg}`] = true;
|
||||||
|
|
||||||
states[States.UNLOCKED] = {
|
states[States.UNLOCKED] = {
|
||||||
title: titleString,
|
titleKey,
|
||||||
html: this.getShareLinkBlock() + this.getAddPasswordBlock(),
|
html: this.getShareLinkBlock() + this.getAddPasswordBlock(),
|
||||||
buttons
|
buttons
|
||||||
};
|
};
|
||||||
states[States.LOCKED] = {
|
states[States.LOCKED] = {
|
||||||
title: titleString,
|
titleKey,
|
||||||
html: this.getShareLinkBlock() + this.getPasswordBlock(),
|
html: this.getShareLinkBlock() + this.getPasswordBlock(),
|
||||||
buttons
|
buttons
|
||||||
};
|
};
|
||||||
|
@ -128,34 +118,24 @@ export default class InviteDialogView {
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
getShareLinkBlock() {
|
getShareLinkBlock() {
|
||||||
let copyKey = 'dialog.copy';
|
|
||||||
let copyText = APP.translation.translateString(copyKey);
|
|
||||||
let roomLockDescKey = 'dialog.roomLocked';
|
|
||||||
let roomLockDesc = APP.translation.translateString(roomLockDescKey);
|
|
||||||
let roomUnlockKey = 'roomUnlocked';
|
|
||||||
let roomUnlock = APP.translation.translateString(roomUnlockKey);
|
|
||||||
let classes = 'button-control button-control_light copyInviteLink';
|
let classes = 'button-control button-control_light copyInviteLink';
|
||||||
return (
|
return (
|
||||||
`<div class="input-control">
|
`<div class="input-control">
|
||||||
<label class="input-control__label" for="inviteLinkRef">
|
<label class="input-control__label" for="inviteLinkRef"
|
||||||
${this.dialog.titleString}
|
data-i18n="${this.dialog.titleKey}"></label>
|
||||||
</label>
|
|
||||||
<div class="input-control__container">
|
<div class="input-control__container">
|
||||||
<input class="input-control__input inviteLink"
|
<input class="input-control__input inviteLink"
|
||||||
id="inviteLinkRef" type="text"
|
id="inviteLinkRef" type="text"
|
||||||
${this.inviteAttributes} readonly>
|
${this.inviteAttributes} readonly>
|
||||||
<button data-i18n="${copyKey}"
|
<button data-i18n="dialog.copy" class="${classes}"></button>
|
||||||
class="${classes}">
|
|
||||||
${copyText}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<p class="input-control__hint ${this.lockHint}">
|
<p class="input-control__hint ${this.lockHint}">
|
||||||
<span class="icon-security-locked"></span>
|
<span class="icon-security-locked"></span>
|
||||||
<span data-i18n="${roomLockDescKey}">${roomLockDesc}</span>
|
<span data-i18n="dialog.roomLocked"></span>
|
||||||
</p>
|
</p>
|
||||||
<p class="input-control__hint ${this.unlockHint}">
|
<p class="input-control__hint ${this.unlockHint}">
|
||||||
<span class="icon-security"></span>
|
<span class="icon-security"></span>
|
||||||
<span data-i18n="${roomUnlockKey}">${roomUnlock}</span>
|
<span data-i18n="roomUnlocked"></span>
|
||||||
</p>
|
</p>
|
||||||
</div>`
|
</div>`
|
||||||
);
|
);
|
||||||
|
@ -166,27 +146,21 @@ export default class InviteDialogView {
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
getAddPasswordBlock() {
|
getAddPasswordBlock() {
|
||||||
let addPassKey = 'dialog.addPassword';
|
|
||||||
let addPassText = APP.translation.translateString(addPassKey);
|
|
||||||
let addKey = 'dialog.add';
|
|
||||||
let addText = APP.translation.translateString(addKey);
|
|
||||||
let hintKey = 'dialog.createPassword';
|
|
||||||
let hintMsg = APP.translation.translateString(hintKey);
|
|
||||||
let html;
|
let html;
|
||||||
|
|
||||||
if (this.model.isModerator) {
|
if (this.model.isModerator) {
|
||||||
html = (`
|
html = (`
|
||||||
<div class="input-control">
|
<div class="input-control">
|
||||||
<label class="input-control__label
|
<label class="input-control__label"
|
||||||
for="newPasswordInput"
|
for="newPasswordInput" data-i18n="dialog.addPassword">
|
||||||
data-i18n="${addPassKey}">${addPassText}</label>
|
</label>
|
||||||
<div class="input-control__container">
|
<div class="input-control__container">
|
||||||
<input class="input-control__input" id="newPasswordInput"
|
<input class="input-control__input" id="newPasswordInput"
|
||||||
type="text" placeholder="${hintMsg}">
|
type="text"
|
||||||
|
data-i18n="[placeholder]dialog.createPassword">
|
||||||
<button id="addPasswordBtn" id="inviteDialogAddPassword"
|
<button id="addPasswordBtn" id="inviteDialogAddPassword"
|
||||||
disabled data-i18n="${addKey}"
|
disabled data-i18n="dialog.add"
|
||||||
class="button-control button-control_light">
|
class="button-control button-control_light">
|
||||||
${addText}
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -204,22 +178,16 @@ export default class InviteDialogView {
|
||||||
*/
|
*/
|
||||||
getPasswordBlock() {
|
getPasswordBlock() {
|
||||||
let { password, isModerator } = this.model;
|
let { password, isModerator } = this.model;
|
||||||
let removePassKey = 'dialog.removePassword';
|
|
||||||
let removePassText = APP.translation.translateString(removePassKey);
|
|
||||||
let currentPassKey = 'dialog.currentPassword';
|
|
||||||
let currentPassText = APP.translation.translateString(currentPassKey);
|
|
||||||
let passwordKey = "dialog.passwordLabel";
|
|
||||||
let passwordText = APP.translation.translateString(passwordKey);
|
|
||||||
|
|
||||||
if (isModerator) {
|
if (isModerator) {
|
||||||
return (`
|
return (`
|
||||||
<div class="input-control">
|
<div class="input-control">
|
||||||
<label class="input-control__label"
|
<label class="input-control__label"
|
||||||
data-i18n="${passwordKey}">${passwordText}</label>
|
data-i18n="dialog.passwordLabel"></label>
|
||||||
<div class="input-control__container">
|
<div class="input-control__container">
|
||||||
<p class="input-control__text"
|
<p>
|
||||||
data-i18n="${currentPassKey}">
|
<span class="input-control__text"
|
||||||
${currentPassText}
|
data-i18n="dialog.currentPassword"></span>
|
||||||
<span id="inviteDialogPassword"
|
<span id="inviteDialogPassword"
|
||||||
class="input-control__em">
|
class="input-control__em">
|
||||||
${password}
|
${password}
|
||||||
|
@ -227,9 +195,7 @@ export default class InviteDialogView {
|
||||||
</p>
|
</p>
|
||||||
<a class="link input-control__right"
|
<a class="link input-control__right"
|
||||||
id="inviteDialogRemovePassword"
|
id="inviteDialogRemovePassword"
|
||||||
data-i18n="${removePassKey}">
|
data-i18n="dialog.removePassword"></a>
|
||||||
${removePassText}
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`);
|
`);
|
||||||
|
@ -355,10 +321,17 @@ export default class InviteDialogView {
|
||||||
*/
|
*/
|
||||||
updateView() {
|
updateView() {
|
||||||
let pass = this.model.getPassword();
|
let pass = this.model.getPassword();
|
||||||
if (!pass)
|
if (this.model.getRoomLocker().lockedElsewhere || !pass)
|
||||||
pass = APP.translation.translateString("passwordSetRemotely");
|
$('#inviteDialogPassword').attr("data-i18n", "passwordSetRemotely");
|
||||||
|
else
|
||||||
$('#inviteDialogPassword').text(pass);
|
$('#inviteDialogPassword').text(pass);
|
||||||
|
|
||||||
|
// if we are not moderator we cannot remove password
|
||||||
|
if (APP.conference.isModerator)
|
||||||
|
$('#inviteDialogRemovePassword').show();
|
||||||
|
else
|
||||||
|
$('#inviteDialogRemovePassword').hide();
|
||||||
|
|
||||||
$('#newPasswordInput').val('');
|
$('#newPasswordInput').val('');
|
||||||
this.disableAddPassIfInputEmpty();
|
this.disableAddPassIfInputEmpty();
|
||||||
|
|
||||||
|
|
|
@ -41,8 +41,6 @@ function _isRecordingButtonEnabled() {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
function _requestLiveStreamId() {
|
function _requestLiveStreamId() {
|
||||||
const msg = APP.translation.generateTranslationHTML("dialog.liveStreaming");
|
|
||||||
const token = APP.translation.translateString("dialog.streamKey");
|
|
||||||
const cancelButton
|
const cancelButton
|
||||||
= APP.translation.generateTranslationHTML("dialog.Cancel");
|
= APP.translation.generateTranslationHTML("dialog.Cancel");
|
||||||
const backButton = APP.translation.generateTranslationHTML("dialog.Back");
|
const backButton = APP.translation.generateTranslationHTML("dialog.Back");
|
||||||
|
@ -55,11 +53,11 @@ function _requestLiveStreamId() {
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
dialog = APP.UI.messageHandler.openDialogWithStates({
|
dialog = APP.UI.messageHandler.openDialogWithStates({
|
||||||
state0: {
|
state0: {
|
||||||
title: msg,
|
titleKey: "dialog.liveStreaming",
|
||||||
html:
|
html:
|
||||||
`<input name="streamId" type="text"
|
`<input name="streamId" type="text"
|
||||||
data-i18n="[placeholder]dialog.streamKey"
|
data-i18n="[placeholder]dialog.streamKey"
|
||||||
placeholder="${token}" autofocus>`,
|
autofocus>`,
|
||||||
persistent: false,
|
persistent: false,
|
||||||
buttons: [
|
buttons: [
|
||||||
{title: cancelButton, value: false},
|
{title: cancelButton, value: false},
|
||||||
|
@ -89,7 +87,7 @@ function _requestLiveStreamId() {
|
||||||
},
|
},
|
||||||
|
|
||||||
state1: {
|
state1: {
|
||||||
title: msg,
|
titleKey: "dialog.liveStreaming",
|
||||||
html: streamIdRequired,
|
html: streamIdRequired,
|
||||||
persistent: false,
|
persistent: false,
|
||||||
buttons: [
|
buttons: [
|
||||||
|
@ -122,11 +120,10 @@ function _requestLiveStreamId() {
|
||||||
*/
|
*/
|
||||||
function _requestRecordingToken () {
|
function _requestRecordingToken () {
|
||||||
let titleKey = "dialog.recordingToken";
|
let titleKey = "dialog.recordingToken";
|
||||||
let token = APP.translation.translateString("dialog.token");
|
|
||||||
let messageString = (
|
let messageString = (
|
||||||
`<input name="recordingToken" type="text"
|
`<input name="recordingToken" type="text"
|
||||||
data-i18n="[placeholder]dialog.token"
|
data-i18n="[placeholder]dialog.token"
|
||||||
placeholder="${token}" autofocus>`
|
autofocus>`
|
||||||
);
|
);
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
dialog = APP.UI.messageHandler.openTwoButtonDialog({
|
dialog = APP.UI.messageHandler.openTwoButtonDialog({
|
||||||
|
@ -297,8 +294,7 @@ var Recording = {
|
||||||
|
|
||||||
selector.addClass(this.baseClass);
|
selector.addClass(this.baseClass);
|
||||||
selector.attr("data-i18n", "[content]" + this.recordingButtonTooltip);
|
selector.attr("data-i18n", "[content]" + this.recordingButtonTooltip);
|
||||||
selector.attr("content",
|
APP.translation.translateElement(selector);
|
||||||
APP.translation.translateString(this.recordingButtonTooltip));
|
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
selector.click(function () {
|
selector.click(function () {
|
||||||
|
@ -365,7 +361,7 @@ var Recording = {
|
||||||
dialog = APP.UI.messageHandler.openMessageDialog(
|
dialog = APP.UI.messageHandler.openMessageDialog(
|
||||||
self.recordingTitle,
|
self.recordingTitle,
|
||||||
self.recordingBusy,
|
self.recordingBusy,
|
||||||
null, null,
|
null,
|
||||||
function () {
|
function () {
|
||||||
dialog = null;
|
dialog = null;
|
||||||
}
|
}
|
||||||
|
@ -376,7 +372,7 @@ var Recording = {
|
||||||
dialog = APP.UI.messageHandler.openMessageDialog(
|
dialog = APP.UI.messageHandler.openMessageDialog(
|
||||||
self.recordingTitle,
|
self.recordingTitle,
|
||||||
self.recordingUnavailable,
|
self.recordingUnavailable,
|
||||||
null, null,
|
null,
|
||||||
function () {
|
function () {
|
||||||
dialog = null;
|
dialog = null;
|
||||||
}
|
}
|
||||||
|
@ -505,7 +501,7 @@ var Recording = {
|
||||||
moveToCorner(labelSelector, !isCentered);
|
moveToCorner(labelSelector, !isCentered);
|
||||||
|
|
||||||
labelTextSelector.attr("data-i18n", textKey);
|
labelTextSelector.attr("data-i18n", textKey);
|
||||||
labelTextSelector.text(APP.translation.translateString(textKey));
|
APP.translation.translateElement(labelSelector);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -40,7 +40,9 @@ class PageReloadOverlayImpl extends Overlay{
|
||||||
<div id='reloadProgressBar' class="aui-progress-indicator">
|
<div id='reloadProgressBar' class="aui-progress-indicator">
|
||||||
<span class="aui-progress-indicator-value"></span>
|
<span class="aui-progress-indicator-value"></span>
|
||||||
</div>
|
</div>
|
||||||
<span id='reloadSecRemaining' class='reload_overlay_msg'>
|
<span id='reloadSecRemaining'
|
||||||
|
data-i18n="dialog.conferenceReloadTimeLeft"
|
||||||
|
class='reload_overlay_msg'>
|
||||||
</span>
|
</span>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
@ -50,11 +52,8 @@ class PageReloadOverlayImpl extends Overlay{
|
||||||
*/
|
*/
|
||||||
updateDisplay() {
|
updateDisplay() {
|
||||||
|
|
||||||
const timeLeftTxt
|
APP.translation.translateElement(
|
||||||
= APP.translation.translateString(
|
$("#reloadSecRemaining"), { seconds: this.timeLeft });
|
||||||
"dialog.conferenceReloadTimeLeft",
|
|
||||||
{ seconds: this.timeLeft });
|
|
||||||
$("#reloadSecRemaining").text(timeLeftTxt);
|
|
||||||
|
|
||||||
const ratio = (this.timeout - this.timeLeft) / this.timeout;
|
const ratio = (this.timeout - this.timeLeft) / this.timeout;
|
||||||
AJS.progressBars.update("#reloadProgressBar", ratio);
|
AJS.progressBars.update("#reloadProgressBar", ratio);
|
||||||
|
|
|
@ -93,7 +93,7 @@ export default class SharedVideoManager {
|
||||||
dialog = APP.UI.messageHandler.openMessageDialog(
|
dialog = APP.UI.messageHandler.openMessageDialog(
|
||||||
"dialog.shareVideoTitle",
|
"dialog.shareVideoTitle",
|
||||||
"dialog.alreadySharedVideoMsg",
|
"dialog.alreadySharedVideoMsg",
|
||||||
null, null,
|
null,
|
||||||
function () {
|
function () {
|
||||||
dialog = null;
|
dialog = null;
|
||||||
}
|
}
|
||||||
|
@ -750,24 +750,19 @@ function showStopVideoPropmpt() {
|
||||||
*/
|
*/
|
||||||
function requestVideoLink() {
|
function requestVideoLink() {
|
||||||
let i18n = APP.translation;
|
let i18n = APP.translation;
|
||||||
const title = i18n.generateTranslationHTML("dialog.shareVideoTitle");
|
|
||||||
const cancelButton = i18n.generateTranslationHTML("dialog.Cancel");
|
const cancelButton = i18n.generateTranslationHTML("dialog.Cancel");
|
||||||
const shareButton = i18n.generateTranslationHTML("dialog.Share");
|
const shareButton = i18n.generateTranslationHTML("dialog.Share");
|
||||||
const backButton = i18n.generateTranslationHTML("dialog.Back");
|
const backButton = i18n.generateTranslationHTML("dialog.Back");
|
||||||
const linkError
|
const linkError
|
||||||
= i18n.generateTranslationHTML("dialog.shareVideoLinkError");
|
= i18n.generateTranslationHTML("dialog.shareVideoLinkError");
|
||||||
const i18nOptions = {url: defaultSharedVideoLink};
|
|
||||||
const defaultUrl = i18n.translateString("defaultLink", i18nOptions);
|
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
dialog = APP.UI.messageHandler.openDialogWithStates({
|
dialog = APP.UI.messageHandler.openDialogWithStates({
|
||||||
state0: {
|
state0: {
|
||||||
title: title,
|
titleKey: "dialog.shareVideoTitle",
|
||||||
html: `
|
html: `
|
||||||
<input name="sharedVideoUrl" type="text"
|
<input name="sharedVideoUrl" type="text"
|
||||||
data-i18n="[placeholder]defaultLink"
|
data-i18n="[placeholder]defaultLink"
|
||||||
data-i18n-options="${JSON.stringify(i18nOptions)}"
|
|
||||||
placeholder="${defaultUrl}"
|
|
||||||
autofocus>`,
|
autofocus>`,
|
||||||
persistent: false,
|
persistent: false,
|
||||||
buttons: [
|
buttons: [
|
||||||
|
@ -802,7 +797,7 @@ function requestVideoLink() {
|
||||||
},
|
},
|
||||||
|
|
||||||
state1: {
|
state1: {
|
||||||
title: title,
|
titleKey: "dialog.shareVideoTitle",
|
||||||
html: linkError,
|
html: linkError,
|
||||||
persistent: false,
|
persistent: false,
|
||||||
buttons: [
|
buttons: [
|
||||||
|
@ -825,7 +820,8 @@ function requestVideoLink() {
|
||||||
close: function () {
|
close: function () {
|
||||||
dialog = null;
|
dialog = null;
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
url: defaultSharedVideoLink
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,8 @@ function updateNumberOfParticipants(delta) {
|
||||||
|
|
||||||
$("#numberOfParticipants").text(numberOfContacts);
|
$("#numberOfParticipants").text(numberOfContacts);
|
||||||
|
|
||||||
$("#contacts_container>div.title").text(
|
APP.translation.translateElement(
|
||||||
APP.translation.translateString("contactlist")
|
$("#contacts_container>div.title"), {pcount: numberOfContacts});
|
||||||
+ ' (' + numberOfContacts + ')');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,7 +49,6 @@ function createDisplayNameParagraph(key, displayName) {
|
||||||
p.innerHTML = displayName;
|
p.innerHTML = displayName;
|
||||||
} else if(key) {
|
} else if(key) {
|
||||||
p.setAttribute("data-i18n",key);
|
p.setAttribute("data-i18n",key);
|
||||||
p.innerHTML = APP.translation.translateString(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
|
@ -82,10 +80,11 @@ var ContactListView = {
|
||||||
*/
|
*/
|
||||||
addInviteButton() {
|
addInviteButton() {
|
||||||
let container = document.getElementById('contacts_container');
|
let container = document.getElementById('contacts_container');
|
||||||
let title = container.firstElementChild;
|
|
||||||
|
|
||||||
let htmlLayout = this.getInviteButtonLayout();
|
container.firstElementChild // this is the title
|
||||||
title.insertAdjacentHTML('afterend', htmlLayout);
|
.insertAdjacentHTML('afterend', this.getInviteButtonLayout());
|
||||||
|
|
||||||
|
APP.translation.translateElement($(container));
|
||||||
$(document).on('click', '#addParticipantsBtn', () => {
|
$(document).on('click', '#addParticipantsBtn', () => {
|
||||||
APP.UI.emitEvent(UIEvents.INVITE_CLICKED);
|
APP.UI.emitEvent(UIEvents.INVITE_CLICKED);
|
||||||
});
|
});
|
||||||
|
@ -97,32 +96,26 @@ var ContactListView = {
|
||||||
let classes = 'button-control button-control_primary';
|
let classes = 'button-control button-control_primary';
|
||||||
classes += ' button-control_full-width';
|
classes += ' button-control_full-width';
|
||||||
let key = 'addParticipants';
|
let key = 'addParticipants';
|
||||||
let text = APP.translation.translateString(key);
|
|
||||||
|
|
||||||
let lockedHtml = this.getLockDescriptionLayout(this.lockKey);
|
let lockedHtml = this.getLockDescriptionLayout(this.lockKey);
|
||||||
let unlockedHtml = this.getLockDescriptionLayout(this.unlockKey);
|
let unlockedHtml = this.getLockDescriptionLayout(this.unlockKey);
|
||||||
|
|
||||||
let html = (
|
return (
|
||||||
`<div class="sideToolbarBlock first">
|
`<div class="sideToolbarBlock first">
|
||||||
<button id="addParticipantsBtn"
|
<button id="addParticipantsBtn"
|
||||||
data-i18n="${key}"
|
data-i18n="${key}"
|
||||||
class="${classes}">
|
class="${classes}"></button>
|
||||||
${text}
|
|
||||||
</button>
|
|
||||||
<div>
|
<div>
|
||||||
${lockedHtml}
|
${lockedHtml}
|
||||||
${unlockedHtml}
|
${unlockedHtml}
|
||||||
</div>
|
</div>
|
||||||
</div>`);
|
</div>`);
|
||||||
|
|
||||||
return html;
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Adds layout for lock description
|
* Adds layout for lock description
|
||||||
*/
|
*/
|
||||||
getLockDescriptionLayout(key) {
|
getLockDescriptionLayout(key) {
|
||||||
let classes = "input-control__hint input-control_full-width";
|
let classes = "input-control__hint input-control_full-width";
|
||||||
let description = APP.translation.translateString(key);
|
|
||||||
let padlockSuffix = '';
|
let padlockSuffix = '';
|
||||||
if (key === this.lockKey) {
|
if (key === this.lockKey) {
|
||||||
padlockSuffix = '-locked';
|
padlockSuffix = '-locked';
|
||||||
|
@ -130,7 +123,7 @@ var ContactListView = {
|
||||||
|
|
||||||
return `<p id="contactList${key}" class="${classes}">
|
return `<p id="contactList${key}" class="${classes}">
|
||||||
<span class="icon-security${padlockSuffix}"></span>
|
<span class="icon-security${padlockSuffix}"></span>
|
||||||
<span data-i18n="${key}">${description}</span>
|
<span data-i18n="${key}"></span>
|
||||||
</p>`;
|
</p>`;
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
|
@ -198,6 +191,7 @@ var ContactListView = {
|
||||||
createDisplayNameParagraph(
|
createDisplayNameParagraph(
|
||||||
isLocal ? interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME : null,
|
isLocal ? interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME : null,
|
||||||
isLocal ? null : interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME));
|
isLocal ? null : interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME));
|
||||||
|
APP.translation.translateElement($(newContact));
|
||||||
|
|
||||||
if (APP.conference.isLocalId(id)) {
|
if (APP.conference.isLocalId(id)) {
|
||||||
contactlist.prepend(newContact);
|
contactlist.prepend(newContact);
|
||||||
|
|
|
@ -279,7 +279,6 @@ function showSipNumberInput () {
|
||||||
? config.defaultSipNumber
|
? config.defaultSipNumber
|
||||||
: '';
|
: '';
|
||||||
let titleKey = "dialog.sipMsg";
|
let titleKey = "dialog.sipMsg";
|
||||||
let sipMsg = APP.translation.generateTranslationHTML("dialog.sipMsg");
|
|
||||||
let msgString = (`
|
let msgString = (`
|
||||||
<input name="sipNumber" type="text"
|
<input name="sipNumber" type="text"
|
||||||
value="${defaultNumber}" autofocus>
|
value="${defaultNumber}" autofocus>
|
||||||
|
@ -287,7 +286,6 @@ function showSipNumberInput () {
|
||||||
|
|
||||||
APP.UI.messageHandler.openTwoButtonDialog({
|
APP.UI.messageHandler.openTwoButtonDialog({
|
||||||
titleKey,
|
titleKey,
|
||||||
titleString: sipMsg,
|
|
||||||
msgString,
|
msgString,
|
||||||
leftButtonKey: "dialog.Dial",
|
leftButtonKey: "dialog.Dial",
|
||||||
submitFunction: function (e, v, m, f) {
|
submitFunction: function (e, v, m, f) {
|
||||||
|
|
|
@ -1,22 +1,26 @@
|
||||||
/* global $ */
|
/* global $ */
|
||||||
var JitsiPopover = (function () {
|
var JitsiPopover = (function () {
|
||||||
|
/**
|
||||||
|
* The default options
|
||||||
|
*/
|
||||||
|
const defaultOptions = {
|
||||||
|
skin: 'white',
|
||||||
|
content: '',
|
||||||
|
hasArrow: true,
|
||||||
|
onBeforePosition: undefined
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs new JitsiPopover and attaches it to the element
|
* Constructs new JitsiPopover and attaches it to the element
|
||||||
* @param element jquery selector
|
* @param element jquery selector
|
||||||
* @param options the options for the popover.
|
* @param options the options for the popover.
|
||||||
|
* - {Function} onBeforePosition - function executed just before
|
||||||
|
* positioning the popover. Useful for translation.
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function JitsiPopover(element, options)
|
function JitsiPopover(element, options)
|
||||||
{
|
{
|
||||||
let { skin, content, hasArrow } = options;
|
this.options = Object.assign({}, defaultOptions, options);
|
||||||
this.options = {};
|
|
||||||
this.options.skin = skin || 'white';
|
|
||||||
this.options.content = content || '';
|
|
||||||
this.options.hasArrow = true;
|
|
||||||
|
|
||||||
if (typeof(hasArrow) !== 'undefined') {
|
|
||||||
this.options.hasArrow = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.elementIsHovered = false;
|
this.elementIsHovered = false;
|
||||||
this.popoverIsHovered = false;
|
this.popoverIsHovered = false;
|
||||||
|
@ -86,7 +90,11 @@ var JitsiPopover = (function () {
|
||||||
*/
|
*/
|
||||||
JitsiPopover.prototype.createPopover = function () {
|
JitsiPopover.prototype.createPopover = function () {
|
||||||
$("body").append(this.template);
|
$("body").append(this.template);
|
||||||
$(".jitsipopover > .jitsipopover__content").html(this.options.content);
|
let popoverElem = $(".jitsipopover > .jitsipopover__content");
|
||||||
|
popoverElem.html(this.options.content);
|
||||||
|
if(typeof this.options.onBeforePosition === "function") {
|
||||||
|
this.options.onBeforePosition($(".jitsipopover"));
|
||||||
|
}
|
||||||
var self = this;
|
var self = this;
|
||||||
$(".jitsipopover").on("mouseenter", function () {
|
$(".jitsipopover").on("mouseenter", function () {
|
||||||
self.popoverIsHovered = true;
|
self.popoverIsHovered = true;
|
||||||
|
|
|
@ -29,30 +29,20 @@ var messageHandler = {
|
||||||
*
|
*
|
||||||
* @param titleKey the key used to find the translation of the title of the
|
* @param titleKey the key used to find the translation of the title of the
|
||||||
* message, if a message title is not provided.
|
* message, if a message title is not provided.
|
||||||
* @param messageKey the key used to find the translation of the message,
|
* @param messageKey the key used to find the translation of the message
|
||||||
* if a message is not provided.
|
* @param i18nOptions the i18n options (optional)
|
||||||
* @param title the title of the message. If a falsy value is provided,
|
|
||||||
* titleKey will be used to get a title via the translation API.
|
|
||||||
* @param message the message to show. If a falsy value is provided,
|
|
||||||
* messageKey will be used to get a message via the translation API.
|
|
||||||
* @param closeFunction function to be called after
|
* @param closeFunction function to be called after
|
||||||
* the prompt is closed (optional)
|
* the prompt is closed (optional)
|
||||||
* @return the prompt that was created, or null
|
* @return the prompt that was created, or null
|
||||||
*/
|
*/
|
||||||
openMessageDialog: function(titleKey, messageKey, title, message,
|
openMessageDialog:
|
||||||
closeFunction) {
|
function(titleKey, messageKey, i18nOptions, closeFunction) {
|
||||||
if (!popupEnabled)
|
if (!popupEnabled)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (!title) {
|
let dialog = $.prompt(
|
||||||
title = APP.translation.generateTranslationHTML(titleKey);
|
APP.translation.generateTranslationHTML(messageKey, i18nOptions), {
|
||||||
}
|
title: this._getFormattedTitleString(titleKey),
|
||||||
if (!message) {
|
|
||||||
message = APP.translation.generateTranslationHTML(messageKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $.prompt(message, {
|
|
||||||
title: this._getFormattedTitleString(title),
|
|
||||||
persistent: false,
|
persistent: false,
|
||||||
promptspeed: 0,
|
promptspeed: 0,
|
||||||
classes: this._getDialogClasses(),
|
classes: this._getDialogClasses(),
|
||||||
|
@ -61,12 +51,14 @@ var messageHandler = {
|
||||||
closeFunction(e, v, m, f);
|
closeFunction(e, v, m, f);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
APP.translation.translateElement(dialog, i18nOptions);
|
||||||
|
return dialog;
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Shows a message to the user with two buttons: first is given as a
|
* Shows a message to the user with two buttons: first is given as a
|
||||||
* parameter and the second is Cancel.
|
* parameter and the second is Cancel.
|
||||||
*
|
*
|
||||||
* @param titleString the title of the message
|
* @param titleKey the key for the title of the message
|
||||||
* @param msgString the text of the message
|
* @param msgString the text of the message
|
||||||
* @param persistent boolean value which determines whether the message is
|
* @param persistent boolean value which determines whether the message is
|
||||||
* persistent or not
|
* persistent or not
|
||||||
|
@ -84,7 +76,6 @@ var messageHandler = {
|
||||||
openTwoButtonDialog: function(options) {
|
openTwoButtonDialog: function(options) {
|
||||||
let {
|
let {
|
||||||
titleKey,
|
titleKey,
|
||||||
titleString,
|
|
||||||
msgKey,
|
msgKey,
|
||||||
msgString,
|
msgString,
|
||||||
leftButtonKey,
|
leftButtonKey,
|
||||||
|
@ -112,10 +103,7 @@ var messageHandler = {
|
||||||
= APP.translation.generateTranslationHTML("dialog.Cancel");
|
= APP.translation.generateTranslationHTML("dialog.Cancel");
|
||||||
buttons.push({title: cancelButton, value: false});
|
buttons.push({title: cancelButton, value: false});
|
||||||
|
|
||||||
var message = msgString, title = titleString;
|
var message = msgString;
|
||||||
if (titleKey) {
|
|
||||||
title = APP.translation.generateTranslationHTML(titleKey);
|
|
||||||
}
|
|
||||||
if (msgKey) {
|
if (msgKey) {
|
||||||
message = APP.translation.generateTranslationHTML(msgKey);
|
message = APP.translation.generateTranslationHTML(msgKey);
|
||||||
}
|
}
|
||||||
|
@ -125,7 +113,7 @@ var messageHandler = {
|
||||||
}
|
}
|
||||||
|
|
||||||
twoButtonDialog = $.prompt(message, {
|
twoButtonDialog = $.prompt(message, {
|
||||||
title: this._getFormattedTitleString(title),
|
title: this._getFormattedTitleString(titleKey),
|
||||||
persistent: false,
|
persistent: false,
|
||||||
buttons: buttons,
|
buttons: buttons,
|
||||||
defaultButton: defaultButton,
|
defaultButton: defaultButton,
|
||||||
|
@ -147,6 +135,7 @@ var messageHandler = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
APP.translation.translateElement(twoButtonDialog);
|
||||||
return twoButtonDialog;
|
return twoButtonDialog;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -154,7 +143,7 @@ var messageHandler = {
|
||||||
* Shows a message to the user with two buttons: first is given as a
|
* Shows a message to the user with two buttons: first is given as a
|
||||||
* parameter and the second is Cancel.
|
* parameter and the second is Cancel.
|
||||||
*
|
*
|
||||||
* @param titleString the title of the message
|
* @param titleKey the key for the title of the message
|
||||||
* @param msgString the text of the message
|
* @param msgString the text of the message
|
||||||
* @param persistent boolean value which determines whether the message is
|
* @param persistent boolean value which determines whether the message is
|
||||||
* persistent or not
|
* persistent or not
|
||||||
|
@ -166,13 +155,13 @@ var messageHandler = {
|
||||||
* loaded
|
* loaded
|
||||||
* @param closeFunction function to be called on dialog close
|
* @param closeFunction function to be called on dialog close
|
||||||
*/
|
*/
|
||||||
openDialog: function (titleString, msgString, persistent, buttons,
|
openDialog: function (titleKey, msgString, persistent, buttons,
|
||||||
submitFunction, loadedFunction, closeFunction) {
|
submitFunction, loadedFunction, closeFunction) {
|
||||||
if (!popupEnabled)
|
if (!popupEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let args = {
|
let args = {
|
||||||
title: this._getFormattedTitleString(titleString),
|
title: this._getFormattedTitleString(titleKey),
|
||||||
persistent: persistent,
|
persistent: persistent,
|
||||||
buttons: buttons,
|
buttons: buttons,
|
||||||
defaultButton: 1,
|
defaultButton: 1,
|
||||||
|
@ -187,7 +176,9 @@ var messageHandler = {
|
||||||
args.closeText = '';
|
args.closeText = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Impromptu(msgString, args);
|
let dialog = new Impromptu(msgString, args);
|
||||||
|
APP.translation.translateElement(dialog.getPrompt());
|
||||||
|
return dialog;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -195,13 +186,11 @@ var messageHandler = {
|
||||||
*
|
*
|
||||||
* @return the title string formatted as a div.
|
* @return the title string formatted as a div.
|
||||||
*/
|
*/
|
||||||
_getFormattedTitleString(titleString) {
|
_getFormattedTitleString(titleKey) {
|
||||||
let $titleString = $('<h2>');
|
let $titleString = $('<h2>');
|
||||||
$titleString.addClass('aui-dialog2-header-main');
|
$titleString.addClass('aui-dialog2-header-main');
|
||||||
$titleString.append(titleString);
|
$titleString.attr('data-i18n',titleKey);
|
||||||
titleString = $('<div>').append($titleString).html();
|
return $('<div>').append($titleString).html();
|
||||||
|
|
||||||
return titleString;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -235,8 +224,10 @@ var messageHandler = {
|
||||||
* Shows a dialog with different states to the user.
|
* Shows a dialog with different states to the user.
|
||||||
*
|
*
|
||||||
* @param statesObject object containing all the states of the dialog.
|
* @param statesObject object containing all the states of the dialog.
|
||||||
|
* @param options impromptu options
|
||||||
|
* @param translateOptions options passed to translation
|
||||||
*/
|
*/
|
||||||
openDialogWithStates: function (statesObject, options) {
|
openDialogWithStates: function (statesObject, options, translateOptions) {
|
||||||
if (!popupEnabled)
|
if (!popupEnabled)
|
||||||
return;
|
return;
|
||||||
let { classes, size } = options;
|
let { classes, size } = options;
|
||||||
|
@ -246,12 +237,14 @@ var messageHandler = {
|
||||||
|
|
||||||
for (let state in statesObject) {
|
for (let state in statesObject) {
|
||||||
let currentState = statesObject[state];
|
let currentState = statesObject[state];
|
||||||
if(currentState.title) {
|
if(currentState.titleKey) {
|
||||||
let title = currentState.title;
|
currentState.title
|
||||||
currentState.title = this._getFormattedTitleString(title);
|
= this._getFormattedTitleString(currentState.titleKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new Impromptu(statesObject, options);
|
let dialog = new Impromptu(statesObject, options);
|
||||||
|
APP.translation.translateElement(dialog.getPrompt(), translateOptions);
|
||||||
|
return dialog;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -340,20 +333,18 @@ var messageHandler = {
|
||||||
if (displayName) {
|
if (displayName) {
|
||||||
displayNameSpan += ">" + UIUtil.escapeHtml(displayName);
|
displayNameSpan += ">" + UIUtil.escapeHtml(displayName);
|
||||||
} else {
|
} else {
|
||||||
displayNameSpan += "data-i18n='" + displayNameKey +
|
displayNameSpan += "data-i18n='" + displayNameKey + "'>";
|
||||||
"'>" + APP.translation.translateString(displayNameKey);
|
|
||||||
}
|
}
|
||||||
displayNameSpan += "</span>";
|
displayNameSpan += "</span>";
|
||||||
return toastr.info(
|
let element = toastr.info(
|
||||||
displayNameSpan + '<br>' +
|
displayNameSpan + '<br>' +
|
||||||
'<span class=' + cls + ' data-i18n="' + messageKey + '"' +
|
'<span class=' + cls + ' data-i18n="' + messageKey + '"' +
|
||||||
(messageArguments?
|
(messageArguments?
|
||||||
" data-i18n-options='" + JSON.stringify(messageArguments)
|
" data-i18n-options='"
|
||||||
+ "'"
|
+ JSON.stringify(messageArguments) + "'"
|
||||||
: "") + ">" +
|
: "") + "></span>", null, options);
|
||||||
APP.translation.translateString(messageKey,
|
APP.translation.translateElement(element);
|
||||||
messageArguments) +
|
return element;
|
||||||
'</span>', null, options);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global APP, $, config */
|
/* global $, APP, config */
|
||||||
/* jshint -W101 */
|
/* jshint -W101 */
|
||||||
import JitsiPopover from "../util/JitsiPopover";
|
import JitsiPopover from "../util/JitsiPopover";
|
||||||
import VideoLayout from "./VideoLayout";
|
import VideoLayout from "./VideoLayout";
|
||||||
|
@ -63,8 +63,6 @@ ConnectionIndicator.getStringFromArray = function (array) {
|
||||||
ConnectionIndicator.prototype.generateText = function () {
|
ConnectionIndicator.prototype.generateText = function () {
|
||||||
var downloadBitrate, uploadBitrate, packetLoss, i;
|
var downloadBitrate, uploadBitrate, packetLoss, i;
|
||||||
|
|
||||||
var translate = APP.translation.translateString;
|
|
||||||
|
|
||||||
if(this.bitrate === null) {
|
if(this.bitrate === null) {
|
||||||
downloadBitrate = "N/A";
|
downloadBitrate = "N/A";
|
||||||
uploadBitrate = "N/A";
|
uploadBitrate = "N/A";
|
||||||
|
@ -99,9 +97,7 @@ ConnectionIndicator.prototype.generateText = function () {
|
||||||
`<table class="connection-info__container" style='width:100%'>
|
`<table class="connection-info__container" style='width:100%'>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<span data-i18n='connectionindicator.bitrate'>
|
<span data-i18n='connectionindicator.bitrate'></span>
|
||||||
${translate("connectionindicator.bitrate")}
|
|
||||||
</span>
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class='connection-info__download'>↓</span>${downloadBitrate}
|
<span class='connection-info__download'>↓</span>${downloadBitrate}
|
||||||
|
@ -110,17 +106,13 @@ ConnectionIndicator.prototype.generateText = function () {
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<span data-i18n='connectionindicator.packetloss'>
|
<span data-i18n='connectionindicator.packetloss'></span>
|
||||||
${translate("connectionindicator.packetloss")}
|
|
||||||
</span>
|
|
||||||
</td>
|
</td>
|
||||||
<td>${packetLoss}</td>
|
<td>${packetLoss}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<span data-i18n='connectionindicator.resolution'>
|
<span data-i18n='connectionindicator.resolution'></span>
|
||||||
${translate("connectionindicator.resolution")}
|
|
||||||
</span>
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
${resolutionStr}
|
${resolutionStr}
|
||||||
|
@ -134,9 +126,7 @@ ConnectionIndicator.prototype.generateText = function () {
|
||||||
// FIXME: we do not know local id when this text is generated
|
// FIXME: we do not know local id when this text is generated
|
||||||
//this.id + "')\" data-i18n='connectionindicator." +
|
//this.id + "')\" data-i18n='connectionindicator." +
|
||||||
"local')\" data-i18n='connectionindicator." +
|
"local')\" data-i18n='connectionindicator." +
|
||||||
(this.showMoreValue ? "less" : "more") + "'>" +
|
(this.showMoreValue ? "less" : "more") + "'></a>";
|
||||||
translate("connectionindicator." + (this.showMoreValue ? "less" : "more")) +
|
|
||||||
"</a>";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.showMoreValue) {
|
if (this.showMoreValue) {
|
||||||
|
@ -156,8 +146,7 @@ ConnectionIndicator.prototype.generateText = function () {
|
||||||
if (!this.transport || this.transport.length === 0) {
|
if (!this.transport || this.transport.length === 0) {
|
||||||
transport = "<tr>" +
|
transport = "<tr>" +
|
||||||
"<td><span " +
|
"<td><span " +
|
||||||
"data-i18n='connectionindicator.address'>" +
|
"data-i18n='connectionindicator.address'></span></td>" +
|
||||||
translate("connectionindicator.address") + "</span></td>" +
|
|
||||||
"<td> N/A</td></tr>";
|
"<td> N/A</td></tr>";
|
||||||
} else {
|
} else {
|
||||||
var data = {remoteIP: [], localIP:[], remotePort:[], localPort:[]};
|
var data = {remoteIP: [], localIP:[], remotePort:[], localPort:[]};
|
||||||
|
@ -190,18 +179,15 @@ ConnectionIndicator.prototype.generateText = function () {
|
||||||
var localTransport =
|
var localTransport =
|
||||||
"<tr><td><span data-i18n='" +
|
"<tr><td><span data-i18n='" +
|
||||||
local_address_key +"' data-i18n-options='" +
|
local_address_key +"' data-i18n-options='" +
|
||||||
JSON.stringify({count: data.localIP.length}) + "'>" +
|
JSON.stringify({count: data.localIP.length})
|
||||||
translate(local_address_key, {count: data.localIP.length}) +
|
+ "'></span></td><td> " +
|
||||||
"</span></td><td> " +
|
|
||||||
ConnectionIndicator.getStringFromArray(data.localIP) +
|
ConnectionIndicator.getStringFromArray(data.localIP) +
|
||||||
"</td></tr>";
|
"</td></tr>";
|
||||||
transport =
|
transport =
|
||||||
"<tr><td><span data-i18n='" +
|
"<tr><td><span data-i18n='" +
|
||||||
remote_address_key + "' data-i18n-options='" +
|
remote_address_key + "' data-i18n-options='" +
|
||||||
JSON.stringify({count: data.remoteIP.length}) + "'>" +
|
JSON.stringify({count: data.remoteIP.length})
|
||||||
translate(remote_address_key,
|
+ "'></span></td><td> " +
|
||||||
{count: data.remoteIP.length}) +
|
|
||||||
"</span></td><td> " +
|
|
||||||
ConnectionIndicator.getStringFromArray(data.remoteIP) +
|
ConnectionIndicator.getStringFromArray(data.remoteIP) +
|
||||||
"</td></tr>";
|
"</td></tr>";
|
||||||
|
|
||||||
|
@ -212,16 +198,14 @@ ConnectionIndicator.prototype.generateText = function () {
|
||||||
"<td>" +
|
"<td>" +
|
||||||
"<span data-i18n='" + key_remote +
|
"<span data-i18n='" + key_remote +
|
||||||
"' data-i18n-options='" +
|
"' data-i18n-options='" +
|
||||||
JSON.stringify({count: this.transport.length}) + "'>" +
|
JSON.stringify({count: this.transport.length})
|
||||||
translate(key_remote, {count: this.transport.length}) +
|
+ "'></span></td><td>";
|
||||||
"</span></td><td>";
|
|
||||||
localTransport += "<tr>" +
|
localTransport += "<tr>" +
|
||||||
"<td>" +
|
"<td>" +
|
||||||
"<span data-i18n='" + key_local +
|
"<span data-i18n='" + key_local +
|
||||||
"' data-i18n-options='" +
|
"' data-i18n-options='" +
|
||||||
JSON.stringify({count: this.transport.length}) + "'>" +
|
JSON.stringify({count: this.transport.length})
|
||||||
translate(key_local, {count: this.transport.length}) +
|
+ "'></span></td><td>";
|
||||||
"</span></td><td>";
|
|
||||||
|
|
||||||
transport +=
|
transport +=
|
||||||
ConnectionIndicator.getStringFromArray(data.remotePort);
|
ConnectionIndicator.getStringFromArray(data.remotePort);
|
||||||
|
@ -231,7 +215,7 @@ ConnectionIndicator.prototype.generateText = function () {
|
||||||
transport += localTransport + "</td></tr>";
|
transport += localTransport + "</td></tr>";
|
||||||
transport +="<tr>" +
|
transport +="<tr>" +
|
||||||
"<td><span data-i18n='connectionindicator.transport'>" +
|
"<td><span data-i18n='connectionindicator.transport'>" +
|
||||||
translate("connectionindicator.transport") + "</span></td>" +
|
"</span></td>" +
|
||||||
"<td>" + this.transport[0].type + "</td></tr>";
|
"<td>" + this.transport[0].type + "</td></tr>";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -239,8 +223,7 @@ ConnectionIndicator.prototype.generateText = function () {
|
||||||
result += "<table class='connection-info__container' style='width:100%'>" +
|
result += "<table class='connection-info__container' style='width:100%'>" +
|
||||||
"<tr>" +
|
"<tr>" +
|
||||||
"<td>" +
|
"<td>" +
|
||||||
"<span data-i18n='connectionindicator.bandwidth'>" +
|
"<span data-i18n='connectionindicator.bandwidth'></span>" +
|
||||||
translate("connectionindicator.bandwidth") + "</span>" +
|
|
||||||
"</td><td>" +
|
"</td><td>" +
|
||||||
"<span class='connection-info__download'>↓</span>" +
|
"<span class='connection-info__download'>↓</span>" +
|
||||||
downloadBandwidth +
|
downloadBandwidth +
|
||||||
|
@ -282,10 +265,12 @@ ConnectionIndicator.prototype.create = function () {
|
||||||
this.videoContainer.container.appendChild(
|
this.videoContainer.container.appendChild(
|
||||||
this.connectionIndicatorContainer);
|
this.connectionIndicatorContainer);
|
||||||
this.popover = new JitsiPopover(
|
this.popover = new JitsiPopover(
|
||||||
$("#" + this.videoContainer.videoSpanId + " > .connectionindicator"),
|
$("#" + this.videoContainer.videoSpanId + " > .connectionindicator"), {
|
||||||
{content: "<div class=\"connection-info\" data-i18n='connectionindicator.na'>" +
|
content: "<div class=\"connection-info\" " +
|
||||||
APP.translation.translateString("connectionindicator.na") + "</div>",
|
"data-i18n='connectionindicator.na'></div>",
|
||||||
skin: "black"});
|
skin: "black",
|
||||||
|
onBeforePosition: el => APP.translation.translateElement(el)
|
||||||
|
});
|
||||||
|
|
||||||
// override popover show method to make sure we will update the content
|
// override popover show method to make sure we will update the content
|
||||||
// before showing the popover
|
// before showing the popover
|
||||||
|
@ -398,7 +383,6 @@ ConnectionIndicator.prototype.updatePopoverData = function (force) {
|
||||||
this.popover.updateContent(
|
this.popover.updateContent(
|
||||||
`<div class="connection-info">${this.generateText()}</div>`
|
`<div class="connection-info">${this.generateText()}</div>`
|
||||||
);
|
);
|
||||||
APP.translation.translateElement($(".connection-info"));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -379,9 +379,10 @@ export default class LargeVideoManager {
|
||||||
*/
|
*/
|
||||||
_setRemoteConnectionMessage (msgKey, msgOptions) {
|
_setRemoteConnectionMessage (msgKey, msgOptions) {
|
||||||
if (msgKey) {
|
if (msgKey) {
|
||||||
let text = APP.translation.translateString(msgKey, msgOptions);
|
|
||||||
$('#remoteConnectionMessage')
|
$('#remoteConnectionMessage')
|
||||||
.attr("data-i18n", msgKey).text(text);
|
.attr("data-i18n", msgKey)
|
||||||
|
.attr("data-i18n-options", JSON.stringify(msgOptions));
|
||||||
|
APP.translation.translateElement($('#remoteConnectionMessage'));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.videoContainer.positionRemoteConnectionMessage();
|
this.videoContainer.positionRemoteConnectionMessage();
|
||||||
|
@ -400,7 +401,8 @@ export default class LargeVideoManager {
|
||||||
_setLocalConnectionMessage (msgKey, msgOptions) {
|
_setLocalConnectionMessage (msgKey, msgOptions) {
|
||||||
$('#localConnectionMessage')
|
$('#localConnectionMessage')
|
||||||
.attr("data-i18n", msgKey)
|
.attr("data-i18n", msgKey)
|
||||||
.text(APP.translation.translateString(msgKey, msgOptions));
|
.attr("data-i18n-options", JSON.stringify(msgOptions));
|
||||||
|
APP.translation.translateElement($('#localConnectionMessage'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -96,14 +96,12 @@ LocalVideo.prototype.setDisplayName = function(displayName) {
|
||||||
editableText.value = displayName;
|
editableText.value = displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultNickname = APP.translation.translateString(
|
|
||||||
"defaultNickname", {name: "Jane Pink"});
|
|
||||||
editableText.setAttribute('style', 'display:none;');
|
editableText.setAttribute('style', 'display:none;');
|
||||||
editableText.setAttribute('data-18n',
|
editableText.setAttribute('data-i18n',
|
||||||
'[placeholder]defaultNickname');
|
'[placeholder]defaultNickname');
|
||||||
editableText.setAttribute("data-i18n-options",
|
editableText.setAttribute("data-i18n-options",
|
||||||
JSON.stringify({name: "Jane Pink"}));
|
JSON.stringify({name: "Jane Pink"}));
|
||||||
editableText.setAttribute("placeholder", defaultNickname);
|
APP.translation.translateElement($(editableText));
|
||||||
|
|
||||||
this.container
|
this.container
|
||||||
.querySelector('.videocontainer__toolbar')
|
.querySelector('.videocontainer__toolbar')
|
||||||
|
@ -253,7 +251,8 @@ LocalVideo.prototype._buildContextMenu = function () {
|
||||||
events: {
|
events: {
|
||||||
show : function(options){
|
show : function(options){
|
||||||
options.items.flip.name =
|
options.items.flip.name =
|
||||||
APP.translation.translateString("videothumbnail.flip");
|
APP.translation.generateTranslationHTML(
|
||||||
|
"videothumbnail.flip");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -78,7 +78,8 @@ RemoteVideo.prototype._initPopupMenu = function (popupMenuElement) {
|
||||||
let options = {
|
let options = {
|
||||||
content: popupMenuElement.outerHTML,
|
content: popupMenuElement.outerHTML,
|
||||||
skin: "black",
|
skin: "black",
|
||||||
hasArrow: false
|
hasArrow: false,
|
||||||
|
onBeforePosition: el => APP.translation.translateElement(el)
|
||||||
};
|
};
|
||||||
let element = $("#" + this.videoSpanId + " .remotevideomenu");
|
let element = $("#" + this.videoSpanId + " .remotevideomenu");
|
||||||
this.popover = new JitsiPopover(element, options);
|
this.popover = new JitsiPopover(element, options);
|
||||||
|
@ -112,16 +113,10 @@ RemoteVideo.prototype._generatePopupContent = function () {
|
||||||
var mutedIndicator = "<i class='icon-mic-disabled'></i>";
|
var mutedIndicator = "<i class='icon-mic-disabled'></i>";
|
||||||
|
|
||||||
var doMuteHTML = mutedIndicator +
|
var doMuteHTML = mutedIndicator +
|
||||||
" <div " +
|
" <div data-i18n='videothumbnail.domute'></div>";
|
||||||
"data-i18n='videothumbnail.domute'>" +
|
|
||||||
APP.translation.translateString("videothumbnail.domute") +
|
|
||||||
"</div>";
|
|
||||||
|
|
||||||
var mutedHTML = mutedIndicator +
|
var mutedHTML = mutedIndicator +
|
||||||
" <div " +
|
" <div data-i18n='videothumbnail.muted'></div>";
|
||||||
"data-i18n='videothumbnail.muted'>" +
|
|
||||||
APP.translation.translateString("videothumbnail.muted") +
|
|
||||||
"</div>";
|
|
||||||
|
|
||||||
muteLinkItem.id = "mutelink_" + this.id;
|
muteLinkItem.id = "mutelink_" + this.id;
|
||||||
|
|
||||||
|
@ -153,10 +148,7 @@ RemoteVideo.prototype._generatePopupContent = function () {
|
||||||
var ejectMenuItem = document.createElement('li');
|
var ejectMenuItem = document.createElement('li');
|
||||||
var ejectLinkItem = document.createElement('a');
|
var ejectLinkItem = document.createElement('a');
|
||||||
|
|
||||||
var ejectText = "<div " +
|
var ejectText = "<div data-i18n='videothumbnail.kick'></div>";
|
||||||
"data-i18n='videothumbnail.kick'>" +
|
|
||||||
APP.translation.translateString("videothumbnail.kick") +
|
|
||||||
"</div>";
|
|
||||||
|
|
||||||
ejectLinkItem.className = 'ejectlink';
|
ejectLinkItem.className = 'ejectlink';
|
||||||
ejectLinkItem.innerHTML = ejectIndicator + ' ' + ejectText;
|
ejectLinkItem.innerHTML = ejectIndicator + ' ' + ejectText;
|
||||||
|
@ -170,6 +162,8 @@ RemoteVideo.prototype._generatePopupContent = function () {
|
||||||
ejectMenuItem.appendChild(ejectLinkItem);
|
ejectMenuItem.appendChild(ejectLinkItem);
|
||||||
popupmenuElement.appendChild(ejectMenuItem);
|
popupmenuElement.appendChild(ejectMenuItem);
|
||||||
|
|
||||||
|
APP.translation.translateElement($(popupmenuElement));
|
||||||
|
|
||||||
return popupmenuElement;
|
return popupmenuElement;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -190,8 +190,7 @@ var KeyboardShortcut = {
|
||||||
let descriptionClass = "shortcuts-list__description";
|
let descriptionClass = "shortcuts-list__description";
|
||||||
descriptionElement.className = descriptionClass;
|
descriptionElement.className = descriptionClass;
|
||||||
descriptionElement.setAttribute("data-i18n", shortcutDescriptionKey);
|
descriptionElement.setAttribute("data-i18n", shortcutDescriptionKey);
|
||||||
descriptionElement.innerHTML
|
APP.translation.translateElement($(descriptionElement));
|
||||||
= APP.translation.translateString(shortcutDescriptionKey);
|
|
||||||
|
|
||||||
listElement.appendChild(spanElement);
|
listElement.appendChild(spanElement);
|
||||||
listElement.appendChild(descriptionElement);
|
listElement.appendChild(descriptionElement);
|
||||||
|
|
|
@ -89,9 +89,6 @@ module.exports = {
|
||||||
|
|
||||||
i18n.init(options, initCompleted);
|
i18n.init(options, initCompleted);
|
||||||
},
|
},
|
||||||
translateString: function (key, options) {
|
|
||||||
return i18n.t(key, options);
|
|
||||||
},
|
|
||||||
setLanguage: function (lang) {
|
setLanguage: function (lang) {
|
||||||
if(!lang)
|
if(!lang)
|
||||||
lang = DEFAULT_LANG;
|
lang = DEFAULT_LANG;
|
||||||
|
@ -100,16 +97,19 @@ module.exports = {
|
||||||
getCurrentLanguage: function () {
|
getCurrentLanguage: function () {
|
||||||
return i18n.lng();
|
return i18n.lng();
|
||||||
},
|
},
|
||||||
translateElement: function (selector) {
|
translateElement: function (selector, options) {
|
||||||
selector.i18n();
|
// i18next expects undefined if options are missing, check if its null
|
||||||
|
selector.i18n(
|
||||||
|
options === null ? undefined : options);
|
||||||
},
|
},
|
||||||
generateTranslationHTML: function (key, options) {
|
generateTranslationHTML: function (key, options) {
|
||||||
var str = "<span data-i18n=\"" + key + "\"";
|
var str = "<span data-i18n=\"" + key + "\"";
|
||||||
if (options) {
|
if (options) {
|
||||||
str += " data-i18n-options=\"" + JSON.stringify(options) + "\"";
|
str += " data-i18n-options='" + JSON.stringify(options) + "'";
|
||||||
}
|
}
|
||||||
str += ">";
|
str += ">";
|
||||||
str += this.translateString(key, options);
|
// i18next expects undefined if options ARE missing, check if its null
|
||||||
|
str += i18n.t(key, options === null ? undefined : options);
|
||||||
str += "</span>";
|
str += "</span>";
|
||||||
return str;
|
return str;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue