web-dev-qa-db-fra.com

JavaScript pour détecter les préférences de langue du navigateur

J'ai essayé de détecter la préférence de langue du navigateur à l'aide de JavaScript.

Si je règle la langue du navigateur dans IE dans Tools>Internet Options>General>Languages, comment lire cette valeur à l'aide de JavaScript?

Même problème pour Firefox. Je ne parviens pas à détecter le réglage de tools>options>content>languages avec navigator.language.

En utilisant navigator.userLanguage, il détecte le réglage effectué dans l’onglet Start>ControlPanel>RegionalandLanguageOptions>Regional Options.

J'ai testé avec navigator.browserLanguage et navigator.systemLanguage mais je ne retourne ni la valeur du premier paramètre (Tools>InternetOptions>General>Languages).

J'ai trouvé un lien qui en discute en détail, mais la question reste sans réponse :(

412
Annibigi

Je pense que le principal problème ici est que les paramètres du navigateur n’affectent pas la propriété navigator.language obtenue via javascript.

Ce qu'ils affectent, c'est l'en-tête HTTP 'Accept-Language', mais il semble que cette valeur ne soit pas disponible via JavaScript. (Probablement pourquoi @anddoutoi déclare qu’il ne trouve pas de référence qui n’implique pas le côté serveur.)

J'ai codé une solution de contournement: j'ai créé un script de moteur d'application Google à l'adresse http://ajaxhttpheaders.appspot.com qui vous renverra les en-têtes de requête HTTP via JSONP.

(Remarque: il ne s'agit que d'un hack à utiliser si vous ne disposez pas d'un back-end disponible pouvant le faire pour vous. En général, vous ne devriez pas appeler de fichiers javascript hébergés tiers dans vos pages, sauf si vous avez une niveau de confiance dans l'hôte.)

J'ai l'intention de le laisser là-bas à perpétuité, alors n'hésitez pas à l'utiliser dans votre code.

Voici un exemple de code (en jQuery) pour son utilisation

$.ajax({ 
    url: "http://ajaxhttpheaders.appspot.com", 
    dataType: 'jsonp', 
    success: function(headers) {
        language = headers['Accept-Language'];
        nowDoSomethingWithIt(language);
    }
});

J'espère que quelqu'un trouve cela utile.

Edit: J'ai écrit un petit plugin jQuery sur github qui englobe cette fonctionnalité: https://github.com/dansingerman/jQuery-Browser-Language

Edit 2: Comme demandé, voici le code qui tourne sur AppEngine (super trivial):

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 __== "__main__":
    main()

Edit3: Open source a obtenu le code du moteur de l'application ici: https://github.com/dansingerman/app-engine-headers

280
DanSingerman
var language = window.navigator.userLanguage || window.navigator.language;
alert(language); //works IE/SAFARI/CHROME/FF

window.navigator.userLanguage n'est que IE et c'est la langue définie dans Panneau de configuration Windows - Options régionales et PAS la langue du navigateur, mais vous pouvez supposer qu'un utilisateur utilisant une machine avec Windows Les paramètres régionaux définis en France sont probablement des utilisateurs français.

navigator.language est FireFox et tous les autres navigateurs.

Quelques codes de langue: 'it' = italie, 'en-US' = anglais US, etc.


Comme souligné par rcoup et le WebMacheter dans les commentaires ci-dessous, cette solution de contournement ne vous laissera pas distinguer les dialectes anglais lorsque les utilisateurs consultent des sites Web dans des navigateurs autres que IE.

window.navigator.language (Chrome/FF/Safari) renvoie toujours la langue du navigateur et non la langue préférée du navigateur, mais: "il est assez courant que les anglophones (gb, au, nz, etc.) avoir une version fr-us de Firefox/Chrome/Safari ". Par conséquent, window.navigator.language retournera toujours en-US même si la langue préférée de l'utilisateur est en-GB.

240
Marco Demaio

Mise à jour de l'année 2014.

