traduzioni 4 lingue e catalogo razze portati dai sorgenti Flutter; asset foto, icone dall'artwork originale, test node
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Genera qml/js/i18n.js e qml/js/catalog.js dai sorgenti Flutter di Henflow.
|
||||
|
||||
- i18n.js: le 4 mappe di traduzione (it/en/fr/de, 111 chiavi) estratte
|
||||
verbatim da lib/app_language.dart + la funzione t(key, arg, lang).
|
||||
- catalog.js: le 7 razze di lib/models/breed_catalog.dart con il path delle
|
||||
foto installate nel datadir dell'app.
|
||||
|
||||
I file generati sono ES5 (motore QML di Qt 5.6) con guard module.exports.
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
|
||||
SRC = "/home/kaneda/workspace/henflow-flutter"
|
||||
DST = "/home/kaneda/workspace/harbour-henflow/qml/js"
|
||||
|
||||
LANGS = ["it", "en", "fr", "de"]
|
||||
|
||||
|
||||
def dart_unescape(s):
|
||||
out = []
|
||||
i = 0
|
||||
while i < len(s):
|
||||
c = s[i]
|
||||
if c == "\\" and i + 1 < len(s):
|
||||
n = s[i + 1]
|
||||
out.append({"n": "\n", "t": "\t", "r": "\r", "'": "'", '"': '"', "\\": "\\"}.get(n, n))
|
||||
i += 2
|
||||
else:
|
||||
out.append(c)
|
||||
i += 1
|
||||
return "".join(out)
|
||||
|
||||
|
||||
def extract_strings():
|
||||
# NB: la tabella VIVA e' quella inline in main.dart (126 chiavi).
|
||||
# app_language.dart e' una copia vecchia (111 chiavi, usata solo da
|
||||
# lib/dialogs/confirm_dialogs.dart) con gli a capo scritti '\\n' invece
|
||||
# che '\n': estrarla produrrebbe testi con un backslash visibile.
|
||||
text = open(os.path.join(SRC, "lib/main.dart"), encoding="utf-8").read()
|
||||
data = {}
|
||||
for lang in LANGS:
|
||||
m = re.search(r"AppLanguage\.%s:\s*\{(.*?)\n \}," % lang, text, re.S)
|
||||
if not m:
|
||||
raise SystemExit("blocco %s non trovato" % lang)
|
||||
pairs = re.findall(r"'([a-z0-9_]+)':\s*'((?:[^'\\]|\\.)*)'", m.group(1))
|
||||
data[lang] = {k: dart_unescape(v) for k, v in pairs}
|
||||
print("%s: %d chiavi" % (lang, len(data[lang])))
|
||||
|
||||
# L'app non ha fallback: t() su chiave assente restituisce la CHIAVE
|
||||
# (in francese la razza "generic" usciva come "name_generic"). Nel porting
|
||||
# i buchi si colmano con l'inglese e si segnalano qui.
|
||||
keys = set(data["en"])
|
||||
for lang in LANGS:
|
||||
if lang == "en":
|
||||
continue
|
||||
missing = sorted(keys - set(data[lang]))
|
||||
extra = sorted(set(data[lang]) - keys)
|
||||
if extra:
|
||||
raise SystemExit("%s: chiavi non presenti in inglese: %s" % (lang, extra))
|
||||
for k in missing:
|
||||
data[lang][k] = data["en"][k]
|
||||
if missing:
|
||||
print(" %s: colmate dall'inglese %d chiavi: %s" % (lang, len(missing), missing))
|
||||
return data, len(keys)
|
||||
|
||||
|
||||
def extract_catalog():
|
||||
text = open(os.path.join(SRC, "lib/models/breed_catalog.dart"), encoding="utf-8").read()
|
||||
items = []
|
||||
for block in re.findall(r"BreedCatalogItem\((.*?)\)\s*,?\s*(?=BreedCatalogItem|\];)", text, re.S):
|
||||
def field(name):
|
||||
m = re.search(r"%s:\s*'([^']*)'" % name, block)
|
||||
return m.group(1) if m else None
|
||||
def number(name):
|
||||
m = re.search(r"%s:\s*([0-9.]+)" % name, block)
|
||||
return float(m.group(1)) if m else None
|
||||
asset = field("assetPath")
|
||||
items.append({
|
||||
"id": field("id"),
|
||||
"name": field("name"),
|
||||
"description": field("description"),
|
||||
"eggColor": field("eggColor"),
|
||||
"eggsPerHenPerDay": number("eggsPerHenPerDay"),
|
||||
"asset": "/usr/share/harbour-henflow/" + asset.replace("assets/", ""),
|
||||
})
|
||||
return items
|
||||
|
||||
|
||||
def js_value(v, indent=4):
|
||||
return json.dumps(v, ensure_ascii=False, indent=indent)
|
||||
|
||||
|
||||
def main():
|
||||
data, nkeys = extract_strings()
|
||||
os.makedirs(DST, exist_ok=True)
|
||||
|
||||
header = """// GENERATO da tools/gen_from_flutter.py — non modificare a mano.
|
||||
// Traduzioni estratte verbatim da lib/app_language.dart dell'app Flutter
|
||||
// (%d chiavi x %d lingue). ES5: il motore QML di Qt 5.6 non supporta
|
||||
// let/const, arrow function, template literal.
|
||||
|
||||
var HF_STRINGS = %s;
|
||||
|
||||
// t(chiave, argomento, lingua): come il TranslationService dell'app,
|
||||
// riempie il primo '{}' (o i successivi, con un array). Fallback: inglese,
|
||||
// poi la chiave stessa.
|
||||
function t(key, arg, lang) {
|
||||
var table = HF_STRINGS[lang] || HF_STRINGS.en;
|
||||
var text = table[key];
|
||||
if (text === undefined) text = HF_STRINGS.en[key];
|
||||
if (text === undefined) return key;
|
||||
if (arg !== undefined && arg !== null) {
|
||||
if (Object.prototype.toString.call(arg) === "[object Array]") {
|
||||
for (var i = 0; i < arg.length; i++) {
|
||||
text = text.replace("{}", String(arg[i]));
|
||||
}
|
||||
} else {
|
||||
text = text.replace("{}", String(arg));
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function availableLanguages() {
|
||||
var out = [];
|
||||
for (var k in HF_STRINGS) {
|
||||
if (HF_STRINGS.hasOwnProperty(k)) out.push(k);
|
||||
}
|
||||
return out.sort();
|
||||
}
|
||||
|
||||
if (typeof module !== "undefined" && module.exports) {
|
||||
module.exports = {
|
||||
HF_STRINGS: HF_STRINGS,
|
||||
t: t,
|
||||
availableLanguages: availableLanguages
|
||||
};
|
||||
}
|
||||
""" % (nkeys, len(LANGS), js_value(data))
|
||||
|
||||
open(os.path.join(DST, "i18n.js"), "w", encoding="utf-8").write(header)
|
||||
|
||||
catalog = extract_catalog()
|
||||
cat_js = """// GENERATO da tools/gen_from_flutter.py — non modificare a mano.
|
||||
// Catalogo razze da lib/models/breed_catalog.dart: nome e descrizione sono
|
||||
// chiavi di traduzione, le foto stanno nel datadir dell'app.
|
||||
|
||||
var HF_BREEDS = %s;
|
||||
|
||||
function breedFromId(id) {
|
||||
for (var i = 0; i < HF_BREEDS.length; i++) {
|
||||
if (HF_BREEDS[i].id === id) return HF_BREEDS[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof module !== "undefined" && module.exports) {
|
||||
module.exports = { HF_BREEDS: HF_BREEDS, breedFromId: breedFromId };
|
||||
}
|
||||
""" % json.dumps(catalog, ensure_ascii=False, indent=4)
|
||||
open(os.path.join(DST, "catalog.js"), "w", encoding="utf-8").write(cat_js)
|
||||
|
||||
print("scritti: i18n.js (%d chiavi x %d lingue), catalog.js (%d razze)"
|
||||
% (nkeys, len(LANGS), len(catalog)))
|
||||
for c in catalog:
|
||||
print(" ", c["id"], "->", c["asset"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user