Files
deskhub/DeskHub-Webseite/tests/plugin_website_i18n.php
T
2026-11-04 07:55:43 +00:00

80 lines
6.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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";