Il existe maintenant un moyen d'obtenir Accept-Languages ​​dans Firefox et Chrome en utilisant navigator.languages ( fonctionne dans Chrome> = 32 et Firefox> = 32)

En outre, navigator.language dans Firefox ces années reflète la langue de contenu la plus préférée, et non la langue de l'interface utilisateur. Mais comme cette notion n’est pas encore supportée par d’autres navigateurs, elle n’est pas très utile.

Donc, pour obtenir la langue de contenu la plus préférée lorsque possible et utiliser la langue de l'interface utilisateur comme solution de secours:

navigator.languages
    ? navigator.languages[0]
    : (navigator.language || navigator.userLanguage)
197
Tim Babych

Je suis tombé sur ce morceau de code pour détecter la langue du navigateur dans module de traduction angulaire , dont vous pouvez trouver la source ici . J'ai légèrement modifié le code en remplaçant angular.isArray par Array.isArray pour le rendre indépendant de la bibliothèque 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());
50
Hamid Tavakoli
var language = navigator.languages && navigator.languages[0] || // Chrome / Firefox
               navigator.language ||   // All browsers
               navigator.userLanguage; // IE <= 10

console.log(language);

Essayez le modèle PWA https://github.com/StartPolymer/progressive-web-app-template

31
Josef Ježek
<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>

Je n'avais besoin que du composant principal pour mes besoins, mais vous pouvez facilement utiliser la chaîne complète. Fonctionne avec les dernières versions de Chrome, Firefox, Safari et IE10 +.

28
Kristian Williams

Il n'y a pas de moyen décent d'obtenir ce paramètre, du moins pas quelque chose d'indépendant du navigateur.

Mais le serveur a cette information, car elle fait partie de l’en-tête de la requête HTTP (le champ Accept-Language, voir http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14). 4 )

Le seul moyen fiable consiste donc à obtenir une réponse du serveur. Vous aurez besoin de quelque chose qui fonctionne sur le serveur (comme .asp, .jsp, .php, CGI) et cette "chose" peut renvoyer cette information. Bons exemples ici: http://www.developershome.com/wap/detection/detection.asp?page=readHeader

17
Mihai Nita

navigator.userLanguage pour IE

window.navigator.language pour firefox/opera/safari

15
mitchbryson

J'utilise la réponse de Hamid depuis un moment, mais dans les cas où le tableau de langues ressemble à ["en", "en-GB", "en-US", "fr-FR", "fr", "en -ZA "] il retournera" en ", quand" en-GB "serait un meilleur match.

Ma mise à jour (ci-dessous) renverra le premier code long format, par exemple. "en-GB", sinon le premier code abrégé sera retourné, par exemple. "en", sinon il retournera null.

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());
14
EamonnM

J'ai eu le même problème et j'ai écrit la bibliothèque suivante uniquement front-end qui enveloppe le code pour plusieurs navigateurs. Ce n'est pas beaucoup de code, mais il est agréable de ne pas avoir à copier et coller le même code sur plusieurs sites Web.

Obtenez-le: sharedlanguages.js

Utilise le:

<script src="acceptedlanguages.js"></script>
<script type="text/javascript">
  console.log('Accepted Languages:  ' + acceptedlanguages.accepted);
</script>

Il retourne toujours un tableau, classé par préférence des utilisateurs. Dans Safari & IE, le tableau est toujours de longueur simple. En FF et Chrome, il peut s’agir de plusieurs langues.

7
Leigh McCulloch

Manière Javascript:

var language = window.navigator.userLanguage || window.navigator.language;//returns value like 'en-us'

Si vous utilisez plugin jQuery.i18n , vous pouvez utiliser:

jQuery.i18n.browserLang();//returns value like '"en-US"'
7
Jaskey

Je ne trouve pas une seule référence indiquant que c'est possible sans impliquer le côté serveur.

MSDN sur:

De browserLanguage:

Dans Microsoft Internet Explorer 4.0 et versions antérieures, la propriété browserLanguage reflète la langue de l'interface utilisateur du navigateur installé. Par exemple, si vous installez une version japonaise de Windows Internet Explorer sur un système d'exploitation anglais, browserLanguage serait ja.

