Jér*_*ôme 6 python localization flask flask-babel
假设我有一个应用程序,其中有一些可用的翻译:
\nAVAILABLE_LOCALES = [\'en_US\', \'en_EN\', \'de_AT\']\n
Run Code Online (Sandbox Code Playgroud)\n我想根据Accept-Language
标题选择最合适的。
为了获取语言环境,我会写这样的内容:
\n@babel.localeselector\ndef get_locale():\n user = getattr(g, \'user\', None)\n if user is not None:\n return user.locale\n return request.accept_languages.best_match(AVAILABLE_LOCALES)\n
Run Code Online (Sandbox Code Playgroud)\n问题是,如果用户代理要求de_DE
,则匹配失败并且选择会退回到默认值(英语),而de_AT
显然我宁愿得到 。
注意:文档页面中的示例如下
\nreturn request.accept_languages.best_match([\'de\', \'fr\', \'en\'])\n
Run Code Online (Sandbox Code Playgroud)\n但这不允许同一语言有两个不同版本(en_EN
,en_US
)。
在这个GitHub 问题中,有人建议使用 Babel 的negotiate_locale
函数:
@babel.localeselector\ndef get_locale():\n user = getattr(g, \'user\', None)\n if user is not None:\n return user.locale\n preferred = [x.replace(\'-\', \'_\') for x in request.accept_languages.values()]\n return negotiate_locale(preferred, AVAILABLE_LOCALES)\n
Run Code Online (Sandbox Code Playgroud)\n但是 AFAIU,这并不能解决所有用例。仅当用户代理询问可用[\'de_AT\', \'de\']
区域设置时[\'en_US\', \'en_EN\', \'de_DE\']
。但反之则不然:
negotiate_locale([\'de_AT\', \'de\'], [\'en_US\', \'en_EN\', \'de_DE\']) #\xc2\xa0returns de_DE\nnegotiate_locale([\'de_DE\', \'de\'], [\'en_US\', \'en_EN\', \'de_AT\']) #\xc2\xa0returns None\n
Run Code Online (Sandbox Code Playgroud)\n第一个之所以有效,是因为硬编码的别名列表指向.de
de_DE
de_AT
另外,浏览器只发送而不发送的情况也de
被破坏,但我不确定这是一个常见的配置(请参阅下一段)。
有没有可靠的方法来处理这个问题?
\n作为一个子问题,我想知道我可以从现代浏览器中获得什么样的值。
\nAccept-Language
假设现代浏览器(除非用户错误定制)会发送[lang+territory, lang] 这样的形式,是否安全?
[\'en-US\', \'en\']\n
Run Code Online (Sandbox Code Playgroud)\n另外,我尝试了我的 Firefox 版本,看看会得到什么,结果有点令人惊讶。
\n我的系统上的区域设置是法语:
\nlocale\nLANG=fr_FR.UTF-8\nLANGUAGE=\nLC_CTYPE="fr_FR.UTF-8"\nLC_NUMERIC="fr_FR.UTF-8"\nLC_TIME="fr_FR.UTF-8"\nLC_COLLATE="fr_FR.UTF-8"\nLC_MONETARY="fr_FR.UTF-8"\nLC_MESSAGES="fr_FR.UTF-8"\nLC_PAPER="fr_FR.UTF-8"\nLC_NAME="fr_FR.UTF-8"\nLC_ADDRESS="fr_FR.UTF-8"\nLC_TELEPHONE="fr_FR.UTF-8"\nLC_MEASUREMENT="fr_FR.UTF-8"\nLC_IDENTIFICATION="fr_FR.UTF-8"\nLC_ALL=\n
Run Code Online (Sandbox Code Playgroud)\n该about:config
页面说:
general.useragent.locale: en-US\nintl.accept_languages: fr, fr-fr, en-us, en\n
Run Code Online (Sandbox Code Playgroud)\n当我连接到我的测试 Flask 应用程序时,我得到
\nprint(request.accept_languages.values())\n# [\'en_US\', \'en\']\n
Run Code Online (Sandbox Code Playgroud)\n因此建议@babel.localeselector
将返回英语语言环境。
我使用 Chromium 得到相同的值。
\n我的浏览器配置错误吗?
\n