From a57449e030777eb042ec86f183a7b8089676bc5e Mon Sep 17 00:00:00 2001 From: Paul McLanahan Date: Mon, 31 Jan 2022 09:48:15 -0500 Subject: [PATCH] Use default language if none match accept-language Fix bug 1752823 --- lib/l10n_utils/__init__.py | 13 ++++++++++++- lib/l10n_utils/tests/test_base.py | 7 ++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/l10n_utils/__init__.py b/lib/l10n_utils/__init__.py index 1ba0d66dcf3..959210e39db 100644 --- a/lib/l10n_utils/__init__.py +++ b/lib/l10n_utils/__init__.py @@ -170,6 +170,10 @@ def get_best_translation(translations, accept_languages): """ lang_map = _get_language_map() + # translations contains mixed-case items e.g. "en-US" while the keys + # of `lang_map` are all lowercase. But this works because the values + # of the `lang_map` dict are mixed-case like translations and the + # comparison below is with the values. valid_lang_map = {k: v for k, v in lang_map.items() if v in translations} for lang in accept_languages: lang.lower() @@ -179,7 +183,14 @@ def get_best_translation(translations, accept_languages): if pre in valid_lang_map: return valid_lang_map[pre] - return lang_map[translations[0].lower()] + # If all the attempts failed, just use en-US, the default locale of + # the site, if it is an available translation. + if settings.LANGUAGE_CODE in translations: + return settings.LANGUAGE_CODE + + # In the rare case the default language isn't in the list, return the + # first translation in the valid_lang_map. + return list(valid_lang_map.values())[0] def get_translations_native_names(locales): diff --git a/lib/l10n_utils/tests/test_base.py b/lib/l10n_utils/tests/test_base.py index 4f683805a0f..55abb1e7ffe 100644 --- a/lib/l10n_utils/tests/test_base.py +++ b/lib/l10n_utils/tests/test_base.py @@ -3,7 +3,7 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. import os -from unittest.mock import ANY, call, patch +from unittest.mock import ANY, Mock, call, patch from django.test import TestCase from django.test.client import RequestFactory @@ -168,6 +168,7 @@ def test_ftl_activations(self, render_mock): render_mock.assert_called_with(self.req, ["dude.html"], ANY, ftl_files="dude", activation_files=["dude", "donny"]) +@patch.object(l10n_utils, "_get_language_map", Mock(return_value={"an": "an", "de": "de", "en": "en-US", "en-us": "en-US", "fr": "fr"})) @pytest.mark.parametrize( "translations, accept_languages, expected", ( @@ -184,6 +185,10 @@ def test_ftl_activations(self, render_mock): (["en-US", "de"], ["de", "en-US"], "de"), (["en-US", "de", "fr"], ["fr", "de"], "fr"), (["en-US", "de", "fr"], ["en-CA", "fr", "de"], "en-US"), + # A request for only inactive translations should default to 'en-US'. Bug 1752823 + (["am", "an", "en-US"], ["mk", "gu-IN"], "en-US"), + # "am" is not a valid language in the list of PROD_LANGUAGES + (["am", "an"], ["mk", "gu-IN"], "an"), ), ) def test_get_best_translation(translations, accept_languages, expected):