traduzioni 4 lingue e catalogo razze portati dai sorgenti Flutter; asset foto, icone dall'artwork originale, test node

This commit is contained in:
Carlo Baratto
2026-10-09 09:02:41 +02:00
parent 0ef017cbab
commit b1ee0c78b5
21 changed files with 982 additions and 41 deletions
+85
View File
@@ -0,0 +1,85 @@
// Banchi di prova delle traduzioni (node, fuori dal pacchetto RPM).
// node tests/i18n.test.js
// Verifica che i quattro cataloghi abbiano le stesse chiavi dell'app Flutter,
// che i segnaposto '{}' siano conservati e che t() li sostituisca come fa il
// TranslationService originale.
var I18N = require("../qml/js/i18n.js");
var CATALOG = require("../qml/js/catalog.js");
var failures = 0;
function check(name, got, expected) {
var ok = JSON.stringify(got) === JSON.stringify(expected);
if (!ok) failures++;
console.log((ok ? "OK " : "FAIL ") + name + " got=" + JSON.stringify(got)
+ (ok ? "" : " expected=" + JSON.stringify(expected)));
}
var S = I18N.HF_STRINGS;
check("quattro lingue", I18N.availableLanguages(), ["de", "en", "fr", "it"]);
// stesse chiavi in tutte le lingue (contratto fra i cataloghi)
var enKeys = Object.keys(S.en).sort();
["it", "fr", "de"].forEach(function (lang) {
var keys = Object.keys(S[lang]).sort();
var missing = enKeys.filter(function (k) { return keys.indexOf(k) === -1; });
var extra = keys.filter(function (k) { return enKeys.indexOf(k) === -1; });
check(lang + ": stesse chiavi dell'inglese (" + enKeys.length + ")", [missing, extra], [[], []]);
});
// nessuna traduzione vuota
["en", "it", "fr", "de"].forEach(function (lang) {
var empty = enKeys.filter(function (k) { return !String(S[lang][k] || "").trim(); });
check(lang + ": nessuna voce vuota", empty, []);
});
// segnaposto coerenti fra le lingue
enKeys.forEach(function (k) {
var n = (String(S.en[k]).match(/\{\}/g) || []).length;
["it", "fr", "de"].forEach(function (lang) {
var m = (String(S[lang][k]).match(/\{\}/g) || []).length;
if (m !== n) {
failures++;
console.log("FAIL segnaposto in '" + k + "' (" + lang + "): " + m + " invece di " + n);
}
});
});
console.log("OK segnaposto '{}' coerenti in tutte le lingue");
// t(): sostituzione, array, fallback
check("t() senza segnaposto", I18N.t("new_order", null, "it"), "Nuovo ordine");
check("t() con un argomento", I18N.t("in_days", "3", "it").indexOf("3") >= 0, true);
check("t() con array", I18N.t("share_order_msg", ["Marans", "2", "28/04/2026"], "en").indexOf("Marans") >= 0, true);
check("t() lingua sconosciuta -> inglese", I18N.t("new_order", null, "xx"), S.en.new_order);
check("t() chiave sconosciuta -> chiave", I18N.t("chiave_inesistente", null, "it"), "chiave_inesistente");
// il testo con a capo e' una vera nuova riga (in main.dart e' '\n')
check("newline reale (no_breeds_sel)",
S.it.no_breeds_sel.indexOf("\n") > 0, true);
check("nessun backslash-n letterale nel testo",
S.it.no_breeds_sel.indexOf("\\n") === -1, true);
// contratto: nessuna chiave resta non tradotta (l'app originale, senza
// fallback, mostrava la chiave stessa: in francese "name_generic").
// L'inglese e' escluso: li' la chiave 'hens' ha come testo "hens", parola vera.
["it", "fr", "de"].forEach(function (lang) {
var leaked = enKeys.filter(function (k) { return I18N.t(k, null, lang) === k; });
check(lang + ": nessuna chiave grezza a schermo", leaked, []);
});
// catalogo razze
var ids = CATALOG.HF_BREEDS.map(function (b) { return b.id; });
check("7 razze nel catalogo", ids.length, 7);
check("le razze dello store ci sono",
["marans", "araucana", "olive", "livorno", "sussex", "australorp", "generic"].every(function (id) {
return ids.indexOf(id) >= 0;
}), true);
check("nome/descrizione sono chiavi tradotte", CATALOG.HF_BREEDS.every(function (b) {
return S.en[b.name] !== undefined && S.en[b.description] !== undefined && S.en[b.eggColor] !== undefined;
}), true);
check("breedFromId sconosciuto -> null", CATALOG.breedFromId("nope"), null);
check("percorso foto installata", CATALOG.HF_BREEDS[0].asset,
"/usr/share/harbour-henflow/breeds/marans.jpg");
console.log(failures === 0 ? "\ntutti i controlli superati" : "\n" + failures + " controlli falliti");
process.exit(failures === 0 ? 0 : 1);