วิธีที่ดีที่สุดในการกำหนดสถานที่ของผู้ใช้ภายในเบราว์เซอร์


203

ฉันมีเว็บไซต์ (Flash) เป็นภาษาท้องถิ่นหลายสิบภาษาและฉันต้องการกำหนดค่าเริ่มต้นโดยอัตโนมัติขึ้นอยู่กับการตั้งค่าเบราว์เซอร์ของผู้ใช้เพื่อลดขั้นตอนในการเข้าถึงเนื้อหาให้น้อยที่สุด

FYI ฉันไม่สามารถใช้เซิร์ฟเวอร์สคริปต์เนื่องจากข้อ จำกัด พร็อกซี่ดังนั้นฉันจึงคาดว่า JavaScript หรือ ActionScript จะเหมาะสมในการแก้ปัญหา

คำถาม:

  1. อะไรจะเป็นวิธีที่ดีที่สุดในการ 'เดา' ตำแหน่งที่ตั้งของผู้ใช้

  2. มีคลาส / ฟังก์ชันพื้นฐานที่มีอยู่ที่สามารถช่วยฉันได้ (ไม่มีบันเดิลการแปลที่ซับซ้อน)? พิเศษเพื่อแยกภาษาที่เป็นไปได้ทั้งหมดออกเป็นตัวเลขที่เล็กลง (การแปลที่ฉันมี) อย่างชาญฉลาด

  3. ฉันเชื่อถือโซลูชั่นดังกล่าวได้จนถึงจุดใด

  4. การแก้ไขปัญหาอื่น ๆ หรือข้อเสนอแนะ?


มีเพียงวิธีเดียวที่เบราว์เซอร์สามารถแบ่งปันข้อมูลเมตาเกี่ยวกับผู้ใช้และคำขอจะทำผ่าน URL และส่วนหัว หยิบ Firefox และมองที่ส่วนหัวที่ถูกส่งเมื่อมีการร้องขอ มันค่อนข้างน่าสนใจในการตรวจสอบคำขอทั่วไปและส่วนหัวการตอบสนอง
mP

คำตอบ:


188

วิธีที่เหมาะสมคือดูที่ส่วนหัวHTTP Accept-Language ที่ส่งไปยังเซิร์ฟเวอร์ รายการนี้ประกอบด้วยรายการภาษาที่เรียงลำดับและถ่วงน้ำหนักที่ผู้ใช้กำหนดค่าเบราว์เซอร์ให้เป็นที่ต้องการ

น่าเสียดายที่ส่วนหัวนี้ไม่สามารถอ่านได้จาก JavaScript สิ่งที่คุณจะได้รับคือnavigator.languageสิ่งที่บอกคุณว่ามีการติดตั้งเว็บเบราว์เซอร์เวอร์ชันที่แปลเป็นภาษาท้องถิ่น สิ่งนี้ไม่จำเป็นต้องเหมือนกับภาษาที่ผู้ใช้ต้องการ ใน IE คุณจะได้รับsystemLanguage(ภาษาที่ติดตั้งระบบปฏิบัติการ), browserLanguage(เหมือนlanguage) และuserLanguage(ผู้ใช้กำหนดค่าภูมิภาค OS) ซึ่งไม่ช่วยเหลือในทำนองเดียวกัน

ถ้าผมต้องเลือกระหว่างคุณสมบัติเหล่านั้นผมสูดอากาศสำหรับuserLanguageครั้งแรกลดลงกลับไปlanguageและหลังจากที่ (ถ้าผู้ที่ไม่ตรงกับภาษาใด ๆ ) กำลังมองหาที่และในที่สุดbrowserLanguagesystemLanguage

หากคุณสามารถวางสคริปต์ฝั่งเซิร์ฟเวอร์ไว้ที่อื่นที่อยู่บนเน็ตก็เพียงแค่อ่านส่วนหัวยอมรับภาษาและแยกออกเป็นไฟล์ JavaScript ที่มีค่าส่วนหัวในสตริงเช่น:

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

