Der beste Weg, um das Gebietsschema des Benutzers im Browser zu bestimmen


201

Ich habe eine Website (Flash) in einem Dutzend Sprachen lokalisiert und möchte abhängig von den Browsereinstellungen des Benutzers automatisch einen Standardwert definieren, um die Schritte für den Zugriff auf den Inhalt zu minimieren.

Zu Ihrer Information, ich kann aufgrund von Proxy-Einschränkungen keine Server-Skripte verwenden. Ich denke, JavaScript oder ActionScript wären geeignet, um das Problem zu lösen.

Fragen:

  1. Was wäre die beste Methode, um das Gebietsschema des Benutzers zu erraten?

  2. Gibt es einfache Klassen / Funktionen, die mir helfen könnten (keine komplexen Lokalisierungspakete)? Insbesondere, um alle möglichen Sprachen auf intelligente Weise in eine kleinere Anzahl (die Übersetzungen, die ich habe) zu zerlegen.

  3. Bis zu welchem ​​Punkt kann ich einer solchen Lösung vertrauen?

  4. Irgendwelche anderen Problemumgehungen oder Vorschläge?


Nur so kann ein Browser Metadaten über seinen Benutzer freigeben, und die Anforderung erfolgt über URLs und Header. Holen Sie sich Firefox und werfen Sie einen Blick auf die Header, die gesendet werden, wenn eine Anfrage gestellt wird. Es ist sehr interessant, typische Anforderungs- und Antwortheader zu untersuchen.
mP.

Antworten:


188

Der richtige Weg ist, sich den an den Server gesendeten HTTP Accept-Language- Header anzusehen . Diese enthält die geordnete, gewichtete Liste der Sprachen, für die der Benutzer seinen Browser konfiguriert hat.

Leider ist dieser Header nicht zum Lesen in JavaScript verfügbar. Sie erhalten navigator.languagelediglich Informationen darüber, welche lokalisierte Version des Webbrowsers installiert wurde. Dies ist nicht unbedingt dasselbe wie die bevorzugte (n) Sprache (n) des Benutzers. Auf IE erhalten Sie stattdessen systemLanguage(Betriebssystem installierte Sprache), browserLanguage(wie language) unduserLanguage (vom Benutzer konfigurierte Betriebssystemregion), die alle ähnlich wenig hilfreich sind.

Wenn ich mich zwischen diesen Eigenschaften entscheiden müsste, würde ich zuerst schnüffeln userLanguage, auf languageund erst danach zurückgreifen (wenn diese nicht mit einer verfügbaren Sprache übereinstimmen) browserLanguageund schließlich schauen systemLanguage.

Wenn Sie ein serverseitiges Skript an einer anderen Stelle im Netz platzieren können, das einfach den Accept-Language-Header liest und ihn als JavaScript-Datei mit dem Header-Wert in der Zeichenfolge wieder ausspuckt, z.

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

Dann können Sie ein <script src>, das auf diesen externen Dienst verweist, in den HTML-Code aufnehmen und JavaScript verwenden, um den Sprachheader zu analysieren. Ich kenne jedoch keinen vorhandenen Bibliothekscode, da dies fast immer auf der Serverseite erfolgt.

