defaultLocale = $defaultLocale ?? I18n::$defaultLocale; $this->availableLocales = $availableLocales ?? (defined('APP_LOCALES') ? APP_LOCALES : [$this->defaultLocale]); $this->basePath = trim(parse_url(\MintyPHP\Router::getBaseUrl(), PHP_URL_PATH) ?: '/', '/'); } /** * Parse a request URI and extract locale information. * * @return array{ * locale: string, * pathWithoutLocale: string, * query: string, * hadLocaleInUrl: bool, * hadInvalidLocale: bool * } */ public function parseUri(string $uri): array { $path = parse_url($uri, PHP_URL_PATH) ?: ''; $query = parse_url($uri, PHP_URL_QUERY) ?: ''; $relativePath = Request::stripBasePath($path); $segments = $relativePath === '' ? [] : explode('/', $relativePath); $localeCandidate = $segments[0] ?? ''; $hadLocaleInUrl = false; $hadInvalidLocale = false; $locale = ''; if ($localeCandidate !== '' && in_array($localeCandidate, $this->availableLocales, true)) { $locale = array_shift($segments); $hadLocaleInUrl = true; } elseif ($localeCandidate !== '' && $this->looksLikeLocale($localeCandidate)) { array_shift($segments); $hadInvalidLocale = true; } return [ 'locale' => $locale, 'pathWithoutLocale' => implode('/', $segments), 'query' => $query, 'hadLocaleInUrl' => $hadLocaleInUrl, 'hadInvalidLocale' => $hadInvalidLocale, ]; } /** * Resolve the effective locale from multiple sources (priority order): * 1. URL segment (explicit) * 2. User session preference * 3. Cookie preference * 4. Default locale */ public function resolveLocale(string $urlLocale, ?string $userLocale = null, ?string $cookieLocale = null): string { if ($urlLocale !== '' && $this->isValidLocale($urlLocale)) { return $urlLocale; } if ($userLocale !== null && $userLocale !== '' && $this->isValidLocale($userLocale)) { return $userLocale; } if ($cookieLocale !== null && $cookieLocale !== '' && $this->isValidLocale($cookieLocale)) { return $cookieLocale; } return $this->defaultLocale; } /** * Build a new REQUEST_URI without the locale segment. */ public function buildUriWithoutLocale(string $pathWithoutLocale, string $query): string { $newPath = $this->basePath !== '' ? '/' . $this->basePath : ''; if ($pathWithoutLocale !== '') { $newPath .= '/' . $pathWithoutLocale; } elseif ($newPath === '') { $newPath = '/'; } return $newPath . ($query !== '' ? '?' . $query : ''); } /** * Check if a locale string is valid (exists in available locales). */ public function isValidLocale(string $locale): bool { return in_array($locale, $this->availableLocales, true); } private function looksLikeLocale(string $candidate): bool { return preg_match('/^[a-z]{2}(?:-[a-z]{2})?$/i', $candidate) === 1; } }