Cara terbaik untuk menentukan lokal pengguna di dalam browser

203

Saya memiliki situs web (Flash) yang dilokalisasi ke dalam selusin bahasa dan saya ingin menetapkan nilai default secara otomatis tergantung pada pengaturan browser pengguna untuk meminimalkan langkah-langkah untuk mengakses konten.

FYI, saya tidak bisa menggunakan server-skrip karena pembatasan proxy, jadi saya kira JavaScript atau ActionScript akan sesuai untuk menyelesaikan masalah.

Pertanyaan:

  1. Apa yang akan menjadi metode terbaik untuk 'menebak' lokal pengguna?

  2. Apakah ada kelas / fungsi sederhana yang ada yang dapat membantu saya (tidak ada bundel pelokalan yang kompleks)? Khusus untuk memecah semua bahasa yang mungkin menjadi jumlah yang lebih kecil (terjemahan yang saya miliki) dengan cara yang cerdas.

  3. Sampai di mana saya bisa mempercayai solusi semacam itu?

  4. Ada solusi atau saran lain?

Theo.T
sumber
Satu-satunya cara browser dapat membagikan data meta tentang penggunanya dan permintaannya adalah melalui URL dan header. Raih Firefox dan intip tajuk yang dikirim saat ada permintaan. Cukup menarik untuk memeriksa header permintaan dan respons yang khas.
mP.

Jawaban:

188

Cara yang tepat adalah dengan melihat tajuk Bahasa Terima HTTP yang dikirim ke server. Ini berisi daftar bahasa yang dipesan dan tertimbang yang telah dikonfigurasikan pengguna untuk browser mereka.

Sayangnya tajuk ini tidak tersedia untuk dibaca di dalam JavaScript; yang Anda dapatkan hanyalah navigator.language, yang memberi tahu Anda versi lokal dari browser web yang diinstal. Ini tidak harus sama dengan bahasa pilihan pengguna. Pada IE Anda malah mendapatkan systemLanguage(bahasa yang diinstal OS), browserLanguage(sama dengan language) dan userLanguage(wilayah OS yang dikonfigurasi pengguna), yang semuanya sama-sama tidak membantu.

Jika saya harus memilih di antara sifat-sifat itu, saya akan mengendus userLanguageterlebih dahulu, kembali ke languagedan hanya setelah itu (jika itu tidak cocok dengan bahasa yang tersedia) melihat browserLanguagedan akhirnya systemLanguage.

Jika Anda dapat menempatkan skrip sisi-server di tempat lain di internet yang cukup membaca header Terima-Bahasa dan meludahkannya kembali sebagai file JavaScript dengan nilai header di string, mis .: .:

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

maka Anda dapat menyertakan <script src> yang menunjuk pada layanan eksternal dalam HTML, dan menggunakan JavaScript untuk mem-parsing header bahasa. Saya tidak tahu kode perpustakaan yang ada untuk melakukan ini, karena parsing Accept-Language hampir selalu dilakukan di sisi server.

