-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Revert "Remove locale selector/translation support"
This reverts commit ea29db1.
- Loading branch information
1 parent
e51c2d9
commit f0d99c5
Showing
8 changed files
with
165 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from . import get_lang # noqa | ||
from . import set_lang # noqa |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
from babel import negotiate_locale | ||
from flask import request | ||
|
||
from fsd_utils import CommonConfig | ||
|
||
|
||
def get_lang(): | ||
# get lang if lang query arg is set | ||
language_from_query_args = request.args.get("lang") | ||
if language_from_query_args: | ||
if language_from_query_args not in ["cy", "en"]: | ||
return "en" | ||
return language_from_query_args | ||
|
||
# get locale from cookie if set | ||
locale_from_cookie = request.cookies.get(CommonConfig.FSD_LANG_COOKIE_NAME) | ||
if locale_from_cookie: | ||
if locale_from_cookie not in ["cy", "en"]: | ||
return "en" | ||
return locale_from_cookie | ||
|
||
# otherwise guess preference based on user accept header | ||
preferred = [accept_language.replace("-", "_") for accept_language in request.accept_languages.values()] | ||
negotiated_locale = negotiate_locale(preferred, ["en", "cy"]) | ||
if negotiated_locale: | ||
return negotiated_locale | ||
|
||
# default is to return english | ||
return "en" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
from flask import Response, current_app, make_response, redirect, request | ||
|
||
from fsd_utils import CommonConfig | ||
|
||
|
||
class LanguageSelector: | ||
@staticmethod | ||
def get_cookie_domain(cookie_domain): | ||
if not cookie_domain: | ||
return None | ||
else: | ||
return cookie_domain | ||
|
||
@staticmethod | ||
def set_language_cookie(locale: str, response: Response): | ||
response.set_cookie( | ||
CommonConfig.FSD_LANG_COOKIE_NAME, | ||
locale, | ||
domain=LanguageSelector.get_cookie_domain(current_app.config["COOKIE_DOMAIN"]), | ||
max_age=86400 * 30, # 30 days | ||
) | ||
Check warning Code scanning / CodeQL Failure to use secure cookies Medium
Cookie is added without the Secure and HttpOnly attributes properly set.
|
||
|
||
def __init__(self, app): | ||
self.flask_app = app | ||
self.flask_app.add_url_rule("/language/<locale>", view_func=self.select_language) | ||
|
||
@staticmethod | ||
def select_language(locale): | ||
# TODO: Perform additional validation on referrer | ||
response = make_response(redirect(request.referrer or "/", 302)) | ||
Check warning Code scanning / CodeQL URL redirection from remote source Medium
Untrusted URL redirection depends on a
user-provided value Error loading related location Loading |
||
LanguageSelector.set_language_cookie(locale, response) | ||
|
||
return response |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
from fsd_utils.locale_selector.get_lang import get_lang | ||
|
||
|
||
class TestGetLang: | ||
def test_get_lang_query_arg_valid(self, flask_test_client): | ||
with flask_test_client.application.test_request_context("/?lang=cy"): | ||
assert get_lang() == "cy" | ||
|
||
def test_get_lang_query_arg_invalid(self, flask_test_client): | ||
with flask_test_client.application.test_request_context("/?lang=fr"): | ||
assert get_lang() == "en" | ||
|
||
def test_get_lang_cookie_preference(self, flask_test_client): | ||
with flask_test_client.application.test_request_context("/", headers={"Cookie": "language=cy"}): | ||
assert get_lang() == "cy" | ||
|
||
def test_get_lang_cookie_preference_for_non_en_cy_language(self, flask_test_client): | ||
with flask_test_client.application.test_request_context("/", headers={"Cookie": "language=de"}): | ||
assert get_lang() == "en" | ||
|
||
def test_get_lang_accept_language_preference_en(self, flask_test_client): | ||
with flask_test_client.application.test_request_context( | ||
"/", | ||
headers={"Accept-Language": "en,en-GB;q=0.9,cy;q=0.8,en-US;q=0.7"}, | ||
): | ||
assert get_lang() == "en" | ||
|
||
def test_get_lang_accept_language_preference_cy(self, flask_test_client): | ||
with flask_test_client.application.test_request_context( | ||
"/", | ||
headers={"Accept-Language": "cy,en;q=0.9,en-GB;q=0.8,en-US;q=0.7"}, # noqa: E501 | ||
): | ||
assert get_lang() == "cy" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from unittest.mock import ANY, Mock | ||
|
||
from fsd_utils.locale_selector.set_lang import LanguageSelector | ||
|
||
|
||
def test_set_lang(flask_test_client): | ||
mock_app = Mock() | ||
set_lang = LanguageSelector(mock_app) | ||
mock_app.add_url_rule.assert_called_with("/language/<locale>", view_func=ANY) | ||
with flask_test_client.application.test_request_context(): | ||
response = set_lang.select_language("cy") | ||
response_cookie = response.headers.get("Set-Cookie") | ||
assert response_cookie is not None, "No cookie set for language" | ||
assert response_cookie.split(";")[0] == ("language" + "=cy") |