Il modo migliore per determinare le impostazioni internazionali dell'utente nel browser


203

Ho un sito Web (Flash) localizzato in una dozzina di lingue e desidero definire automaticamente un valore predefinito in base alle impostazioni del browser dell'utente al fine di ridurre al minimo i passaggi per accedere al contenuto.

Cordiali saluti, non riesco a utilizzare gli script del server a causa delle restrizioni del proxy, quindi credo che JavaScript o ActionScript siano appropriati per risolvere il problema.

Domande:

  1. Quale sarebbe il metodo migliore per "indovinare" le impostazioni locali dell'utente?

  2. Esistono classi / funzioni semplici esistenti che potrebbero aiutarmi (nessun pacchetto di localizzazione complesso)? Specialmente per scomporre tutte le lingue possibili in un numero più piccolo (le traduzioni che ho) in modo intelligente.

  3. A che punto posso fidarmi di una soluzione del genere?

  4. Altre soluzioni alternative o suggerimenti?


L'unico modo in cui un browser può condividere metadati sull'utente e la richiesta è tramite URL e intestazioni. Prendi Firefox e dai un'occhiata alle intestazioni inviate quando viene effettuata una richiesta. È piuttosto interessante esaminare le tipiche intestazioni di richiesta e risposta.
mP.

Risposte:


188

Il modo corretto è guardare la HTTP Accept-Language intestazione inviata al server. Questo contiene l'elenco ordinato e ponderato delle lingue che l'utente ha configurato per preferire il proprio browser.

Purtroppo questa intestazione non è disponibile per la lettura all'interno di JavaScript; tutto ciò che ottieni è navigator.language, che ti dice quale versione localizzata del browser web è stata installata. Non si tratta necessariamente della stessa lingua preferita dell'utente. Su IE invece ottieni systemLanguage(lingua del sistema operativo installato), browserLanguage(uguale a language) e userLanguage(regione del sistema operativo configurata dall'utente), che sono tutti ugualmente inutili.

Se dovessi scegliere tra quelle proprietà, annuserei per userLanguageprimo, tornando indietro languagee solo dopo (se quelli non corrispondevano a nessuna lingua disponibile) guardando browserLanguagee infine systemLanguage.

Se riesci a mettere uno script sul lato server da qualche altra parte in rete che legge semplicemente l'intestazione Accept-Language e lo sputa indietro come file JavaScript con il valore dell'intestazione nella stringa, ad es .:

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

quindi è possibile includere un <script src> che punta a quel servizio esterno nell'HTML e utilizzare JavaScript per analizzare l'intestazione della lingua. Non conosco alcun codice di libreria esistente per fare questo, tuttavia, poiché l'analisi Accept-Language viene quasi sempre eseguita sul lato server.

Qualunque cosa tu finisca di fare, avrai sicuramente bisogno di un override dell'utente perché per alcune persone indovinerà sempre qualcosa di sbagliato. Spesso è più semplice inserire l'impostazione della lingua nell'URL (ad es. Http: //www.example.com/en/site vs http: //www.example.com/de/site) e lasciare che l'utente faccia clic collegamenti tra i due. A volte si desidera un singolo URL per entrambe le versioni linguistiche, nel qual caso è necessario memorizzare l'impostazione nei cookie, ma ciò può confondere i programmi utente senza supporto per cookie e motori di ricerca.


11
Da MDN developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/… "L'intestazione HTTP Accept-Language in ogni richiesta HTTP dal browser dell'utente utilizza lo stesso valore per la proprietà navigator.languages ​​ad eccezione del supplemento campo qvalues ​​(valori di qualità) (ad es. en-US; q = 0.8). "
S Meaden,

3
Aggiornamento: ora esiste (2020) una funzione sperimentale supportata da tutti i browser moderni che restituisce una serie di preferenze linguistiche: navigator.languages //["en-US", "zh-CN", "ja-JP"]questo dovrebbe funzionare su almeno il 95% dei browser nel 2020.
Cornelius Roemer

1
navigator.languages, secondo MDN e caniuse.com , è ora disponibile in tutti i principali browser: prova il minuscolo pacchetto di lingue di navigazione (~ 200 byte) per l'approccio più moderno e compatibile con le versioni precedenti.
mindplay.dk

84

Su Chrome e Firefox 32+, navigator.languages ​​contiene una serie di locali in ordine di preferenza dell'utente ed è più preciso di navigator.language, tuttavia per renderlo compatibile con le versioni precedenti (testato Chrome / IE / Firefox / Safari), quindi utilizzare Questo:

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

2
Questo non funziona per IE9 e IE10. Per loro, devi esaminare invece navigator.browserLanguage.
user393274

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

4
@ChStark Non dovrebbe essere return navigator.languages[0] || navigator.language;?
James,

23
Inoltre, la corretta "one-liner" sarebbe simile a questa: return (navigator.languages && navigator.languages.length) ? navigator.languages[0] : navigator.language;. Altrimenti si ottiene un'eccezione se navigator.languagesnon definita o vuota.
Max Truxa,

Per una versione ancora più compattaconst getLang = () => navigator.language || navigator.browserLanguage || ( navigator.languages || [ "en" ] ) [ 0 ]
João Miguel Brandão,

41

Questo articolo suggerisce le seguenti proprietà dell'oggetto navigatore del browser :

  • navigator.language (Netscape - Localizzazione del browser)
  • navigator.browserLanguage (Specifico per IE - Lingua localizzata del browser)
  • navigator.systemLanguage (Specifico per IE - Sistema operativo Windows - Lingua localizzata)
  • navigator.userLanguage

Inseriscili in una funzione JavaScript e dovresti essere in grado di indovinare la lingua giusta, nella maggior parte dei casi. Assicurati di degradare con grazia, quindi fai un div contenente i tuoi collegamenti di scelta della lingua, in modo che se non ci sono javascript o il metodo non funziona, l'utente può comunque decidere. Se funziona, basta nascondere il div.

L'unico problema nel fare ciò sul lato client è che o servi tutte le lingue al client, o devi aspettare fino a quando lo script è stato eseguito e ha rilevato la lingua prima di richiedere la versione giusta. Forse servire la versione in lingua più popolare come impostazione predefinita irrita il minor numero di persone.

Modifica: acconsentirei al suggerimento sui cookie di Ivan, ma assicurerei che l'utente possa sempre cambiare la lingua in seguito; non tutti preferiscono la lingua di default del browser.


Grazie Phil per i tuoi suggerimenti. Per quanto riguarda l'articolo, ha 6 anni ... non sei sicuro di poterci affidare?
Theo.T

1
Sospetto che i browser moderni supportino tutti navigator.language. Il mio browser (FF3 su Ubuntu 8.10) riporta 'en-GB'. Se qualcuno sta ancora usando IE6 - circa il 20% delle persone - vale la pena tenerlo presente. IE6 è apparso 8 anni fa.
Phil H,

Internet Explorer 8 non supporta navigator.language. Forse IE 9 lo farà?
spig

36

Combinando i molteplici modi in cui i browser utilizzano per memorizzare la lingua dell'utente, ottieni questa funzione:

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

Per prima cosa controlliamo l' navigator.languagesarray per il suo primo elemento.
Quindi otteniamo uno navigator.userLanguageo navigator.language.
Se questo fallisce, otteniamo navigator.browserLanguage.
Infine, lo impostiamo su 'en'se tutto il resto fallisce.


Ed ecco il sexy one-liner:

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

c'è apparentemente anche qualcosa come navigator.userLanguage(per IE). Potresti aggiungerlo per completarlo :)
pors

Perché non semplicemente navigator.languages[0] || navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en'?
Emerica,

@Curse Perché navigator.languagespuò essereundefined
Zenoo,

@Zenoo Sai su quali browser?
Emerica,

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

10

C'è una differenza tra le lingue preferite dell'utente e le impostazioni internazionali del sistema / browser.

Un utente può configurare le lingue preferite nel browser, che verranno utilizzate navigator.language(s)e utilizzate quando si richiedono risorse da un server, per richiedere il contenuto in base a un elenco di priorità linguistiche.

Tuttavia, le impostazioni internazionali del browser decideranno come eseguire il rendering di numero, data, ora e valuta. Questa impostazione è probabilmente la lingua con il punteggio più alto, ma non è garantita. Su Mac e Linux, le impostazioni internazionali vengono decise dal sistema indipendentemente dalle preferenze della lingua dell'utente. Su Windows può essere eletto tra le lingue nell'elenco preferito su Chrome.

Utilizzando Intl ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl ), gli sviluppatori possono sovrascrivere / impostare le impostazioni locali da utilizzare per il rendering di queste cose, ma ci sono elementi che non può essere sovrascritto, ad esempio il <input type="date">formato.