Dans Internet Explorer 5 et versions ultérieures, toutefois, la propriété browserLanguage reflète la langue du système d'exploitation, quelle que soit la version linguistique installée d'Internet Explorer. Toutefois, si la version multilingue de Microsoft Windows 2000 est installée, la propriété browserLanguage indique la langue définie dans les menus et les boîtes de dialogue actuels du système d'exploitation, comme indiqué dans les Options régionales du Panneau de configuration. Par exemple, si vous installez une version japonaise d'Internet Explorer 5 sur un système d'exploitation anglais (Royaume-Uni), browserLanguage serait en-gb. Si vous installez la version multilingue de Windows 2000 et définissez la langue des menus et des boîtes de dialogue en français, browserLanguage sera fr, même si vous disposez d'une version japonaise d'Internet Explorer.

Remarque Cette propriété n'indique pas la ou les langues définies par l'utilisateur dans les préférences de langue, situées dans la boîte de dialogue Options Internet.

De plus, il semble que browserLanguage soit déconseillé car IE8 ne l’a pas répertorié.

7
anddoutoi

Si vous développez une application/extension Chrome, utilisez le API chrome.i18n .

chrome.i18n.getAcceptLanguages(function(languages) {
  console.log(languages);
  // ["en-AU", "en", "en-US"]
});
7
warrickh

Je viens juste de proposer ça. Il combine la nouvelle syntaxe de déstructuration JS avec quelques opérations standard pour récupérer la langue et les paramètres régionaux.

var [lang, locale] = (((navigator.userLanguage || navigator.language).replace('-', '_')).toLowerCase()).split('_');

J'espère que ça aide quelqu'un

7
MrMesees

Pour ce que cela vaut, la bibliothèque de sélecteurs de langue universelle de Wikimedia a des crochets pour cela: https://www.mediawiki.org/wiki/Extension:UniversalLanguageSelector

Voir la fonction getFrequentLanguageList dans resources/js/ext.uls.init.js. Lien direct: https://gerrit.wikimedia.org/r/gitweb?p=mediawiki/extensions/UniversalLanguageSelector.git;a=blob;f=resources/js/ext.uls.init.js;hb = HEAD

Cela dépend toujours du serveur, ou plus précisément de l'API MediaWiki. La raison pour laquelle je le montre est que cela peut fournir un bon exemple pour obtenir toutes les informations utiles sur la langue de l'utilisateur: langue du navigateur, Accept-Language, géolocalisation (avec obtention d'informations de pays/langue par le CLDR), et bien sûr, les préférences du site de l'utilisateur.

6
Amir E. Aharoni

Si vous avez seulement besoin de supporter certains navigateurs modernes, vous pouvez maintenant utiliser:

navigator.languages

qui renvoie un tableau des préférences de langue de l'utilisateur dans l'ordre spécifié par l'utilisateur.

À compter de maintenant (septembre 2014), cela fonctionne sur: Chrome (v37), Firefox (v32) et Opera (v24)

Mais pas sur: IE (v11)

6
Mr Incredible

DanSingerman a une très bonne solution à cette question.

La seule source fiable pour la langue se trouve dans l'en-tête de requête HTTP. Vous avez donc besoin d'un script côté serveur pour répondre à l'en-tête de la requête ou au moins au champ Accept-Language.

Voici un serveur très simple, Node.js, qui devrait être compatible avec le plugin 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');
6
skython

Tout d'abord, excusez-moi pour mon anglais. Je voudrais partager mon code, parce que cela fonctionne et qu’il est différent des autres réponses données. Dans cet exemple, si vous parlez français (France, Belgique ou autre langue française), vous êtes redirigé sur la page française, sinon sur la page anglaise, en fonction de la configuration du navigateur:

<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>
3
Becca

La réponse de Dan Singerman pose un problème: l'en-tête récupéré doit être utilisé immédiatement, en raison de la nature asynchrone de la commande ajax de jQuery. Cependant, avec son serveur d'applications Google, j'ai écrit ce qui suit, de sorte que l'en-tête est défini dans le cadre de la configuration initiale et peut être utilisé ultérieurement.

<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>
2
user3097579

Si vous avez le contrôle d'un backend et utilisez Django, une implémentation à 4 lignes de l'idée de Dan est:

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})

