diff --git a/bin/language_scan.js b/bin/language_scan.js index 2a92fded1..5ab25428c 100755 --- a/bin/language_scan.js +++ b/bin/language_scan.js @@ -2,15 +2,20 @@ /* Scans for strings that may be in English in each app, and outputs a list of strings that have been found. -Early work towards internationalisation. -See https://github.com/espruino/BangleApps/issues/136 +See https://github.com/espruino/BangleApps/issues/1311 */ +var IGNORE_STRINGS = [ + "5x5", + "5x9Numeric7Seg", + "Vector" +]; + var BASEDIR = __dirname+"/../"; Espruino = require(BASEDIR+"core/lib/espruinotools.js"); var fs = require("fs"); - var APPSDIR = BASEDIR+"apps/"; + function ERROR(s) { console.error("ERROR: "+s); process.exit(1); @@ -18,6 +23,9 @@ function ERROR(s) { function WARN(s) { console.log("Warning: "+s); } +function log(s) { + console.log(s); +} var appsFile, apps; try { @@ -39,31 +47,65 @@ function isNotString(s) { if (s.endsWith(".json") || s.endsWith(".img")) return true; // a filename if (s.endsWith("=")) return true; // probably base64 if (s.startsWith("BTN")) return true; // button name + if (IGNORE_STRINGS.includes(s)) return true; // one we know to ignore return false; } -var textStrings = []; +// A string that *could* be translated? +var untranslatedStrings = []; +// Strings that are marked with 'LANG' +var translatedStrings = []; -console.log("Scanning..."); +console.log("Scanning apps..."); apps.forEach((app,appIdx) => { var appDir = APPSDIR+app.id+"/"; app.storage.forEach((file) => { if (!file.url || !file.name.endsWith(".js")) return; var fileContents = fs.readFileSync(appDir+file.url).toString(); var lex = Espruino.Core.Utils.getLexer(fileContents); + var lastIdx = 0; var tok = lex.next(); while (tok!==undefined) { + var previousString = fileContents.substring(lastIdx, tok.startIdx); if (tok.type=="STRING") { - if (!isNotString(tok.value)) { - //console.log(tok.str); - if (!textStrings.includes(tok.value)) - textStrings.push(tok.value); + if (previousString.includes("/*LANG*/")) { // translated! + if (!translatedStrings.includes(tok.value)) + translatedStrings.push(tok.value); + } else { // untranslated - potential to translate? + if (!isNotString(tok.value)) { + if (!untranslatedStrings.includes(tok.value)) + untranslatedStrings.push(tok.value); + } } } + lastIdx = tok.endIdx; tok = lex.next(); } }); }); -console.log("Done"); -textStrings.sort(); -console.log(textStrings.join("\n")); +untranslatedStrings.sort(); +translatedStrings.sort(); + +var report = ""; +/* // too many! don't output these +log("Possible English Strings that could be translated"); +log("================================================================="); +log(""); +log("Add these to IGNORE_STRINGS if the don't make sense..."); +log(""); +log(untranslatedStrings.map(s=>JSON.stringify(s)).join(",\n"));*/ +log(""); + +var languages = JSON.parse(fs.readFileSync(BASEDIR+"/lang/index.json").toString()); +languages.forEach(language => { + console.log("Scanning "+language.code); + log(language.code); + log("=========="); + var translations = JSON.parse(fs.readFileSync(BASEDIR+"/lang/"+language.url).toString()); + translatedStrings.forEach(str => { + if (!translations.GLOBAL[str]) + console.log(`Missing translation for ${JSON.stringify(str)}`); + }); + log(""); +}); +console.log("Done."); diff --git a/index.html b/index.html index e22a1f9e7..7e818ee72 100644 --- a/index.html +++ b/index.html @@ -141,6 +141,11 @@ Always update time when we connect +
+   Translations (BETA - more info) +
diff --git a/lang/en_GB.json b/lang/en_GB.json index e85fe8029..6bf1279d1 100644 --- a/lang/en_GB.json +++ b/lang/en_GB.json @@ -1,9 +1,9 @@ { "//":"British English language translations - the default strings in apps are all english anyway, so no need to have translations for most things", "GLOBAL": { - "//":"Translations that apply for all apps", + "//":"Translations that apply for all apps" }, "alarm": { - "//":"App-specific overrides", + "//":"App-specific overrides" } } diff --git a/loader.js b/loader.js index a0c280634..0355ea89c 100644 --- a/loader.js +++ b/loader.js @@ -164,6 +164,48 @@ window.addEventListener('load', (event) => { showToast("App Install failed, "+err,"error"); }); }); + + // Load language list + httpGet("lang/index.json").then(languagesJSON=>{ + var languages; + try { + languages = JSON.parse(languagesJSON); + } catch(e) { + console.error("lang/index.json Corrupted", e); + } + + function reloadLanguage() { + LANGUAGE = undefined; + if (SETTINGS.language) { + var language = languages.find(l=>l.code==SETTINGS.language); + if (language) { + var langURL = "lang/"+language.url; + httpGet(langURL).then(languageJSON=>{ + try { + LANGUAGE = JSON.parse(languageJSON); + console.log(`${langURL} loaded successfully`); + } catch(e) { + console.error(`${langURL} Corrupted`, e); + } + }); + } else { + console.error(`Language code ${JSON.stringify(SETTINGS.language)} not found in lang/index.json`); + } + } + } + + var selectLang = document.getElementById("settings-lang"); + console.log(languages); + languages.forEach(lang => { + selectLang.innerHTML += ``; + }); + selectLang.addEventListener("change",event=>{ + SETTINGS.language = event.target.value; + reloadLanguage(); + saveSettings(); + }); + reloadLanguage(); + }); }); function onAppJSONLoaded() {