Per estrarre correttamente questa lingua, l'unico modo che ho trovato è:

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

( Intl.NumberFormat().resolvedOptions().localesembra funzionare anche)

Ciò creerà una nuova istanza NumberFormat per la locale predefinita e quindi rileggerà la locale di quelle opzioni risolte.


5

Ho fatto un po 'di ricerche al riguardo e ho riassunto i miei risultati finora nella tabella seguente

inserisci qui la descrizione dell'immagine

Quindi la soluzione consigliata è scrivere uno script lato server per analizzare l' Accept-Languageintestazione e passarlo al client per impostare la lingua del sito Web. È strano il motivo per cui il server sarebbe necessario per rilevare la preferenza linguistica del client, ma è così per ora Ci sono altri vari hack disponibili per rilevare la lingua, ma leggere l' Accept-Languageintestazione è la soluzione consigliata secondo la mia comprensione.


2

Puoi anche provare a ottenere la lingua dal documento, se potrebbe essere la tua prima porta di chiamata, quindi ricorrere ad altri mezzi poiché spesso le persone vorranno che la loro lingua JS corrisponda alla lingua del documento.

HTML5:

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

Legacy:

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

Nessuna vera fonte è necessariamente affidabile al 100% in quanto le persone possono semplicemente mettere nella lingua sbagliata.

Esistono librerie di rilevamento della lingua che potrebbero consentire di determinare la lingua in base al contenuto.


1

Ho usato tutte le risposte e ho creato una soluzione a riga singola:

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

console.log(getLanguage());

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.