Apa pun yang Anda lakukan pada akhirnya, Anda tentu saja harus menimpa pengguna karena akan selalu menebak salah untuk beberapa orang. Seringkali lebih mudah untuk meletakkan pengaturan bahasa di URL (mis. Http: //www.example.com/en/site vs http: //www.example.com/de/site), dan biarkan pengguna mengklik hubungan antara keduanya. Kadang-kadang Anda memang menginginkan satu URL untuk kedua versi bahasa, dalam hal ini Anda harus menyimpan pengaturan di cookie, tetapi ini dapat membingungkan agen pengguna tanpa dukungan untuk cookie dan mesin pencari.

bobince
sumber
11
Dari MDN developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/… "Header HTTP Terima-Bahasa di setiap permintaan HTTP dari browser pengguna menggunakan nilai yang sama untuk properti navigator.languages ​​kecuali untuk tambahan bidang qvalues ​​(nilai kualitas) (mis. en-US; q = 0.8). "
S Meaden
3
Pembaruan: Sekarang ada (2020) fitur eksperimental yang didukung oleh semua browser modern yang mengembalikan sejumlah preferensi bahasa: navigator.languages //["en-US", "zh-CN", "ja-JP"]Ini harus bekerja pada setidaknya 95% browser pada tahun 2020.
Cornelius Roemer
1
navigator.languages, menurut MDN dan caniuse.com , sekarang tersedia di semua browser utama - cobalah paket bahasa navigator-bahasa yang kecil (~ 200 byte) untuk pendekatan yang paling modern dan kompatibel dengan mundur.
mindplay.dk
84

Di Chrome dan Firefox 32+, navigator.languages ​​berisi larik lokal sesuai urutan preferensi pengguna, dan lebih akurat daripada navigator.language, namun untuk membuatnya kompatibel-mundur (Chrome yang diuji / IE / Firefox / Safari), kemudian gunakan ini:

function getLang()
{
 if (navigator.languages != undefined) 
 return navigator.languages[0]; 
 else 
 return navigator.language;
}
Fiach Reid
sumber
2
Ini tidak berfungsi untuk IE9 dan IE10. Bagi mereka, Anda harus memeriksa navigator.browserLanguage sebagai gantinya.
user393274
2
OneLiner:function getLang(){ return ( navigator.language || navigator.languages[0] ); }
JorgeGarza
4
@ ChStark Bukankah seharusnya begitu return navigator.languages[0] || navigator.language;?
James_
23
Juga, yang benar "satu-kapal" akan terlihat seperti ini: return (navigator.languages && navigator.languages.length) ? navigator.languages[0] : navigator.language;. Kalau tidak, Anda akan mendapatkan pengecualian jika navigator.languagestidak ditentukan atau kosong.
Max Truxa
Untuk versi yang lebih ringkasconst getLang = () => navigator.language || navigator.browserLanguage || ( navigator.languages || [ "en" ] ) [ 0 ]
João Miguel Brandão
41

Artikel ini menyarankan properti objek navigator browser berikut :

  • navigator.language (Netscape - Lokalisasi Browser)
  • navigator.browserLanguage (Khusus IE - Bahasa yang Dibatalkan Browser)
  • navigator.systemLanguage (Khusus IE - OS Windows - Bahasa Lokal)
  • navigator.userLanguage

Gulung ini ke dalam fungsi javascript dan Anda harus bisa menebak bahasa yang tepat, dalam sebagian besar keadaan. Pastikan untuk menurunkan dengan anggun, sehingga memiliki div berisi tautan pilihan bahasa Anda, sehingga jika tidak ada javascript atau metode tidak berfungsi, pengguna masih dapat memutuskan. Jika berhasil, sembunyikan div saja.

Satu-satunya masalah dengan melakukan ini di sisi klien adalah bahwa Anda melayani semua bahasa untuk klien, atau Anda harus menunggu sampai skrip berjalan dan mendeteksi bahasa sebelum meminta versi yang tepat. Mungkin menyajikan versi bahasa paling populer sebagai default akan membuat jengkel orang yang paling sedikit.

Sunting: Saya menyarankan saran kuki Ivan, tetapi pastikan pengguna selalu dapat mengubah bahasa nanti; tidak semua orang lebih suka bahasa default browser mereka.

Phil H
sumber
Terima kasih Phil atas saran Anda. Mengenai artikel itu, sudah 6 tahun ... tidak yakin kita bisa mengandalkannya?
Theo.T
1
Saya menduga bahwa browser modern semuanya mendukung navigator.language. Browser saya (FF3 pada Ubuntu 8.10) melaporkan 'en-GB'. Jika seseorang masih menggunakan IE6 - sekitar 20% orang - maka layak untuk itu. IE6 muncul 8 tahun yang lalu.
Phil H
IE 8 tidak mendukung navigator.language. Mungkin IE 9 akan?
spig
36

Menggabungkan berbagai cara yang digunakan browser untuk menyimpan bahasa pengguna, Anda mendapatkan fungsi ini:

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

Kami pertama-tama memeriksa navigator.languagesarray untuk elemen pertamanya.
Lalu kita dapat salah satu navigator.userLanguageatau navigator.language.
Jika gagal kita dapatkan navigator.browserLanguage.
Akhirnya, kami mengaturnya 'en'jika semuanya gagal.


Dan inilah yang seksi:

const getNavigatorLanguage = () => (navigator.languages && navigator.languages.length) ? navigator.languages[0] : navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en';
Zenoo
sumber
ada rupanya juga sesuatu sebagai navigator.userLanguage(untuk IE). Anda bisa menambahkannya agar lengkap :)
pors
Kenapa tidak sederhana saja navigator.languages[0] || navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en'?
Emerica
@Curse Karena navigator.languagesbisaundefined
Zenoo
@ Zenoo Apakah Anda tahu di browser mana?
Emerica
(navigator.languages || [])[0] || navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en'
Steve Bennett
10

