80 lines
6.8 KiB
PHP
80 lines
6.8 KiB
PHP
<?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 & mehr</p>') === '<p>Übersicht & 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> <script></p>') === '<p><b>Packages</b> <script></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";
|