Cách tốt nhất để xác định ngôn ngữ của người dùng trong trình duyệt


203

Tôi có một trang web (Flash) được bản địa hóa thành hàng tá ngôn ngữ và tôi muốn tự động xác định giá trị mặc định tùy thuộc vào cài đặt trình duyệt của người dùng để giảm thiểu các bước truy cập nội dung.

FYI, tôi không thể sử dụng tập lệnh máy chủ do hạn chế proxy, vì vậy tôi đoán JavaScript hoặc ActionScript sẽ phù hợp để giải quyết vấn đề.

Câu hỏi:

  1. Điều gì sẽ là phương pháp tốt nhất để 'đoán' miền địa phương của người dùng?

  2. Có bất kỳ lớp / hàm đơn giản hiện có nào có thể giúp tôi không (không có gói nội địa hóa phức tạp)? Đặc biệt để chia tất cả các ngôn ngữ có thể thành một số nhỏ hơn (bản dịch tôi có) một cách thông minh.

  3. Đến điểm nào tôi có thể tin tưởng một giải pháp như vậy?

  4. Bất kỳ cách giải quyết hoặc đề xuất khác?


Họ chỉ có cách trình duyệt có thể chia sẻ dữ liệu meta về người dùng của mình và yêu cầu là thông qua URL và tiêu đề. Lấy Firefox và xem qua các tiêu đề được gửi khi có yêu cầu. Nó khá thú vị để kiểm tra các tiêu đề yêu cầu và phản hồi điển hình.
mP.

Câu trả lời:


188

Cách thích hợp là xem tiêu đề Ngôn ngữ chấp nhận HTTP được gửi đến máy chủ. Điều này chứa danh sách các ngôn ngữ có trọng số theo thứ tự mà người dùng đã định cấu hình trình duyệt của họ để thích.

Thật không may, tiêu đề này không có sẵn để đọc bên trong JavaScript; tất cả những gì bạn nhận được là navigator.language, nó cho bạn biết phiên bản trình duyệt web đã được cài đặt. Điều này không nhất thiết giống với ngôn ngữ ưa thích của người dùng. Trên IE, thay vào đó, bạn nhận được systemLanguage(ngôn ngữ được cài đặt hệ điều hành), browserLanguage(giống như language) và userLanguage(khu vực hệ điều hành được cấu hình bởi người dùng), tất cả đều không có ích tương tự.

Nếu tôi phải lựa chọn giữa các thuộc tính đó, userLanguagetrước tiên tôi sẽ đánh hơi , quay lại languagevà chỉ sau đó (nếu những ngôn ngữ đó không phù hợp với bất kỳ ngôn ngữ có sẵn nào) browserLanguagevà cuối cùng systemLanguage.

Nếu bạn có thể đặt tập lệnh phía máy chủ ở một nơi khác trên mạng chỉ cần đọc tiêu đề Ngôn ngữ chấp nhận và gửi nó ra dưới dạng tệp JavaScript có giá trị tiêu đề trong chuỗi, ví dụ:

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

sau đó, bạn có thể bao gồm <script src> trỏ đến dịch vụ bên ngoài đó trong HTML và sử dụng JavaScript để phân tích tiêu đề ngôn ngữ. Tuy nhiên, tôi không biết bất kỳ mã thư viện hiện có nào để thực hiện việc này, vì phân tích ngôn ngữ Chấp nhận hầu như luôn được thực hiện ở phía máy chủ.

