Merge pull request #1056 from jitsi/translations-update

Translations update
This commit is contained in:
hristoterezov 2016-10-25 18:11:15 -05:00 committed by GitHub
commit 221f6d1d68
24 changed files with 237 additions and 342 deletions

View File

@ -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(

View File

@ -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">

View File

@ -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":

View File

@ -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.

View File

@ -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();
} }

View File

@ -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);

View File

@ -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,

View File

@ -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 = {

View File

@ -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,

View File

@ -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();

View File

@ -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();

View File

@ -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);
}, },
/** /**

View File

@ -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);

View File

@ -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
}); });
}); });
} }

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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);
}, },
/** /**

View File

@ -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'>&darr;</span>${downloadBitrate} <span class='connection-info__download'>&darr;</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'>&darr;</span>" + "<span class='connection-info__download'>&darr;</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"));
} }
}; };

View File

@ -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'));
} }
/** /**

View File

@ -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");
} }
} }
}); });

View File

@ -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;
}; };

View File

@ -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);

View File

@ -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;