• Home
  • -
  • TYPO3: Autolanguage detection with PSR-15

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;
        }
    }