Ada perbedaan antara bahasa pilihan pengguna dan lokal sistem / browser.

Seorang pengguna dapat mengonfigurasi bahasa yang disukai di browser, dan ini akan digunakan untuk navigator.language(s), dan digunakan ketika meminta sumber daya dari server, untuk meminta konten sesuai dengan daftar prioritas bahasa.

Namun, lokal browser akan memutuskan cara merender nomor, tanggal, waktu dan mata uang. Pengaturan ini kemungkinan merupakan bahasa peringkat tertinggi, tetapi tidak ada jaminan. Di Mac dan Linux, lokal ditentukan oleh sistem terlepas dari preferensi bahasa pengguna. Pada Windows dapat dipilih di antara bahasa-bahasa dalam daftar pilihan di Chrome.

Dengan menggunakan Intl ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl ), pengembang dapat mengesampingkan / mengatur lokal yang akan digunakan untuk membuat hal-hal ini, tetapi ada elemen yang tidak dapat diganti, seperti <input type="date">format.

Untuk mengekstrak bahasa ini dengan benar, satu-satunya cara yang saya temukan adalah:

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

( Intl.NumberFormat().resolvedOptions().localetampaknya juga berfungsi)

Ini akan membuat instance NumberFormat baru untuk lokal default dan kemudian membaca kembali lokal dari opsi yang diselesaikan.

Patrik Kullman - Neovici
sumber
5

Saya melakukan sedikit riset tentang ini & saya telah meringkas temuan saya sejauh ini di bawah tabel

masukkan deskripsi gambar di sini

Jadi solusi yang disarankan adalah menulis skrip sisi server untuk mengurai Accept-Languageheader & meneruskannya ke klien untuk mengatur bahasa situs web. Sungguh aneh bahwa mengapa server akan diperlukan untuk mendeteksi preferensi bahasa klien, tetapi begitulah sekarang. Ada berbagai peretasan lain yang tersedia untuk mendeteksi bahasa, tetapi membaca Accept-Languagetajuk adalah solusi yang disarankan sesuai pemahaman saya.

Abhishek V
sumber
2

Anda juga dapat mencoba untuk mendapatkan bahasa dari dokumen yang seharusnya menjadi porta panggilan pertama Anda, lalu kembali ke cara lain karena sering kali orang ingin bahasa JS mereka cocok dengan bahasa dokumen.

HTML5:

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

Warisan:

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

Tidak ada sumber nyata yang 100% dapat diandalkan karena orang hanya dapat menggunakan bahasa yang salah.

Ada perpustakaan pendeteksi bahasa yang memungkinkan Anda menentukan bahasa berdasarkan konten.

jgmjgm
sumber
1

Saya menggunakan semua jawaban dan menciptakan solusi baris tunggal:

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

console.log(getLanguage());
Caio Santos
sumber