如何在PHP中自动设置用户的语言环境?

时间:2022-05-25 00:20:53

Is there an easy way to parse the user's HTTP_ACCEPT_LANGUAGE and set the locale in PHP?

有没有一种简单的方法来解析用户的HTTP_ACCEPT_LANGUAGE并在PHP中设置语言环境?

I know the Zend framework has a method to do this, but I'd rather not install the whole framework just to use that one bit of functionality.

我知道Zend框架有一个方法可以做到这一点,但我宁愿不安装整个框架只是为了使用那一点功能。

The PEAR I18Nv2 package is in beta and hasn't been changed for almost three years, so I'd rather not use that if possible.

PEAR I18Nv2软件包处于测试阶段,并且近三年没有改变,所以如果可能的话我宁愿不使用它。

Also nice would be if it could figure out if the server was running on Windows or not, since Windows's locale strings are different from the rest of the world's... (German is "deu" or "german" instead of "de".)

如果它可以判断服务器是否在Windows上运行,那也很好,因为Windows的语言环境字符串与世界其他地方不同......(德语是“deu”或“german”而不是“de”。 )

4 个解决方案

#1


2  

Nice solution is on its way.

好的解决方案即将推出。

Without that you'll need to parse that header. It's a comma-separated list of semicolon-separated locales and attributes.

如果没有它,您将需要解析该标头。它是以逗号分隔的以分号分隔的区域设置和属性的列表。

It can look like this:

它看起来像这样:

en_US, en;q=0.8, fr_CA;q=0.2, *;q=0.1

and then try each locale until setlocale() accepts it. Be prepared that none of them may match.

然后尝试每个语言环境,直到setlocale()接受它。做好准备,没有一个可以匹配。

Don't base on it anything too important or allow users to override it, because some users may have misconfigured browsers.

不要基于它太重要或允许用户覆盖它,因为一些用户可能有错误配置的浏览器。


For Windows locale, perhaps you need to convert ISO 639-1 names to ISO 639-2/3?

对于Windows语言环境,您可能需要将ISO 639-1名称转换为ISO 639-2 / 3吗?

#2


5  

It's not as easy as it should be (in my humble opinion). First of all you have to extract the locales from the $_SERVER['HTTP_ACCEPT_LANGUAGE'] and sort them by their q values. Afterwards you have to retrieve the appropriate system locale for each of the given locales, which should be no problem on a *nix machine (you only might have to cope with the correct charset) but on Windows you'll have to translate the locales into Windows locales, e.g. de_DE will be German_Germany (again you also have to cope with charset issues if you're using UTF-8 in your app for example). I think you'll have to build a lookup table for this issue - and there are a lot of locales ;-)

它并不像它应该那么容易(以我的拙见)。首先,您必须从$ _SERVER ['HTTP_ACCEPT_LANGUAGE']中提取区域设置,并按q值对其进行排序。之后你必须为每个给定的语言环境检索适当的系统语言环境,这在* nix机器上应该没问题(你可能只需要处理正确的字符集)但是在Windows上你必须将语言环境翻译成Windows语言环境,例如de_DE将是German_Germany(例如,如果您在应用程序中使用UTF-8,则还必须处理字符集问题)。我认为你必须为这个问题构建一个查找表 - 并且有很多语言环境;-)

No you try one locale after the other (sorted with descending q values) until you find a match using setlocale() (the function will return false if the given locale could not be set).

不是你在另一个之后尝试一个语言环境(用降序q值排序),直到你找到使用setlocale()的匹配(如果无法设置给定的语言环境,该函数将返回false)。

But then there will be a last obstacle to cope with:

但随后将面临最后一个障碍:

The locale information is maintained per process, not per thread. If you are running PHP on a multithreaded server api like IIS or Apache on Windows you may experience sudden changes of locale settings while a script is running although the script itself never called setlocale() itself. This happens due to other scripts running in different threads of the same process at the same time changing the processwide locale using setlocale().

每个进程维护区域设置信息,而不是每个线程。如果您在Windows上的IIS或Apache等多线程服务器api上运行PHP,则在脚本运行时可能会遇到区域设置的突然更改,尽管脚本本身从未调用过setlocale()本身。这是因为在同一进程的不同线程中运行的其他脚本同时使用setlocale()更改了进程范围的语言环境。