Was auch immer Sie am Ende tun, Sie müssen auf jeden Fall einen Benutzer überschreiben, da dies für manche Menschen immer falsch ist. Oft ist es am einfachsten, die Spracheinstellung in die URL einzufügen (z. B. http: //www.example.com/en/site vs http: //www.example.com/de/site) und den Benutzer klicken zu lassen Verbindungen zwischen den beiden. Manchmal möchten Sie eine einzige URL für beide Sprachversionen. In diesem Fall müssen Sie die Einstellung in Cookies speichern. Dies kann jedoch Benutzeragenten verwirren, die Cookies und Suchmaschinen nicht unterstützen.


11
Von MDN developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/… "Der HTTP-Header" Accept-Language "in jeder HTTP-Anforderung vom Browser des Benutzers verwendet denselben Wert für die Eigenschaft" navigator.languages ​​", mit Ausnahme des Zusatzwerts Feld qWerte (Qualitätswerte) (z. B. en-US; q = 0,8). "
S Meaden

3
Update: Es gibt jetzt (2020) eine experimentelle Funktion, die von allen modernen Browsern unterstützt wird und eine Reihe von Sprachpräferenzen zurückgibt: navigator.languages //["en-US", "zh-CN", "ja-JP"]Dies sollte 2020 bei mindestens 95% der Browser funktionieren.
Cornelius Roemer

1
navigator.languagesLaut MDN und caniuse.com ist es jetzt in allen gängigen Browsern verfügbar. Probieren Sie das winzige Navigationssprachenpaket (~ 200 Byte) für den modernsten und abwärtskompatibelsten Ansatz.
mindplay.dk

84

Unter Chrome und Firefox 32+ enthält navigator.languages ​​eine Reihe von Gebietsschemas in der Reihenfolge der Benutzereinstellungen und ist genauer als navigator.language. Um es jedoch abwärtskompatibel zu machen (Getestetes Chrome / IE / Firefox / Safari), verwenden Sie es Dies:

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

2
Dies funktioniert nicht für IE9 und IE10. Für sie müssen Sie stattdessen navigator.browserLanguage untersuchen.
user393274

2
OneLiner:function getLang(){ return ( navigator.language || navigator.languages[0] ); }
JorgeGarza

4
@ChStark Sollte es nicht sein return navigator.languages[0] || navigator.language;?
James_

23
Außerdem würde der richtige "Einzeiler" so aussehen : return (navigator.languages && navigator.languages.length) ? navigator.languages[0] : navigator.language;. Andernfalls erhalten Sie eine Ausnahme, wenn sie navigator.languagesundefiniert oder leer ist.
Max Truxa

Für eine noch kompaktere Versionconst getLang = () => navigator.language || navigator.browserLanguage || ( navigator.languages || [ "en" ] ) [ 0 ]
João Miguel Brandão

41

Dieser Artikel schlägt die folgenden Eigenschaften des Navigatorobjekts des Browsers vor :

  • navigator.language (Netscape - Browser-Lokalisierung)
  • navigator.browserLanguage (IE-spezifisch - Browser-lokalisierte Sprache)
  • navigator.systemLanguage (IE-spezifisch - Windows-Betriebssystem - Lokalisierte Sprache)
  • navigator.userLanguage

Wenn Sie diese in eine Javascript-Funktion umwandeln, sollten Sie in den meisten Fällen in der Lage sein, die richtige Sprache zu erraten. Stellen Sie sicher, dass Sie sich ordnungsgemäß verschlechtern. Verwenden Sie daher ein Div, das Ihre Links zur Sprachauswahl enthält, damit der Benutzer dennoch entscheiden kann, ob kein Javascript vorhanden ist oder die Methode nicht funktioniert. Wenn es funktioniert, verstecken Sie einfach das div.

Das einzige Problem dabei auf der Client-Seite ist, dass Sie entweder dienen alle Sprachen für den Client bereitstellen oder warten müssen, bis das Skript ausgeführt und die Sprache erkannt wurde, bevor Sie die richtige Version anfordern. Vielleicht würde das Servieren der beliebtesten Sprachversion als Standard die wenigsten Leute irritieren.

Bearbeiten: Ich würde Iwans Cookie-Vorschlag unterstützen, aber sicherstellen, dass der Benutzer die Sprache später jederzeit ändern kann. Nicht jeder bevorzugt die Sprache, in der sein Browser standardmäßig verwendet wird.


Danke Phil für deine Vorschläge. Der Artikel ist 6 Jahre alt ... nicht sicher, ob wir uns darauf verlassen können?
Theo.T

1
Ich vermute, dass alle modernen Browser navigator.language unterstützen. Mein Browser (FF3 unter Ubuntu 8.10) meldet 'en-GB'. Wenn noch jemand IE6 verwendet - etwa 20% der Menschen -, lohnt es sich, dies zu berücksichtigen. IE6 erschien vor 8 Jahren.
Phil H

IE 8 unterstützt navigator.language nicht. Vielleicht wird IE 9?
Spig

36

Durch die Kombination der verschiedenen Möglichkeiten, mit denen Browser die Sprache des Benutzers speichern, erhalten Sie folgende Funktion:

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

Wir überprüfen zuerst das navigator.languagesArray auf sein erstes Element.
Dann bekommen wir entweder navigator.userLanguageoder navigator.language.
Wenn dies fehlschlägt, bekommen wir navigator.browserLanguage.
Schließlich setzen wir es auf, 'en'wenn alles andere fehlschlägt.


Und hier ist der sexy Einzeiler:

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

es gibt anscheinend auch etwas wie navigator.userLanguage(für IE). Sie könnten das hinzufügen, um es zu vervollständigen :)
Pors

