我使用Symfony 3。我的网站是两种语言,法语和英语,人们可以通过选择的形式切换。默认语言是法语。主要网址是: example.com/fr为法文本,example.com/en为英文版
那么,现在,我会喜欢当用户到达网站,以检测他的浏览器语言,并重定向到正确的语言自动。例如,如果浏览器是法语的,则将其重定向到法语版本: example.com/fr --否则他将被重定向到英文版本: example.com/en
有什么办法能做到这一点吗?
谢谢你的帮助
发布于 2017-09-03 13:36:18
如果您不想依赖像JMSI18nRoutingBundle这样的其他包,那么您必须熟悉Symfony的事件系统,例如阅读HttpKernel。
对于您的情况,您希望连接到kernel.request事件。
典型用途:向请求添加更多信息,初始化系统的部分,或在可能的情况下返回响应(例如拒绝访问的安全层)。
在您的自定义EventListener中,您可以侦听该事件,向路由器中使用的请求对象添加信息。它可能看起来像这样:
class LanguageListener implements EventSubscriberInterface
{
private $supportedLanguages;
public function __construct(array $supportedLanguages)
{
if (empty($supportedLanguages)) {
throw new \InvalidArgumentException('At least one supported language must be given.');
}
$this->supportedLanguages = $supportedLanguages;
}
public static function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => ['redirectToLocalizedHomepage', 100],
];
}
public function redirectToLocalizedHomepage(GetResponseEvent $event)
{
// Do not modify sub-requests
if (KernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
// Assume all routes except the frontpage use the _locale parameter
if ($event->getRequest()->getPathInfo() !== '/') {
return;
}
$language = $this->supportedLanguages[0];
if (null !== $acceptLanguage = $event->getRequest()->headers->get('Accept-Language')) {
$negotiator = new LanguageNegotiator();
$best = $negotiator->getBest(
$event->getRequest()->headers->get('Accept-Language'),
$this->supportedLanguages
);
if (null !== $best) {
$language = $best->getType();
}
}
$response = new RedirectResponse('/' . $language);
$event->setResponse($response);
}
}此侦听器将检查请求的Accept-Language头,并使用协商\LanguageNegotiator确定最佳区域设置。请小心,因为我没有添加use语句,但是它们应该是相当明显的。
对于更高级的版本,您只需从LocaleChoosingListener中读取JMSI18nRoutingBundle的源代码即可。
通常只需要对frontpage执行此操作,这就是为什么我发布的示例和JMSBundle中的示例都排除了所有其他路径的原因。对于这些用户,您只需使用文档中描述的特殊参数_locale:
https://symfony.com/doc/current/translation/locale.html#the-locale-and-the-url
Symfony文档还包含一个示例,如何使用侦听器读取区域设置并使其在会话中粘稠:session.html --这个示例还展示了如何在services.yml中注册侦听器。
发布于 2021-12-13 22:45:35
对@dbrumann回答使用我的用例和设置所做的轻微更改:
可用区域设置列表在services.yml文件中定义:
parameters:
available_locales:
- nl
- en
- cs我想在网站的任何登陆页面上确定地点。如果解析失败,则返回到_locale参数或默认参数。
class LocaleDetermineSubscriber implements EventSubscriberInterface
{
private $defaultLocale;
private $parameterBag;
private $logger;
public function __construct(ParameterBagInterface $parameterBag,
LoggerInterface $logger,
$defaultLocale = 'en')
{
$this->defaultLocale = $defaultLocale;
$this->parameterBag = $parameterBag;
$this->logger = $logger;
}
public function onKernelRequest(RequestEvent $event)
{
$request = $event->getRequest();
//do this on first request only
if ($request->hasPreviousSession()) {
return;
}
$allowedLocales = $this->parameterBag->get('available_locales'); //defined in services.yml
$determinedLocale = null;
// use locale from the user preference header
$acceptLanguage = $event->getRequest()->headers->get('Accept-Language');
if ($acceptLanguage != null) {
$negotiator = new LanguageNegotiator();
try {
$best = $negotiator->getBest($acceptLanguage, $allowedLocales);
if ($best != null) {
$language = $best->getType();
$request->setLocale($language);
$determinedLocale = $language;
}
} catch (Exception $e) {
$this->logger->warning("Failed to determine language from Accept-Language header " . $e);
}
}
//check if locale is set with _locale parameter if user preference header parsing not happened
if($determinedLocale == null) {
if ($locale = $request->attributes->get('_locale')) {
if(in_array($locale, $allowedLocales)) {
$request->getSession()->set('_locale', $locale);
} else {
$request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
}
} else {
//fallback to default
$request->setLocale($this->defaultLocale);
}
}
}
public static function getSubscribedEvents()
{
return [
// must be registered before (i.e. with a higher priority than) the default Locale listener
KernelEvents::REQUEST => [['onKernelRequest', 25]],
];
}
}它使用了威尔杜兰特/协商包,因此需要首先安装:
composer require willdurand/negotiationhttps://stackoverflow.com/questions/46022235
复制相似问题