PHP 或 htaccess 通过 Accept-Language 重写 URL?
我已经设置了我的网站,所以我只需要添加“?lang=en”或“?lang=es”来更改语言英语/西班牙语。
当我使用“http://domain.com/something/something_else?lang=es”进入网站时,会设置一个 cookie,以便我继续以该语言浏览该网站。
我想首先通过浏览器的“接受语言”值重定向用户,然后允许他们继续以其他语言导航网站(如果他们愿意)。
最好的方法是什么? .htaccess 是否可以与选择语言时设置的 cookie 一起使用?
编辑:这是我与保罗回答的更新代码:
编辑2:哦,我只有“en”和“es”语言。我不确定此代码如何仅在这两者之间进行选择或设置默认值...:/
if (isset($_GET["lang"]))
$this->setLanguage($_GET["lang"]);
elseif (isset($_COOKIE["language"]))
$this->setLanguage($_COOKIE["language"]);
elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
{
// Parse the Accept-Language according to:
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
preg_match_all(
'/([a-z]{1,8})' . // First part of language e.g en
'(-[a-z]{1,8})*\s*' . // other parts of language e.g -us
// Optional quality factor
'(;\s*q\s*=\s*((1(\.0{0,3}))|(0(\.[0-9]{0,3}))))?/i',
$_SERVER['HTTP_ACCEPT_LANGUAGE'],
$langParse);
$langs = $langParse[1];
$quals = $langParse[4];
$numLanguages = count($langs);
$langArr = array();
for ($num = 0; $num < $numLanguages; $num++)
{
$newLang = strtoupper($langs[$num]);
$newQual = isset($quals[$num]) ?
(empty($quals[$num]) ? 1.0 : floatval($quals[$num])) : 0.0;
// Choose whether to upgrade or set the quality factor for the
// primary language.
$langArr[$newLang] = (isset($langArr[$newLang])) ?
max($langArr[$newLang], $newQual) : $newQual;
}
// sort list based on value
arsort($langArr, SORT_NUMERIC);
$acceptedLanguages = array_keys($langArr);
$preferredLanguage = reset($acceptedLanguages);
$this->setLanguage($preferredLanguage);
}
else
$this->setLanguage("en");
I've my site set up so I just need to add "?lang=en" or "?lang=es" to change languages English / Spanish.
When I enter the site with, for ex, "http://domain.com/something/something_else?lang=es", a cookie is set so I continue to navigate the site in that language.
I would like to redirect my users first by the "Accept-Language" value of their browser, but then allow them to continue to navigate the site in other language if they want to.
What would be the best way to do it? Would .htaccess work along with the cookie that's set when the language is chosen?
EDIT: Here's my updated code with Paul answer:
EDIT2: Oh, I just have "en" and "es" languages. I'm not sure on how this code wpuld choose only between this two or set the default... :/
if (isset($_GET["lang"]))
$this->setLanguage($_GET["lang"]);
elseif (isset($_COOKIE["language"]))
$this->setLanguage($_COOKIE["language"]);
elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
{
// Parse the Accept-Language according to:
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
preg_match_all(
'/([a-z]{1,8})' . // First part of language e.g en
'(-[a-z]{1,8})*\s*' . // other parts of language e.g -us
// Optional quality factor
'(;\s*q\s*=\s*((1(\.0{0,3}))|(0(\.[0-9]{0,3}))))?/i',
$_SERVER['HTTP_ACCEPT_LANGUAGE'],
$langParse);
$langs = $langParse[1];
$quals = $langParse[4];
$numLanguages = count($langs);
$langArr = array();
for ($num = 0; $num < $numLanguages; $num++)
{
$newLang = strtoupper($langs[$num]);
$newQual = isset($quals[$num]) ?
(empty($quals[$num]) ? 1.0 : floatval($quals[$num])) : 0.0;
// Choose whether to upgrade or set the quality factor for the
// primary language.
$langArr[$newLang] = (isset($langArr[$newLang])) ?
max($langArr[$newLang], $newQual) : $newQual;
}
// sort list based on value
arsort($langArr, SORT_NUMERIC);
$acceptedLanguages = array_keys($langArr);
$preferredLanguage = reset($acceptedLanguages);
$this->setLanguage($preferredLanguage);
}
else
$this->setLanguage("en");
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我用 PHP 来做这个。接受语言是一件复杂的事情。浏览器可以建议多种它想要接受的语言(每种语言都有一个质量因素来表明它更喜欢哪种语言)。对于我的网站,我有一个要显示的默认语言(当我的翻译列表中没有任何接受语言时显示)。否则,如果没有语言集(setLang),我会通过解析 Accept-Language 根据浏览器最可接受的语言来选择它。我使用的函数如下(它包含用于设置 cookie 的会话管理器 - 但您可以通过直接调用 $_SESSION[etc] = $foo; 来重新实现它)。
编辑:不幸的是,我的网站只有主要语言(EN、ES、FR)的翻译,而不是(en_US、en_GB、es_MX、es_ES)的翻译,因此我选择其中指定的最高品质因数作为主要语言语言。
I do this in PHP. Accept-Language is a complex thing. A browser can suggest more than one language that it would like to accept (each with a quality factor that shows which it prefers). For my site I have a default language to display (which is shown when none of the Accept-Languages is in my translation list). Otherwise if there is no language set (setLang) I choose it based on the most acceptable for the browser by parsing the Accept-Language. The function I use is below (it contains my session manager for setting cookies - but you could reimplement that with direct calls to $_SESSION[etc] = $foo;).
Edit: Unfortunately my website only has translations for the primary languages (EN, ES, FR) rather than (en_US, en_GB, es_MX, es_ES) so I choose the highest quality factor specified in these for the primary language.
我用 PHP 来做这个。接受语言是一件复杂的事情。浏览器可以建议多种它想要接受的语言(每种语言都有一个质量因素来表明它更喜欢哪种语言)。
不幸的是,我的网站只有主要语言(EN、ES、FR)的翻译,而不是(en_US、en_GB、es_MX、es_ES)的翻译,因此我选择主要语言中指定的最高质量因子。
下面是未经测试的编辑,它应该从我的代码中删除大部分或全部依赖项。抱歉,事情与我之前的回答令人困惑。我对我的函数进行了几次调用,并在其他地方完成了一些语言检查。下面的代码应该设置会话语言变量,您应该在其他地方使用该变量来确定正确的翻译。
它似乎比我之前的答案复杂得多,不久我就必须在自己的代码中实现它。对于需要特定翻译(EN_US、EN_GB)的人,应修改以下代码以考虑 preg_match_all 中的匹配 2。
I do this in PHP. Accept-Language is a complex thing. A browser can suggest more than one language that it would like to accept (each with a quality factor that shows which it prefers).
Unfortunately my website only has translations for the primary languages (EN, ES, FR) rather than (en_US, en_GB, es_MX, es_ES) so I choose the highest quality factor specified in these for the primary language.
Below is an untested edit which should remove most or all of the dependencies from my code. Sorry, things were confusing with my previous answer. I had a few calls to my function with some checking of languages are done elsewhere. The code below should set the session language variable, which you should use elsewhere for determining the correct translation.
It seems a lot less complicated than my previous answer and I will have to implement this in my own code before long. For people who need specific translations (EN_US, EN_GB) then the below code should be modified to take account of Match 2 in the preg_match_all.