puis dans urls.py:

url(r'^browserlang/$', views.get_browser_lang, name='get_browser_lang'),

et sur le devant:

$.get(lg('SERVER') + 'browserlang/', function(data){
    var lang_code = data.response.split(',')[0].split(';')[0].split('-')[0];
});

(vous devez bien sûr définir DEFAULT_LANG dans settings.py)

0
Gobi Dasu

Si vous ne souhaitez pas utiliser un serveur externe et que vous en possédez un, vous pouvez utiliser un simple script PHP pour obtenir le même comportement que @DanSingerman answer.

languageDetector.php:

<?php
$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
echo json_encode($lang);
?>

Et changez simplement ces lignes du script jQuery:

url: "languageDetector.php",
dataType: 'json',
success: function(language) {
    nowDoSomethingWithIt(language);
}
0
Mijail

Basé sur la réponse ici Accès aux en-têtes HTTP de la page Web en JavaScript J'ai construit le script suivant pour obtenir la langue du navigateur:

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();
}
0
Andreas Jantschnig

J'ai un hack qui, à mon avis, utilise très peu de code et est assez fiable.

Placez les fichiers de votre site dans un sous-répertoire. SSL sur votre serveur et créez des liens symboliques vers ce sous-répertoire où sont stockés vos fichiers qui indiquent vos langues.

Quelque chose comme ça:

ln -s /var/www/yourhtml /var/www/en
ln -s /var/www/yourhtml /var/www/sp
ln -s /var/www/yourhtml /var/www/it

Utilisez votre serveur Web pour lire HTTP_ACCEPT_LANGUAGE et redirigez-les vers ces "sous-répertoires différents" en fonction de la valeur de langue fournie.

Vous pouvez maintenant utiliser le fichier window.location.href de Javascript pour obtenir votre URL et l'utiliser de manière conditionnelle pour identifier de manière fiable la langue de votre choix.

url_string = window.location.href;
if (url_string = "http://yoursite.com/it/index.html") {
    document.getElementById("page-wrapper").className = "italian";
}
0
user612161

j'avais une approche différente, cela pourrait aider quelqu'un à l'avenir:

le client voulait une page où vous pouvez échanger des langues. J'avais besoin de formater les nombres avec ce paramètre (pas avec le navigateur ni avec aucun paramètre prédéfini)

donc je définis un paramètre initial en fonction des paramètres de configuration (i18n)

$clang = $this->Session->read('Config.language');
echo "<script type='text/javascript'>var clang = '$clang'</script>";

plus tard dans le script, j'ai utilisé une fonction pour déterminer ce que j'ai besoin deformulation numérique

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 : "."}
  }
}

donc j'ai utilisé la langue définie de la page et comme solution de rechange, j'ai utilisé les paramètres du navigateur.

ce qui devrait être utile aux fins de test.

en fonction de vos clients, vous n'aurez peut-être pas besoin de ces paramètres.

0
Arthur Kielbasa

Pour qui cherche Java solution de serveur

Voici 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();
}
0
vanduc1102

Si vous utilisez ASP .NET MVC et que vous souhaitez obtenir l'en-tête Accepted-Languages à partir de JavaScript, voici un exemple de solution de contournement qui ne comporte aucune requête asynchrone.

Dans votre fichier .cshtml, stockez l'en-tête de manière sécurisée dans l'attribut data d'un attribut:

<div data-languages="@Json.Encode(HttpContext.Current.Request.UserLanguages)"></div>

Ensuite, votre code JavaScript peut accéder aux informations, par exemple. en utilisant 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>

Bien sûr, vous pouvez utiliser une approche similaire avec d’autres technologies de serveur, comme d’autres l'ont mentionné.

0
Johan Franzén