Warum nicht einfach navigator.languages[0] || navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en'?
Emerica

@Curse Weil navigator.languageskann seinundefined
Zenoo

@ Zenoo Weißt du in welchen Browsern?
Emerica

(navigator.languages || [])[0] || navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en'
Steve Bennett

10

Es gibt einen Unterschied zwischen den bevorzugten Sprachen des Benutzers und dem Gebietsschema des Systems / Browsers.

Ein Benutzer kann bevorzugte Sprachen im Browser konfigurieren. Diese werden verwendet navigator.language(s), um Ressourcen von einem Server anzufordern und um Inhalte gemäß einer Liste von Sprachprioritäten anzufordern.

Das Gebietsschema des Browsers entscheidet jedoch, wie Nummer, Datum, Uhrzeit und Währung gerendert werden. Diese Einstellung ist wahrscheinlich die Sprache mit dem höchsten Rang, es gibt jedoch keine Garantie. Unter Mac und Linux wird das Gebietsschema vom System unabhängig von den Einstellungen der Benutzersprache festgelegt. Unter Windows kann unter den Sprachen in der Vorzugsliste auf Chrome gewählt werden.

Mithilfe von Intl ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl ) können Entwickler das Gebietsschema zum Rendern dieser Elemente überschreiben / festlegen, es gibt jedoch Elemente, die dies tun kann nicht überschrieben werden, wie z. B. das <input type="date">Format.

Um diese Sprache richtig zu extrahieren, habe ich nur Folgendes gefunden:

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

( Intl.NumberFormat().resolvedOptions().localescheint auch zu funktionieren)

Dadurch wird eine neue NumberFormat-Instanz für das Standardgebietsschema erstellt und anschließend das Gebietsschema dieser aufgelösten Optionen zurückgelesen.


5

Ich habe diesbezüglich ein wenig recherchiert und meine bisherigen Ergebnisse in der folgenden Tabelle zusammengefasst

Geben Sie hier die Bildbeschreibung ein

Die empfohlene Lösung besteht darin, ein serverseitiges Skript zu schreiben, um den Accept-LanguageHeader zu analysieren und an den Client zu übergeben, um die Sprache der Website festzulegen. Es ist seltsam, warum der Server benötigt wird, um die Sprachpräferenz des Clients zu erkennen, aber so ist es ab sofort. Es gibt verschiedene andere Hacks, um die Sprache zu erkennen, aber das Lesen des Accept-LanguageHeaders ist nach meinem Verständnis die empfohlene Lösung.


2

Sie können auch versuchen, die Sprache aus dem Dokument abzurufen, sollte dies Ihre erste Anlaufstelle sein, und dann auf andere Mittel zurückgreifen, da die JS-Sprache häufig mit der Dokumentensprache übereinstimmen soll.

HTML5:

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

Erbe:

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

Keine echte Quelle ist notwendigerweise 100% zuverlässig, da die Leute einfach die falsche Sprache eingeben können.

Es gibt Spracherkennungsbibliotheken, mit denen Sie die Sprache anhand des Inhalts bestimmen können.


1

Ich habe alle Antworten verwendet und eine einzeilige Lösung erstellt:

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

console.log(getLanguage());

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.