Pesquisa de site

javascript - Como posso determinar o local de um usuário dentro do navegador?


Eu tenho um site (Flash) localizado em uma dúzia de idiomas e quero definir automaticamente um valor padrão dependendo das configurações do navegador do usuário, a fim de minimizar os passos para acessar o conteúdo.

Para sua informação, não posso usar scripts de servidor devido a restrições de proxy, então acho que JavaScript ou ActionScript seriam apropriados para resolver o problema.

Perguntas:

  1. Qual seria o melhor método para 'adivinhar' a localidade do usuário?

  2. Existem alguma classes/funções simples existentes que possam me ajudar (sem pacotes complexos de localização)? Especialmente para reduzir todos os idiomas possíveis para um número menor (as traduções que eu tenho) de forma inteligente.

  3. Até que ponto posso confiar em uma solução assim?

  4. Alguma outra solução alternativa ou sugestão?

Resposta #1

A maneira correta é olhar para o cabeçalho HTTP Accept-Language enviado ao servidor. Isso contém a lista ordenada e ponderada de idiomas que o usuário configurou como preferidos em seu navegador.

Infelizmente, este cabeçalho não está disponível para leitura dentro do JavaScript; tudo que você obtém é navigator.language, que indica qual versão localizada do navegador foi instalada. Isso não é necessariamente a mesma coisa que o(s) idioma(s) preferido(s) do usuário. No IE, você obtém em vez disso systemLanguage (idioma instalado no SO), browserLanguage (mesmo que language) e userLanguage (região do SO configurada pelo usuário), que são todos igualmente pouco úteis.

Se eu tivesse que escolher entre essas propriedades, eu verificaria primeiro userLanguage, recorrendo a language e somente depois disso (se essas não correspondessem a nenhum idioma disponível) olhando para browserLanguage e finalmente systemLanguage.

Se você puder colocar um script do lado do servidor em outro lugar na rede que simplesmente leia o cabeçalho Accept-Language e o devolva como um arquivo JavaScript com o valor do cabeçalho na string, por exemplo:

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

então você poderia incluir um <script src> apontando para esse serviço externo no HTML, e usar JavaScript para analisar o cabeçalho de idioma. No entanto, eu não conheço nenhum código de biblioteca existente para fazer isso, já que a análise do Accept-Language é quase sempre feita no lado do servidor.

Seja o que você acabar fazendo, você certamente precisará de uma opção de substituição pelo usuário, porque ele sempre vai adivinhar errado para algumas pessoas. Frequentemente, é mais fácil colocar a configuração de idioma na URL (por exemplo, http://www.example.com/en/site vs http://www.example.com/de/site) e deixar o usuário clicar em links entre os dois. Às vezes, você quer uma única URL para ambas as versões de idioma, nesse caso você terá que armazenar a configuração em cookies, mas isso pode confundir agentes de usuário sem suporte a cookies e motores de busca.

Resposta #2

No Chrome e no Firefox 32+, Navigator.languages contém um array de locais na ordem de preferência do usuário, e é mais preciso que navigator.language, no entanto, para torná-lo compatível com versões anteriores (Testado no Chrome/IE/Firefox/Safari), use:

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

Resposta #3

Há uma diferença entre os idiomas preferidos pelo usuário e o idioma/locale do sistema/navegador.

Um usuário pode configurar idiomas preferidos no navegador, e estes serão usados para navigator.language(s), e usados ao solicitar recursos de um servidor, para solicitar conteúdo de acordo com uma lista de prioridades de idiomas.

No entanto, a localidade do navegador decidirá como exibir números, datas, horários e moeda. Essa configuração provavelmente é a linguagem de maior prioridade, mas não há garantia. No Mac e no Linux, a localidade é decidida pelo sistema independentemente das preferências de idioma do usuário. No Windows, ela pode ser escolhida entre os idiomas na lista de preferências no Chrome.

Usando o Intl (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl), os desenvolvedores podem substituir/definir o local a ser usado para renderizar essas coisas, mas há elementos que não podem ser substituídos, como o formato <input type="date">.

Para extrair corretamente este idioma, a única maneira que encontrei é:

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

(Intl.NumberFormat().resolvedOptions().locale também parece funcionar)

Isso criará uma nova instância NumberFormat para o locale padrão e, em seguida, lerá de volta o locale dessas opções resolvidas.

Resposta #4

Este artigo sugere as seguintes propriedades do objeto navigator do navegador:

  • navigator.language (Netscape - Localização do Navegador)
  • navigator.browserLanguage (Específico do IE - Idioma localizado do navegador)
  • navigator.systemLanguage (Específico do IE - Windows OS - Idioma Localizado)
  • navigator.userLanguage

Transforme isso em uma função JavaScript e você deverá ser capaz de adivinhar o idioma correto na maioria das situações. Certifique-se de degradar graciosamente, então tenha uma div contendo os links das suas opções de idioma, para que, se não houver JavaScript ou o método não funcionar, o usuário ainda possa decidir. Se funcionar, apenas esconda a div.

O único problema de fazer isso no lado do cliente é que você ou fornece todas as línguas para o cliente, ou precisa esperar até que o script tenha sido executado e detectado o idioma antes de solicitar a versão correta. Talvez fornecer a versão na língua mais popular como padrão irrite o menor número de pessoas.

Edit: Eu apoiaria a sugestão de cookies do Ivan, mas certifique-se de que o usuário possa sempre mudar o idioma mais tarde; nem todos preferem o idioma que o navegador deles define por padrão.

Resposta #5

Combinando as múltiplas maneiras que os navegadores estão usando para armazenar o idioma do usuário, você obtém esta função:

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

Primeiro verificamos o array navigator.languages pelo seu primeiro elemento. Então obtemos navigator.userLanguage ou navigator.language. Se isso falhar, obtemos navigator.browserLanguage. Finalmente, definimos como 'en' se tudo mais falhar.


E aqui está a frase de efeito sexy:

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

Resposta #6

Usei todas as respostas e criei uma solução em uma única linha:

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

console.log(getLanguage());

Artigos relacionados