用Accept-Language确定用户的区域设置

问题

是否应该用HTTP的Accept-Language标头(header)来确定用户的区域设置?

背景

出于许多完全正当的原因,一些Web应用希望给每个用户关联一个区域设置(locale),这样这些Web应用就能够以用户的本地格式提供信息。其中一些信息对于传统软件的区域设置很常见,如:

在其他情况下,其他信息可以从区域设置信息加上附加知识得出,例如:

由于HTTP协议中没有包含这些内容,许多Web开发者用Accept-Language标头来推断用户的区域设置。

Accept-Language标头是请求文档时通过HTTP传递的用户语言偏好设置信息。在主流浏览器中,用户可修改语言偏好设置。该值由BCP 47定义,通常为两个或三个字母的语言代码(例如fr代表法语),后跟代表国家/地区等内容的可选子代码(例如fr-CA代表加拿大使用的法语)。

问题在于这个信息是否适合确定用户的区域设置。

答案

HTTP的Accept-Language标头最初只是用来指定用户的语言。然而,由于许多应用需要知道用户的区域设置,一种常见的做法是用Accept-Language来确定区域设置信息。只使用Accept-Language标头来确定用户的区域设置并不是一个好主意,因为这可能把用户束缚在一系列不符合其喜好的选择中。

对于网站的初次访问者,使用Accept-Language值来推断区域设置可能是一个很好的起点,但请务必让他们根据需要更改语言,并在必要时更准确地指定其区域设置,并将结果存储在数据库或cookie中以供以后访问。

一些潜在的问题包括:

顺便一提

用Accept-Language标头也是确定用户语言(而不是区域设置)的一个好的起点,但即便如此,你也需要了解其局限性,并且为用户提供更改你所做的假设的方法。上面列出的很多潜在问题也适用于这种情况。

即使你不是有意对区域设置做出了假设,你的编程环境可能会代表你做出此类假设。默认情况下,许多Web服务器、服务器端语言和环境从Accept-Language解析并推断它们的原生区域设置对象。例如,.NET使用Accept-Language来确定默认的CultureInfo,Java Servlet提供了一对解析Accept-Language的getLocale()和getLocales()方法等等。这些对象对于获取资源和“语言偏好”非常有用。正如上面所指出的,它们在确定用户的许多细粒度属性或设计网站的国际化行为时用处不大。语言偏好是es-MX并不一定代表应该使用墨西哥的地址格式显示或者验证表单。用户可能居住在美国(或其他地方)。