Flask-Babel使用Accept-Language标题

时间:2016-09-15 21:28:54

标签: python flask localization flask-babel

说我有一个提供一些翻译的应用程序:

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

注意:doc page中的示例读取

return request.accept_languages.best_match(['de', 'fr', 'en'])

但是这不允许使用相同语言的两个不同版本(en_ENen_US)。

使用negotiate_locale

在这个GitHub issue中,有人建议使用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)

但AFAIU,这并不能解决所有用例问题。仅当用户代理在可用区域设置时请求['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

第一个有效,因为hardcoded list of aliases使de指向de_DE

此外,浏览器只发送de_AT而不是de的情况也会被破坏,但我不确定这是一个常见的配置(参见下一段)。

有没有可靠的方法来解决这个问题?

现代浏览器中的典型值?

作为一个子问题,我想知道现代浏览器可以期待什么样的价值。

假设现代浏览器是否安全,除非用户自定义错误,否则会发送{lang + territory,lang]这样的Accept-Language形式?

['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获得相同的值。

我的浏览器配置错误了吗?

0 个答案:

没有答案