Skip to content

Instantly share code, notes, and snippets.

@geerteltink
Created September 29, 2016 15:54
Show Gist options
  • Save geerteltink/c5be44df8e5ce6262eb904f1b09b034c to your computer and use it in GitHub Desktop.
Save geerteltink/c5be44df8e5ce6262eb904f1b09b034c to your computer and use it in GitHub Desktop.
<?php
namespace App\I18n;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Zend\Diactoros\Response\RedirectResponse;
use Zend\I18n\Translator\Translator;
use Zend\Stratigility\MiddlewareInterface;
class LocalizationMiddleware implements MiddlewareInterface
{
const LOCALE_ATTRIBUTE = 'locale';
private $translator;
private $languages;
public function __construct(Translator $translator, array $languages)
{
$this->translator = $translator;
$this->languages = $languages;
}
public function __invoke(Request $request, Response $response, callable $next = null)
{
$locale = $requestLocale = $request->getAttribute('locale');
// If there is no or an invalid locale
if (! $locale || ! in_array(substr(trim($locale), 0, 2), $this->languages, true)) {
// Fallback to first language
$locale = $this->languages[0];
// Try the user preferred locales
foreach ($this->getLocales($request) as $userLocale => $factor) {
if (in_array(substr(trim($userLocale), 0, 2), $this->languages, true)) {
$locale = $userLocale;
break;
}
}
}
// Only the language is needed
$locale = substr(trim($locale), 0, 2);
if ($request->getUri()->getPath() === '/') {
// Redirect and set the locale for the homepage
return new RedirectResponse('/' . $locale);
}
// Set current locale
$this->translator->setLocale($locale);
// Get response first, apply content language later
if (null !== $next) {
$response = $next($request->withAttribute(self::LOCALE_ATTRIBUTE, $locale), $response);
}
// Add the content language to the response
return $response->withHeader('Content-Language', $locale);
}
private function getLocales(Request $request)
{
$locales = [];
if (! array_key_exists('HTTP_ACCEPT_LANGUAGE', $request->getServerParams())) {
return $locales;
}
// break up string into pieces (locales and q factors)
preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[\d]+))?/i',
$request->getServerParams()['HTTP_ACCEPT_LANGUAGE'], $matches);
if (count($matches[1])) {
// create a list like "en" => 0.8
$locales = array_combine($matches[1], $matches[4]);
// set default to 1 for any without q factor
foreach ($locales as $locale => $factor) {
if ($factor === '') {
$locales[$locale] = 1;
}
}
// sort list based on value
arsort($locales, SORT_NUMERIC);
}
return $locales;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment