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';