จากนั้นคุณสามารถรวม <script src> ชี้ไปที่บริการภายนอกนั้นใน HTML และใช้ JavaScript เพื่อแยกส่วนหัวของภาษา ฉันไม่ทราบรหัสห้องสมุดใด ๆ ที่มีอยู่ในการทำเช่นนี้เนื่องจากการแยกวิเคราะห์ยอมรับภาษามักจะทำในฝั่งเซิร์ฟเวอร์

ไม่ว่าคุณจะทำอะไรคุณต้องลบล้างผู้ใช้อย่างแน่นอนเพราะบางคนจะเดาผิด บ่อยครั้งที่ง่ายที่สุดในการตั้งค่าภาษาใน URL (เช่น http: //www.example.com/en/site vs http: //www.example.com/de/site) และให้ผู้ใช้คลิก ลิงก์ระหว่างสอง บางครั้งคุณต้องการ URL เดียวสำหรับทั้งสองภาษาซึ่งในกรณีนี้คุณต้องจัดเก็บการตั้งค่าในคุกกี้ แต่สิ่งนี้อาจทำให้ตัวแทนผู้ใช้สับสนโดยไม่สนับสนุนคุกกี้และเครื่องมือค้นหา


11
จาก MDN developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/ ...... "ส่วนหัว Accept-Language HTTP ในทุกคำขอ HTTP จากเบราว์เซอร์ของผู้ใช้ใช้ค่าเดียวกันสำหรับคุณสมบัติ navigator.languages ฟิลด์ qvalues ​​(ค่าคุณภาพ) (เช่น en-US; q = 0.8) "
S Meaden

3
อัปเดต: ตอนนี้มีคุณสมบัติการทดลอง (2020) ที่สนับสนุนโดยเบราว์เซอร์สมัยใหม่ทั้งหมดที่ส่งคืนการตั้งค่าภาษา: navigator.languages //["en-US", "zh-CN", "ja-JP"]มันควรใช้กับเบราว์เซอร์อย่างน้อย 95% ในปี 2020
คอร์เนเลียสรูแม

1
navigator.languagesตามMDNและcaniuse.comตอนนี้มีให้ใช้งานในเบราว์เซอร์หลักทั้งหมด - ลองใช้แพคเกจเนวิเกเตอร์ภาษาขนาดเล็ก (~ 200 ไบต์) สำหรับวิธีการที่ทันสมัยที่สุดและเข้ากันได้แบบย้อนหลัง
mindplay.dk

84

ใน Chrome และ Firefox 32+ navigator.languages ​​มีอาร์เรย์ของโลแคลตามลำดับการตั้งค่าของผู้ใช้และแม่นยำกว่า navigator.language อย่างไรก็ตามเพื่อให้ใช้งานร่วมกับระบบย้อนหลังได้ (ทดสอบ Chrome / IE / Firefox / Safari) แล้วใช้ นี้:

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

2
สิ่งนี้ใช้ไม่ได้กับ IE9 และ IE10 สำหรับพวกเขาคุณต้องตรวจสอบ navigator.browserLanguage แทน
user393274

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

4
@ChStark ไม่ควรจะเป็นreturn navigator.languages[0] || navigator.language;?
James_

23
นอกจากนี้การที่ถูกต้อง "หนึ่งซับ" return (navigator.languages && navigator.languages.length) ? navigator.languages[0] : navigator.language;จะมีลักษณะเช่นนี้ มิฉะนั้นคุณจะได้รับข้อยกเว้นหากnavigator.languagesไม่ได้กำหนดหรือว่างเปล่า
Max Truxa

สำหรับรุ่นที่กะทัดรัดยิ่งขึ้นconst getLang = () => navigator.language || navigator.browserLanguage || ( navigator.languages || [ "en" ] ) [ 0 ]
João Miguel Brandão

41

บทความนี้แนะนำคุณสมบัติต่อไปนี้ของวัตถุนำทางของเบราว์เซอร์:

  • navigator.language (Netscape - การแปลเบราว์เซอร์)
  • navigator.browserLanguage (เฉพาะภาษา IE - ภาษาท้องถิ่นของเบราว์เซอร์)
  • navigator.systemLanguage (เฉพาะ IE - Windows OS - ภาษาท้องถิ่น)
  • navigator.userLanguage

สะสมสิ่งเหล่านี้เป็นฟังก์ชั่นจาวาสคริปต์และคุณควรจะเดาภาษาที่ถูกต้องในสถานการณ์ส่วนใหญ่ ตรวจสอบให้แน่ใจว่าได้ลดระดับลงอย่างงดงามดังนั้นให้ div มีลิงค์ตัวเลือกภาษาของคุณดังนั้นหากไม่มีจาวาสคริปต์หรือวิธีการใช้งานไม่ได้ผู้ใช้ยังคงสามารถตัดสินใจได้ ถ้ามันใช้งานได้ก็แค่ซ่อน div

ปัญหาเดียวของการทำสิ่งนี้ทางฝั่งไคลเอ็นต์คือคุณให้บริการทุกภาษาแก่ลูกค้าหรือคุณต้องรอจนกว่าสคริปต์จะทำงานและตรวจพบภาษาก่อนที่จะขอรุ่นที่ถูกต้อง บางทีการใช้ภาษาที่เป็นที่นิยมมากที่สุดเป็นค่าเริ่มต้นอาจทำให้คนที่มีน้อย

แก้ไข: ฉันต้องการแนะนำคุกกี้ของ Ivan ที่สอง แต่ให้แน่ใจว่าผู้ใช้สามารถเปลี่ยนภาษาได้ในภายหลัง ทุกคนไม่ชอบภาษาที่เบราว์เซอร์เป็นค่าเริ่มต้น


ขอบคุณ Phil สำหรับคำแนะนำของคุณ เกี่ยวกับบทความอายุ 6 ปี ... ไม่แน่ใจว่าเราจะเชื่อถือได้หรือไม่
Theo.T

1
ฉันสงสัยว่าเบราว์เซอร์ที่ทันสมัยรองรับ navigator.language เบราว์เซอร์ของฉัน (FF3 บน Ubuntu 8.10) รายงาน 'en-GB' หากใครบางคนยังคงใช้ IE6 - ประมาณ 20% ของคน - มันก็คุ้มค่าที่จะยอมให้ทำเช่นนั้น IE6 ปรากฏขึ้นเมื่อ 8 ปีที่แล้ว
Phil H

IE 8 ไม่รองรับ navigator.language บางที IE 9 จะเป็นเช่นนั้น?
spig

36

เมื่อรวมหลายวิธีที่เบราว์เซอร์ใช้เพื่อจัดเก็บภาษาของผู้ใช้คุณจะได้รับฟังก์ชันนี้:

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

ก่อนอื่นเราตรวจสอบnavigator.languagesอาร์เรย์สำหรับองค์ประกอบแรก
จากนั้นเราได้รับอย่างใดอย่างหนึ่งหรือnavigator.userLanguage หากล้มเหลวที่เราได้รับ ในที่สุดเราตั้งเป็นหากทุกอย่างล้มเหลวnavigator.language
navigator.browserLanguage
'en'


และนี่คือหนึ่งซับเซ็กซี่:

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

เห็นได้ชัดว่ามีบางสิ่งบางอย่างเช่นnavigator.userLanguage(สำหรับ IE) คุณสามารถเพิ่มที่จะทำให้มันสมบูรณ์ :)
Pors

