【问题标题】:How to determine user's locale within browser?如何在浏览器中确定用户的语言环境?
【发布时间】:2010-10-15 00:08:43
【问题描述】:

我有一个本地化为十几种语言的网站 (Flash),我想根据用户的浏览器设置自动定义一个默认值,以最大限度地减少访问内容的步骤。

仅供参考,由于代理限制,我无法使用服务器脚本,所以我想 JavaScript 或 ActionScript 可以解决这个问题。

问题:

  1. “猜测”用户所在地区的最佳方法是什么?

  2. 是否有任何现有的简单类/函数可以帮助我(没有复杂的本地化包)?尤其是以一种巧妙的方式将所有可能的语言(我拥有的翻译)减少到一个较小的数量。

  3. 我可以信任这样的解决方案到什么程度?

  4. 还有其他解决方法或建议吗?

【问题讨论】:

  • 浏览器可以共享有关其用户和请求的元数据的唯一方法是通过 URL 和标头。抓住 Firefox 并查看发出请求时发送的标头。检查典型的请求和响应标头非常有趣。

标签: javascript flash browser localization


【解决方案1】:

正确的方法是查看发送到服务器的 HTTP Accept-Language 标头。这包含用户已将其浏览器配置为首选语言的有序加权列表。

很遗憾,此标头无法在 JavaScript 中读取;你得到的只是navigator.language,它告诉你安装了哪个本地化版本的网络浏览器。这不一定与用户的首选语言相同。在 IE 上,您会得到 systemLanguage(操作系统安装的语言)、browserLanguage(与 language 相同)和 userLanguage(用户配置的操作系统区域),这些都同样没有帮助。

如果我必须在这些属性之间进行选择,我会先嗅探userLanguage,然后返回到language,然后再查看browserLanguage(如果这些属性与任何可用语言不匹配),最后再查找browserLanguage systemLanguage.

如果您可以将服务器端脚本放在网络上的其他位置,该脚本只需读取 Accept-Language 标头并将其作为 JavaScript 文件返回,并在字符串中包含标头值,例如:

var acceptLanguage= 'en-gb,en;q=0.7,de;q=0.3';

那么您可以在 HTML 中包含一个指向该外部服务的

无论你最终做什么,你肯定需要一个用户覆盖,因为它总是会被某些人猜错。通常将语言设置放在 URL 中是最简单的(例如 http​://www.example.com/en/site vs http​://www.example.com/de/site),然后让用户点击两者之间的联系。有时您确实希望两种语言版本都有一个 URL,在这种情况下,您必须将设置存储在 cookie 中,但这可能会使不支持 cookie 和搜索引擎的用户代理感到困惑。

【讨论】:

  • From MDN developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/… "来自用户浏览器的每个 HTTP 请求中的 Accept-Language HTTP 标头对 navigator.languages 属性使用相同的值,除了额外的 qvalues(质量值)字段(例如zh-CN;q=0.8)。”
  • 更新:现在 (2020) 有一个实验性功能,所有现代浏览器都支持它返回一组语言偏好:navigator.languages //["en-US", "zh-CN", "ja-JP"] 这应该在 2020 年至少适用于 95% 的浏览器。跨度>
  • navigator.languages,根据MDNcaniuse.com,现在在所有主要浏览器中都可用 - 尝试最现代和向后的微型(~200 字节)navigator-languages 包 -兼容的方法。
【解决方案2】:

在 Chrome 和 Firefox 32+ 上,navigator.languages 包含按用户偏好顺序排列的语言环境数组,并且比 navigator.language 更准确,但是为了使其向后兼容(经过测试的 Chrome / IE / Firefox / Safari ),然后使用这个:

function getLang() {
  if (navigator.languages != undefined) 
    return navigator.languages[0]; 
  return navigator.language;
}

【讨论】:

  • 这不适用于 IE9 和 IE10。对于他们,您必须改为检查 navigator.browserLanguage。
  • OneLiner : function getLang(){ return ( navigator.language || navigator.languages[0] ); }
  • @ChStark 不应该是return navigator.languages[0] || navigator.language;吗?
  • 另外,正确的“单行”看起来像这样:return (navigator.languages && navigator.languages.length) ? navigator.languages[0] : navigator.language;。否则,如果 navigator.languages 未定义或为空,则会出现异常。
  • 更紧凑的版本const getLang = () => navigator.language || navigator.browserLanguage || ( navigator.languages || [ "en" ] ) [ 0 ]
【解决方案3】:

This article 建议浏览器 navigator 对象的以下属性:

  • navigator.language(网景 - 浏览器本地化)
  • navigator.browserLanguage(特定于 IE - 浏览器本地化语言)
  • navigator.systemLanguage(特定于 IE - Windows 操作系统 - 本地化语言)
  • navigator.userLanguage

将这些滚动到 javascript 函数中,在大多数情况下,您应该能够猜出正确的语言。一定要优雅地降级,所以有一个 div 包含你的语言选择链接,这样如果没有 javascript 或方法不起作用,用户仍然可以决定。如果它确实有效,只需隐藏 div。

在客户端执行此操作的唯一问题是,您要么向客户端提供所有语言,要么必须等到脚本运行并检测到语言才能请求正确的版本。也许默认提供最流行的语言版本会激怒最少的人。

编辑:我同意 Ivan 的 cookie 建议,但要确保用户以后可以随时更改语言;不是每个人都喜欢他们的浏览器默认使用的语言。

【讨论】:

  • 感谢菲尔的建议。关于这篇文章,它已经有 6 年历史了......不确定我们是否可以依赖它?
  • 我怀疑现代浏览器都支持navigator.language。我的浏览器(Ubuntu 8.10 上的 FF3)报告“en-GB”。如果有人仍在使用 IE6(大约 20% 的人),那么值得允许这样做。 IE6 出现在 8 年前。
  • IE 8 不支持 navigator.language。也许 IE 9 会?
【解决方案4】:

结合浏览器用来存储用户语言的多种方式,你得到了这个功能:

const getNavigatorLanguage = () => {
  if (navigator.languages && navigator.languages.length) {
    return navigator.languages[0];
  } else {
    return navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en';
  }
}

我们首先检查 navigator.languages 数组的第一个元素。
然后我们得到navigator.userLanguagenavigator.language
如果失败,我们会得到navigator.browserLanguage
最后,如果一切都失败了,我们将其设置为'en'


这是性感的单眼线:

const getNavigatorLanguage = () => (navigator.languages && navigator.languages.length) ? navigator.languages[0] : navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en';

【讨论】:

  • 显然还有 navigator.userLanguage (对于 IE)。您可以添加它以使其完整:)
  • 为什么不简单地navigator.languages[0] || navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en'
  • @Curse 因为navigator.languages 可以是undefined
  • @Zenoo 你知道在哪些浏览器上?
  • (navigator.languages || [])[0] || navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en'
