Veröffentlichte Quellen
Quellen als ZIP herunterladen
CH-J Tools
Durchsuchen Sie Verzeichnisse und Dateien einer bestimmten Anwendungsausgabe.
CH-J / Server Manager
406 Dateien
core-20261024T135205Z-7c487d719de2
Hinzugefügt: · Erstellt:
1
"use strict";3
// The bundled plugins written in Czech translate through ui/i18n.js (Czech texts are the keys). Every key used in4
// index.html (data-i18n*) and every literal t("…")/k("…") key in index.js needs an English and a German text with the same5
// {placeholders}, and no Czech text may stay outside the catalog.6
const test = require("node:test");7
const assert = require("node:assert/strict");8
const fs = require("node:fs");9
const path = require("node:path");11
const ROOT = path.join(__dirname, "../src/main/firstPartyPlugins");12
const PLUGINS = ["chj.log-viewer", "chj.key-generator", "chj.nginx-manager", "chj.system-monitor", "chj.file-manager", "chj.users"];13
const CZECH = /[ěščřžýáíéůúťďňĚŠČŘŽÝÁÍÉŮÚŤĎŇ]/;14
const placeholders = (text) => [...String(text).matchAll(/\{(\w+)\}/g)].map((match) => match[1]).sort();15
const decode = (text) => text.replace(/"/g, "\"").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");17
function usedKeys(ui) {18
const html = fs.readFileSync(path.join(ui, "index.html"), "utf8");19
const js = fs.readFileSync(path.join(ui, "index.js"), "utf8");20
const keys = new Set();21
for (const match of html.matchAll(/data-i18n(?:-placeholder|-title|-aria-label)?="([^"]*)"/g)) keys.add(decode(match[1]));22
for (const match of js.matchAll(/\b[tk]\(\s*("(?:[^"\\]|\\.)*")/g)) keys.add(JSON.parse(match[1]));23
return { html, js, keys };24
}26
for (const plugin of PLUGINS) {27
test(`${plugin}: every UI text has English and German translations`, () => {28
const ui = path.join(ROOT, plugin, "0.0.1/ui");29
const { catalogs, createI18n } = require(path.join(ui, "i18n.js"));30
const { html, js, keys } = usedKeys(ui);31
assert.ok(keys.size > 0);32
for (const key of keys) {33
for (const language of ["en", "de"]) {34
const value = catalogs[language][key];35
assert.equal(typeof value, "string", `${language} missing: ${key}`);36
assert.equal(CZECH.test(value), false, `${language} still Czech: ${key}`);37
assert.deepEqual(placeholders(value), placeholders(key), `${language} placeholders: ${key}`);38
}39
}40
assert.match(html, /<script src="i18n\.js"><\/script>\s*<script src="index\.js">/);41
// Czech in index.html only as data-i18n keys, as the text of such elements or in attributes they translate.42
const strippedHtml = html.replace(/<([a-z][\w-]*)([^>]*)>([^<]*)/gi, (whole, tag, attributes, text) => {43
let kept = attributes;44
for (const attribute of ["placeholder", "title", "aria-label"]) {45
if (new RegExp(`\\sdata-i18n-${attribute}="`).test(kept)) kept = kept.replace(new RegExp(`\\s${attribute}="[^"]*"`), "");46
}47
kept = kept.replace(/\sdata-i18n(?:-[\w-]+)?="[^"]*"/g, "");48
return `<${tag}${kept}>${/\sdata-i18n="/.test(attributes) ? "" : text}`;49
});50
assert.deepEqual(strippedHtml.split("\n").filter((line) => CZECH.test(line)), [], "untranslated Czech in index.html");51
// Czech in index.js only inside t("…")/k("…") keys or comments.52
const stray = js.split("\n").filter((line) => !/^\s*\/\//.test(line))53
.map((line) => line.replace(/\b[tk]\(\s*"(?:[^"\\]|\\.)*"/g, "t(\"\""))54
.filter((line) => CZECH.test(line));55
assert.deepEqual(stray, []);56
const i18n = createI18n("en");57
assert.equal(i18n.getLanguage(), "en");58
assert.equal(createI18n("fr").getLanguage(), "en", "unsupported languages fall back to English");59
assert.equal(createI18n("cs").t([...keys][0]), [...keys][0], "Czech keys are shown unchanged in Czech");60
});61
}SHA-256
6273fafe04c88dad29f17d1aa5d48b9ecdb2659df013ed1d816674513cf056fdCH-J Proprietary Software License 1.14 · Die Quellen werden unter der CH-J Proprietary Software License 1.14 bereitgestellt. Ihre Verfügbarkeit ändert die Lizenzbedingungen nicht und gewährt keine zusätzlichen Rechte.
SHA-256 des Archivs
476ed8aef0f1e96a5acdf223127b6692acdf4492eeaf5d0816b6e2a634fbbda6