Dù cuối cùng bạn làm gì, bạn chắc chắn cần một người dùng ghi đè vì nó sẽ luôn đoán sai đối với một số người. Thông thường, dễ nhất là đặt cài đặt ngôn ngữ trong URL (ví dụ: http: //www.example.com/en/site so với http: //www.example.com/de/site) và cho phép người dùng nhấp vào liên kết giữa hai. Đôi khi bạn muốn có một URL duy nhất cho cả hai phiên bản ngôn ngữ, trong trường hợp đó bạn phải lưu trữ cài đặt trong cookie, nhưng điều này có thể gây nhầm lẫn cho các tác nhân người dùng không hỗ trợ cookie và công cụ tìm kiếm.


11
Từ MDN developer.mozilla.org/en-US/docs/Web/API/NavigatorL Language / '"Tiêu đề HTTP Ngôn ngữ chấp nhận trong mọi yêu cầu HTTP từ trình duyệt của người dùng sử dụng cùng một giá trị cho thuộc tính navigator.lacular ngoại trừ trường qvalues ​​(giá trị chất lượng) (ví dụ: en-US; q = 0.8). "
S Meaden

3
Cập nhật: Hiện tại (2020) một tính năng thử nghiệm được hỗ trợ bởi tất cả các trình duyệt hiện đại trả về một loạt các ưu tiên ngôn ngữ: navigator.languages //["en-US", "zh-CN", "ja-JP"]Điều này sẽ hoạt động trên ít nhất 95% trình duyệt vào năm 2020.
Cornelius RoTable

1
navigator.languages, theo cả MDN caniuse.com , hiện có sẵn trong tất cả các trình duyệt chính - hãy thử gói ngôn ngữ điều hướng nhỏ (~ 200 byte) cho cách tiếp cận hiện đại nhất và tương thích ngược.
mindplay.dk

84

Trên Chrome và Firefox 32+, navigator.liances chứa một loạt các vị trí theo thứ tự ưu tiên của người dùng và chính xác hơn navigator.l Language, tuy nhiên để làm cho nó tương thích ngược (Đã kiểm tra Chrome / IE / Firefox / Safari), sau đó sử dụng điều này:

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

2
Điều này không hoạt động cho IE9 và IE10. Đối với họ, bạn phải kiểm tra navigator.browserL Language thay thế.
dùng393274

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

4
@ChStark Có nên không return navigator.languages[0] || navigator.language;?
James_

23
Ngoài ra, "một lớp lót" chính xác sẽ trông như thế này : return (navigator.languages && navigator.languages.length) ? navigator.languages[0] : navigator.language;. Nếu không, bạn nhận được một ngoại lệ nếu navigator.languageskhông xác định hoặc trống.
Max Truxa

Đối với phiên bản nhỏ gọn hơnconst getLang = () => navigator.language || navigator.browserLanguage || ( navigator.languages || [ "en" ] ) [ 0 ]
João Miguel Brandão

41

Bài viết này đề xuất các thuộc tính sau của trình duyệt đối tượng điều hướng :

  • navigator.language (Netscape - Bản địa hóa trình duyệt)
  • navigator.browserLanguage (Cụ thể IE - Ngôn ngữ địa phương hóa trình duyệt)
  • navigator.systemLanguage (Cụ thể IE - HĐH Windows - Ngôn ngữ địa phương)
  • navigator.userLanguage

Đưa những thứ này vào một chức năng javascript và bạn sẽ có thể đoán đúng ngôn ngữ, trong hầu hết các trường hợp. Hãy chắc chắn xuống cấp một cách duyên dáng, do đó, có một div chứa các liên kết lựa chọn ngôn ngữ của bạn, để nếu không có javascript hoặc phương thức không hoạt động, người dùng vẫn có thể quyết định. Nếu nó hoạt động, chỉ cần ẩn div.

Vấn đề duy nhất khi làm điều này ở phía khách hàng là bạn phục vụ tất cả các ngôn ngữ cho máy khách hoặc bạn phải đợi cho đến khi tập lệnh chạy và phát hiện ngôn ngữ trước khi yêu cầu phiên bản phù hợp. Có lẽ việc phục vụ phiên bản ngôn ngữ phổ biến nhất như một mặc định sẽ gây khó chịu cho những người ít nhất.

Chỉnh sửa: Tôi muốn đề xuất cookie thứ hai của Ivan, nhưng đảm bảo người dùng luôn có thể thay đổi ngôn ngữ sau này; không phải ai cũng thích ngôn ngữ mà trình duyệt của họ mặc định.


Cảm ơn Phil cho đề xuất của bạn. Về bài báo, nó đã 6 tuổi ... không chắc chúng ta có thể dựa vào nó không?
Theo.T

1
Tôi nghi ngờ rằng tất cả các trình duyệt hiện đại đều hỗ trợ navigator.l Language. Trình duyệt của tôi (FF3 trên Ubuntu 8.10) báo cáo 'en-GB'. Nếu ai đó vẫn đang sử dụng IE6 - khoảng 20% ​​số người - thì đáng để cho phép điều đó. IE6 xuất hiện 8 năm trước.
Phil H

IE 8 không hỗ trợ điều hướng. Ngôn ngữ. Có lẽ IE 9 sẽ?
spig

36

Kết hợp nhiều cách trình duyệt đang sử dụng để lưu trữ ngôn ngữ của người dùng, bạn sẽ có được chức năng này:

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

Đầu tiên chúng ta kiểm tra navigator.languagesmảng cho phần tử đầu tiên của nó.
Sau đó, chúng tôi nhận được navigator.userLanguagehoặc navigator.language.
Nếu thất bại, chúng tôi nhận được navigator.browserLanguage.
Cuối cùng, chúng tôi đặt nó thành 'en'nếu mọi thứ khác không thành công.


Và đây là bộ đồ lót gợi cảm:

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

rõ ràng cũng có một cái gì đó như navigator.userLanguage(đối với IE). Bạn có thể thêm nó để hoàn thành nó :)
pors

