对@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]],
];
}
}
使用的是willdurand/negotiation包,所以需要先安装:
composer require willdurand/negotiation
https://packagist.org/packages/willdurand/negotiation