瀏覽代碼

Removes translateString and use translateElement.

Removing translateString forces using data-i18n attributes, to make sure we do not forget to set them. Missing data-i18n attributes is a problem with late loading where we can end up without translation, without text. Missing data-i18n attributes is also problem that strings will not be translated when changing language.
Fixes a bug in invite dialog, where remove password button was shown for non moderators.
master
damencho 8 年之前
父節點
當前提交
5217bf0bb8

+ 8
- 12
conference.js 查看文件

@@ -194,12 +194,9 @@ function maybeRedirectToWelcomePage(showThankYou) {
194 194
     }
195 195
 
196 196
     if (showThankYou) {
197
-        APP.UI.messageHandler.openMessageDialog(
198
-            null, "dialog.thankYou",
199
-            APP.translation.translateString(
200
-                "dialog.thankYou", {appName:interfaceConfig.APP_NAME}
201
-            )
202
-        );
197
+        APP.UI.messageHandler.openMessageDialog(null, null,
198
+            APP.translation.generateTranslationHTML(
199
+                "dialog.thankYou", {appName:interfaceConfig.APP_NAME}));
203 200
     }
204 201
 
205 202
     if (!config.enableWelcomePage) {
@@ -1050,21 +1047,20 @@ export default {
1050 1047
                 // TrackErrors.GENERAL
1051 1048
                 // and any other
1052 1049
                 let dialogTxt;
1053
-                let dialogTitle;
1050
+                let dialogTitleKey;
1054 1051
 
1055 1052
                 if (err.name === TrackErrors.PERMISSION_DENIED) {
1056 1053
                     dialogTxt = APP.translation.generateTranslationHTML(
1057 1054
                         "dialog.screenSharingPermissionDeniedError");
1058
-                    dialogTitle = APP.translation.generateTranslationHTML(
1059
-                        "dialog.error");
1055
+                    dialogTitleKey = "dialog.error";
1060 1056
                 } else {
1061 1057
                     dialogTxt = APP.translation.generateTranslationHTML(
1062 1058
                         "dialog.failtoinstall");
1063
-                    dialogTitle = APP.translation.generateTranslationHTML(
1064
-                        "dialog.permissionDenied");
1059
+                    dialogTitleKey = "dialog.permissionDenied";
1065 1060
                 }
1066 1061
 
1067
-                APP.UI.messageHandler.openDialog(dialogTitle, dialogTxt, false);
1062
+                APP.UI.messageHandler.openDialog(
1063
+                    dialogTitleKey, dialogTxt, false);
1068 1064
             });
1069 1065
         } else {
1070 1066
             createLocalTracks({ devices: ['video'] }).then(

+ 1
- 1
index.html 查看文件

@@ -174,7 +174,7 @@
174 174
                     </div>
175 175
                 </div>
176 176
                 <div id="contacts_container" class="sideToolbarContainer__inner">
177
-                    <div class="title" data-i18n="contactlist"></div>
177
+                    <div class="title" data-i18n="contactlist" data-i18n-options='{"pcount":"1"}'></div>
178 178
                     <ul id="contacts"></ul>
179 179
                 </div>
180 180
                 <div id="settings_container" class="sideToolbarContainer__inner">

+ 2
- 2
lang/main.json 查看文件

@@ -1,5 +1,5 @@
1 1
 {
2
-    "contactlist": "Participants",
2
+    "contactlist": "Participants (__pcount__)",
3 3
     "addParticipants": "Add Participants",
4 4
     "roomLocked": "Callers must enter a password",
5 5
     "roomUnlocked": "Anyone with the link can join",
@@ -340,7 +340,7 @@
340 340
         "ATTACHED": "Attached",
341 341
         "FETCH_SESSION_ID": "Obtaining session-id...",
342 342
         "GOT_SESSION_ID": "Obtaining session-id... Done",
343
-        "GET_SESSION_ID_ERROR": "Get session-id error: ",
343
+        "GET_SESSION_ID_ERROR": "Get session-id error: __code__",
344 344
         "USER_CONNECTION_INTERRUPTED": "__displayName__ is having connectivity issues..."
345 345
     },
346 346
     "recording":

+ 10
- 28
modules/UI/UI.js 查看文件

@@ -75,16 +75,13 @@ JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP.microphone[TrackErrors.NO_DATA_FROM_SOURCE]
75 75
  */
76 76
 function promptDisplayName() {
77 77
     let labelKey = 'dialog.enterDisplayName';
78
-    let labelStr = APP.translation.translateString(labelKey);
79
-    let defaultNickMsg = APP.translation.translateString("defaultNickname");
80 78
     let message = (
81 79
         `<div class="input-control">
82
-            <label data-i18n="${labelKey}" 
83
-                class="input-control__label">${labelStr}</label>
80
+            <label data-i18n="${labelKey}" class="input-control__label"></label>
84 81
             <input name="displayName" type="text"
85 82
                data-i18n="[placeholder]defaultNickname"
86 83
                class="input-control__input"
87
-               placeholder="${defaultNickMsg}" autofocus>
84
+               autofocus>
88 85
          </div>`
89 86
     );
90 87
 
@@ -166,11 +163,10 @@ UI.notifyGracefulShutdown = function () {
166 163
  * Notify user that reservation error happened.
167 164
  */
168 165
 UI.notifyReservationError = function (code, msg) {
169
-    var title = APP.translation.generateTranslationHTML(
170
-        "dialog.reservationError");
171 166
     var message = APP.translation.generateTranslationHTML(
172 167
         "dialog.reservationErrorMsg", {code: code, msg: msg});
173
-    messageHandler.openDialog(title, message, true, {}, () => false);
168
+    messageHandler.openDialog(
169
+        "dialog.reservationError", message, true, {}, () => false);
174 170
 };
175 171
 
176 172
 /**
@@ -189,9 +185,8 @@ UI.notifyKicked = function () {
189 185
 UI.notifyConferenceDestroyed = function (reason) {
190 186
     //FIXME: use Session Terminated from translation, but
191 187
     // 'reason' text comes from XMPP packet and is not translated
192
-    const title
193
-        = APP.translation.generateTranslationHTML("dialog.sessTerminated");
194
-    messageHandler.openDialog(title, reason, true, {}, () => false);
188
+    messageHandler.openDialog(
189
+        "dialog.sessTerminated", reason, true, {}, () => false);
195 190
 };
196 191
 
197 192
 /**
@@ -919,9 +914,6 @@ UI.setUserAvatarUrl = function (id, url) {
919 914
  * @param {string} stropheErrorMsg raw Strophe error message
920 915
  */
921 916
 UI.notifyConnectionFailed = function (stropheErrorMsg) {
922
-    var title = APP.translation.generateTranslationHTML(
923
-        "dialog.error");
924
-
925 917
     var message;
926 918
     if (stropheErrorMsg) {
927 919
         message = APP.translation.generateTranslationHTML(
@@ -931,7 +923,7 @@ UI.notifyConnectionFailed = function (stropheErrorMsg) {
931 923
             "dialog.connectError");
932 924
     }
933 925
 
934
-    messageHandler.openDialog(title, message, true, {}, () => false);
926
+    messageHandler.openDialog("dialog.error", message, true, {}, () => false);
935 927
 };
936 928
 
937 929
 
@@ -939,13 +931,10 @@ UI.notifyConnectionFailed = function (stropheErrorMsg) {
939 931
  * Notify user that maximum users limit has been reached.
940 932
  */
941 933
 UI.notifyMaxUsersLimitReached = function () {
942
-    var title = APP.translation.generateTranslationHTML(
943
-        "dialog.error");
944
-
945 934
     var message = APP.translation.generateTranslationHTML(
946 935
             "dialog.maxUsersLimitReached");
947 936
 
948
-    messageHandler.openDialog(title, message, true, {}, () => false);
937
+    messageHandler.openDialog("dialog.error", message, true, {}, () => false);
949 938
 };
950 939
 
951 940
 /**
@@ -1112,14 +1101,11 @@ UI.notifyFocusDisconnected = function (focus, retrySec) {
1112 1101
  * Notify user that focus left the conference so page should be reloaded.
1113 1102
  */
1114 1103
 UI.notifyFocusLeft = function () {
1115
-    let title = APP.translation.generateTranslationHTML(
1116
-        'dialog.serviceUnavailable'
1117
-    );
1118 1104
     let msg = APP.translation.generateTranslationHTML(
1119 1105
         'dialog.jicofoUnavailable'
1120 1106
     );
1121 1107
     messageHandler.openDialog(
1122
-        title,
1108
+        'dialog.serviceUnavailable',
1123 1109
         msg,
1124 1110
         true, // persistent
1125 1111
         [{title: 'retry'}],
@@ -1284,8 +1270,6 @@ UI.showDeviceErrorDialog = function (micError, cameraError) {
1284 1270
         }
1285 1271
     }
1286 1272
 
1287
-    let title = getTitleKey();
1288
-    let titleMsg = `<span data-i18n="${title}"></span>`;
1289 1273
     let cameraJitsiTrackErrorMsg = cameraError
1290 1274
         ? JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP.camera[cameraError.name]
1291 1275
         : undefined;
@@ -1339,7 +1323,7 @@ UI.showDeviceErrorDialog = function (micError, cameraError) {
1339 1323
     deviceErrorDialog && deviceErrorDialog.close();
1340 1324
 
1341 1325
     deviceErrorDialog = messageHandler.openDialog(
1342
-        titleMsg,
1326
+        getTitleKey(),
1343 1327
         message,
1344 1328
         false,
1345 1329
         {Ok: true},
@@ -1363,8 +1347,6 @@ UI.showDeviceErrorDialog = function (micError, cameraError) {
1363 1347
         }
1364 1348
     );
1365 1349
 
1366
-    APP.translation.translateElement($(".jqibox"));
1367
-
1368 1350
     function getTitleKey() {
1369 1351
         let title = "dialog.error";
1370 1352
 

+ 1
- 1
modules/UI/authentication/AuthHandler.js 查看文件

@@ -164,7 +164,7 @@ function doXmppAuth (room, lockPassword) {
164 164
                 console.error('Auth on the fly failed', error);
165 165
 
166 166
                 loginDialog.displayError(
167
-                    'connection.GET_SESSION_ID_ERROR', code);
167
+                    'connection.GET_SESSION_ID_ERROR', {code: code});
168 168
             });
169 169
         }, function (err) {
170 170
             loginDialog.displayError(err);

+ 9
- 15
modules/UI/authentication/LoginDialog.js 查看文件

@@ -1,4 +1,4 @@
1
-/* global APP, config */
1
+/* global $, APP, config */
2 2
 
3 3
 /**
4 4
  * Build html for "password required" dialog.
@@ -8,11 +8,8 @@ function getPasswordInputHtml() {
8 8
     let placeholder = config.hosts.authdomain
9 9
         ? "user identity"
10 10
         : "user@domain.net";
11
-    let passRequiredMsg = APP.translation.translateString(
12
-        "dialog.passwordRequired"
13
-    );
14 11
     return `
15
-        <h2 data-i18n="dialog.passwordRequired">${passRequiredMsg}</h2>
12
+        <h2 data-i18n="dialog.passwordRequired"></h2>
16 13
         <input name="username" type="text" placeholder=${placeholder} autofocus>
17 14
         <input name="password" type="password"
18 15
                data-i18n="[placeholder]dialog.userPassword"
@@ -68,7 +65,7 @@ function LoginDialog(successCallback, cancelCallback) {
68 65
         value: true
69 66
     }];
70 67
     let finishedButtons = [{
71
-        title: APP.translation.translateString('dialog.retry'),
68
+        title: APP.translation.generateTranslationHTML('dialog.retry'),
72 69
         value: 'retry'
73 70
     }];
74 71
 
@@ -129,16 +126,16 @@ function LoginDialog(successCallback, cancelCallback) {
129 126
      * Displays error message in 'finished' state which allows either to cancel
130 127
      * or retry.
131 128
      * @param messageKey the key to the message to be displayed.
132
-     * @param code the code error (optional)
129
+     * @param options the options to the error message (optional)
133 130
      */
134
-    this.displayError = function (messageKey, code) {
131
+    this.displayError = function (messageKey, options) {
135 132
 
136 133
         let finishedState = connDialog.getState('finished');
137 134
 
138 135
         let errorMessageElem = finishedState.find('#errorMessage');
139 136
         errorMessageElem.attr("data-i18n", messageKey);
140
-        errorMessageElem.text(
141
-            APP.translation.translateString(messageKey) + (code ? code : ''));
137
+
138
+        APP.translation.translateElement($(errorMessageElem), options);
142 139
 
143 140
         connDialog.goToState('finished');
144 141
     };
@@ -152,7 +149,7 @@ function LoginDialog(successCallback, cancelCallback) {
152 149
 
153 150
         let connectionStatus = connectingState.find('#connectionStatus');
154 151
         connectionStatus.attr("data-i18n", messageKey);
155
-        connectionStatus.text(APP.translation.translateString(messageKey));
152
+        APP.translation.translateElement($(connectionStatus));
156 153
     };
157 154
 
158 155
     /**
@@ -206,9 +203,6 @@ export default {
206 203
      * @returns dialog
207 204
      */
208 205
     showAuthRequiredDialog: function (roomName, onAuthNow) {
209
-        var title = APP.translation.generateTranslationHTML(
210
-            "dialog.WaitingForHost"
211
-        );
212 206
         var msg = APP.translation.generateTranslationHTML(
213 207
             "dialog.WaitForHostMsg", {room: roomName}
214 208
         );
@@ -219,7 +213,7 @@ export default {
219 213
         var buttons = [{title: buttonTxt, value: "authNow"}];
220 214
 
221 215
         return APP.UI.messageHandler.openDialog(
222
-            title,
216
+            "dialog.WaitingForHost",
223 217
             msg,
224 218
             true,
225 219
             buttons,

+ 3
- 5
modules/UI/feedback/FeedbackWindow.js 查看文件

@@ -35,7 +35,6 @@ function toggleStars(starCount) {
35 35
  * @returns {string} the contructed html string
36 36
  */
37 37
 function createRateFeedbackHTML() {
38
-    let feedbackHelp = APP.translation.translateString('dialog.feedbackHelp');
39 38
 
40 39
     let starClassName = (interfaceConfig.ENABLE_FEEDBACK_ANIMATION)
41 40
         ? "icon-star-full shake-rotate"
@@ -67,8 +66,7 @@ function createRateFeedbackHTML() {
67 66
                 </div>
68 67
             </div>
69 68
             <div class="details">
70
-                <textarea id="feedbackTextArea" class="input-control__input"
71
-                    placeholder="${ feedbackHelp }" 
69
+                <textarea id="feedbackTextArea" class="input-control__input" 
72 70
                     data-i18n="[placeholder]dialog.feedbackHelp"></textarea>
73 71
             </div>
74 72
         </form>`;
@@ -148,10 +146,10 @@ export default class Dialog {
148 146
         this.submitted = false;
149 147
         this.onCloseCallback = function() {};
150 148
 
151
-        this.setDefoulOptions();
149
+        this.setDefaulOptions();
152 150
     }
153 151
 
154
-    setDefoulOptions() {
152
+    setDefaulOptions() {
155 153
         var self = this;
156 154
 
157 155
         this.options = {

+ 1
- 3
modules/UI/invite/AskForPassword.js 查看文件

@@ -8,12 +8,10 @@ import UIUtil from '../util/UIUtil';
8 8
  */
9 9
 export default function askForPassword () {
10 10
     let titleKey = "dialog.passwordRequired";
11
-    let passMsg = APP.translation.translateString("dialog.password");
12 11
     let msgString = `
13 12
         <input name="lockKey" type="text"
14 13
                data-i18n="[placeholder]dialog.password"
15
-               placeholder="${passMsg}" autofocus>
16
-    `;
14
+               autofocus>`;
17 15
     return new Promise(function (resolve, reject) {
18 16
         APP.UI.messageHandler.openTwoButtonDialog({
19 17
             titleKey,

+ 4
- 2
modules/UI/invite/Invite.js 查看文件

@@ -203,8 +203,10 @@ class Invite {
203 203
      * @param isLocked
204 204
      */
205 205
     setLockedFromElsewhere(isLocked) {
206
-        let oldLockState = this.roomLocker.lockedElsewhere;
207
-        if (oldLockState !== isLocked) {
206
+        // isLocked can be 1, true or false
207
+        let newLockState = (isLocked === 1) || isLocked;
208
+        let oldLockState = this.roomLocker.isLocked;
209
+        if (oldLockState !== newLockState) {
208 210
             this.roomLocker.lockedElsewhere = isLocked;
209 211
             APP.UI.emitEvent(UIEvents.TOGGLE_ROOM_LOCK);
210 212
             this.updateView();

+ 28
- 55
modules/UI/invite/InviteDialogView.js 查看文件

@@ -15,20 +15,15 @@ const States = {
15 15
  */
16 16
 export default class InviteDialogView {
17 17
     constructor(model) {
18
-        let inviteAttributesKey = 'inviteUrlDefaultMsg';
19
-        let title = APP.translation.translateString(inviteAttributesKey);
20
-
21 18
         this.unlockHint = "unlockHint";
22 19
         this.lockHint = "lockHint";
23 20
         this.model = model;
24 21
 
25 22
         if (this.model.inviteUrl === null) {
26
-            this.inviteAttributes = (
27
-                `data-i18n="[value]${inviteAttributesKey}" value="${title}"`
28
-            );
23
+            this.inviteAttributes = `data-i18n="[value]inviteUrlDefaultMsg"`;
29 24
         } else {
30
-            let encodedInviteUrl = this.model.getEncodedInviteUrl();
31
-            this.inviteAttributes = `value="${encodedInviteUrl}"`;
25
+            this.inviteAttributes
26
+                = `value="${this.model.getEncodedInviteUrl()}"`;
32 27
         }
33 28
 
34 29
         this.initDialog();
@@ -99,8 +94,7 @@ export default class InviteDialogView {
99 94
         let {
100 95
             titleKey
101 96
         } = this.dialog;
102
-        let doneKey = 'dialog.done';
103
-        let doneMsg = APP.translation.translateString(doneKey);
97
+        let doneMsg = APP.translation.generateTranslationHTML('dialog.done');
104 98
         let states = {};
105 99
         let buttons = {};
106 100
         buttons[`${doneMsg}`] = true;
@@ -124,36 +118,24 @@ export default class InviteDialogView {
124 118
      * @returns {string}
125 119
      */
126 120
     getShareLinkBlock() {
127
-        let copyKey = 'dialog.copy';
128
-        let copyText = APP.translation.translateString(copyKey);
129
-        let roomLockDescKey = 'dialog.roomLocked';
130
-        let roomLockDesc = APP.translation.translateString(roomLockDescKey);
131
-        let roomUnlockKey = 'roomUnlocked';
132
-        let roomUnlock = APP.translation.translateString(roomUnlockKey);
133 121
         let classes = 'button-control button-control_light copyInviteLink';
134
-        let title = APP.translation.translateString(this.dialog.titleKey);
135 122
         return (
136 123
             `<div class="input-control">
137 124
                 <label class="input-control__label" for="inviteLinkRef"
138
-                    data-i18n="${this.dialog.titleKey}">
139
-                        ${title}
140
-                </label>
125
+                    data-i18n="${this.dialog.titleKey}"></label>
141 126
                 <div class="input-control__container">
142 127
                     <input class="input-control__input inviteLink"
143 128
                            id="inviteLinkRef" type="text"
144 129
                            ${this.inviteAttributes} readonly>
145
-                    <button data-i18n="${copyKey}"
146
-                            class="${classes}">
147
-                        ${copyText}
148
-                    </button>
130
+                    <button data-i18n="dialog.copy" class="${classes}"></button>
149 131
                 </div>
150 132
                 <p class="input-control__hint ${this.lockHint}">
151 133
                    <span class="icon-security-locked"></span>
152
-                   <span data-i18n="${roomLockDescKey}">${roomLockDesc}</span>
134
+                   <span data-i18n="dialog.roomLocked"></span>
153 135
                 </p>
154 136
                 <p class="input-control__hint ${this.unlockHint}">
155 137
                    <span class="icon-security"></span>
156
-                   <span data-i18n="${roomUnlockKey}">${roomUnlock}</span>
138
+                   <span data-i18n="roomUnlocked"></span>
157 139
                 </p>
158 140
             </div>`
159 141
         );
@@ -164,27 +146,20 @@ export default class InviteDialogView {
164 146
      * @returns {string}
165 147
      */
166 148
     getAddPasswordBlock() {
167
-        let addPassKey = 'dialog.addPassword';
168
-        let addPassText = APP.translation.translateString(addPassKey);
169
-        let addKey = 'dialog.add';
170
-        let addText = APP.translation.translateString(addKey);
171
-        let hintKey = 'dialog.createPassword';
172
-        let hintMsg = APP.translation.translateString(hintKey);
173 149
         let html;
174 150
 
175 151
         if (this.model.isModerator) {
176 152
             html = (`
177 153
             <div class="input-control">
178
-                <label class="input-control__label
179
-                       for="newPasswordInput"
180
-                       data-i18n="${addPassKey}">${addPassText}</label>
154
+                <label class="input-control__label"
155
+                       for="newPasswordInput" data-i18n="dialog.addPassword">
156
+               </label>
181 157
                 <div class="input-control__container">
182 158
                     <input class="input-control__input" id="newPasswordInput"
183
-                           type="text" placeholder="${hintMsg}">
159
+                           type="text" data-i18n="dialog.createPassword">
184 160
                     <button id="addPasswordBtn" id="inviteDialogAddPassword"
185
-                            disabled data-i18n="${addKey}"
161
+                            disabled data-i18n="dialog.add"
186 162
                             class="button-control button-control_light">
187
-                        ${addText}
188 163
                     </button>
189 164
                 </div>
190 165
             </div>
@@ -202,22 +177,16 @@ export default class InviteDialogView {
202 177
      */
203 178
     getPasswordBlock() {
204 179
         let { password, isModerator } = this.model;
205
-        let removePassKey = 'dialog.removePassword';
206
-        let removePassText = APP.translation.translateString(removePassKey);
207
-        let currentPassKey = 'dialog.currentPassword';
208
-        let currentPassText = APP.translation.translateString(currentPassKey);
209
-        let passwordKey = "dialog.passwordLabel";
210
-        let passwordText = APP.translation.translateString(passwordKey);
211 180
 
212 181
         if (isModerator) {
213 182
             return (`
214 183
                 <div class="input-control">
215 184
                     <label class="input-control__label"
216
-                           data-i18n="${passwordKey}">${passwordText}</label>
185
+                           data-i18n="dialog.passwordLabel"></label>
217 186
                     <div class="input-control__container">
218
-                        <p class="input-control__text"
219
-                           data-i18n="${currentPassKey}">
220
-                            ${currentPassText}
187
+                        <p>
188
+                            <span class="input-control__text"
189
+                                  data-i18n="dialog.currentPassword"></span>
221 190
                             <span id="inviteDialogPassword"
222 191
                                   class="input-control__em">
223 192
                                 ${password}
@@ -225,9 +194,7 @@ export default class InviteDialogView {
225 194
                         </p>
226 195
                         <a class="link input-control__right"
227 196
                            id="inviteDialogRemovePassword"
228
-                           data-i18n="${removePassKey}">
229
-                           ${removePassText}
230
-                       </a>
197
+                           data-i18n="dialog.removePassword"></a>
231 198
                     </div>
232 199
                 </div>
233 200
             `);
@@ -349,11 +316,17 @@ export default class InviteDialogView {
349 316
      */
350 317
     updateView() {
351 318
         let pass = this.model.getPassword();
352
-        if (!pass)
353
-            pass = APP.translation.translateString("passwordSetRemotely");
319
+        if (this.model.getRoomLocker().lockedElsewhere || !pass)
320
+            $('#inviteDialogPassword').attr("data-i18n", "passwordSetRemotely");
321
+        else
322
+            $('#inviteDialogPassword').text(pass);
323
+
324
+        // if we are not moderator we cannot remove password
325
+        if (APP.conference.isModerator)
326
+            $('#inviteDialogRemovePassword').show();
327
+        else
328
+            $('#inviteDialogRemovePassword').hide();
354 329
 
355
-        $('#inviteDialogPassword').attr("data-i18n", "passwordSetRemotely");
356
-        $('#inviteDialogPassword').text(pass);
357 330
         $('#newPasswordInput').val('');
358 331
         this.disableAddPassIfInputEmpty();
359 332
 

+ 6
- 10
modules/UI/recording/Recording.js 查看文件

@@ -41,8 +41,6 @@ function _isRecordingButtonEnabled() {
41 41
  * @returns {Promise}
42 42
  */
43 43
 function _requestLiveStreamId() {
44
-    const msg = APP.translation.generateTranslationHTML("dialog.liveStreaming");
45
-    const token = APP.translation.translateString("dialog.streamKey");
46 44
     const cancelButton
47 45
         = APP.translation.generateTranslationHTML("dialog.Cancel");
48 46
     const backButton = APP.translation.generateTranslationHTML("dialog.Back");
@@ -55,11 +53,11 @@ function _requestLiveStreamId() {
55 53
     return new Promise(function (resolve, reject) {
56 54
         dialog = APP.UI.messageHandler.openDialogWithStates({
57 55
             state0: {
58
-                title: msg,
56
+                titleKey: "dialog.liveStreaming",
59 57
                 html:
60 58
                     `<input name="streamId" type="text"
61 59
                     data-i18n="[placeholder]dialog.streamKey"
62
-                    placeholder="${token}" autofocus>`,
60
+                    autofocus>`,
63 61
                 persistent: false,
64 62
                 buttons: [
65 63
                     {title: cancelButton, value: false},
@@ -89,7 +87,7 @@ function _requestLiveStreamId() {
89 87
             },
90 88
 
91 89
             state1: {
92
-                title: msg,
90
+                titleKey: "dialog.liveStreaming",
93 91
                 html: streamIdRequired,
94 92
                 persistent: false,
95 93
                 buttons: [
@@ -122,11 +120,10 @@ function _requestLiveStreamId() {
122 120
  */
123 121
 function _requestRecordingToken () {
124 122
     let titleKey = "dialog.recordingToken";
125
-    let token = APP.translation.translateString("dialog.token");
126 123
     let messageString = (
127 124
         `<input name="recordingToken" type="text"
128 125
                 data-i18n="[placeholder]dialog.token"
129
-                placeholder="${token}" autofocus>`
126
+                autofocus>`
130 127
     );
131 128
     return new Promise(function (resolve, reject) {
132 129
         dialog = APP.UI.messageHandler.openTwoButtonDialog({
@@ -297,8 +294,7 @@ var Recording = {
297 294
 
298 295
         selector.addClass(this.baseClass);
299 296
         selector.attr("data-i18n", "[content]" + this.recordingButtonTooltip);
300
-        selector.attr("content",
301
-            APP.translation.translateString(this.recordingButtonTooltip));
297
+        APP.translation.translateElement(selector);
302 298
 
303 299
         var self = this;
304 300
         selector.click(function () {
@@ -505,7 +501,7 @@ var Recording = {
505 501
         moveToCorner(labelSelector, !isCentered);
506 502
 
507 503
         labelTextSelector.attr("data-i18n", textKey);
508
-        labelTextSelector.text(APP.translation.translateString(textKey));
504
+        APP.translation.translateElement(labelSelector);
509 505
     },
510 506
 
511 507
     /**

+ 4
- 8
modules/UI/shared_video/SharedVideo.js 查看文件

@@ -750,24 +750,19 @@ function showStopVideoPropmpt() {
750 750
  */
751 751
 function requestVideoLink() {
752 752
     let i18n = APP.translation;
753
-    const title = i18n.generateTranslationHTML("dialog.shareVideoTitle");
754 753
     const cancelButton = i18n.generateTranslationHTML("dialog.Cancel");
755 754
     const shareButton = i18n.generateTranslationHTML("dialog.Share");
756 755
     const backButton = i18n.generateTranslationHTML("dialog.Back");
757 756
     const linkError
758 757
         = i18n.generateTranslationHTML("dialog.shareVideoLinkError");
759
-    const i18nOptions = {url: defaultSharedVideoLink};
760
-    const defaultUrl = i18n.translateString("defaultLink", i18nOptions);
761 758
 
762 759
     return new Promise(function (resolve, reject) {
763 760
         dialog = APP.UI.messageHandler.openDialogWithStates({
764 761
             state0: {
765
-                title: title,
762
+                titleKey: "dialog.shareVideoTitle",
766 763
                 html:  `
767 764
                     <input name="sharedVideoUrl" type="text"
768 765
                            data-i18n="[placeholder]defaultLink"
769
-                           data-i18n-options="${JSON.stringify(i18nOptions)}"
770
-                           placeholder="${defaultUrl}"
771 766
                            autofocus>`,
772 767
                 persistent: false,
773 768
                 buttons: [
@@ -802,7 +797,7 @@ function requestVideoLink() {
802 797
             },
803 798
 
804 799
             state1: {
805
-                title: title,
800
+                titleKey: "dialog.shareVideoTitle",
806 801
                 html: linkError,
807 802
                 persistent: false,
808 803
                 buttons: [
@@ -825,7 +820,8 @@ function requestVideoLink() {
825 820
             close: function () {
826 821
                 dialog = null;
827 822
             }
823
+        }, {
824
+            url: defaultSharedVideoLink
828 825
         });
829
-
830 826
     });
831 827
 }

+ 10
- 16
modules/UI/side_pannels/contactlist/ContactListView.js 查看文件

@@ -21,9 +21,8 @@ function updateNumberOfParticipants(delta) {
21 21
 
22 22
     $("#numberOfParticipants").text(numberOfContacts);
23 23
 
24
-    $("#contacts_container>div.title").text(
25
-        APP.translation.translateString("contactlist")
26
-            + ' (' + numberOfContacts + ')');
24
+    APP.translation.translateElement(
25
+        $("#contacts_container>div.title"), {pcount: numberOfContacts});
27 26
 }
28 27
 
29 28
 /**
@@ -50,7 +49,6 @@ function createDisplayNameParagraph(key, displayName) {
50 49
         p.innerHTML = displayName;
51 50
     } else if(key) {
52 51
         p.setAttribute("data-i18n",key);
53
-        p.innerHTML = APP.translation.translateString(key);
54 52
     }
55 53
 
56 54
     return p;
@@ -82,10 +80,11 @@ var ContactListView = {
82 80
      */
83 81
     addInviteButton() {
84 82
         let container = document.getElementById('contacts_container');
85
-        let title = container.firstElementChild;
86 83
 
87
-        let htmlLayout =  this.getInviteButtonLayout();
88
-        title.insertAdjacentHTML('afterend', htmlLayout);
84
+        container.firstElementChild // this is the title
85
+            .insertAdjacentHTML('afterend', this.getInviteButtonLayout());
86
+
87
+        APP.translation.translateElement($(container));
89 88
         $(document).on('click', '#addParticipantsBtn', () => {
90 89
             APP.UI.emitEvent(UIEvents.INVITE_CLICKED);
91 90
         });
@@ -97,32 +96,26 @@ var ContactListView = {
97 96
         let classes = 'button-control button-control_primary';
98 97
         classes += ' button-control_full-width';
99 98
         let key = 'addParticipants';
100
-        let text = APP.translation.translateString(key);
101 99
 
102 100
         let lockedHtml = this.getLockDescriptionLayout(this.lockKey);
103 101
         let unlockedHtml = this.getLockDescriptionLayout(this.unlockKey);
104 102
 
105
-        let html = (
103
+        return (
106 104
             `<div class="sideToolbarBlock first">
107 105
                 <button id="addParticipantsBtn" 
108 106
                          data-i18n="${key}" 
109
-                         class="${classes}">
110
-                    ${text}
111
-                </button>
107
+                         class="${classes}"></button>
112 108
                 <div>
113 109
                     ${lockedHtml}
114 110
                     ${unlockedHtml}
115 111
                 </div>
116 112
             </div>`);
117
-
118
-        return html;
119 113
     },
120 114
     /**
121 115
      * Adds layout for lock description
122 116
      */
123 117
     getLockDescriptionLayout(key) {
124 118
         let classes = "input-control__hint input-control_full-width";
125
-        let description = APP.translation.translateString(key);
126 119
         let padlockSuffix = '';
127 120
         if (key === this.lockKey) {
128 121
             padlockSuffix = '-locked';
@@ -130,7 +123,7 @@ var ContactListView = {
130 123
 
131 124
         return `<p id="contactList${key}" class="${classes}">
132 125
                     <span class="icon-security${padlockSuffix}"></span>
133
-                    <span data-i18n="${key}">${description}</span>
126
+                    <span data-i18n="${key}"></span>
134 127
                 </p>`;
135 128
     },
136 129
     /**
@@ -198,6 +191,7 @@ var ContactListView = {
198 191
             createDisplayNameParagraph(
199 192
                 isLocal ? interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME : null,
200 193
                 isLocal ? null : interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME));
194
+        APP.translation.translateElement($(newContact));
201 195
 
202 196
         if (APP.conference.isLocalId(id)) {
203 197
             contactlist.prepend(newContact);

+ 4
- 2
modules/UI/util/JitsiPopover.js 查看文件

@@ -1,4 +1,4 @@
1
-/* global $ */
1
+/* global $, APP */
2 2
 var JitsiPopover = (function () {
3 3
     /**
4 4
      * Constructs new JitsiPopover and attaches it to the element
@@ -76,7 +76,9 @@ var JitsiPopover = (function () {
76 76
      */
77 77
     JitsiPopover.prototype.createPopover = function () {
78 78
         $("body").append(this.template);
79
-        $(".jitsipopover > .jitsipopover-content").html(this.options.content);
79
+        let popoverElem = $(".jitsipopover > .jitsipopover-content");
80
+        popoverElem.html(this.options.content);
81
+        APP.translation.translateElement(popoverElem);
80 82
         var self = this;
81 83
         $(".jitsipopover").on("mouseenter", function () {
82 84
             self.popoverIsHovered = true;

+ 20
- 14
modules/UI/util/MessageHandler.js 查看文件

@@ -45,7 +45,7 @@ var messageHandler = {
45 45
             message = APP.translation.generateTranslationHTML(messageKey);
46 46
         }
47 47
 
48
-        return $.prompt(message, {
48
+        let dialog = $.prompt(message, {
49 49
             title: this._getFormattedTitleString(titleKey),
50 50
             persistent: false,
51 51
             promptspeed: 0,
@@ -55,6 +55,8 @@ var messageHandler = {
55 55
                     closeFunction(e, v, m, f);
56 56
             }
57 57
         });
58
+        APP.translation.translateElement(dialog);
59
+        return dialog;
58 60
     },
59 61
     /**
60 62
      * Shows a message to the user with two buttons: first is given as a
@@ -137,6 +139,7 @@ var messageHandler = {
137 139
                 }
138 140
             }
139 141
         });
142
+        APP.translation.translateElement(twoButtonDialog);
140 143
         return twoButtonDialog;
141 144
     },
142 145
 
@@ -177,7 +180,9 @@ var messageHandler = {
177 180
             args.closeText = '';
178 181
         }
179 182
 
180
-        return new Impromptu(msgString, args);
183
+        let dialog = new Impromptu(msgString, args);
184
+        APP.translation.translateElement(dialog.getPrompt());
185
+        return dialog;
181 186
     },
182 187
 
183 188
     /**
@@ -189,7 +194,6 @@ var messageHandler = {
189 194
         let $titleString = $('<h2>');
190 195
         $titleString.addClass('aui-dialog2-header-main');
191 196
         $titleString.attr('data-i18n',titleKey);
192
-        $titleString.append(APP.translation.translateString(titleKey));
193 197
         return $('<div>').append($titleString).html();
194 198
     },
195 199
 
@@ -224,8 +228,10 @@ var messageHandler = {
224 228
      * Shows a dialog with different states to the user.
225 229
      *
226 230
      * @param statesObject object containing all the states of the dialog.
231
+     * @param options impromptu options
232
+     * @param translateOptions options passed to translation
227 233
      */
228
-    openDialogWithStates: function (statesObject, options) {
234
+    openDialogWithStates: function (statesObject, options, translateOptions) {
229 235
         if (!popupEnabled)
230 236
             return;
231 237
         let { classes, size } = options;
@@ -240,7 +246,9 @@ var messageHandler = {
240 246
                     = this._getFormattedTitleString(currentState.titleKey);
241 247
             }
242 248
         }
243
-        return new Impromptu(statesObject, options);
249
+        let dialog = new Impromptu(statesObject, options);
250
+        APP.translation.translateElement(dialog.getPrompt(), translateOptions);
251
+        return dialog;
244 252
     },
245 253
 
246 254
     /**
@@ -329,20 +337,18 @@ var messageHandler = {
329 337
         if (displayName) {
330 338
             displayNameSpan += ">" + UIUtil.escapeHtml(displayName);
331 339
         } else {
332
-            displayNameSpan += "data-i18n='" + displayNameKey +
333
-                "'>" + APP.translation.translateString(displayNameKey);
340
+            displayNameSpan += "data-i18n='" + displayNameKey + "'>";
334 341
         }
335 342
         displayNameSpan += "</span>";
336
-        return toastr.info(
343
+        let element = toastr.info(
337 344
             displayNameSpan + '<br>' +
338 345
             '<span class=' + cls + ' data-i18n="' + messageKey + '"' +
339 346
                 (messageArguments?
340
-                    " data-i18n-options='" + JSON.stringify(messageArguments)
341
-                        + "'"
342
-                    : "") + ">" +
343
-            APP.translation.translateString(messageKey,
344
-                messageArguments) +
345
-            '</span>', null, options);
347
+                    " data-i18n-options='"
348
+                        + JSON.stringify(messageArguments) + "'"
349
+                    : "") + "></span>", null, options);
350
+        APP.translation.translateElement(element);
351
+        return element;
346 352
     },
347 353
 
348 354
     /**

+ 13
- 34
modules/UI/videolayout/ConnectionIndicator.js 查看文件

@@ -1,4 +1,4 @@
1
-/* global APP, $, config */
1
+/* global $, config */
2 2
 /* jshint -W101 */
3 3
 import JitsiPopover from "../util/JitsiPopover";
4 4
 import VideoLayout from "./VideoLayout";
@@ -63,8 +63,6 @@ ConnectionIndicator.getStringFromArray = function (array) {
63 63
 ConnectionIndicator.prototype.generateText = function () {
64 64
     var downloadBitrate, uploadBitrate, packetLoss, i;
65 65
 
66
-    var translate = APP.translation.translateString;
67
-
68 66
     if(this.bitrate === null) {
69 67
         downloadBitrate = "N/A";
70 68
         uploadBitrate = "N/A";
@@ -97,18 +95,15 @@ ConnectionIndicator.prototype.generateText = function () {
97 95
 
98 96
     var result = "<table style='width:100%'>" +
99 97
         "<tr>" +
100
-        "<td><span class='jitsipopover_blue' data-i18n='connectionindicator.bitrate'>" +
101
-        translate("connectionindicator.bitrate") + "</span></td>" +
98
+        "<td><span class='jitsipopover_blue' data-i18n='connectionindicator.bitrate'></span></td>" +
102 99
         "<td><span class='jitsipopover_green'>&darr;</span>" +
103 100
         downloadBitrate + " <span class='jitsipopover_orange'>&uarr;</span>" +
104 101
         uploadBitrate + "</td>" +
105 102
         "</tr><tr>" +
106
-        "<td><span class='jitsipopover_blue' data-i18n='connectionindicator.packetloss'>" +
107
-        translate("connectionindicator.packetloss") + "</span></td>" +
103
+        "<td><span class='jitsipopover_blue' data-i18n='connectionindicator.packetloss'></span></td>" +
108 104
         "<td>" + packetLoss  + "</td>" +
109 105
         "</tr><tr>" +
110
-        "<td><span class='jitsipopover_blue' data-i18n='connectionindicator.resolution'>" +
111
-        translate("connectionindicator.resolution") + "</span></td>" +
106
+        "<td><span class='jitsipopover_blue' data-i18n='connectionindicator.resolution'></span></td>" +
112 107
         "<td>" + resolutionStr + "</td></tr></table>";
113 108
 
114 109
     if(this.videoContainer.videoSpanId == "localVideoContainer") {
@@ -117,9 +112,7 @@ ConnectionIndicator.prototype.generateText = function () {
117 112
             // FIXME: we do not know local id when this text is generated
118 113
             //this.id + "')\"  data-i18n='connectionindicator." +
119 114
             "local')\"  data-i18n='connectionindicator." +
120
-                (this.showMoreValue ? "less" : "more") + "'>" +
121
-            translate("connectionindicator." + (this.showMoreValue ? "less" : "more")) +
122
-            "</div><br />";
115
+                (this.showMoreValue ? "less" : "more") + "'></div><br />";
123 116
     }
124 117
 
125 118
     if (this.showMoreValue) {
@@ -139,8 +132,7 @@ ConnectionIndicator.prototype.generateText = function () {
139 132
         if (!this.transport || this.transport.length === 0) {
140 133
             transport = "<tr>" +
141 134
                 "<td><span class='jitsipopover_blue' " +
142
-                "data-i18n='connectionindicator.address'>" +
143
-                translate("connectionindicator.address") + "</span></td>" +
135
+                "data-i18n='connectionindicator.address'></span></td>" +
144 136
                 "<td> N/A</td></tr>";
145 137
         } else {
146 138
             var data = {remoteIP: [], localIP:[], remotePort:[], localPort:[]};
@@ -173,18 +165,13 @@ ConnectionIndicator.prototype.generateText = function () {
173 165
             var localTransport =
174 166
                 "<tr><td><span class='jitsipopover_blue' data-i18n='" +
175 167
                 local_address_key +"' data-i18n-options='" +
176
-                    JSON.stringify({count: data.localIP.length}) + "'>" +
177
-                    translate(local_address_key, {count: data.localIP.length}) +
178
-                    "</span></td><td> " +
168
+                    JSON.stringify({count: data.localIP.length}) + "'></span></td><td> " +
179 169
                 ConnectionIndicator.getStringFromArray(data.localIP) +
180 170
                 "</td></tr>";
181 171
             transport =
182 172
                 "<tr><td><span class='jitsipopover_blue' data-i18n='" +
183 173
                 remote_address_key + "' data-i18n-options='" +
184
-                    JSON.stringify({count: data.remoteIP.length}) + "'>" +
185
-                    translate(remote_address_key,
186
-                        {count: data.remoteIP.length}) +
187
-                    "</span></td><td> " +
174
+                    JSON.stringify({count: data.remoteIP.length}) + "'></span></td><td> " +
188 175
                 ConnectionIndicator.getStringFromArray(data.remoteIP) +
189 176
                 "</td></tr>";
190 177
 
@@ -195,16 +182,12 @@ ConnectionIndicator.prototype.generateText = function () {
195 182
                 "<td>" +
196 183
                 "<span class='jitsipopover_blue' data-i18n='" + key_remote +
197 184
                 "' data-i18n-options='" +
198
-                JSON.stringify({count: this.transport.length}) + "'>" +
199
-                translate(key_remote, {count: this.transport.length}) +
200
-                "</span></td><td>";
185
+                JSON.stringify({count: this.transport.length}) + "'></span></td><td>";
201 186
             localTransport += "<tr>" +
202 187
                 "<td>" +
203 188
                 "<span class='jitsipopover_blue' data-i18n='" + key_local +
204 189
                 "' data-i18n-options='" +
205
-                JSON.stringify({count: this.transport.length}) + "'>" +
206
-                translate(key_local, {count: this.transport.length}) +
207
-                "</span></td><td>";
190
+                JSON.stringify({count: this.transport.length}) + "'></span></td><td>";
208 191
 
209 192
             transport +=
210 193
                 ConnectionIndicator.getStringFromArray(data.remotePort);
@@ -213,8 +196,7 @@ ConnectionIndicator.prototype.generateText = function () {
213 196
             transport += "</td></tr>";
214 197
             transport += localTransport + "</td></tr>";
215 198
             transport +="<tr>" +
216
-                "<td><span class='jitsipopover_blue' data-i18n='connectionindicator.transport'>" +
217
-                translate("connectionindicator.transport") + "</span></td>" +
199
+                "<td><span class='jitsipopover_blue' data-i18n='connectionindicator.transport'></span></td>" +
218 200
                 "<td>" + this.transport[0].type + "</td></tr>";
219 201
 
220 202
         }
@@ -222,8 +204,7 @@ ConnectionIndicator.prototype.generateText = function () {
222 204
         result += "<table  style='width:100%'>" +
223 205
             "<tr>" +
224 206
             "<td>" +
225
-            "<span class='jitsipopover_blue' data-i18n='connectionindicator.bandwidth'>" +
226
-            translate("connectionindicator.bandwidth") + "</span>" +
207
+            "<span class='jitsipopover_blue' data-i18n='connectionindicator.bandwidth'></span>" +
227 208
             "</td><td>" +
228 209
             "<span class='jitsipopover_green'>&darr;</span>" +
229 210
             downloadBandwidth +
@@ -266,8 +247,7 @@ ConnectionIndicator.prototype.create = function () {
266 247
         this.connectionIndicatorContainer);
267 248
     this.popover = new JitsiPopover(
268 249
         $("#" + this.videoContainer.videoSpanId + " > .connectionindicator"),
269
-        {content: "<div class=\"connection_info\" data-i18n='connectionindicator.na'>" +
270
-            APP.translation.translateString("connectionindicator.na") + "</div>",
250
+        {content: "<div class=\"connection_info\" data-i18n='connectionindicator.na'></div>",
271 251
             skin: "black"});
272 252
 
273 253
     // override popover show method to make sure we will update the content
@@ -381,7 +361,6 @@ ConnectionIndicator.prototype.updatePopoverData = function (force) {
381 361
         this.popover.updateContent(
382 362
             `<div class="connection_info">${this.generateText()}</div>`
383 363
         );
384
-        APP.translation.translateElement($(".connection_info"));
385 364
     }
386 365
 };
387 366
 

+ 5
- 3
modules/UI/videolayout/LargeVideoManager.js 查看文件

@@ -379,9 +379,10 @@ export default class LargeVideoManager {
379 379
      */
380 380
     _setRemoteConnectionMessage (msgKey, msgOptions) {
381 381
         if (msgKey) {
382
-            let text = APP.translation.translateString(msgKey, msgOptions);
383 382
             $('#remoteConnectionMessage')
384
-                .attr("data-i18n", msgKey).text(text);
383
+                .attr("data-i18n", msgKey)
384
+                .attr("data-i18n-options", JSON.stringify(msgOptions));
385
+            APP.translation.translateElement($('#remoteConnectionMessage'));
385 386
         }
386 387
 
387 388
         this.videoContainer.positionRemoteConnectionMessage();
@@ -400,7 +401,8 @@ export default class LargeVideoManager {
400 401
     _setLocalConnectionMessage (msgKey, msgOptions) {
401 402
         $('#localConnectionMessage')
402 403
             .attr("data-i18n", msgKey)
403
-            .text(APP.translation.translateString(msgKey, msgOptions));
404
+            .attr("data-i18n-options", JSON.stringify(msgOptions));
405
+        APP.translation.translateElement($('#localConnectionMessage'));
404 406
     }
405 407
 
406 408
     /**

+ 4
- 5
modules/UI/videolayout/LocalVideo.js 查看文件

@@ -96,14 +96,12 @@ LocalVideo.prototype.setDisplayName = function(displayName) {
96 96
             editableText.value = displayName;
97 97
         }
98 98
 
99
-        var defaultNickname = APP.translation.translateString(
100
-            "defaultNickname", {name: "Jane Pink"});
101 99
         editableText.setAttribute('style', 'display:none;');
102
-        editableText.setAttribute('data-18n',
100
+        editableText.setAttribute('data-i18n',
103 101
             '[placeholder]defaultNickname');
104 102
         editableText.setAttribute("data-i18n-options",
105 103
             JSON.stringify({name: "Jane Pink"}));
106
-        editableText.setAttribute("placeholder", defaultNickname);
104
+        APP.translation.translateElement($(editableText));
107 105
 
108 106
         this.container
109 107
             .querySelector('.videocontainer__toolbar')
@@ -253,7 +251,8 @@ LocalVideo.prototype._buildContextMenu = function () {
253 251
         events: {
254 252
             show : function(options){
255 253
                 options.items.flip.name =
256
-                    APP.translation.translateString("videothumbnail.flip");
254
+                    APP.translation.generateTranslationHTML(
255
+                        "videothumbnail.flip");
257 256
             }
258 257
         }
259 258
     });

+ 5
- 12
modules/UI/videolayout/RemoteVideo.js 查看文件

@@ -109,16 +109,10 @@ RemoteVideo.prototype._generatePopupContent = function () {
109 109
     var mutedIndicator = "<i class='icon-mic-disabled'></i>";
110 110
 
111 111
     var doMuteHTML = mutedIndicator +
112
-        " <div " +
113
-        "data-i18n='videothumbnail.domute'>" +
114
-        APP.translation.translateString("videothumbnail.domute") +
115
-        "</div>";
112
+        " <div data-i18n='videothumbnail.domute'></div>";
116 113
 
117 114
     var mutedHTML = mutedIndicator +
118
-        " <div " +
119
-        "data-i18n='videothumbnail.muted'>" +
120
-        APP.translation.translateString("videothumbnail.muted") +
121
-        "</div>";
115
+        " <div data-i18n='videothumbnail.muted'></div>";
122 116
 
123 117
     muteLinkItem.id = "mutelink_" + this.id;
124 118
 
@@ -150,10 +144,7 @@ RemoteVideo.prototype._generatePopupContent = function () {
150 144
     var ejectMenuItem = document.createElement('li');
151 145
     var ejectLinkItem = document.createElement('a');
152 146
 
153
-    var ejectText = "<div " +
154
-        "data-i18n='videothumbnail.kick'>" +
155
-        APP.translation.translateString("videothumbnail.kick") +
156
-        "</div>";
147
+    var ejectText = "<div data-i18n='videothumbnail.kick'></div>";
157 148
 
158 149
     ejectLinkItem.className = 'ejectlink';
159 150
     ejectLinkItem.innerHTML = ejectIndicator + ' ' + ejectText;
@@ -167,6 +158,8 @@ RemoteVideo.prototype._generatePopupContent = function () {
167 158
     ejectMenuItem.appendChild(ejectLinkItem);
168 159
     popupmenuElement.appendChild(ejectMenuItem);
169 160
 
161
+    APP.translation.translateElement($(popupmenuElement));
162
+
170 163
     return popupmenuElement;
171 164
 };
172 165
 

+ 1
- 2
modules/keyboardshortcut/keyboardshortcut.js 查看文件

@@ -190,8 +190,7 @@ var KeyboardShortcut = {
190 190
         let descriptionClass = "shortcuts-list__description";
191 191
         descriptionElement.className = descriptionClass;
192 192
         descriptionElement.setAttribute("data-i18n", shortcutDescriptionKey);
193
-        descriptionElement.innerHTML
194
-            = APP.translation.translateString(shortcutDescriptionKey);
193
+        APP.translation.translateElement($(descriptionElement));
195 194
 
196 195
         listElement.appendChild(spanElement);
197 196
         listElement.appendChild(descriptionElement);

+ 4
- 7
modules/translation/translation.js 查看文件

@@ -89,9 +89,6 @@ module.exports = {
89 89
 
90 90
         i18n.init(options, initCompleted);
91 91
     },
92
-    translateString: function (key, options) {
93
-        return i18n.t(key, options);
94
-    },
95 92
     setLanguage: function (lang) {
96 93
         if(!lang)
97 94
             lang = DEFAULT_LANG;
@@ -100,16 +97,16 @@ module.exports = {
100 97
     getCurrentLanguage: function () {
101 98
         return i18n.lng();
102 99
     },
103
-    translateElement: function (selector) {
104
-        selector.i18n();
100
+    translateElement: function (selector, options) {
101
+        selector.i18n(options);
105 102
     },
106 103
     generateTranslationHTML: function (key, options) {
107 104
         var str = "<span data-i18n=\"" + key + "\"";
108 105
         if (options) {
109
-            str += " data-i18n-options=\"" + JSON.stringify(options) + "\"";
106
+            str += " data-i18n-options='" + JSON.stringify(options) + "'";
110 107
         }
111 108
         str += ">";
112
-        str += this.translateString(key, options);
109
+        str += i18n.t(key, options);
113 110
         str += "</span>";
114 111
         return str;
115 112
 

Loading…
取消
儲存