(see: http://de2.php.net/manual/en/function.setlocale.php)

This means that you could experience sudden locale changes during the execution of a script because another user with a different locale set just hit your webpage.

这意味着您可以在执行脚本期间遇到突然的区域设置更改,因为具有不同区域设置的其他用户只会访问您的网页。

Therefore the mentioned Zend_Locale does not rely on the PHP function setlocale() (it's only used to retrieve the system locale information) but instead uses a system based on the data provided by the Unicode CLDR Project. This makes the component independent from all those setlocale() issues but this also introduces some other deficiencies such as the lack of support for locale-aware string operations (sorting for example).

因此,提到的Zend_Locale不依赖于PHP函数setlocale()(它仅用于检索系统区域设置信息),而是使用基于Unicode CLDR项目提供的数据的系统。这使得组件独立于所有setlocale()问题,但这也引入了一些其他缺陷,例如缺乏对区域设置感知字符串操作的支持(例如排序)。

#3


2  

I know the Zend framework has a method to do this, but I'd rather not install the whole framework just to use that one bit of functionality.

我知道Zend框架有一个方法可以做到这一点,但我宁愿不安装整个框架只是为了使用那一点功能。

The good news about Zend is, you don't need to install it all. It's a losely coupled framework and you can just make use of Zend_Locale without using any of the other components. Maybe you want to combine it with Zend_Translate.

关于Zend的好消息是,你不需要全部安装它。它是一个丢失耦合的框架,您可以在不使用任何其他组件的情况下使用Zend_Locale。也许你想把它与Zend_Translate结合起来。

Check it out

看看这个

#4


1  

There's http_negotiate_language, but it depends on the http-extension. Alternatively, see the comments on the manual page, for a userland implementation.

有http_negotiate_language,但它取决于http扩展名。或者,请参阅手册页上的注释,以获取用户态实现。

#1


2  

Nice solution is on its way.

好的解决方案即将推出。

Without that you'll need to parse that header. It's a comma-separated list of semicolon-separated locales and attributes.

如果没有它,您将需要解析该标头。它是以逗号分隔的以分号分隔的区域设置和属性的列表。

It can look like this:

它看起来像这样:

en_US, en;q=0.8, fr_CA;q=0.2, *;q=0.1

and then try each locale until setlocale() accepts it. Be prepared that none of them may match.

然后尝试每个语言环境,直到setlocale()接受它。做好准备,没有一个可以匹配。

Don't base on it anything too important or allow users to override it, because some users may have misconfigured browsers.

不要基于它太重要或允许用户覆盖它,因为一些用户可能有错误配置的浏览器。


For Windows locale, perhaps you need to convert ISO 639-1 names to ISO 639-2/3?

对于Windows语言环境,您可能需要将ISO 639-1名称转换为ISO 639-2 / 3吗?

#2


5  

It's not as easy as it should be (in my humble opinion). First of all you have to extract the locales from the $_SERVER['HTTP_ACCEPT_LANGUAGE'] and sort them by their q values. Afterwards you have to retrieve the appropriate system locale for each of the given locales, which should be no problem on a *nix machine (you only might have to cope with the correct charset) but on Windows you'll have to translate the locales into Windows locales, e.g. de_DE will be German_Germany (again you also have to cope with charset issues if you're using UTF-8 in your app for example). I think you'll have to build a lookup table for this issue - and there are a lot of locales ;-)

它并不像它应该那么容易(以我的拙见)。首先,您必须从$ _SERVER ['HTTP_ACCEPT_LANGUAGE']中提取区域设置,并按q值对其进行排序。之后你必须为每个给定的语言环境检索适当的系统语言环境,这在* nix机器上应该没问题(你可能只需要处理正确的字符集)但是在Windows上你必须将语言环境翻译成Windows语言环境,例如de_DE将是German_Germany(例如,如果您在应用程序中使用UTF-8,则还必须处理字符集问题)。我认为你必须为这个问题构建一个查找表 - 并且有很多语言环境;-)

No you try one locale after the other (sorted with descending q values) until you find a match using setlocale() (the function will return false if the given locale could not be set).

不是你在另一个之后尝试一个语言环境(用降序q值排序),直到你找到使用setlocale()的匹配(如果无法设置给定的语言环境,该函数将返回false)。

But then there will be a last obstacle to cope with:

但随后将面临最后一个障碍:

The locale information is maintained per process, not per thread. If you are running PHP on a multithreaded server api like IIS or Apache on Windows you may experience sudden changes of locale settings while a script is running although the script itself never called setlocale() itself. This happens due to other scripts running in different threads of the same process at the same time changing the processwide locale using setlocale().

每个进程维护区域设置信息,而不是每个线程。如果您在Windows上的IIS或Apache等多线程服务器api上运行PHP,则在脚本运行时可能会遇到区域设置的突然更改,尽管脚本本身从未调用过setlocale()本身。这是因为在同一进程的不同线程中运行的其他脚本同时使用setlocale()更改了进程范围的语言环境。

(see: http://de2.php.net/manual/en/function.setlocale.php)

This means that you could experience sudden locale changes during the execution of a script because another user with a different locale set just hit your webpage.

这意味着您可以在执行脚本期间遇到突然的区域设置更改,因为具有不同区域设置的其他用户只会访问您的网页。

Therefore the mentioned Zend_Locale does not rely on the PHP function setlocale() (it's only used to retrieve the system locale information) but instead uses a system based on the data provided by the Unicode CLDR Project. This makes the component independent from all those setlocale() issues but this also introduces some other deficiencies such as the lack of support for locale-aware string operations (sorting for example).

因此,提到的Zend_Locale不依赖于PHP函数setlocale()(它仅用于检索系统区域设置信息),而是使用基于Unicode CLDR项目提供的数据的系统。这使得组件独立于所有setlocale()问题,但这也引入了一些其他缺陷,例如缺乏对区域设置感知字符串操作的支持(例如排序)。

#3


2  

I know the Zend framework has a method to do this, but I'd rather not install the whole framework just to use that one bit of functionality.

我知道Zend框架有一个方法可以做到这一点,但我宁愿不安装整个框架只是为了使用那一点功能。

The good news about Zend is, you don't need to install it all. It's a losely coupled framework and you can just make use of Zend_Locale without using any of the other components. Maybe you want to combine it with Zend_Translate.

关于Zend的好消息是,你不需要全部安装它。它是一个丢失耦合的框架,您可以在不使用任何其他组件的情况下使用Zend_Locale。也许你想把它与Zend_Translate结合起来。

Check it out

看看这个

#4


1  

There's http_negotiate_language, but it depends on the http-extension. Alternatively, see the comments on the manual page, for a userland implementation.

有http_negotiate_language,但它取决于http扩展名。或者,请参阅手册页上的注释,以获取用户态实现。