Tại sao không đơn giản navigator.languages[0] || navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en'?
Emerica

@Curse Bởi vì navigator.languagescó thểundefined
Zenoo

@Zenoo Bạn có biết trên trình duyệt nào không?
Emerica

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

10

Có sự khác biệt giữa ngôn ngữ ưa thích của người dùng và ngôn ngữ hệ thống / trình duyệt.

Người dùng có thể định cấu hình các ngôn ngữ ưa thích trong trình duyệt và những ngôn ngữ này sẽ được sử dụng cho navigator.language(s) và sử dụng khi yêu cầu tài nguyên từ máy chủ, để yêu cầu nội dung theo danh sách ưu tiên ngôn ngữ.

Tuy nhiên, ngôn ngữ trình duyệt sẽ quyết định cách hiển thị số, ngày, giờ và tiền tệ. Cài đặt này có thể là ngôn ngữ xếp hạng cao nhất, nhưng không có gì đảm bảo. Trên Mac và Linux, ngôn ngữ được hệ thống quyết định bất kể tùy chọn ngôn ngữ người dùng. Trên Windows có thể được chọn trong số các ngôn ngữ trong danh sách ưa thích trên Chrome.

Bằng cách sử dụng Intl ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl ), nhà phát triển có thể ghi đè / đặt ngôn ngữ để sử dụng để hiển thị những thứ này, nhưng có những yếu tố không thể bị ghi đè, chẳng hạn như <input type="date">định dạng.

Để trích xuất chính xác ngôn ngữ này, cách duy nhất tôi tìm thấy là:

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

( Intl.NumberFormat().resolvedOptions().localedường như cũng hoạt động)

Điều này sẽ tạo một cá thể NumberFormat mới cho miền địa phương mặc định và sau đó đọc lại miền địa phương của các tùy chọn đã giải quyết đó.


5

Tôi đã làm một chút nghiên cứu về điều này và tôi đã tóm tắt những phát hiện của tôi cho đến nay trong bảng dưới đây

nhập mô tả hình ảnh ở đây

Vì vậy, giải pháp được đề xuất là viết một kịch bản phía máy chủ để phân tích Accept-Languagetiêu đề và chuyển nó cho khách hàng để thiết lập ngôn ngữ của trang web. Thật kỳ lạ là tại sao máy chủ lại cần thiết để phát hiện sở thích ngôn ngữ của khách hàng nhưng đó là hiện tại có nhiều cách hack khác để phát hiện ngôn ngữ nhưng đọc Accept-Languagetiêu đề là giải pháp được đề xuất theo sự hiểu biết của tôi.


2

Bạn cũng có thể thử lấy ngôn ngữ từ tài liệu có thể là cổng gọi đầu tiên của bạn, sau đó quay lại các phương tiện khác vì mọi người sẽ muốn ngôn ngữ JS của họ khớp với ngôn ngữ tài liệu.

HTML5:

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

Di sản:

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

Không có nguồn thực sự nào đáng tin cậy 100% vì mọi người chỉ có thể đặt sai ngôn ngữ.

Có những thư viện phát hiện ngôn ngữ có thể cho phép bạn xác định ngôn ngữ theo nội dung.


1

Tôi đã sử dụng tất cả các câu trả lời và tạo ra một giải pháp dòng duy nhất:

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

console.log(getLanguage());

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.