diff --git a/securedrop/i18n.py b/securedrop/i18n.py index e0df618a84..1169e6762a 100644 --- a/securedrop/i18n.py +++ b/securedrop/i18n.py @@ -202,28 +202,6 @@ def configure(config: SDConfig, app: Flask) -> None: map_locale_display_names(config) -def resolve_fallback_locale(config: SDConfig) -> str: - """ - Return a *usable* fallback locale. Namely: - - 1. Don't fall back to the configured `DEFAULT_LOCALE` if it isn't available. - - 2. Don't fall back to the hard-coded `FALLBACK_LOCALE` (`en_US`) if it isn't configured. - - NB. If neither the default nor the fallback locale is usable, then we should have crashed - already in `validate_locale_configuration()`. - """ - - if Locale.parse(config.DEFAULT_LOCALE) in USABLE_LOCALES: - return config.DEFAULT_LOCALE - - elif Locale.parse(FALLBACK_LOCALE) in USABLE_LOCALES: - return FALLBACK_LOCALE - - else: - raise ValueError('No usable fallback locale') - - def get_locale(config: SDConfig) -> str: """ Return the best supported locale for a request. @@ -232,25 +210,24 @@ def get_locale(config: SDConfig) -> str: - l request argument or session['locale'] - browser suggested locale, from the Accept-Languages header - config.DEFAULT_LOCALE + - config.FALLBACK_LOCALE """ - # Default to any usable locale set in the session. - locale = session.get("locale") - if locale: - locale = negotiate_locale([locale], LOCALES.keys()) - - # A usable locale specified in request.args takes precedence. + preferences = [] + if session.get("locale"): + preferences.append(session.get("locale")) if request.args.get("l"): - negotiated = negotiate_locale([request.args["l"]], LOCALES.keys()) - if negotiated: - locale = negotiated + preferences.insert(0, request.args.get("l")) + if not preferences: + preferences.extend(get_accepted_languages()) + preferences.append(config.DEFAULT_LOCALE) + preferences.append(FALLBACK_LOCALE) + + negotiated = negotiate_locale(preferences, LOCALES.keys()) - # If the locale is not in the session or request.args, negotiate - # the best supported option from the browser's accepted languages. - if not locale: - locale = negotiate_locale(get_accepted_languages(), LOCALES.keys()) + if not negotiated: + raise ValueError("No usable locale") - # Finally, if we can't negotiate a requested locale, resolve a fallback. - return locale or resolve_fallback_locale(config) + return negotiated def get_accepted_languages() -> List[str]: diff --git a/securedrop/tests/test_i18n.py b/securedrop/tests/test_i18n.py index 1ede55eaf7..8c47c15922 100644 --- a/securedrop/tests/test_i18n.py +++ b/securedrop/tests/test_i18n.py @@ -32,7 +32,7 @@ from flask import request from flask import session from flask_babel import gettext -from i18n import parse_locale_set, resolve_fallback_locale +from i18n import parse_locale_set from sdconfig import FALLBACK_LOCALE, SDConfig from sh import pybabel from sh import sed @@ -233,32 +233,6 @@ def test_parse_locale_set(): assert parse_locale_set([FALLBACK_LOCALE]) == set([Locale.parse(FALLBACK_LOCALE)]) -def test_resolve_fallback_locale(config): - """ - Only a usable default or fallback locale is returned. - """ - i18n.USABLE_LOCALES = parse_locale_set([FALLBACK_LOCALE, 'es_ES']) - fake_config = SDConfig() - - # The default locale is neither configured nor available. - fake_config.DEFAULT_LOCALE = NEVER_LOCALE - assert resolve_fallback_locale(fake_config) == FALLBACK_LOCALE - - # The default locale is configured but not available. - fake_config.SUPPORTED_LOCALES = [FALLBACK_LOCALE, NEVER_LOCALE] - assert resolve_fallback_locale(fake_config) == FALLBACK_LOCALE - - # The default locale is available but not configured. - fake_config.SUPPORTED_LOCALES = [FALLBACK_LOCALE] - fake_config.DEFAULT_LOCALE = NEVER_LOCALE - assert resolve_fallback_locale(fake_config) == FALLBACK_LOCALE - - # Happy path: a non-fallback default locale is both available and configured. - fake_config.SUPPORTED_LOCALES = [FALLBACK_LOCALE, 'es_ES'] - fake_config.DEFAULT_LOCALE = 'es_ES' - assert resolve_fallback_locale(fake_config) == 'es_ES' - - def test_no_usable_fallback_locale(journalist_app, config): """ The apps fail if neither the default nor the fallback locale is usable. @@ -269,8 +243,6 @@ def test_no_usable_fallback_locale(journalist_app, config): fake_config.TRANSLATION_DIRS = Path(config.TEMP_DIR) i18n.USABLE_LOCALES = set() - with pytest.raises(ValueError, match='No usable fallback locale'): - resolve_fallback_locale(fake_config) with pytest.raises(ValueError, match='in the set of usable locales'): journalist_app_module.create_app(fake_config)