请注意,由于代理限制,我无法使用服务器脚本,所以我想JavaScript或ActionScript可能是解决这个问题的合适方法。
问题:
1. “猜测”用户的区域设置的最佳方法是什么? 2. 是否有任何现有的简单类/函数可以帮助我(不使用复杂的本地化包)?特别是以一种聪明的方式将所有可能的语言缩减为较少的数量(我已经有了翻译)。 3. 我能够对这样的解决方案有多大的信任? 4. 是否有其他解决方法或建议?
正确的方法是查看发送到服务器的HTTP Accept-Language 标头。这个标头包含了用户在浏览器中配置的偏好语言的有序、加权列表。
不幸的是,JavaScript 中无法读取此标头。您只能使用navigator.language
,该属性告诉您安装的本地化版本的 Web 浏览器。这并不一定是用户首选的语言。在 IE 上,您可以获取systemLanguage
(操作系统安装的语言)、browserLanguage
(与language
相同)和userLanguage
(用户配置的操作系统区域),它们都没有什么帮助。
如果我必须在这些属性之间进行选择,我会首先检测userLanguage
,然后回退到language
,仅当这两个属性没有匹配任何可用语言时,才查看browserLanguage
,最后是systemLanguage
。
如果您可以在其他网络位置上放置一个服务器端脚本,该脚本仅读取 Accept-Language 标头并将其作为 JavaScript 文件输出,并在字符串中包含标头值,例如:
var acceptLanguage= 'en-gb,en;q=0.7,de;q=0.3';
如果你想要在HTML中包含指向外部服务的<script src>,并使用JavaScript解析语言标头,那么可以这样做。不过我不知道是否有现成的库可以完成此操作,因为Accept-Language解析通常是在服务器端完成的。
无论你最终选择了哪种方法,你肯定需要提供用户自定义设置选项,因为对于某些人来说,猜测可能总是错误的。通常最简单的方法是将语言设置放在URL中(例如,http://www.example.com/en/site vs http://www.example.com/de/site),并让用户在两者之间点击链接。有时候你确实需要一个单一的URL来支持两种语言版本,在这种情况下,你必须将设置存储在cookie中,但这可能会使不支持cookie和搜索引擎的用户代理产生困惑。
navigator.languages //["en-US", "zh-CN", "ja-JP"]
这应该在2020年至少适用于95%的浏览器。 - Cornelius Roemernavigator.languages
现在可在所有主要浏览器中使用。如果需要最现代化且向后兼容的方法,请尝试使用体积小(约200字节)的navigator-languages包。 - mindplay.dknavigator.languages
相同,而navigator.language
是数组的第一个元素。顺便说一下,在大多数浏览器中,navigator.language
早在很久以前就得到了支持。 - bora89Navigator.languages
包含一个以用户偏好顺序排列的区域设置数组,并且比 navigator.language
更准确,然而为了实现向后兼容性(已测试在 Chrome / IE / Firefox / Safari 上),请使用以下代码:function getLang() {
if (navigator.languages != undefined)
return navigator.languages[0];
return navigator.language;
}
return navigator.languages[0] || navigator.language;
吗? - James_return (navigator.languages && navigator.languages.length) ? navigator.languages[0] : navigator.language;
。否则,如果navigator.languages
未定义或为空,将会抛出异常。 - Max Truxaconst getLang = () => (navigator.language || navigator.browserLanguage || (navigator.languages || ["en"])[0]);
- João Miguel Brandão这篇文章提出了以下浏览器navigator对象的属性:
navigator.language
(Netscape - 浏览器本地化)navigator.browserLanguage
(IE-Specific - 浏览器本地化语言)navigator.systemLanguage
(IE-Specific - Windows OS - 本地化语言)navigator.userLanguage
将它们合并成一个JavaScript函数,你应该能够在大多数情况下猜到正确的语言。一定要优雅地降级,因此请使用包含语言选择链接的div,以便如果没有JavaScript或方法不起作用,则用户仍然可以进行选择。如果它确实起作用,请隐藏div。
在客户端执行此操作的唯一问题是,您必须为客户端提供所有语言,或者等待脚本运行并检测到语言后再请求正确的版本。也许默认提供最受欢迎的语言版本会使最少的人感到烦恼。
编辑:我赞同Ivan的cookie建议,但请确保用户始终可以稍后更改语言;不是每个人都喜欢浏览器默认的语言。
const getNavigatorLanguage = () => {
if (navigator.languages && navigator.languages.length) {
return navigator.languages[0];
} else {
return navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en';
}
}
navigator.languages
数组的第一个元素。
然后我们获取 navigator.userLanguage
或者 navigator.language
。
如果这个失败了,我们获取 navigator.browserLanguage
。
最后,如果其他方法都失败了,我们将其设置为 'en'
。
const getNavigatorLanguage = () => (navigator.languages && navigator.languages.length) ? navigator.languages[0] : navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en';
navigator.userLanguage
(适用于IE)的东西。你可以添加它以使其完整 :) - porsnavigator.languages[0] || navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en'
? - Emericnavigator.languages
可能是undefined
,所以会出现这种情况。 - Zenoo(navigator.languages || [])[0] || navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en'
- Steve Bennett用户的首选语言和系统/浏览器区域设置之间有所不同。
用户可以在浏览器中配置首选语言,并且这些语言将用于 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 实例,然后读取这些已解决选项的区域设置。
navigator.language
返回de-DE(这是我的系统设置),但所有日期和数字都以en-US格式显示(这是我的浏览器设置),这个答案正确地确定了这一点。 - Philzen我使用了所有的答案,创建了一种单行解决方案:
const getLanguage = () => navigator.userLanguage || (navigator.languages && navigator.languages.length && navigator.languages[0]) || navigator.language || navigator.browserLanguage || navigator.systemLanguage || 'en';
console.log(getLanguage());
你可以尝试从文档中获取语言,这可能是你的首选,然后再退而求其次,因为通常人们希望他们的JS语言与文档语言相匹配。
HTML5:
document.querySelector('html').getAttribute('lang')
旧版:
document.querySelector('meta[http-equiv=content-language]').getAttribute('content')
没有真正可靠的来源,因为人们可能会简单地输入错误的语言。
有一些语言检测库可以根据内容帮助你确定语言。
将此从JavaScript检测浏览器语言偏好移植过来
https://dev59.com/j3NA5IYBdhLWcg3wPLL-#42649975
我刚想出这个。它结合了更新的JS解构语法和一些标准操作来检索语言和区域设置。
var [lang, locale] = (
(
(
navigator.userLanguage || navigator.language
).replace(
'-', '_'
)
).toLowerCase()
).split('_');
希望对某些人有所帮助
**更新:** 我还建议测试并结合其他答案,例如https://dev59.com/CHRB5IYBdhLWcg3wSVYI#52112155,这似乎是获取语言更健壮的方式。我们还有空值合并运算符??
,因此||
可能不是最好的方法。我想象这会像这样
var [lang, locale] = (
(
getBrowserLanguage()
.replace('-', '_')
).toLowerCase()
).split('_');
getBrowserLanguage
称为getNavigatorLanguage
,这是故意的。也许您使用navigator,但未来可能会出现其他情况。这确实是一种偏好。无论如何,我希望这仍然有用。你说你的网站有Flash,那么作为另一个选项,你可以使用flash.system.Capabilities.language
获取操作系统的语言—请参见如何在浏览器中确定操作系统语言来猜测操作系统的区域设置。