いくつかの翻訳が利用可能なアプリケーションがあるとします。
AVAILABLE_LOCALES = ['en_US', 'en_EN', 'de_AT']
Accept-Language
ヘッダーに従って最も適切なものを選択したいと思います。
request.accept_languages.best_match の使用
ロケールを取得するには、次のように記述します。
@babel.localeselector
def get_locale():
user = getattr(g, 'user', None)
if user is not None:
return user.locale
return request.accept_languages.best_match(AVAILABLE_LOCALES)
問題は、ユーザー エージェントが を要求した場合、一致が失敗し、選択がデフォルト値 (英語) に戻りますが、明らかにde_DE
を取得したい場合です。de_AT
注:ドキュメントページの例は次のとおりです
return request.accept_languages.best_match(['de', 'fr', 'en'])
en_EN
ただし、これは同じ言語の 2 つの異なるバージョン ( 、 )を許可しませんen_US
。
交渉_ロケールの使用
このGitHub の問題で、誰かが Babel のnegotiate_locale
関数の使用を提案しています。
@babel.localeselector
def get_locale():
user = getattr(g, 'user', None)
if user is not None:
return user.locale
preferred = [x.replace('-', '_') for x in request.accept_languages.values()]
return negotiate_locale(preferred, AVAILABLE_LOCALES)
しかし、知る限り、これですべてのユースケースが修正されるわけではありません。利用可能なロケール['de_AT', 'de']
が['en_US', 'en_EN', 'de_DE']
. しかし、その逆ではありません:
negotiate_locale(['de_AT', 'de'], ['en_US', 'en_EN', 'de_DE']) # returns de_DE
negotiate_locale(['de_DE', 'de'], ['en_US', 'en_EN', 'de_AT']) # returns None
エイリアスのハードコーディングされたリストがをde
指すため、最初の方法が機能しde_DE
ます。
また、ブラウザが送信するだけで送信de_AT
しない場合de
も壊れていますが、これが一般的な構成かどうかはわかりません (次の段落を参照)。
これに対処する信頼できる方法はありますか?
最新のブラウザの典型的な値?
サブ質問として、最新のブラウザーにどのような値を期待できるかを知りたいです。
ユーザーが間違ってカスタマイズしない限り、最新のブラウザーがAccept-Language
[lang+territory, lang] のような形式の を送信すると仮定しても安全ですか?
['en-US', 'en']
また、Firefox のバージョンを試してみましたが、これは少し驚くべきことでした。
私のシステムのロケールはフランス語です:
locale
LANG=fr_FR.UTF-8
LANGUAGE=
LC_CTYPE="fr_FR.UTF-8"
LC_NUMERIC="fr_FR.UTF-8"
LC_TIME="fr_FR.UTF-8"
LC_COLLATE="fr_FR.UTF-8"
LC_MONETARY="fr_FR.UTF-8"
LC_MESSAGES="fr_FR.UTF-8"
LC_PAPER="fr_FR.UTF-8"
LC_NAME="fr_FR.UTF-8"
LC_ADDRESS="fr_FR.UTF-8"
LC_TELEPHONE="fr_FR.UTF-8"
LC_MEASUREMENT="fr_FR.UTF-8"
LC_IDENTIFICATION="fr_FR.UTF-8"
LC_ALL=
about:config
ページには次のように記載されています。
general.useragent.locale: en-US
intl.accept_languages: fr, fr-fr, en-us, en
テストFlaskアプリに接続すると、
print(request.accept_languages.values())
# ['en_US', 'en']
したがって、提案されたもの@babel.localeselector
は英語のロケールを返します。
Chromium を使用して同じ値を取得します。
ブラウザの設定が間違っていますか?