/** * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event */ public function onKernelException(GetResponseForExceptionEvent $event) { if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { return; } $request = $event->getRequest(); if ('' !== rtrim($request->getPathInfo(), '/')) { return; } $ex = $event->getException(); if (!$ex instanceof NotFoundHttpException || !$ex->getPrevious() instanceof ResourceNotFoundException) { return; } $locale = $this->localeResolver->resolveLocale($request, $this->locales) ?: $this->defaultLocale; $request->setLocale($locale); $params = $request->query->all(); unset($params['hl']); $event->setResponse(new RedirectResponse($request->getBaseUrl() . '/' . $locale . '/' . ($params ? '?' . http_build_query($params) : ''), 301)); }
private function matchI18n(array $params, $url) { if (false === $params) { return false; } if (isset($params['_locales'])) { if (false !== ($pos = strpos($params['_route'], I18nLoader::ROUTING_PREFIX))) { $params['_route'] = substr($params['_route'], $pos + strlen(I18nLoader::ROUTING_PREFIX)); } if (!($currentLocale = $this->context->getParameter('_locale'))) { $currentLocale = $this->localeResolver->resolveLocale($this->container->get('request_stack')->getCurrentRequest(), $params['_locales']); // If the locale resolver was not able to determine a locale, then all efforts to // make an informed decision have failed. Just display something as a last resort. if (!$currentLocale) { $currentLocale = reset($params['_locales']); } } if (!in_array($currentLocale, $params['_locales'], true)) { // We might want to allow the user to be redirected to the route for the given locale if // it exists regardless of whether it would be on another domain, or the same domain. // Below we assume that we do not want to redirect always. // if the available locales are on a different host, throw a ResourceNotFoundException if ($this->hostMap) { // generate host maps $hostMap = $this->hostMap; $availableHosts = array_map(function ($locale) use($hostMap) { return $hostMap[$locale]; }, $params['_locales']); $differentHost = true; foreach ($availableHosts as $host) { if ($this->hostMap[$currentLocale] === $host) { $differentHost = false; break; } } if ($differentHost) { throw new ResourceNotFoundException(sprintf('The route "%s" is not available on the current host "%s", ' . 'but only on these hosts "%s".', $params['_route'], $this->hostMap[$currentLocale], implode(', ', $availableHosts))); } } // no host map, or same host means that the given locale is not supported for this route throw new NotAcceptableLanguageException($currentLocale, $params['_locales']); } unset($params['_locales']); $params['_locale'] = $currentLocale; } else { if (isset($params['_locale']) && false !== ($pos = strpos($params['_route'], I18nLoader::ROUTING_PREFIX))) { $params['_route'] = substr($params['_route'], $pos + strlen(I18nLoader::ROUTING_PREFIX)); } } // check if the matched route belongs to a different locale on another host if (isset($params['_locale']) && isset($this->hostMap[$params['_locale']]) && $this->context->getHost() !== ($host = $this->hostMap[$params['_locale']])) { if (!$this->redirectToHost) { throw new ResourceNotFoundException(sprintf('Resource corresponding to pattern "%s" not found for locale "%s".', $url, $this->getContext()->getParameter('_locale'))); } return ['_controller' => 'JMS\\I18nRoutingBundle\\Controller\\RedirectController::redirectAction', 'path' => $url, 'host' => $host, 'permanent' => true, 'scheme' => $this->context->getScheme(), 'httpPort' => $this->context->getHttpPort(), 'httpsPort' => $this->context->getHttpsPort(), '_route' => $params['_route']]; } // if we have no locale set on the route, we try to set one according to the localeResolver // if we don't do this all _internal routes will have the default locale on first request if (!isset($params['_locale']) && ($locale = $this->localeResolver->resolveLocale($this->container->get('request_stack')->getCurrentRequest(), $this->container->get('octava_mui.locale_manager')->getAllAliases()))) { $params['_locale'] = $locale; } return $params; }