mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
feat: Support timezone and language query params
Support setting the timezone as well as the language via query params: The timezone parameter previously only worked on certain pages. While we're at it, let's also add the language as a param. Refactor code for timezone and language functions. Remove unused AURTZ cookie. Signed-off-by: moson <moson@archlinux.org>
This commit is contained in:
parent
933654fcbb
commit
5d302ae00c
5 changed files with 89 additions and 33 deletions
|
@ -64,11 +64,24 @@ class Translator:
|
||||||
translator = Translator()
|
translator = Translator()
|
||||||
|
|
||||||
|
|
||||||
def get_request_language(request: Request):
|
def get_request_language(request: Request) -> str:
|
||||||
if request.user.is_authenticated():
|
"""Get a request's language from either query param, user setting or
|
||||||
|
cookie. We use the configuration's [options] default_lang otherwise.
|
||||||
|
|
||||||
|
@param request FastAPI request
|
||||||
|
"""
|
||||||
|
request_lang = request.query_params.get("language")
|
||||||
|
cookie_lang = request.cookies.get("AURLANG")
|
||||||
|
if request_lang and request_lang in SUPPORTED_LANGUAGES:
|
||||||
|
return request_lang
|
||||||
|
elif (
|
||||||
|
request.user.is_authenticated()
|
||||||
|
and request.user.LangPreference in SUPPORTED_LANGUAGES
|
||||||
|
):
|
||||||
return request.user.LangPreference
|
return request.user.LangPreference
|
||||||
default_lang = aurweb.config.get("options", "default_lang")
|
elif cookie_lang and cookie_lang in SUPPORTED_LANGUAGES:
|
||||||
return request.cookies.get("AURLANG", default_lang)
|
return cookie_lang
|
||||||
|
return aurweb.config.get_with_fallback("options", "default_lang", "en")
|
||||||
|
|
||||||
|
|
||||||
def get_raw_translator_for_request(request: Request):
|
def get_raw_translator_for_request(request: Request):
|
||||||
|
|
|
@ -3,7 +3,6 @@ import functools
|
||||||
import os
|
import os
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from zoneinfo import ZoneInfoNotFoundError
|
|
||||||
|
|
||||||
import jinja2
|
import jinja2
|
||||||
from fastapi import Request
|
from fastapi import Request
|
||||||
|
@ -75,10 +74,7 @@ def make_context(request: Request, title: str, next: str = None):
|
||||||
# Shorten commit_hash to a short Git hash.
|
# Shorten commit_hash to a short Git hash.
|
||||||
commit_hash = commit_hash[:7]
|
commit_hash = commit_hash[:7]
|
||||||
|
|
||||||
try:
|
|
||||||
timezone = time.get_request_timezone(request)
|
timezone = time.get_request_timezone(request)
|
||||||
except ZoneInfoNotFoundError:
|
|
||||||
timezone = DEFAULT_TIMEZONE
|
|
||||||
language = l10n.get_request_language(request)
|
language = l10n.get_request_language(request)
|
||||||
return {
|
return {
|
||||||
"request": request,
|
"request": request,
|
||||||
|
@ -110,9 +106,7 @@ async def make_variable_context(request: Request, title: str, next: str = None):
|
||||||
)
|
)
|
||||||
|
|
||||||
for k, v in to_copy.items():
|
for k, v in to_copy.items():
|
||||||
if k == "timezone":
|
if k not in context:
|
||||||
context[k] = v if v in time.SUPPORTED_TIMEZONES else DEFAULT_TIMEZONE
|
|
||||||
elif k not in context:
|
|
||||||
context[k] = v
|
context[k] = v
|
||||||
context["q"] = dict(request.query_params)
|
context["q"] = dict(request.query_params)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import zoneinfo
|
import zoneinfo
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from urllib.parse import unquote
|
|
||||||
from zoneinfo import ZoneInfo
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
from fastapi import Request
|
from fastapi import Request
|
||||||
|
@ -58,16 +57,20 @@ SUPPORTED_TIMEZONES = OrderedDict(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_request_timezone(request: Request):
|
def get_request_timezone(request: Request) -> str:
|
||||||
"""Get a request's timezone by its AURTZ cookie. We use the
|
"""Get a request's timezone from either query param or user settings.
|
||||||
configuration's [options] default_timezone otherwise.
|
We use the configuration's [options] default_timezone otherwise.
|
||||||
|
|
||||||
@param request FastAPI request
|
@param request FastAPI request
|
||||||
"""
|
"""
|
||||||
default_tz = aurweb.config.get("options", "default_timezone")
|
request_tz = request.query_params.get("timezone")
|
||||||
if request.user.is_authenticated():
|
if request_tz and request_tz in SUPPORTED_TIMEZONES:
|
||||||
default_tz = request.user.Timezone
|
return request_tz
|
||||||
return unquote(request.cookies.get("AURTZ", default_tz))
|
elif (
|
||||||
|
request.user.is_authenticated() and request.user.Timezone in SUPPORTED_TIMEZONES
|
||||||
|
):
|
||||||
|
return request.user.Timezone
|
||||||
|
return aurweb.config.get_with_fallback("options", "default_timezone", "UTC")
|
||||||
|
|
||||||
|
|
||||||
def now(timezone: str) -> datetime:
|
def now(timezone: str) -> datetime:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
""" Test our l10n module. """
|
""" Test our l10n module. """
|
||||||
from aurweb import filters, l10n
|
from aurweb import config, filters, l10n
|
||||||
from aurweb.testing.requests import Request
|
from aurweb.testing.requests import Request
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,13 +10,55 @@ def test_translator():
|
||||||
|
|
||||||
|
|
||||||
def test_get_request_language():
|
def test_get_request_language():
|
||||||
"""First, tests default_lang, then tests a modified AURLANG cookie."""
|
"""Test getting the language setting from a request."""
|
||||||
|
# Default language
|
||||||
|
default_lang = config.get("options", "default_lang")
|
||||||
request = Request()
|
request = Request()
|
||||||
assert l10n.get_request_language(request) == "en"
|
assert l10n.get_request_language(request) == default_lang
|
||||||
|
|
||||||
|
# Language setting from cookie: de
|
||||||
request.cookies["AURLANG"] = "de"
|
request.cookies["AURLANG"] = "de"
|
||||||
assert l10n.get_request_language(request) == "de"
|
assert l10n.get_request_language(request) == "de"
|
||||||
|
|
||||||
|
# Language setting from cookie: nonsense
|
||||||
|
# Should fallback to default lang
|
||||||
|
request.cookies["AURLANG"] = "nonsense"
|
||||||
|
assert l10n.get_request_language(request) == default_lang
|
||||||
|
|
||||||
|
# Language setting from query param: de
|
||||||
|
request.cookies = {}
|
||||||
|
request.query_params = {"language": "de"}
|
||||||
|
assert l10n.get_request_language(request) == "de"
|
||||||
|
|
||||||
|
# Language setting from query param: nonsense
|
||||||
|
# Should fallback to default lang
|
||||||
|
request.query_params = {"language": "nonsense"}
|
||||||
|
assert l10n.get_request_language(request) == default_lang
|
||||||
|
|
||||||
|
# Language setting from query param: de and cookie
|
||||||
|
# Query param should have precedence
|
||||||
|
request.query_params = {"language": "de"}
|
||||||
|
request.cookies["AURLANG"] = "fr"
|
||||||
|
assert l10n.get_request_language(request) == "de"
|
||||||
|
|
||||||
|
# Language setting from authenticated user
|
||||||
|
request.cookies = {}
|
||||||
|
request.query_params = {}
|
||||||
|
request.user.authenticated = True
|
||||||
|
request.user.LangPreference = "de"
|
||||||
|
assert l10n.get_request_language(request) == "de"
|
||||||
|
|
||||||
|
# Language setting from authenticated user with query param
|
||||||
|
# Query param should have precedence
|
||||||
|
request.query_params = {"language": "fr"}
|
||||||
|
assert l10n.get_request_language(request) == "fr"
|
||||||
|
|
||||||
|
# Language setting from authenticated user with cookie
|
||||||
|
# DB setting should have precedence
|
||||||
|
request.query_params = {}
|
||||||
|
request.cookies["AURLANG"] = "fr"
|
||||||
|
assert l10n.get_request_language(request) == "de"
|
||||||
|
|
||||||
|
|
||||||
def test_get_raw_translator_for_request():
|
def test_get_raw_translator_for_request():
|
||||||
"""Make sure that get_raw_translator_for_request is giving us
|
"""Make sure that get_raw_translator_for_request is giving us
|
||||||
|
|
|
@ -15,18 +15,22 @@ def test_tz_offset_mst():
|
||||||
|
|
||||||
def test_request_timezone():
|
def test_request_timezone():
|
||||||
request = Request()
|
request = Request()
|
||||||
tz = get_request_timezone(request)
|
|
||||||
assert tz == aurweb.config.get("options", "default_timezone")
|
|
||||||
|
|
||||||
|
# Default timezone
|
||||||
|
dtz = aurweb.config.get("options", "default_timezone")
|
||||||
|
assert get_request_timezone(request) == dtz
|
||||||
|
|
||||||
def test_authenticated_request_timezone():
|
# Timezone from query params
|
||||||
# Modify a fake request to be authenticated with the
|
request.query_params = {"timezone": "Europe/Berlin"}
|
||||||
# America/Los_Angeles timezone.
|
assert get_request_timezone(request) == "Europe/Berlin"
|
||||||
request = Request()
|
|
||||||
|
# Timezone from authenticated user.
|
||||||
|
request.query_params = {}
|
||||||
request.user.authenticated = True
|
request.user.authenticated = True
|
||||||
request.user.Timezone = "America/Los_Angeles"
|
request.user.Timezone = "America/Los_Angeles"
|
||||||
|
assert get_request_timezone(request) == "America/Los_Angeles"
|
||||||
|
|
||||||
# Get the request's timezone, it should be America/Los_Angeles.
|
# Timezone from authenticated user with query param
|
||||||
tz = get_request_timezone(request)
|
# Query param should have precedence
|
||||||
assert tz == request.user.Timezone
|
request.query_params = {"timezone": "Europe/Berlin"}
|
||||||
assert tz == "America/Los_Angeles"
|
assert get_request_timezone(request) == "Europe/Berlin"
|
||||||
|
|
Loading…
Add table
Reference in a new issue