ทำไมไม่ง่าย ๆnavigator.languages[0] || navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en'?
Emerica

@ บัญชีเพราะnavigator.languagesสามารถundefined
Zenoo

@Zenoo คุณรู้จักเบราว์เซอร์ใดบ้าง
Emerica

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

10

มีความแตกต่างระหว่างภาษาที่ผู้ใช้ต้องการกับระบบ / ภาษาของเบราว์เซอร์

ผู้ใช้สามารถกำหนดค่าภาษาที่ต้องการในเบราว์เซอร์และจะใช้navigator.language(s)และใช้เมื่อขอทรัพยากรจากเซิร์ฟเวอร์เพื่อขอเนื้อหาตามรายการลำดับความสำคัญของภาษา

อย่างไรก็ตามสถานที่ตั้งของเบราว์เซอร์จะตัดสินใจว่าจะแสดงจำนวนวันที่เวลาและสกุลเงินอย่างไร การตั้งค่านี้น่าจะเป็นภาษาอันดับสูงสุด แต่ไม่มีการรับประกัน บน Mac และ Linux โลแคลถูกตัดสินใจโดยระบบโดยไม่คำนึงถึงค่ากำหนดภาษาของผู้ใช้ บน Windows สามารถเลือกได้ระหว่างภาษาในรายการที่ต้องการบน Chrome

