mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-30 22:48:19 +08:00
Implemented language negotiation.
Implemented Request::getAcceptedContentTypes().
This commit is contained in:
@@ -658,40 +658,133 @@ class Request extends \yii\base\Request
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private $_preferredLanguages;
|
private $_contentTypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the user preferred languages.
|
* Returns the content types accepted by the end user.
|
||||||
* The languages returned are ordered by user's preference, starting with the language that the user
|
* This is determined by the `Accept` HTTP header.
|
||||||
* prefers the most.
|
* @return array the content types ordered by the preference level. The first element
|
||||||
* @return string the user preferred languages. An empty array may be returned if the user has no preference.
|
* represents the most preferred content type.
|
||||||
*/
|
*/
|
||||||
public function getPreferredLanguages()
|
public function getAcceptedContentTypes()
|
||||||
{
|
{
|
||||||
if ($this->_preferredLanguages === null) {
|
if ($this->_contentTypes === null) {
|
||||||
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && ($n = preg_match_all('/([\w\-_]+)\s*(;\s*q\s*=\s*(\d*\.\d*))?/', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches)) > 0) {
|
if (isset($_SERVER['HTTP_ACCEPT'])) {
|
||||||
$languages = array();
|
$this->_contentTypes = $this->parseAcceptHeader($_SERVER['HTTP_ACCEPT']);
|
||||||
for ($i = 0; $i < $n; ++$i) {
|
|
||||||
$languages[$matches[1][$i]] = empty($matches[3][$i]) ? 1.0 : floatval($matches[3][$i]);
|
|
||||||
}
|
|
||||||
arsort($languages);
|
|
||||||
$this->_preferredLanguages = array_keys($languages);
|
|
||||||
} else {
|
} else {
|
||||||
$this->_preferredLanguages = array();
|
$this->_contentTypes = array();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $this->_preferredLanguages;
|
return $this->_contentTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the language most preferred by the user.
|
* @param array $value the content types that are accepted by the end user. They should
|
||||||
* @return string|boolean the language most preferred by the user. If the user has no preference, false
|
* be ordered by the preference level.
|
||||||
* will be returned.
|
|
||||||
*/
|
*/
|
||||||
public function getPreferredLanguage()
|
public function setAcceptedContentTypes($value)
|
||||||
{
|
{
|
||||||
$languages = $this->getPreferredLanguages();
|
$this->_contentTypes = $value;
|
||||||
return isset($languages[0]) ? $languages[0] : false;
|
}
|
||||||
|
|
||||||
|
private $_languages;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the languages accepted by the end user.
|
||||||
|
* This is determined by the `Accept-Language` HTTP header.
|
||||||
|
* @return array the languages ordered by the preference level. The first element
|
||||||
|
* represents the most preferred language.
|
||||||
|
*/
|
||||||
|
public function getAcceptedLanguages()
|
||||||
|
{
|
||||||
|
if ($this->_languages === null) {
|
||||||
|
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
|
||||||
|
$this->_languages = $this->parseAcceptHeader($_SERVER['HTTP_ACCEPT_LANGUAGE']);
|
||||||
|
} else {
|
||||||
|
$this->_languages = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this->_languages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $value the languages that are accepted by the end user. They should
|
||||||
|
* be ordered by the preference level.
|
||||||
|
*/
|
||||||
|
public function setAcceptedLanguages($value)
|
||||||
|
{
|
||||||
|
$this->_languages = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the given `Accept` (or `Accept-Language`) header.
|
||||||
|
* This method will return the accepted values ordered by their preference level.
|
||||||
|
* @param string $header the header to be parsed
|
||||||
|
* @return array the accept values ordered by their preference level.
|
||||||
|
*/
|
||||||
|
protected function parseAcceptHeader($header)
|
||||||
|
{
|
||||||
|
$accepts = array();
|
||||||
|
$n = preg_match_all('/\s*([\w\/\-\*]+)\s*(?:;\s*q\s*=\s*([\d\.]+))?[^,]*/', $header, $matches, PREG_SET_ORDER);
|
||||||
|
for ($i = 0; $i < $n; ++$i) {
|
||||||
|
if (!empty($matches[$i][1])) {
|
||||||
|
$accepts[] = array($matches[$i][1], isset($matches[$i][2]) ? (float)$matches[$i][2] : 1, $i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
usort($accepts, function ($a, $b) {
|
||||||
|
if ($a[1] > $b[1]) {
|
||||||
|
return -1;
|
||||||
|
} elseif ($a[1] < $b[1]) {
|
||||||
|
return 1;
|
||||||
|
} elseif ($a[0] === $b[0]) {
|
||||||
|
return $a[2] > $b[2] ? 1 : -1;
|
||||||
|
} elseif ($a[0] === '*/*') {
|
||||||
|
return 1;
|
||||||
|
} elseif ($b[0] === '*/*') {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
$wa = $a[0][strlen($a[0]) - 1] === '*';
|
||||||
|
$wb = $b[0][strlen($b[0]) - 1] === '*';
|
||||||
|
if ($wa xor $wb) {
|
||||||
|
return $wa ? 1 : -1;
|
||||||
|
} else {
|
||||||
|
return $a[2] > $b[2] ? 1 : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$result = array();
|
||||||
|
foreach ($accepts as $accept) {
|
||||||
|
$result[] = $accept[0];
|
||||||
|
}
|
||||||
|
return array_unique($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the user-preferred language that should be used by this application.
|
||||||
|
* The language resolution is based on the user preferred languages and the languages
|
||||||
|
* supported by the application. The method will try to find the best match.
|
||||||
|
* @param array $languages a list of the languages supported by the application.
|
||||||
|
* If empty, this method will return the first language returned by [[getAcceptedLanguages()]].
|
||||||
|
* @return string the language that the application should use. Null is returned if both [[getAcceptedLanguages()]]
|
||||||
|
* and `$languages` are empty.
|
||||||
|
*/
|
||||||
|
public function getPreferredLanguage($languages = array())
|
||||||
|
{
|
||||||
|
$acceptedLanguages = $this->getAcceptedLanguages();
|
||||||
|
if (empty($languages)) {
|
||||||
|
return isset($acceptedLanguages[0]) ? $acceptedLanguages[0] : null;
|
||||||
|
}
|
||||||
|
foreach ($acceptedLanguages as $acceptedLanguage) {
|
||||||
|
$acceptedLanguage = str_replace('-', '_', strtolower($acceptedLanguage));
|
||||||
|
foreach ($languages as $language) {
|
||||||
|
$language = str_replace('-', '_', strtolower($language));
|
||||||
|
// en_us==en_us, en==en_us, en_us==en
|
||||||
|
if ($language === $acceptedLanguage || strpos($acceptedLanguage, $language . '_') === 0 || strpos($language, $acceptedLanguage . '_') === 0) {
|
||||||
|
return $language;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reset($languages);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user