2) { $code = substr($code, 0, 2); } if ($code === '') { return null; } $label = isset($meta['label']) && $meta['label'] !== '' ? (string)$meta['label'] : strtoupper($code); $flag = isset($meta['flag']) ? (string)$meta['flag'] : ''; return [ 'code' => $code, 'label' => $label, 'flag' => $flag, ]; } /** * Alle verfügbaren Sprachen aus /public/assets/i18n/*.json ermitteln. * Verfügbar = JSON mit meta.enabled === true. * EN wird garantiert hinzugefügt (Fallback), falls nicht gefunden. */ function app_i18n_detect_available_languages(): array { $baseDir = realpath(__DIR__ . '/../public/assets/i18n'); if ($baseDir === false) { // Wenn gar kein Verzeichnis da ist: minimaler EN-Fallback return [ 'en' => [ 'code' => 'en', 'label' => 'English', 'flag' => '', ], ]; } $files = glob($baseDir . '/*.json') ?: []; $langs = []; foreach ($files as $file) { $meta = app_i18n_load_language_meta_from_file($file); if ($meta === null) { continue; } $code = $meta['code']; // Erste gültige Definition pro Code gewinnt if (!isset($langs[$code])) { $langs[$code] = $meta; } } // EN muss immer vorhanden sein (laut deiner Vorgabe) if (!isset($langs['en'])) { // Versuch: gibt es eine en.json, auch wenn enabled=false? foreach ($files as $file) { $base = strtolower(basename($file, '.json')); if ($base === 'en') { $json = @file_get_contents($file); $data = json_decode($json, true); $meta = is_array($data['meta'] ?? null) ? $data['meta'] : []; $label = isset($meta['label']) && $meta['label'] !== '' ? (string)$meta['label'] : 'English'; $flag = isset($meta['flag']) ? (string)$meta['flag'] : ''; $langs['en'] = [ 'code' => 'en', 'label' => $label, 'flag' => $flag, ]; break; } } } // Wenn immer noch kein EN → minimaler Stub if (!isset($langs['en'])) { $langs['en'] = [ 'code' => 'en', 'label' => 'English', 'flag' => '', ]; } ksort($langs); return $langs; } /** * Browsersprache aus HTTP_ACCEPT_LANGUAGE extrahieren (2-Buchstaben), * aber nur, wenn sie in $available existiert. */ function app_i18n_detect_browser_lang(array $available): ?string { $header = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? ''; if ($header === '') { return null; } $parts = explode(',', $header); foreach ($parts as $part) { $part = trim($part); if ($part === '') { continue; } $code = strtolower(substr($part, 0, 2)); // "de-DE" → "de" if (isset($available[$code])) { return $code; } } return null; } /** * Aktuelle Sprache bestimmen: * 1) ?lang=xx (wenn in $available) * 2) Browsersprache (wenn in $available) * 3) Fallback "en" */ function app_i18n_resolve_current_lang(array $available): string { // 1) URL-Parameter ?lang=xx if (!empty($_GET['lang'])) { $param = strtolower(substr($_GET['lang'], 0, 2)); if (isset($available[$param])) { return $param; } } // 2) Browsersprache $browser = app_i18n_detect_browser_lang($available); if ($browser !== null) { return $browser; } // 3) Standard EN if (isset($available['en'])) { return 'en'; } // Sicherheitsfallback: erste verfügbare Sprache $keys = array_keys($available); return $keys[0] ?? 'en'; } // ----------------------------------------------------- // Bootstrap ausführen // ----------------------------------------------------- $availableLangs = app_i18n_detect_available_languages(); $currentLang = app_i18n_resolve_current_lang($availableLangs); // Global bereitstellen $GLOBALS['availableLangs'] = $availableLangs; $GLOBALS['lang'] = $currentLang; // Optional in Session merken (muss nicht, schadet aber auch nicht) $_SESSION['lang'] = $currentLang; /** * Frontend-Config für JS (usbConfig.i18n) * → benutzt direkt die Meta-Daten aus den JSONs (code, label, flag) */ function app_i18n_get_frontend_config(): array { return [ 'current' => $GLOBALS['lang'] ?? 'en', 'available' => $GLOBALS['availableLangs'] ?? [], ]; }