JavaScript для определения языковых предпочтений браузера
Я пытался определить предпочтения языка браузера с помощью JavaScript.
Если я установлю язык браузера в IE в Tools>Internet Options>General>Languages
Как я могу прочитать это значение с помощью JavaScript?
Та же проблема для Firefox. Я не могу определить настройки для tools>options>content>languages
с помощью navigator.language
,
С помощью navigator.userLanguage
, он обнаруживает настройку, выполненную черезStart>ControlPanel>RegionalandLanguageOptions>Regional Options
Вкладка.
Я проверил с navigator.browserLanguage
а также navigator.systemLanguage
но ни один не возвращает значение для первой настройки (Tools>InternetOptions>General>Languages
)
Я нашел ссылку, которая обсуждает это подробно, но вопрос остается без ответа:(
26 ответов
Я думаю, что основная проблема заключается в том, что настройки браузера на самом деле не влияют на navigator.language
свойство, которое получается с помощью JavaScript.
На что они влияют, так это на HTTP-заголовок "Accept-Language", но, похоже, это значение вообще недоступно через javascript. (Вероятно, поэтому @anddoutoi утверждает, что не может найти для него ссылку, которая не затрагивает серверную часть.)
Я кодировал обходной путь: я запустил скрипт механизма приложений Google на http://ajaxhttpheaders.appspot.com/, который вернет вам заголовки HTTP-запроса через JSONP.
(Примечание: этот хак используется только в том случае, если у вас нет доступной серверной части, которая могла бы сделать это за вас. В общем, вам не следует звонить на сторонние размещенные файлы javascript на ваших страницах, если у вас не очень высокий уровень уровень доверия к хозяину.)
Я намерен оставить его там навсегда, поэтому не стесняйтесь использовать его в своем коде.
Вот пример кода (в jQuery) о том, как вы можете его использовать
$.ajax({
url: "http://ajaxhttpheaders.appspot.com",
dataType: 'jsonp',
success: function(headers) {
language = headers['Accept-Language'];
nowDoSomethingWithIt(language);
}
});
Надеюсь, кто-то найдет это полезным.
Изменить: я написал небольшой плагин JQuery на GitHub, который оборачивает эту функциональность: https://github.com/dansingerman/jQuery-Browser-Language
Редактировать 2: В соответствии с просьбой, вот код, который работает на AppEngine (действительно тривиально):
class MainPage(webapp.RequestHandler):
def get(self):
headers = self.request.headers
callback = self.request.get('callback')
if callback:
self.response.headers['Content-Type'] = 'application/javascript'
self.response.out.write(callback + "(")
self.response.out.write(headers)
self.response.out.write(")")
else:
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write("I need a callback=")
application = webapp.WSGIApplication(
[('/', MainPage)],
debug=False)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
Edit3: Откройте исходный код движка приложения здесь: https://github.com/dansingerman/app-engine-headers
var language = window.navigator.userLanguage || window.navigator.language;
alert(language); //works IE/SAFARI/CHROME/FF
window.navigator.userLanguage
только для IE, и это язык, установленный в Панели управления Windows - Региональные параметры, а НЕ язык браузера, но можно предположить, что пользователь, использующий машину с региональными настройками Windows, установленными во Францию, вероятно, является французским пользователем.
navigator.language
есть FireFox и все остальные браузеры.
Некоторый код языка: 'it'
= италия, 'en-US'
= английский США и т. д.
Как отмечено rcoup и The WebMacheter в комментариях ниже, этот обходной путь не позволит вам различать диалекты английского языка, когда пользователи просматривают веб-сайты в браузерах, отличных от IE.
window.navigator.language
(Chrome / FF / Safari) всегда возвращает язык браузера, а не предпочитаемый браузером язык, но: "для носителей английского языка (gb, au, nz и т. Д.) Довольно характерно иметь версию Firefox/Chrome/Safari для en-us". следовательно window.navigator.language
все еще вернется en-US
даже если пользователь предпочитает язык en-GB
,
Обновление 2014 года.
Теперь есть способ получить Accept-Languages в Firefox и Chrome, используя navigator.languages (работает в Chrome >= 32 и Firefox >= 32)
Кроме того, navigator.language в Firefox в эти годы отражает наиболее предпочтительный язык контента, а не язык пользовательского интерфейса. Но поскольку это понятие еще не поддерживается другими браузерами, оно не очень полезно.
Итак, чтобы получить наиболее предпочтительный язык контента, когда это возможно, и использовать язык интерфейса в качестве запасного варианта:
navigator.languages
? navigator.languages[0]
: (navigator.language || navigator.userLanguage)
Я наткнулся на этот фрагмент кода для определения языка браузера в модуле Angular Translate, который вы можете найти здесь. Я немного изменил код, заменив angular.isArray на Array.isArray, чтобы сделать его независимым от библиотеки Angular.
var getFirstBrowserLanguage = function () {
var nav = window.navigator,
browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'],
i,
language;
// support for HTML 5.1 "navigator.languages"
if (Array.isArray(nav.languages)) {
for (i = 0; i < nav.languages.length; i++) {
language = nav.languages[i];
if (language && language.length) {
return language;
}
}
}
// support for other well known properties in browsers
for (i = 0; i < browserLanguagePropertyKeys.length; i++) {
language = nav[browserLanguagePropertyKeys[i]];
if (language && language.length) {
return language;
}
}
return null;
};
console.log(getFirstBrowserLanguage());
<script type="text/javascript">
var lang = window.navigator.languages ? window.navigator.languages[0] : null;
lang = lang || window.navigator.language || window.navigator.browserLanguage || window.navigator.userLanguage;
if (lang.indexOf('-') !== -1)
lang = lang.split('-')[0];
if (lang.indexOf('_') !== -1)
lang = lang.split('_')[0];
</script>
Мне нужен только основной компонент для моих нужд, но вы можете легко использовать полную строку. Работает с последними версиями Chrome, Firefox, Safari и IE10+.
var language = navigator.languages && navigator.languages[0] || // Chrome / Firefox
navigator.language || // All browsers
navigator.userLanguage; // IE <= 10
console.log(language);
- https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/languages
- https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/language
Попробуйте шаблон PWA https://github.com/StartPolymer/progressive-web-app-template
navigator.userLanguage
для IE
window.navigator.language
для Firefox/ Opera/ Safari
Я уже некоторое время использую ответ Хамида, но это в тех случаях, когда массив languages похож на ["en", "en-GB", "en-US", "fr-FR", "fr", "en-ZA"] будет возвращать" en ", когда" en-GB "будет лучшим совпадением.
Мое обновление (ниже) вернет первый длинный форматный код, например, "en-GB", в противном случае он вернет первый короткий код, например, "en", иначе вернет ноль.
function getFirstBrowserLanguage() {
var nav = window.navigator,
browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'],
i,
language,
len,
shortLanguage = null;
// support for HTML 5.1 "navigator.languages"
if (Array.isArray(nav.languages)) {
for (i = 0; i < nav.languages.length; i++) {
language = nav.languages[i];
len = language.length;
if (!shortLanguage && len) {
shortLanguage = language;
}
if (language && len>2) {
return language;
}
}
}
// support for other well known properties in browsers
for (i = 0; i < browserLanguagePropertyKeys.length; i++) {
language = nav[browserLanguagePropertyKeys[i]];
len = language.length;
if (!shortLanguage && len) {
shortLanguage = language;
}
if (language && len > 2) {
return language;
}
}
return shortLanguage;
}
console.log(getFirstBrowserLanguage());
Я только что придумал это. Он сочетает в себе новый синтаксис деструктуризации JS с несколькими стандартными операциями для извлечения языка и локали.
var [lang, locale] = (((navigator.userLanguage || navigator.language).replace('-', '_')).toLowerCase()).split('_');
Надеюсь, это поможет кому-то
Не существует приличного способа получить эту настройку, по крайней мере, не зависящей от браузера.
Но сервер имеет эту информацию, потому что он является частью заголовка HTTP-запроса (поле Accept-Language, см. http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html)
Таким образом, единственный надежный способ - получить ответ с сервера. Вам понадобится что-то, что работает на сервере (например.asp, .jsp, .php, CGI), и эта "вещь" может вернуть эту информацию. Хорошие примеры здесь: http://www.developershome.com/wap/detection/detection.asp?page=readHeader
У меня была та же проблема, и я написал следующую библиотеку только для внешнего интерфейса, которая оборачивает код для нескольких браузеров. Это не так много кода, но приятно не копировать и вставлять один и тот же код на нескольких сайтах.
Получите это: acceptlanguages.js
Используй это:
<script src="acceptedlanguages.js"></script>
<script type="text/javascript">
console.log('Accepted Languages: ' + acceptedlanguages.accepted);
</script>
Он всегда возвращает массив, упорядоченный по предпочтениям пользователя. В Safari & IE массив всегда имеет одну длину. В FF и Chrome это может быть несколько языков.
Прежде всего, извините за мой английский. Я хотел бы поделиться своим кодом, потому что он работает, и он отличается от других, которые дают ответы. В этом примере, если вы говорите по-французски (Франция, Бельгия или другой французский язык), вы будете перенаправлены на французскую страницу, в противном случае на английскую страницу, в зависимости от конфигурации браузера:
<script type="text/javascript">
$(document).ready(function () {
var userLang = navigator.language || navigator.userLanguage;
if (userLang.startsWith("fr")) {
window.location.href = '../fr/index.html';
}
else {
window.location.href = '../en/index.html';
}
});
</script>
Я не могу найти ни одной ссылки, в которой говорится, что это возможно без участия сервера.
MSDN на:
- навигатор. Язык браузера
- навигатор. systemLanguage
- навигатор. UserLanguage
Из браузера Язык:
В Microsoft Internet Explorer 4.0 и более ранних версиях свойство browserLanguage отражает язык пользовательского интерфейса установленного браузера. Например, если вы установите японскую версию Windows Internet Explorer в операционной системе на английском языке, browserLanguage будет иметь значение ja.
Однако в Internet Explorer 5 и более поздних версиях свойство browserLanguage отражает язык операционной системы независимо от установленной языковой версии Internet Explorer. Тем не менее, если установлена версия Microsoft Windows 2000 MultiLanguage, свойство browserLanguage указывает язык, установленный в текущих меню и диалоговых окнах операционной системы, как указано в разделе "Региональные параметры панели управления". Например, если вы установите японскую версию Internet Explorer 5 в операционной системе на английском языке (Великобритания), browserLanguage будет en-gb. Если вы установите версию для Windows 2000 MultiLanguage и установите язык меню и диалогов на французский, то browserLanguage будет французским, даже если у вас есть версия Internet Explorer на японском языке.
Примечание. Это свойство не указывает язык или языки, установленные пользователем в "Языковых настройках", расположенных в диалоговом окне "Свойства обозревателя".
Кроме того, это выглядит как browserLanguage
устарела, потому что IE8 не перечисляет его
Если вы разрабатываете приложение / расширение Chrome, используйте API chrome.i18n.
chrome.i18n.getAcceptLanguages(function(languages) {
console.log(languages);
// ["en-AU", "en", "en-US"]
});
Javascript способ:
var language = window.navigator.userLanguage || window.navigator.language;//returns value like 'en-us'
Если вы используете плагин jQuery.i18n, вы можете использовать:
jQuery.i18n.browserLang();//returns value like '"en-US"'
Если вам нужно только поддерживать определенные современные браузеры, то теперь вы можете использовать:
navigator.languages
который возвращает массив языковых предпочтений пользователя в порядке, указанном пользователем.
На данный момент (сентябрь 2014 г.) это работает для: Chrome (v37), Firefox (v32) и Opera (v24)
Но не на: IE (v11)
Что бы это ни стоило, библиотека Wikimedia Universal Language Selector имеет хуки для этого: https://www.mediawiki.org/wiki/Extension:UniversalLanguageSelector
Смотрите функцию getFrequentLanguageList в ресурсах /js/ext.uls.init.js . Прямая ссылка: https://gerrit.wikimedia.org/r/gitweb?p=mediawiki/extensions/UniversalLanguageSelector.git;a=blob;f=resources/js/ext.uls.init.js;hb=HEAD
Это все еще зависит от сервера или, более конкретно, API MediaWiki. Причина, по которой я показываю это, заключается в том, что он может послужить хорошим примером получения всей полезной информации о языке пользователя: языке браузера, Accept-Language, геолокации (с получением информации о стране / языке из CLDR) и, конечно же, Пользовательские настройки сайта.
У DanSingerman есть очень хорошее решение для этого вопроса.
Единственный надежный источник для языка находится в заголовке HTTP-запроса. Таким образом, вам нужен серверный скрипт для ответа на заголовок запроса или, по крайней мере, Accept-Language
поле обратно к вам.
Вот очень простой сервер Node.js, который должен быть совместим с плагином DanSingermans jQuery.
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(JSON.stringify(req.headers));
}).listen(80,'0.0.0.0');
В ответе Дана Сингермана есть проблема, заключающаяся в том, что извлеченный заголовок должен использоваться сразу же из-за асинхронного характера jjuery ajax. Однако на его сервере приложений Google я написал следующее, так что заголовок устанавливается как часть первоначальной настройки и может быть использован позднее.
<html>
<head>
<script>
var bLocale='raw'; // can be used at any other place
function processHeaders(headers){
bLocale=headers['Accept-Language'];
comma=bLocale.indexOf(',');
if(comma>0) bLocale=bLocale.substring(0, comma);
}
</script>
<script src="jquery-1.11.0.js"></script>
<script type="application/javascript" src="http://ajaxhttpheaders.appspot.com?callback=processHeaders"></script>
</head>
<body>
<h1 id="bLocale">Should be the browser locale here</h1>
</body>
<script>
$("#bLocale").text(bLocale);
</script>
</html>
Если вы не хотите полагаться на внешний сервер и у вас есть собственный сервер, вы можете использовать простой сценарий PHP для достижения того же поведения, что и ответ @DanSingerman.
languageDetector.php:
<?php
$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
echo json_encode($lang);
?>
И просто измените эти строки из скрипта jQuery:
url: "languageDetector.php",
dataType: 'json',
success: function(language) {
nowDoSomethingWithIt(language);
}
Для тех, кто ищет решение Java Server
Здесь RestEasy
@GET
@Path("/preference-language")
@Consumes({"application/json", "application/xml"})
@Produces({"application/json", "application/xml"})
public Response getUserLanguagePreference(@Context HttpHeaders headers) {
return Response.status(200)
.entity(headers.getAcceptableLanguages().get(0))
.build();
}
Если у вас есть контроль над бэкэндом и вы используете django, 4-строчная реализация идеи Дэна:
def get_browser_lang(request):
if request.META.has_key('HTTP_ACCEPT_LANGUAGE'):
return JsonResponse({'response': request.META['HTTP_ACCEPT_LANGUAGE']})
else:
return JsonResponse({'response': settings.DEFAULT_LANG})
тогда в urls.py:
url(r'^browserlang/$', views.get_browser_lang, name='get_browser_lang'),
и на передней части:
$.get(lg('SERVER') + 'browserlang/', function(data){
var lang_code = data.response.split(',')[0].split(';')[0].split('-')[0];
});
(Вы должны установить DEFAULT_LANG в settings.py, конечно)
Основываясь на ответе здесь Доступ к заголовкам HTTP веб-страницы в JavaScript, я создал следующий скрипт для получения языка браузера:
var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = req.getAllResponseHeaders().toLowerCase();
var contentLanguage = headers.match( /^content-language\:(.*)$/gm );
if(contentLanguage[0]) {
return contentLanguage[0].split(":")[1].trim().toUpperCase();
}
У меня был другой подход, это может помочь кому-то в будущем:
клиент хотел страницу, где вы можете поменять языки. мне нужно было отформатировать числа с помощью этой настройки (не настройки браузера / каких-либо предопределенных настроек)
поэтому я установил начальную настройку в зависимости от настроек конфигурации (i18n)
$clang = $this->Session->read('Config.language');
echo "<script type='text/javascript'>var clang = '$clang'</script>";
позже в скрипте я использовал функцию, чтобы определить, какое форматирование мне нужно
function getLangsettings(){
if(typeof clang === 'undefined') clang = navigator.language;
//console.log(clang);
switch(clang){
case 'de':
case 'de-de':
return {precision : 2, thousand : ".", decimal : ","}
case 'en':
case 'en-gb':
default:
return {precision : 2, thousand : ",", decimal : "."}
}
}
поэтому я использовал заданный язык страницы и в качестве запасного варианта я использовал настройки браузера.
что должно быть полезно для целей тестирования.
в зависимости от ваших клиентов вам могут не понадобиться эти настройки.
Если вы используете ASP .NET MVC и хотите получить заголовок Accepted-Languages из JavaScript, то вот пример обходного пути, который не включает никаких асинхронных запросов.
В вашем файле.cshtml надежно сохраните заголовок в атрибуте данных div:
<div data-languages="@Json.Encode(HttpContext.Current.Request.UserLanguages)"></div>
Тогда ваш код JavaScript может получить доступ к информации, например, с помощью JQuery:
<script type="text/javascript">
$('[data-languages]').each(function () {
var languages = $(this).data("languages");
for (var i = 0; i < languages.length; i++) {
var regex = /[-;]/;
console.log(languages[i].split(regex)[0]);
}
});
</script>
Конечно, вы можете использовать аналогичный подход с другими серверными технологиями, как уже упоминали другие.
У меня есть взлом, который, я думаю, использует очень мало кода и довольно надежен.
Поместите файлы вашего сайта в подкаталог. SSL на ваш сервер и создайте символические ссылки на тот подкаталог, где хранятся ваши файлы с указанием ваших языков.
Что-то вроде этого:
ln -s /var/www/yourhtml /var/www/en
ln -s /var/www/yourhtml /var/www/sp
ln -s /var/www/yourhtml /var/www/it
Используйте свой веб-сервер, чтобы прочитать HTTP_ACCEPT_LANGUAGE и перенаправить в эти "разные подкаталоги" в соответствии с языковым значением, которое он предоставляет.
Теперь вы можете использовать window.location.href в Javascript, чтобы получить ваш URL и использовать его в условных выражениях, чтобы надежно идентифицировать предпочтительный язык.
url_string = window.location.href;
if (url_string = "http://yoursite.com/it/index.html") {
document.getElementById("page-wrapper").className = "italian";
}