242 lines
7.2 KiB
PHP
242 lines
7.2 KiB
PHP
<?php
|
||
|
||
// 0) Umgebung / Domains / Error-Level
|
||
require_once __DIR__ . "/config.php";
|
||
|
||
// -----------------------------------------------------------
|
||
// Session starten
|
||
// -----------------------------------------------------------
|
||
if (php_sapi_name() !== 'cli') {
|
||
if (session_status() === PHP_SESSION_NONE) {
|
||
|
||
session_name('usbcheck_session');
|
||
|
||
session_set_cookie_params([
|
||
'lifetime' => 0,
|
||
'path' => '/',
|
||
'domain' => '',
|
||
'secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'),
|
||
'httponly' => true,
|
||
'samesite' => 'Lax',
|
||
]);
|
||
|
||
session_start();
|
||
}
|
||
}
|
||
|
||
// -----------------------------------------------------------
|
||
// Helper: Browser-Sprache aus HTTP_ACCEPT_LANGUAGE bestimmen
|
||
// -----------------------------------------------------------
|
||
function usb_detect_browser_lang(array $availableLangs): ?string
|
||
{
|
||
if (empty($availableLangs)) {
|
||
error_log('[i18n] Browser-Lang: keine availableLangs – abbrechen');
|
||
return null;
|
||
}
|
||
|
||
$header = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '';
|
||
error_log('[i18n] HTTP_ACCEPT_LANGUAGE: ' . $header);
|
||
|
||
if ($header === '') {
|
||
return null;
|
||
}
|
||
|
||
$parts = explode(',', $header);
|
||
|
||
foreach ($parts as $part) {
|
||
$part = trim($part);
|
||
if ($part === '') {
|
||
continue;
|
||
}
|
||
|
||
// Sprache vor dem ; nehmen (z.B. "de-DE", "en-US")
|
||
$langTag = strtolower(explode(';', $part)[0]);
|
||
|
||
if ($langTag === '') {
|
||
continue;
|
||
}
|
||
|
||
// 2-Buchstaben-Code extrahieren (de, en, fr, …)
|
||
$code2 = substr($langTag, 0, 2);
|
||
|
||
if (!preg_match('/^[a-z]{2}$/', $code2)) {
|
||
continue;
|
||
}
|
||
|
||
$exists = array_key_exists($code2, $availableLangs) ? 'yes' : 'no';
|
||
error_log("[i18n] Browser-Lang-Kandidat: {$code2} (exists: {$exists})");
|
||
|
||
if (isset($availableLangs[$code2])) {
|
||
return $code2;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
// -----------------------------------------------------------
|
||
// 1) Sprache aus ?lang lesen (nur 2-Buchstaben-Code zulassen)
|
||
// -----------------------------------------------------------
|
||
$requestedLang = $_GET['lang'] ?? null;
|
||
|
||
if (is_string($requestedLang)) {
|
||
$requestedLang = strtolower($requestedLang);
|
||
if (!preg_match('/^[a-z]{2}$/', $requestedLang)) {
|
||
$requestedLang = null;
|
||
}
|
||
} else {
|
||
$requestedLang = null;
|
||
}
|
||
|
||
error_log('[i18n] requestedLang (GET): ' . var_export($requestedLang, true));
|
||
|
||
// -----------------------------------------------------------
|
||
// 2) Verfügbare JSON-Sprachen erkennen
|
||
// -----------------------------------------------------------
|
||
$i18nDir = __DIR__ . '/../public/assets/i18n';
|
||
|
||
$langFiles = [];
|
||
if (is_dir($i18nDir)) {
|
||
$langFiles = glob($i18nDir . '/*.json') ?: [];
|
||
}
|
||
|
||
$availableLangs = [];
|
||
|
||
// Alle vorhandenen JSONs einsammeln
|
||
foreach ($langFiles as $file) {
|
||
$raw = @file_get_contents($file);
|
||
if ($raw === false) {
|
||
error_log('[i18n] Konnte Datei nicht lesen: ' . $file);
|
||
continue;
|
||
}
|
||
|
||
$json = json_decode($raw, true);
|
||
if (!is_array($json)) {
|
||
error_log('[i18n] Ungültiges JSON in ' . $file . ' :: ' . json_last_error_msg());
|
||
continue;
|
||
}
|
||
|
||
$meta = $json['meta'] ?? [];
|
||
|
||
// Optional: nur Sprachen mit enabled=false ausblenden
|
||
if (array_key_exists('enabled', $meta) && $meta['enabled'] === false) {
|
||
error_log('[i18n] Sprache deaktiviert (enabled=false) in ' . $file);
|
||
continue;
|
||
}
|
||
|
||
// Sprachcode bestimmen (immer 2-Buchstaben)
|
||
$code = strtolower($meta['code'] ?? basename($file, '.json'));
|
||
if (!preg_match('/^[a-z]{2}$/', $code)) {
|
||
// Sonderdateien (template.json etc.) ignorieren
|
||
error_log('[i18n] Ignoriere Datei mit unpassendem Code: ' . $file);
|
||
continue;
|
||
}
|
||
|
||
$label = $meta['label'] ?? strtoupper($code);
|
||
$flag = $meta['flag'] ?? '🏳️';
|
||
|
||
$availableLangs[$code] = [
|
||
'code' => $code,
|
||
'label' => $label,
|
||
'flag' => $flag,
|
||
];
|
||
}
|
||
|
||
error_log('[i18n] availableLangs keys: ' . implode(', ', array_keys($availableLangs)));
|
||
|
||
// Falls keine Sprachdateien gefunden wurden → Minimal-Fallback
|
||
if (empty($availableLangs)) {
|
||
error_log('[i18n] WARN: keine Sprachdateien gefunden, fallback auf en');
|
||
$availableLangs = [
|
||
'en' => [
|
||
'code' => 'en',
|
||
'label' => 'English',
|
||
'flag' => '🏳️',
|
||
],
|
||
];
|
||
}
|
||
|
||
// -----------------------------------------------------------
|
||
// 3) Endgültige Sprache wählen nach deiner Priorität
|
||
// -----------------------------------------------------------
|
||
$lang = null;
|
||
|
||
// 1) ?lang=xx wird bevorzugt, wenn gültig + vorhanden
|
||
if ($requestedLang && isset($availableLangs[$requestedLang])) {
|
||
$lang = $requestedLang;
|
||
error_log('[i18n] Auswahl: requestedLang übernommen: ' . $lang);
|
||
}
|
||
|
||
// 2) Sonst HTTP_ACCEPT_LANGUAGE (Browser), erste passende Sprache
|
||
if ($lang === null) {
|
||
$browserLang = usb_detect_browser_lang($availableLangs);
|
||
if ($browserLang !== null) {
|
||
$lang = $browserLang;
|
||
error_log('[i18n] Auswahl: Browser-Lang übernommen: ' . $lang);
|
||
}
|
||
}
|
||
|
||
// 3) Wenn Browser-Sprache nicht existiert → 'en', wenn vorhanden
|
||
if ($lang === null && isset($availableLangs['en'])) {
|
||
$lang = 'en';
|
||
error_log('[i18n] Auswahl: Fallback auf en, da kein Match');
|
||
}
|
||
|
||
// 4) Sonst: erste Sprache aus $availableLangs
|
||
if ($lang === null) {
|
||
$keys = array_keys($availableLangs);
|
||
$lang = $keys[0] ?? 'en';
|
||
error_log('[i18n] Auswahl: Fallback auf erste Sprache: ' . $lang);
|
||
}
|
||
|
||
error_log('[i18n] FINAL LANG: ' . $lang);
|
||
|
||
// -----------------------------------------------------------
|
||
// 4) Aktive Sprachdatei laden
|
||
// -----------------------------------------------------------
|
||
$activeLangFile = $i18nDir . '/' . $lang . '.json';
|
||
$activeLangData = [];
|
||
|
||
if (is_readable($activeLangFile)) {
|
||
$json = json_decode(@file_get_contents($activeLangFile), true);
|
||
if (is_array($json)) {
|
||
$activeLangData = $json;
|
||
} else {
|
||
error_log('[i18n] Aktive JSON nicht array: ' . $activeLangFile);
|
||
}
|
||
} else {
|
||
error_log('[i18n] Aktive Sprachdatei nicht lesbar: ' . $activeLangFile);
|
||
}
|
||
|
||
// -----------------------------------------------------------
|
||
// 5) Fallback-Sprache: immer EN, wenn vorhanden & nicht aktuell
|
||
// -----------------------------------------------------------
|
||
$fallbackLangData = [];
|
||
$fallbackFile = $i18nDir . '/en.json';
|
||
|
||
if ($lang !== 'en' && is_readable($fallbackFile)) {
|
||
$json = json_decode(@file_get_contents($fallbackFile), true);
|
||
if (is_array($json)) {
|
||
$fallbackLangData = $json;
|
||
} else {
|
||
error_log('[i18n] Fallback-JSON (en) nicht array: ' . $fallbackFile);
|
||
}
|
||
}
|
||
|
||
// -----------------------------------------------------------
|
||
// 6) Globale i18n-Struktur bereitstellen
|
||
// -----------------------------------------------------------
|
||
$GLOBALS['lang'] = $lang;
|
||
$GLOBALS['availableLangs'] = $availableLangs;
|
||
|
||
$GLOBALS['i18n'] = [
|
||
'current' => $activeLangData,
|
||
'fallback' => $fallbackLangData,
|
||
];
|
||
|
||
// -----------------------------------------------------------
|
||
// 7) Rest des Systems laden
|
||
// -----------------------------------------------------------
|
||
require_once __DIR__ . "/db.php";
|
||
require_once __DIR__ . '/../src/functions.php';
|