ブラウザ内でユーザーのロケールを決定する最良の方法


203

数十の言語にローカライズされたWebサイト(Flash)があり、コンテンツへのアクセス手順を最小限に抑えるために、ユーザーのブラウザー設定に応じてデフォルト値を自動定義したいと考えています。

ちなみに、プロキシの制限によりサーバースクリプトを使用できないため、JavaScriptまたはActionScriptで問題を解決できると思います。

質問:

  1. ユーザーのロケールを「推測」する最良の方法は何でしょうか?

  2. 私を助けることができる既存の単純なクラス/関数はありますか(複雑なローカリゼーションバンドルはありません)?特に、可能なすべての言語をより少ない数(私が持っている翻訳)にスマートな方法で分解すること。

  3. このようなソリューションはどの時点で信頼できますか?

  4. 他の回避策や提案はありますか?


ブラウザがユーザーに関するメタデータを共有できる唯一の方法であり、リクエストはURLとヘッダーを介して行われます。Firefoxを入手して、リクエストが行われたときに送信されるヘッダーを確認してください。典型的なリクエストとレスポンスのヘッダーを調べるのはとても興味深いです。
mP。

回答:


188

適切な方法は、サーバーに送信されたHTTP Accept-Languageヘッダーを確認することです。これには、ユーザーがブラウザーを優先するように構成した言語の重み付けされた順序付きリストが含まれています。

残念ながら、このヘッダーはJavaScript内で読み取ることはできません。入手できるのはnavigator.language、ローカライズされたバージョンのWebブラウザーがインストールされていることを通知するだけです。これは、必ずしもユーザーの優先言語と同じではありません。IEでは、代わりにsystemLanguage(OSインストール言語)、browserLanguage(と同じlanguage)、userLanguage(ユーザー設定のOSリージョン)が表示されますが、これらはすべて同様に役に立ちません。

これらのプロパティのいずれかを選択する必要がある場合は、userLanguage最初にスニッフィングし、フォールバックしlanguage、その後に(それらが利用可能な言語に一致しなかった場合のみ)browserLanguage、最後にを調べsystemLanguageます。

Accept-Languageヘッダーを単に読み取り、文字列にヘッダー値を含むJavaScriptファイルとしてそれを吐き出すサーバー側スクリプトをネット上のどこかに置くことができる場合、例えば:

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

次に、その外部サービスを指す<script src>をHTMLに含め、JavaScriptを使用して言語ヘッダーを解析できます。Accept-Language解析はほとんどの場合サーバー側で行われるため、これを行うための既存のライブラリコードはわかりません。

最終的に何をするにしても、一部の人にとっては常に間違っていると推測されるため、ユーザーオーバーライドが必要です。多くの場合、URLに言語設定を配置し(例:http://www.example.com/en/site vs http://www.example.com/de/site)、ユーザーがクリックできるようにします2つの間のリンク。両方の言語バージョンに単一のURLが必要な場合があります。その場合、設定をCookieに保存する必要がありますが、ユーザーエージェントがCookieと検索エンジンをサポートしていないと混乱する可能性があります。


11
MDNからdeveloper.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/...「同意する言語は、ユーザーのブラウザからのすべてのHTTPリクエストに余分以外navigator.languagesプロパティに同じ値を使用してHTTPヘッダーqvalues(品質値)フィールド(例en-US; q = 0.8)。 "
S Meaden

3
更新:言語設定の配列を返すすべての最新ブラウザでサポートされている(2020)実験的な機能が用意されました:navigator.languages //["en-US", "zh-CN", "ja-JP"]これは、2020年には、ブラウザの少なくとも95%で動作するはずです
コーネリアスレーマー

1
navigator.languagesMDNcaniuse.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 2016年

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

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 2016年

さらにコンパクト版についてconst getLang = () => navigator.language || navigator.browserLanguage || ( navigator.languages || [ "en" ] ) [ 0 ]
ジョアン・ミゲルブランドン

41

この記事では、ブラウザーのナビゲーターオブジェクトの次のプロパティを提案しています。

  • navigator.language (Netscape-ブラウザローカリゼーション)
  • navigator.browserLanguage(IE固有-ブラウザローカライズ言語)
  • navigator.systemLanguage (IE固有-Windows OS-ローカライズされた言語)
  • navigator.userLanguage

これらをJavaScript関数に入れれば、ほとんどの状況で正しい言語を推測できるはずです。必ず適切にデグレードするようにしてください。divに言語選択リンクを含めてください。JavaScriptがない場合やメソッドが機能しない場合でも、ユーザーが判断できるようにします。機能する場合は、divを非表示にします。

クライアント側でこれを行う場合の唯一の問題は、クライアントにすべての言語を提供するか、スクリプトが実行されて言語が検出されるまで待ってから適切なバージョンを要求することです。おそらく、最も人気のある言語バージョンをデフォルトとして提供することは、最も少ない人々を苛立たせるでしょう。

編集:私は2番目のIvanのCookieの提案ですが、ユーザーが後でいつでも言語を変更できることを確認してください。誰もがブラウザのデフォルトの言語を好むわけではありません。


Philに提案をありがとう。記事に関しては、それは6年前のものです...私たちがそれを信頼できるかわかりませんか?
Theo.T 2009年

1
最近のブラウザはすべてnavigator.languageをサポートしていると思います。私のブラウザー(Ubuntu 8.10のFF3)は「en-GB」を報告します。誰かがまだIE6を使用している場合-約20%の人-それを許可する価値があります。IE6は8年前に登場しました。
Phil H

IE 8はnavigator.languageをサポートしていません。多分IE 9はするでしょうか?
スパイ

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

@Curseのでnavigator.languages可能undefined
Zenoo

@Zenooどのブラウザで知っていますか?
Emerica

(navigator.languages || [])[0] || navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en'
スティーブベネット

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ヘッダーを解析し、それをクライアントに渡してWebサイトの言語を設定することです。クライアントの言語設定を検出するためにサーバーが必要となる理由は奇妙ですが、それは現在のようです。言語を検出するために利用できる他のさまざまなハックがありますが、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());

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.