TYPO3: Autolanguage detection with PSR-15
Showcase of automatic language detection with PSR-15 Middleware in TYPO3.
Change TYPO3 frontend language depending on accept-language browser setting.
!!! Note:
!!! This example is incomplete and should only be used as an example of how to integrate this kind of functionality with a middleware. !!!
Require the composer package to detect languages
composer require willdurand/negotiation
Implement the middleware
<?php
declare(strict_types=1);
namespace Susanne\Examples;
use Negotiation\AcceptLanguage;
use Negotiation\LanguageNegotiator;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use TYPO3\CMS\Core\Http\RedirectResponse;
use TYPO3\CMS\Core\Site\Entity\Site;
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
use TYPO3\CMS\Core\Utility\GeneralUtility;
class AcceptLanguageResolver implements MiddlewareInterface
{
/**
* Process an incoming server request and return a response, optionally delegating
* response creation to a handler.
*
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param \Psr\Http\Server\RequestHandlerInterface $handler
* @return \Psr\Http\Message\ResponseInterface
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$site = $request->getAttribute('site', null);
$language = $request->getAttribute('language', null);
if ($site instanceof Site && !($language instanceof SiteLanguage)) {
$acceptLanguage = $request->getServerParams()['HTTP_ACCEPT_LANGUAGE'] ?? '';
$language = $site->getDefaultLanguage();
if ($acceptLanguage) {
$language = $this->getPreferredLanguage($site->getLanguages(), $acceptLanguage) ?? $language;
}
return new RedirectResponse($language->getBase(), 307);
}
return $handler->handle($request);
}
/**
* @param SiteLanguage[] $languages
* @param string $acceptLanguageHeader
* @return null|\TYPO3\CMS\Core\Site\Entity\SiteLanguage
*/
private function getPreferredLanguage(array $languages, string $acceptLanguageHeader): ?SiteLanguage
{
$negotiator = GeneralUtility::makeInstance(LanguageNegotiator::class);
$availableLanguages = [];
$langMapping = [];
foreach ($languages as $languageId => $language) {
$availableLanguages[] = $language->getTwoLetterIsoCode();
$langMapping[$language->getTwoLetterIsoCode()] = $language;
}
$acceptLanguage = $negotiator->getBest($acceptLanguageHeader, $availableLanguages);
if ($acceptLanguage instanceof AcceptLanguage) {
$isoTwoLetterCode = $acceptLanguage->getBasePart();
if (isset($langMapping[$isoTwoLetterCode])) {
$bestLanguage = $langMapping[$isoTwoLetterCode];
}
}
return $bestLanguage ?? null;
}
}