lms/scripts/generate_de_lang.php

181 lines
5.8 KiB
PHP

<?php
/**
* Simple offline translator: duplicates lang/en -> lang/de and applies a rule-based
* English->German translation for string values while preserving tokens/placeholders.
*
* Usage: php scripts/generate_de_lang.php
*
* Note: this is a heuristic translator (word-replacement). For high-quality
* translations use a translation provider and enable it in this script.
*/
function ensureDir(string $path)
{
if (!is_dir($path)) mkdir($path, 0755, true);
}
function loadPhpArray(string $file)
{
return require $file;
}
// Basic mapping (expand as needed)
$dictionary = [
'Settings' => 'Einstellungen',
'Setting' => 'Einstellung',
'Update' => 'Aktualisierung',
'Updates' => 'Aktualisierungen',
'Application' => 'Anwendung',
'app' => 'App',
'Backup' => 'Sicherung',
'Backups' => 'Sicherungen',
'Restore' => 'Wiederherstellung',
'File' => 'Datei',
'Files' => 'Dateien',
'Selected file' => 'Ausgewählte Datei',
'Selected file:' => 'Ausgewählte Datei:',
'Cancel' => 'Abbrechen',
'Save' => 'Speichern',
'Upload' => 'Hochladen',
'Uploading...' => 'Hochladen...',
'Name' => 'Name',
'Date' => 'Datum',
'Size' => 'Größe',
'Status' => 'Status',
'Actions' => 'Aktionen',
'History' => 'Verlauf',
'Configure' => 'Konfigurieren',
'Configure Zoom Server-to-Server OAuth Credentials' => 'Zoom Server-to-Server OAuth-Anmeldedaten konfigurieren',
'Language' => 'Sprache',
'Languages' => 'Sprachen',
'Language Settings' => 'Spracheinstellungen',
'Add Language' => 'Sprache hinzufügen',
'Translate Language Properties' => 'Spracheigenschaften übersetzen',
'Application Update' => 'Anwendungs-Aktualisierung',
'Update Application' => 'Anwendung aktualisieren',
'Please do not close this window' => 'Bitte schließe dieses Fenster nicht',
'Are you sure' => 'Bist du sicher',
'Are you sure you want to delete this backup? This action cannot be undone.' => 'Bist du sicher, dass du diese Sicherung löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.',
'Confirm Application Update' => 'Anwendungsaktualisierung bestätigen',
'Process may take several minutes' => 'Der Vorgang kann einige Minuten dauern',
'Test Mode' => 'Testmodus',
'Using Test Environment' => 'Verwendet Testumgebung',
'Using Live Environment' => 'Verwendet Live-Umgebung',
'API Credentials' => 'API-Zugangsdaten',
'Copy' => 'Kopieren',
'Browse Files' => 'Dateien durchsuchen',
'No file selected' => 'Keine Datei ausgewählt',
'Select File (.zip only)' => 'Datei auswählen (.zip nur)',
'Uploading...' => 'Wird hochgeladen...',
];
// Token patterns to preserve
$tokenPatterns = [
'/:(\w+)/', // :seconds, :filename
'/\{\{.*?\}\}/', // {{ var }}
'/\{[^}]+\}/', // {variable}
'/%\w/', // %s %d
'/%\([^\)]+\)s/', // %(name)s
];
function maskTokens(string $s, array $patterns, array &$tokens)
{
$tokens = [];
foreach ($patterns as $p) {
$s = preg_replace_callback($p, function ($m) use (&$tokens) {
$key = '__TOKEN'.count($tokens).'__';
$tokens[$key] = $m[0];
return $key;
}, $s);
}
return $s;
}
function unmaskTokens(string $s, array $tokens)
{
if (!$tokens) return $s;
return strtr($s, $tokens);
}
function translateString(string $s, array $dictionary, array $tokenPatterns)
{
// preserve tokens
$tokens = [];
$masked = maskTokens($s, $tokenPatterns, $tokens);
// quick full-match dictionary
if (isset($dictionary[$masked])) {
$translated = $dictionary[$masked];
} else {
// word-by-word replace, case-sensitive and insensitive
$translated = $masked;
// longer keys first
uksort($dictionary, function($a, $b){ return strlen($b) - strlen($a); });
foreach ($dictionary as $eng => $ger) {
// replace whole words and phrases
$translated = str_ireplace($eng, $ger, $translated);
}
}
// restore tokens
$translated = unmaskTokens($translated, $tokens);
return $translated;
}
function translateRecursive($data, $dictionary, $tokenPatterns)
{
if (is_string($data)) {
return translateString($data, $dictionary, $tokenPatterns);
}
if (is_array($data)) {
$out = [];
foreach ($data as $k => $v) {
$out[$k] = translateRecursive($v, $dictionary, $tokenPatterns);
}
return $out;
}
return $data;
}
$baseEn = __DIR__ . '/../lang/en';
$baseDe = __DIR__ . '/../lang/de';
ensureDir($baseDe);
$files = glob($baseEn.'/*.php');
foreach ($files as $file) {
$name = basename($file);
echo "Processing $name...\n";
$arr = require $file;
$translated = translateRecursive($arr, $dictionary, $tokenPatterns);
$out = "<?php\n\nreturn ".var_export($translated, true).";\n";
file_put_contents($baseDe.'/'.$name, $out);
}
// Also copy storage group files (complex structures)
$groupsEn = __DIR__ . '/../storage/app/lang/groups';
$groupsDe = __DIR__ . '/../storage/app/lang/groups/de';
if (is_dir($groupsEn)) {
ensureDir($groupsDe);
$gfiles = glob($groupsEn.'/*.php');
foreach ($gfiles as $gf) {
$name = basename($gf);
echo "Processing group $name...\n";
$arr = require $gf;
// arr is list of entries with properties arrays
$outArr = [];
foreach ($arr as $entry) {
if (isset($entry['properties']) && is_array($entry['properties'])) {
$entry['properties'] = translateRecursive($entry['properties'], $dictionary, $tokenPatterns);
}
$outArr[] = $entry;
}
$out = "<?php\n\nreturn ".var_export($outArr, true).";\n";
file_put_contents($groupsDe.'/'.$name, $out);
}
}
echo "Done. German lang files generated under lang/de and storage/app/lang/groups/de\n";