โดยใช้ Intl ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl ) ผู้พัฒนาสามารถแทนที่ / ตั้งค่าภาษาเพื่อใช้แสดงสิ่งเหล่านี้ แต่มีองค์ประกอบที่ ไม่สามารถเขียนทับเช่น<input type="date">รูปแบบ

หากต้องการแยกภาษานี้อย่างถูกต้องวิธีเดียวที่ฉันค้นพบคือ:

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

( Intl.NumberFormat().resolvedOptions().localeดูเหมือนว่าจะทำงาน)

สิ่งนี้จะสร้างอินสแตนซ์ NumberFormat ใหม่สำหรับสถานที่เริ่มต้นจากนั้นอ่านสถานที่เกิดเหตุของตัวเลือกที่ได้รับการแก้ไขเหล่านั้นกลับมา


5

ฉันทำการวิจัยเล็กน้อยเกี่ยวกับสิ่งนี้ & ฉันได้สรุปสิ่งที่ฉันค้นพบในตารางด้านล่าง

ป้อนคำอธิบายรูปภาพที่นี่

ดังนั้นทางออกที่แนะนำคือการเขียนสคริปต์ฝั่งเซิร์ฟเวอร์เพื่อวิเคราะห์Accept-Languageส่วนหัวและส่งต่อไปยังไคลเอนต์เพื่อตั้งค่าภาษาของเว็บไซต์ มันแปลกที่ทำไมเซิร์ฟเวอร์จะต้องตรวจจับการตั้งค่าภาษาของลูกค้า แต่นั่นเป็นอย่างไรในขณะนี้มีแฮ็คอื่น ๆ อีกมากมายที่สามารถตรวจจับภาษาได้ แต่การอ่านAccept-Languageส่วนหัวเป็นวิธีที่แนะนำตามความเข้าใจของฉัน


2

คุณยังสามารถลองรับภาษาจากเอกสารที่ควรจะเป็นพอร์ตแรกของการโทรจากนั้นกลับไปที่วิธีการอื่นเพราะผู้คนมักจะต้องการให้ภาษา JS ของพวกเขาตรงกับภาษาของเอกสาร

HTML5:

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

มรดก:

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

ไม่มีแหล่งข้อมูลจริงที่เชื่อถือได้ 100% เนื่องจากผู้คนสามารถใส่ภาษาผิดได้

มีไลบรารีตรวจจับภาษาที่อาจอนุญาตให้คุณกำหนดภาษาตามเนื้อหา


1

ฉันใช้คำตอบทั้งหมดและสร้างโซลูชันบรรทัดเดียว:

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

console.log(getLanguage());

-1

คุณบอกว่าเว็บไซต์ของคุณมี Flash จากนั้นเป็นอีกตัวเลือกหนึ่งคุณสามารถใช้ภาษาของระบบปฏิบัติการได้flash.system.Capabilities.language- ดูวิธีกำหนดภาษา OS ภายในเบราว์เซอร์เพื่อคาดเดาตำแหน่งของระบบปฏิบัติการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.