diff --git a/lib/l10n_utils/__init__.py b/lib/l10n_utils/__init__.py index 0e12af4bd7d..1ba0d66dcf3 100644 --- a/lib/l10n_utils/__init__.py +++ b/lib/l10n_utils/__init__.py @@ -2,7 +2,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. -import re from os.path import relpath, splitext from typing import List @@ -153,33 +152,23 @@ def get_locale(request): def get_accept_languages(request): """ - Parse the user's Accept-Language HTTP header and return a list of languages + Parse the user's Accept-Language HTTP header and return a list of languages in ranked order. """ - languages = [] - pattern = re.compile(r"^([A-Za-z]{2,3})(?:-([A-Za-z]{2})(?:-[A-Za-z0-9]+)?)?$") + ranked = parse_accept_lang_header(request.headers.get("Accept-Language", "")) + return [lang for lang, rank in ranked] - parsed = parse_accept_lang_header(request.headers.get("Accept-Language", "")) - for lang, priority in parsed: - m = pattern.match(lang) - - if not m: - continue - - lang = m.group(1).lower() - - # Check if the shorter code is supported. This covers obsolete long - # codes like fr-FR (should match fr) or ja-JP (should match ja) - if m.group(2) and lang not in settings.PROD_LANGUAGES: - lang += "-" + m.group(2).upper() - - if lang not in languages: - languages.append(lang) +def get_best_translation(translations, accept_languages): + """ + Return the best translation available comparing the accept languages against available translations. - return languages + This attempts to find a matching translation for each accept language. It + compares each accept language in full, and also the root. For example, + "en-CA" looks for "en-CA" as well as "en", which maps to "en-US". + If none found, it returns the first language code for the first available translation. -def get_best_translation(translations, accept_languages): + """ lang_map = _get_language_map() valid_lang_map = {k: v for k, v in lang_map.items() if v in translations} for lang in accept_languages: diff --git a/lib/l10n_utils/tests/test_base.py b/lib/l10n_utils/tests/test_base.py index 7d9af400b11..4f683805a0f 100644 --- a/lib/l10n_utils/tests/test_base.py +++ b/lib/l10n_utils/tests/test_base.py @@ -126,11 +126,13 @@ def test_valid_lang_codes(self): """ Should return a list of valid lang codes """ - self._test("fr-FR", ["fr"]) - self._test("en-us,en;q=0.5", ["en-US", "en"]) - self._test("pt-pt,fr;q=0.8,it-it;q=0.5,de;q=0.3", ["pt-PT", "fr", "it", "de"]) - self._test("ja-JP-mac,ja-JP;q=0.7,ja;q=0.3", ["ja"]) + self._test("fr-FR", ["fr-fr"]) + self._test("en-us,en;q=0.5", ["en-us", "en"]) + self._test("pt-pt,fr;q=0.8,it-it;q=0.5,de;q=0.3", ["pt-pt", "fr", "it-it", "de"]) + self._test("ja-JP-mac,ja-JP;q=0.7,ja;q=0.3", ["ja-jp-mac", "ja-jp", "ja"]) self._test("foo,bar;q=0.5", ["foo", "bar"]) + # Verify the return lang codes are ordered by rank. + self._test("de;q=0.5,en-us", ["en-us", "de"]) def test_invalid_lang_codes(self): """ @@ -138,7 +140,7 @@ def test_invalid_lang_codes(self): """ self._test("", []) self._test("en_us,en*;q=0.5", []) - self._test("Chinese,zh-cn;q=0.5", ["zh-CN"]) + self._test("Chinese,zh-cn;q=0.5", ["chinese", "zh-cn"]) @patch.object(l10n_utils, "render")