【解决方案5】:

用户的首选语言与系统/浏览器区域设置之间存在差异。

用户可以在浏览器中配置首选语言,这些将用于navigator.language(s),并在从服务器请求资源时使用,以根据语言优先级列表请求内容。

但是,浏览器区域设置将决定如何呈现数字、日期、时间和货币。此设置可能是排名最高的语言,但不能保证。在 Mac 和 Linux 上,区域设置由系统决定,而与用户语言偏好无关。在 Windows 上,可以在 Chrome 上的首选列表中选择语言。

通过使用 Intl (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl),开发人员可以覆盖/设置用于渲染这些内容的语言环境,但有些元素不能被覆盖,例如 <input type="date"> 格式。

要正确提取这种语言,我发现的唯一方法是:

(new Intl.NumberFormat()).resolvedOptions().locale

Intl.NumberFormat().resolvedOptions().locale 似乎也可以)

这将为默认语言环境创建一个新的 NumberFormat 实例,然后读回这些已解析选项的语言环境。

【讨论】:

    【解决方案6】:

    我使用了所有答案并创建了一个单行解决方案:

    const getLanguage = () => navigator.userLanguage || (navigator.languages && navigator.languages.length && navigator.languages[0]) || navigator.language || navigator.browserLanguage || navigator.systemLanguage || 'en';
    
    console.log(getLanguage());
    

    【讨论】:

      【解决方案7】:

      我对此进行了一些研究,并在下表中总结了我迄今为止的发现

      因此推荐的解决方案是编写一个服务器端脚本来解析Accept-Language 标头并将其传递给客户端以设置网站的语言。奇怪的是,为什么需要服务器来检测客户端的语言偏好,但到目前为止就是这样。还有其他各种黑客可用于检测语言,但根据我的理解,阅读 Accept-Language 标头是推荐的解决方案。

      【讨论】:

        【解决方案8】:

        您也可以尝试从文档中获取可能是您的第一个停靠点的语言,然后回退到其他方式,因为人们通常希望他们的 JS 语言与文档语言相匹配。

        HTML5:

        document.querySelector('html').getAttribute('lang')

        旧版:

        document.querySelector('meta[http-equiv=content-language]').getAttribute('content')

        没有真正的来源一定是 100% 可靠的,因为人们可能只是用错误的语言输入。

        有一些语言检测库可以让您根据内容确定语言。

        【讨论】:

          【解决方案9】:

          您说您的网站有 Flash,那么作为另一种选择,您可以使用 flash.system.Capabilities.language 获取操作系统的语言——请参阅 How to determine OS language within browser猜测操作系统区域设置。

          【讨论】:

            【解决方案10】:

            您可以使用 http 或 https。

            https://ip2c.org/XXX.XXX.XXX.XXX 要么 https://ip2c.org/?ip=XXX.XXX.XXX.XXX |

            • 从 0.0.0.0 到 255.255.255.255 的标准 IPv4

            https://ip2c.org/s 要么 https://ip2c.org/self 要么 https://ip2c.org/?self |

            • 处理调用者的 IP
            • 比 ?dec= 选项更快,但仅限于一个目的 - 提供有关您自己的信息

            参考: https://about.ip2c.org/#inputs

            【讨论】:

            • 这似乎与问题完全无关
            猜你喜欢
            • 2011-01-19
            • 2020-01-24
            • 2016-09-10
            • 2011-05-27
            • 1970-01-01
            • 1970-01-01
            • 2019-12-31
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多