Skip to content
Snippets Groups Projects
Commit 00028bc4 authored by Jan-Hendrik Willms's avatar Jan-Hendrik Willms
Browse files

get language from accept header only if no valid is started, fixes #1680, fixes #1394

Closes #1680 and #1394

Merge request studip/studip!1089
parent 08f9e74a
No related branches found
No related tags found
No related merge requests found
...@@ -4,6 +4,7 @@ namespace JsonApi\Middlewares; ...@@ -4,6 +4,7 @@ namespace JsonApi\Middlewares;
use Negotiation\LanguageNegotiator; use Negotiation\LanguageNegotiator;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler; use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
/** /**
...@@ -12,7 +13,7 @@ use Psr\Http\Server\RequestHandlerInterface as RequestHandler; ...@@ -12,7 +13,7 @@ use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
* *
* @author Jan-Hendrik Willms <tleilax+studip@gmail.com> * @author Jan-Hendrik Willms <tleilax+studip@gmail.com>
*/ */
class Language final class Language implements MiddlewareInterface
{ {
/** /**
* @param Request $request das Request-Objekt * @param Request $request das Request-Objekt
...@@ -20,79 +21,13 @@ class Language ...@@ -20,79 +21,13 @@ class Language
* *
* @return ResponseInterface das neue Response-Objekt * @return ResponseInterface das neue Response-Objekt
*/ */
public function __invoke(Request $request, RequestHandler $handler) public function process(Request $request, RequestHandler $handler): ResponseInterface
{ {
$language = $this->detectValidLanguageFromRequest($request); $language = $_SESSION['_language'] ?? get_accepted_languages($request);
$language_before = false;
// Set language if detected init_i18n($language);
if ($language) { $_SESSION['_language'] = $language;
$language_before = $_SESSION['_language'];
$_SESSION['_language'] = $language;
setTempLanguage(false, $language);
}
$response = $handler->handle($request); return $handler->handle($request);
if ($language) {
$_SESSION['_language'] = $language_before;
restoreLanguage();
}
return $response;
}
/**
* Tries to detect a valid installed language from the request.
*
* @param Request $request
* @return string|null The detected language (if any)
*/
private function detectValidLanguageFromRequest(Request $request): ?string
{
if (!$request->hasHeader('Accept-Language')) {
return null;
}
$negotiator = new LanguageNegotiator();
$best_language = $negotiator->getBest(
$request->getHeaderLine('Accept-Language'),
$this->getStudIPLanguagePriorities()
);
if (!$best_language) {
return null;
}
return $this->normalizeLanguageForStudIP($best_language->getType());
}
/**
* Returns a list of the normalized installed languages for the Stud.IP
* system.
*
* @return array
*/
private function getStudIPLanguagePriorities(): array
{
return array_map(
function ($language) {
return str_replace('_', '-', $language);
},
array_keys($GLOBALS['INSTALLED_LANGUAGES'])
);
}
/**
* Normalizes the given language string (<language>-<variety>, e.g. de-de)
* for Stud.IP (e.g. de_DE).
*
* @param string $language
* @return string
*/
private function normalizeLanguageForStudIP(string $language): string
{
$tags = explode('-', $language);
return $tags[0] . '_' . strtoupper($tags[1]);
} }
} }
...@@ -27,7 +27,7 @@ return function (App $app) { ...@@ -27,7 +27,7 @@ return function (App $app) {
$app->addRoutingMiddleware(); $app->addRoutingMiddleware();
// Add language middleware // Add language middleware
$app->add(new Middlewares\Language()); $app->add(Middlewares\Language::class);
/** @var array|null */ /** @var array|null */
$corsOrigin = \Config::get()->getValue('JSONAPI_CORS_ORIGIN'); $corsOrigin = \Config::get()->getValue('JSONAPI_CORS_ORIGIN');
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// +---------------------------------------------------------------------------+ // +---------------------------------------------------------------------------+
use Negotiation\AcceptHeader;
/** /**
* This function tries to find the preferred language * This function tries to find the preferred language
...@@ -47,22 +47,38 @@ ...@@ -47,22 +47,38 @@
* @return string preferred user language, given in "en_GB"-style * @return string preferred user language, given in "en_GB"-style
* *
*/ */
function get_accepted_languages() { function get_accepted_languages(Psr\Http\Message\RequestInterface $request = null) {
global $INSTALLED_LANGUAGES; $accepted_languages = null;
if ($request === null) {
$_language = Config::get()->DEFAULT_LANGUAGE; $accepted_languages = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
$accepted_languages = explode(",", getenv("HTTP_ACCEPT_LANGUAGE")); } elseif ($request->hasHeader('Accept-Language')) {
if (is_array($accepted_languages) && count($accepted_languages)) { $accepted_languages = $request->getHeaderLine('Accept-Language');
foreach ($accepted_languages as $temp_accepted_language) { }
foreach ($INSTALLED_LANGUAGES as $temp_language => $temp_language_settings) {
if (mb_substr(trim($temp_accepted_language), 0, 2) == mb_substr($temp_language, 0, 2)) { // No languages found from http header, set default
$_language = $temp_language; if (!$accepted_languages) {
break 2; return Config::get()->DEFAULT_LANGUAGE;
}
}
}
} }
return $_language;
// Use negotiator to identify best match
$negotiator = new Negotiation\LanguageNegotiator();
$best_language = $negotiator->getBest(
$accepted_languages,
array_map(
function ($language) {
return str_replace('_', '-', $language);
},
array_keys($GLOBALS['INSTALLED_LANGUAGES'])
)
);
// No best match, set default
if (!$best_language) {
return Config::get()->DEFAULT_LANGUAGE;
}
// Normalize language definition for stud.ip
return $best_language->getBasePart() . '_' . strtoupper($best_language->getSubPart());
} }
...@@ -192,7 +208,7 @@ function restoreLanguage() { ...@@ -192,7 +208,7 @@ function restoreLanguage() {
* @access public * @access public
*/ */
function setLocaleEnv($language, $language_domain = ''){ function setLocaleEnv($language, $language_domain = ''){
putenv('LANGUAGE'); //unset language preference putenv('LANGUAGE'); //unset language preference
$ret = setlocale(LC_ALL, $language . '.UTF-8'); $ret = setlocale(LC_ALL, $language . '.UTF-8');
setlocale(LC_NUMERIC, 'C'); setlocale(LC_NUMERIC, 'C');
if ($language_domain) { if ($language_domain) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment