Skip to content

Commit 5f20083

Browse files
lang: Ensure missing translations still work in English.
1 parent e29328d commit 5f20083

File tree

9 files changed

+61
-46
lines changed

9 files changed

+61
-46
lines changed

editor.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ <h2 id="modal-msg-title"></h2>
439439
<script>
440440
// Call the web_editor function to start the editor running.
441441
var config = {
442-
translate: language,
442+
translate: LANGUAGE,
443443
flags: {
444444
blocks: false,
445445
snippets: true,

js/python-main.js

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,18 @@ everything does.)
88
/*
99
Lazy load JS script files.
1010
*/
11-
function script(url, id) {
11+
function script(url, id, onLoadCallback) {
1212
var s = document.createElement('script');
13-
if(id){
13+
if (id){
1414
s.id = id;
1515
}
1616
s.type = 'text/javascript';
1717
s.async = false;
1818
s.defer = true;
1919
s.src = url;
20+
if (onLoadCallback) {
21+
s.onload = onLoadCallback;
22+
}
2023
var x = document.getElementsByTagName('head')[0];
2124
x.appendChild(s);
2225
}
@@ -283,40 +286,47 @@ function blocks() {
283286
* Allows the Python Editor to display in multiple languages by manipulating
284287
* strings with correct JS language objects.
285288
*/
286-
function translations() {
289+
function translations(baseLanguage) {
287290
'use strict';
288291
// These values must be valid language codes
289292
// https://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
290293
var validLangs = ['en', 'es', 'pl', 'hr', 'zh-HK', 'zh-CN', 'zh-TW'];
291294

295+
// This is the base language that will be extended with the translations.
296+
// It is assumed this translation object (likely 'en') contains all the
297+
// keys the editor needs. By extending this object instead of replacing it
298+
// we ensure this will still contain any keys a translation might not have.
299+
var _baseLanguage = baseLanguage;
300+
var _extendedLang = baseLanguage;
301+
translateEmbedStrings();
302+
292303
/* Replaces DOM script element with the new language js file. */
293-
function updateLang(newLang, callback) {
304+
function updateLang(newLang, successCallback, errorCallback) {
294305
var elementId = 'lang';
295306
var newLangURL = 'lang/' + newLang + '.js';
296307
var endsWithURL = new RegExp(newLangURL + "$");
297-
var runCallback = function() {
298-
translateEmbedStrings(language);
299-
callback(language);
300-
};
301308
if (endsWithURL.test(document.getElementById(elementId).src)) {
302309
// The request newLang is the current one, don't reload js file
303-
return runCallback(language);
310+
return successCallback();
304311
}
305312
// Check for a valid language
306313
if (validLangs.indexOf(newLang) >- 1) {
314+
LANGUAGE = null;
307315
document.getElementById(elementId).remove();
308-
script(newLangURL, elementId);
309-
document.getElementById(elementId).onload = runCallback;
316+
script(newLangURL, elementId, function() {
317+
_extendedLang = $.extend(true, {}, _baseLanguage, LANGUAGE);
318+
translateEmbedStrings();
319+
successCallback(_extendedLang);
320+
});
310321
} else {
311-
// Don't throw an error, but inform the console
312-
runCallback();
313322
console.error('Requested language not available: ' + newLang);
323+
errorCallback();
314324
}
315325
}
316326

317327
/* Replaces the strings already loaded in the DOM, the rest are dynamically loaded. */
318-
function translateEmbedStrings(language) {
319-
var buttons = language['static-strings']['buttons'];
328+
function translateEmbedStrings() {
329+
var buttons = _extendedLang['static-strings']['buttons'];
320330
$('.roundbutton').each(function(object, value) {
321331
var button_id = $(value).attr('id');
322332
$(value).attr('title', buttons[button_id]['title']);
@@ -328,31 +338,34 @@ function translations() {
328338
$(value).children(':last').text(buttons[button_id]['label-close']);
329339
}
330340
});
331-
$('.ace_text-input').attr('aria-label',language['static-strings']['text-editor']['aria-label']);
332-
$('#script-name-label').text(language['static-strings']['script-name']['label']);
333-
$('#request-repl').text(language['webusb']['request-repl']);
334-
$('#request-serial').text(language['webusb']['request-serial']);
335-
var optionsStrings = language['static-strings']['options-dropdown'];
341+
$('.ace_text-input').attr('aria-label', _extendedLang['static-strings']['text-editor']['aria-label']);
342+
$('#script-name-label').text(_extendedLang['static-strings']['script-name']['label']);
343+
$('#request-repl').text(_extendedLang['webusb']['request-repl']);
344+
$('#request-serial').text(_extendedLang['webusb']['request-serial']);
345+
var optionsStrings = _extendedLang['static-strings']['options-dropdown'];
336346
for (var object in optionsStrings) {
337347
$("#" + object).text(optionsStrings[object]);
338348
}
339-
var helpStrings = language['help'];
349+
var helpStrings = _extendedLang['help'];
340350
for (var object in helpStrings) {
341351
if (helpStrings.hasOwnProperty(object)) {
342352
if (object.match(/ver/)) {
343353
$('#' + object).text(helpStrings[object]);
344354
continue;
345355
}
346356
$('#' + object).text(helpStrings[object]['label']);
347-
$('#' + object).attr('title',helpStrings[object]['title']);
357+
$('#' + object).attr('title', helpStrings[object]['title']);
348358
}
349359
}
350-
var languages = language['languages'];
360+
var languages = _extendedLang['languages'];
351361
for (var object in languages) {
352362
if (languages.hasOwnProperty(object)) {
353363
$('#' + object).attr('title',languages[object]['title']);
354364
}
355365
}
366+
// WebUSB flashing modal
367+
$('#flashing-extra-msg').text(_extendedLang['webusb']['flashing-long-msg']);
368+
$('#flashing-title').text(_extendedLang['webusb']['flashing-title']);
356369
}
357370

358371
return {
@@ -373,7 +386,7 @@ function web_editor(config) {
373386
window.EDITOR = pythonEditor('editor', config.microPythonApi);
374387

375388
var BLOCKS = blocks();
376-
var TRANSLATIONS = translations();
389+
var TRANSLATIONS = translations(config.translate);
377390

378391
// Generating MicroPython hex with user code in the filesystem
379392
window.FS = microbitFsWrapper();
@@ -463,7 +476,11 @@ function web_editor(config) {
463476
config.translate = translations;
464477
document.getElementsByTagName('HTML')[0].setAttribute('lang', lang);
465478
$('ul.tree > li > span > a').removeClass('is-selected');
466-
$('#'+lang).addClass('is-selected');
479+
$('#' + lang).addClass('is-selected');
480+
}, function() {
481+
// At the moment we fail silently. If the language request came
482+
// a URL parameter we ignore it, if it came from a menu it will
483+
// be caught by the CI tests
467484
});
468485
}
469486

@@ -710,7 +727,7 @@ function web_editor(config) {
710727
return alert(config.translate.alerts.no_python + '\n\n' +
711728
config.translate.alerts.error + '\n' +
712729
hexImportError.message + '\n' +
713-
config['translate']['alerts']['no_script']);
730+
config.translate.alerts.no_script);
714731
}
715732
}
716733
// Check if imported files includes a main.py file
@@ -1443,8 +1460,7 @@ function web_editor(config) {
14431460
updateMain();
14441461
var freeFsSpace = FS.getStorageRemaining();
14451462
if (freeFsSpace < 0) {
1446-
// TODO: Create new string for translation
1447-
throw Error('There is no storage space left.')
1463+
throw Error(config.translate.alerts.module_out_of_space);
14481464
}
14491465
} catch(e) {
14501466
return alert(config.translate.alerts.error + '\n' + e.message);
@@ -1456,17 +1472,14 @@ function web_editor(config) {
14561472
$('#flashing-overlay-error').html("");
14571473
$("#flashing-info").removeClass('hidden');
14581474
$("#flashing-overlay-container").css("display", "flex");
1459-
// TODO: Translate these string
1460-
$('#flashing-title').text('Flashing code');
1461-
$('#flashing-extra-msg').text('Initial flash might longer, subsequent flashes will be quicker.').hide();
1475+
$('#flashing-extra-msg').hide();
14621476

14631477
var updateProgress = function(progress, longFlash) {
1464-
// TODO: Translate these string
14651478
if (!!longFlash) {
1466-
$('#flashing-title').text(language['webusb']['flashing-title']);
1479+
$('#flashing-title').text(config.translate.webusb['flashing-title']);
14671480
$('#flashing-extra-msg').show()
14681481
} else {
1469-
$('#flashing-title').text('Flashing code');
1482+
$('#flashing-title').text(config.translate.webusb['flashing-title-code']);
14701483
$('#flashing-extra-msg').hide();
14711484
}
14721485
$('#webusb-flashing-progress').val(progress).css('display', 'inline-block');

lang/en.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var language = {
1+
var LANGUAGE = {
22
'code_snippets': {
33
'title': 'Code Snippets',
44
'description': "Code snippets are short blocks of code to re-use in your own programs. There are snippets for most common things you'll want to do using MicroPython.",
@@ -97,6 +97,8 @@ var language = {
9797
'request-repl': 'Send CTRL-C for REPL',
9898
'request-serial': 'Send CTRL-D to reset',
9999
'flashing-title': 'Flashing MicroPython',
100+
'flashing-title-code': 'Flashing code',
101+
'flashing-long-msg': 'Initial flash might take longer, subsequent flashes will be quicker.',
100102
'download': 'Download Hex'
101103
},
102104
'load': {

lang/es.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var language = {
1+
var LANGUAGE = {
22
"code_snippets": {
33
"title": "Fragmentos de Codigo",
44
"description": "Los fragmentos de código son bloques cortos de código para reutilizar en tus programas. Hay fragmentos de las cosas más comunes que querrás hacer con MicroPython.",
@@ -37,7 +37,7 @@ var language = {
3737
"load_code": "¡Uy! No se pudo añadir el código en el archivo hex.",
3838
"unrecognised_hex": "Lo sentimos, no pudimos reconocer este archivo",
3939
"snippets": "Los fragmentos están deshabilitados cuando blockly está habilitado.",
40-
"error": "Error:\n",
40+
"error": "Error:",
4141
"empty": "El archivo Python no tiene ningún contenido.",
4242
"no_python": "No se pudo encontrar código válido de Python en el archivo hex.",
4343
"no_script": "El archivo hex no contiene un script de Python.",

lang/hr.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var language = {
1+
var LANGUAGE = {
22
"code_snippets": {
33
"title": "Ulomci kôda",
44
"description": "Ulomci kôda su kratki blokovi koda koje možeš više puta koristiti u svojim programima. Postoje ulomci za najčešće stvari koje se izvode pomoću programa MicroPython.",
@@ -37,7 +37,7 @@ var language = {
3737
"load_code": "Uh! Kôd se ne može upisati u .hex datoteku.",
3838
"unrecognised_hex": "Nažalost ne prepoznajemo datoteku",
3939
"snippets": "Ulomci su isključeni kada je uključena \"blockly\" biblioteka.",
40-
"error": "Greška:\n",
40+
"error": "Greška:",
4141
"empty": "Pythonova datoteka je prazna.",
4242
"no_python": "U .hex datoteci nije pronađen važeći Pythonov kôd.",
4343
"no_script": "U hex datoteci nije pronađen Pythonov programski kôd.",

lang/pl.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var language = {
1+
var LANGUAGE = {
22
"code_snippets": {
33
"title": "Fragmenty Kodu",
44
"description": "Fragmenty kodu są krótkimi blokami kodu do użycia we własnych programach. Znajdują się fragmenty dla zwykłych rzeczy, które będziemy chcieli zrobić za pomocą MicroPython.",
@@ -37,7 +37,7 @@ var language = {
3737
"load_code": "Ups! Nie można załadować kodu do pliku hex.",
3838
"unrecognised_hex": "Przepraszamy, nie mogliśmy rozpoznać tego pliku ",
3939
"snippets": "Fragmenty są wyłączone, gdy blockly jest włączony.",
40-
"error": "Błąd:\n",
40+
"error": "Błąd:",
4141
"empty": "Plik Pythona nie zawiera żadnego kodu.",
4242
"no_python": "Nie znaleziono poprawnego kodu Pythona w pliku hex.",
4343
"no_script": "Plik hex nie zawiera skyrptu Pythona.",

lang/zh-CN.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var language = {
1+
var LANGUAGE = {
22
"code_snippets": {
33
"title": "代码段",
44
"description": "代码片段是在您自己的程序中重复使用的短代码块,这是使用MicroPython时最常见的一些代码片段。",

lang/zh-HK.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var language = {
1+
var LANGUAGE = {
22
"code_snippets": {
33
"title": "代碼段",
44
"description": "程式碼片段是在您自己的程序中重複使用的短代碼塊,這是使用MicroPython時最常見的一些程式碼片段。",

lang/zh-TW.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var language = {
1+
var LANGUAGE = {
22
"code_snippets": {
33
"title": "程式碼片段",
44
"description": "程式碼片段(Code snippets)可以讓你在編程中快速使用代碼,這裡提供 MicroPython 裡最常見的一些。",
@@ -37,7 +37,7 @@ var language = {
3737
"load_code": "哎呀!無法將代碼載入到十六進位檔案中。",
3838
"unrecognised_hex": "抱歉,我們無法識別這個檔案",
3939
"snippets": "當 blockly 啟用時無法使用程式碼片段。",
40-
"error": "錯誤:\n",
40+
"error": "錯誤:",
4141
"empty": "這個 Python 檔案沒有任何內容。",
4242
"no_python": "在 hex 檔中找不到有效的 Python 程式碼。",
4343
"no_script": "Hex 檔的內容不包含 Python 腳本。",

0 commit comments

Comments
 (0)