Upload via GUI (396 Dateien)

This commit is contained in:
2026-11-04 07:55:43 +00:00
parent 58a8fab9f5
commit d1aae0f2ce
8 changed files with 931 additions and 3 deletions
@@ -0,0 +1,79 @@
<?php
declare(strict_types=1);
/**
* Prüft die englische Fassung der Plugin-Webseite (plugin-webseite/inc/i18n.php, lang/en.json): Texte, Attribute, Muster mit Zahlen und
* wechselnden Teilen, Auslassen von <code>, Sprachwahl über Cookie und Adresse, und dass die Verwaltung vollständig übersetzt ist.
*/
putenv('PLUGIN_SITE_CONFIG=' . sys_get_temp_dir() . '/gibtesnicht.php');
putenv('PLUGIN_SITE_STORAGE=' . sys_get_temp_dir() . '/deskhub-site-i18n-' . bin2hex(random_bytes(3)));
require_once __DIR__ . '/fixtures/paths.php';
$siteDir = website_dir_or_skip('plugin_website_i18n');
require_once $siteDir . '/inc/i18n.php';
$failures = [];
$check = function (bool $ok, string $what) use (&$failures): void {
if (!$ok) $failures[] = $what;
};
$tr = fn(string $html) => site_translate_html($html, 'en');
// Einfache Texte, Leerraum bleibt erhalten
$check($tr("<h1>\n Pakete\n</h1>") === "<h1>\n Packages\n</h1>", 'Text wird übersetzt, Leerraum bleibt');
$check($tr('<p>Übersicht &amp; mehr</p>') === '<p>Übersicht &amp; mehr</p>', 'Unbekannter Text bleibt deutsch');
$check($tr('<button>Veröffentlichen</button>') === '<button>Publish</button>', 'Knopf wird übersetzt');
// Attribute
$check($tr('<input placeholder="Bild entfernen" title="Entfernen" value="Entfernen">') === '<input placeholder="Remove image" title="Remove" value="Entfernen">', 'placeholder und title werden übersetzt, value nicht');
$check($tr('<form data-confirm="Version wirklich entfernen?"></form>') === '<form data-confirm="Really remove this version?"></form>', 'data-confirm wird übersetzt');
// Muster
$check($tr('<span>2 veröffentlicht</span>') === '<span>2 published</span>', 'Muster mit Zahl');
$check($tr('<span>0 Downloads</span>') === '<span>0 downloads</span>', 'Muster {#} Downloads');
$check($tr('<span>aktuell 1.3.0</span>') === '<span>current 1.3.0</span>', 'Muster mit wechselndem Teil');
$check($tr('<title>Übersicht · Verwaltung · DeskHub Plugins und Themen</title>') === '<title>Übersicht · Verwaltung · DeskHub Plugins und Themen</title>', 'Titel mit unbekanntem Namen bleibt unverändert');
$check($tr('<title>Pakete · Verwaltung · DeskHub Plugins und Themes</title>') === '<title>Packages · Administration · DeskHub plugins and themes</title>', 'Seitentitel: gefundener Teil wird mitübersetzt');
$check($tr('<div class="alert okbox">Veröffentlicht: authentik 1.2.5 (signiert).</div>') === '<div class="alert okbox">Published: authentik 1.2.5 (signed).</div>', 'Meldung mit zwei wechselnden Teilen in der Reihenfolge {1} {2}');
$check($tr('<div>Version 1.0.0 existiert bereits. Bitte eine neue Versionsnummer verwenden, veröffentlichte Versionen bleiben unverändert.</div>') === '<div>Version 1.0.0 already exists. Please use a new version number, published versions stay unchanged.</div>', 'Fehlermeldung mit Versionsnummer');
$check($tr('<div>Das Paket ist leer oder größer als 10 MB.</div>') === '<div>The package is empty or larger than 10 MB.</div>', 'Muster mit Zahl in der Mitte');
// Code, Skripte und Vorformatiertes bleiben unberührt; Text daneben wird übersetzt
$check($tr('<p>ZIP-Datei mit <code>plugin.json</code> bzw. Theme-CSS</p>') === '<p>ZIP file with <code>plugin.json</code> or theme CSS</p>', 'Teile neben <code> werden übersetzt, <code> bleibt');
$check($tr('<code>Pakete</code><pre>Pakete</pre><script>var a = "Pakete";</script>') === '<code>Pakete</code><pre>Pakete</pre><script>var a = "Pakete";</script>', '<code>, <pre> und <script> bleiben unverändert');
// Sicherheit: Übersetzung wird maskiert, Eingaben bleiben, wie sie sind
$check(str_contains($tr('<p>Name</p>'), 'Name'), 'Name bleibt Name');
$check($tr('<p><b>Pakete</b> &lt;script&gt;</p>') === '<p><b>Packages</b> &lt;script&gt;</p>', 'Maskierte Zeichen im Text bleiben maskiert');
// Deutsch: unverändert
$check(site_translate_html('<h1>Pakete</h1>', 'de') === '<h1>Pakete</h1>', 'Deutsch bleibt unverändert');
$check(site_translate_html('<h1>Pakete</h1>', 'xx') === '<h1>Pakete</h1>', 'Unbekannte Sprache bleibt unverändert');
$check(site_translate_html('<h1>Pakete</h1>', '../../etc') === '<h1>Pakete</h1>', 'Sprachcode wird nicht als Pfad benutzt');
// Sprachwahl
unset($_GET['lang'], $_COOKIE['site_lang']);
$check(site_lang() === 'de', 'Standard ist Deutsch');
$sw = site_lang_switcher();
$check(str_contains($sw, 'lang=en') && str_contains($sw, '>English<') && str_contains($sw, 'aria-current'), 'Umschalter bietet die andere Sprache an');
// Vollständigkeit: alle Texte der Verwaltung, die beim Durchklicken der deutschen Seiten gefunden wurden
$known = ['Übersicht', 'Pakete', 'Apps', 'Push-Dienst', 'Einstellungen', 'Anmelden', 'Abmelden', 'Benutzername', 'Passwort', 'Schnellzugriff', 'Häufige Aufgaben',
'Plugin oder Theme hochladen', 'App-Version veröffentlichen', 'DeskHub-Einstellungen', 'Neues Paket veröffentlichen', 'Art', 'ZIP-Paket', 'Kennung (Slug)', 'Name', 'Version', 'Autor', 'Beschreibung',
'Veröffentlichen', 'Als Empfehlung markieren', 'Empfehlung entfernen', 'kein Bild', 'Bild ersetzen', 'Bild hinzufügen', 'Bild entfernen', 'signiert', 'nicht signiert', 'Entfernen',
'Neue App-Version hochladen', 'Plattform', 'Versionsnummer', 'Installationsdatei', 'App-Version hochladen', 'noch nichts veröffentlicht', 'Noch keine Version veröffentlicht.', 'Datum', 'Größe',
'Angemeldete Installationen', 'Noch keine DeskHub-Installation angemeldet.', 'Zuletzt genutzt', 'Gesendet', 'gesperrt', 'aktiv', 'Sperren', 'Entsperren', 'Löschen',
'Konto', 'Signierschlüssel', 'Systemstatus', 'Zugangsschlüssel für Katalog und Downloads', 'Push-Geräte', 'Benutzername oder Passwort ist falsch.', 'Version entfernt.', 'App-Version entfernt.',
'Vorschaubild geändert. Es bleibt bei weiteren Versionen erhalten.', 'Vorschaubild entfernt.', 'Windows – Setup (EXE)', 'WordPress – Plugin (ZIP)', 'Chrome – Erweiterung (ZIP)', 'Minecraft – Plugin (JAR)'];
$dict = site_i18n_dictionary('en');
$missing = array_values(array_filter($known, fn($k) => !isset($dict['exact'][site_i18n_norm($k)])));
$check($missing === [], 'alle bekannten Texte der Verwaltung sind übersetzt, es fehlen: ' . implode(' | ', $missing));
// Jede Übersetzung ist gefüllt, jedes Muster hat gleich viele Platzhalter wie sein Schlüssel
$bad = [];
foreach ((array) json_decode((string) file_get_contents($siteDir . '/lang/en.json'), true) as $de => $en) {
if (!is_string($en) || trim($en) === '') $bad[] = $de;
$holes = substr_count($de, '{}') + substr_count($de, '{#}');
$used = preg_match_all('/\{\d+\}|\{#?\}/', (string) $en);
if ($holes !== $used) $bad[] = 'Platzhalter: ' . $de;
}
$check($bad === [], 'Wörterbuch: leere Übersetzungen oder ungleiche Platzhalter: ' . implode(' | ', array_slice($bad, 0, 5)));
if ($failures) {
fwrite(STDERR, "Fehlgeschlagen:\n - " . implode("\n - ", $failures) . "\n");
exit(1);
}
echo "Plugin website i18n checks passed.\n";