feat: Locale extension to parse the Accept-Language header

l10n
Inex Code 2023-04-12 16:59:23 +03:00
parent e0ea004e80
commit c7a65febe7
3 changed files with 36 additions and 3 deletions

View File

@ -1,10 +1,13 @@
"""GraphQL API for SelfPrivacy."""
# pylint: disable=too-few-public-methods
import typing
from strawberry.permission import BasePermission
from strawberry.types import Info
from strawberry.extensions import Extension
from selfprivacy_api.actions.api_tokens import is_token_valid
from selfprivacy_api.utils.localization import Localization
class IsAuthenticated(BasePermission):
@ -19,3 +22,14 @@ class IsAuthenticated(BasePermission):
if token is None:
return False
return is_token_valid(token.replace("Bearer ", ""))
class LocaleExtension(Extension):
"""Parse the Accept-Language header and set the locale in the context as one of the supported locales."""
def resolve(self, _next, root, info: Info, *args, **kwargs):
locale = Localization().get_locale(
info.context["request"].headers.get("Accept-Language")
)
info.context["locale"] = locale
return _next(root, info, *args, **kwargs)

View File

@ -6,7 +6,7 @@ from typing import AsyncGenerator
import strawberry
from strawberry.types import Info
from selfprivacy_api.graphql import IsAuthenticated
from selfprivacy_api.graphql import IsAuthenticated, LocaleExtension
from selfprivacy_api.graphql.mutations.api_mutations import ApiMutations
from selfprivacy_api.graphql.mutations.job_mutations import JobMutations
from selfprivacy_api.graphql.mutations.mutation_interface import GenericMutationReturn
@ -63,7 +63,7 @@ class Query:
@strawberry.field()
def test(self, info: Info) -> str:
"""Test query"""
return info.context["request"].headers["Accept-Language"]
return info.context["locale"]
@strawberry.type
@ -102,4 +102,9 @@ class Subscription:
await asyncio.sleep(0.5)
schema = strawberry.Schema(query=Query, mutation=Mutation, subscription=Subscription)
schema = strawberry.Schema(
query=Query,
mutation=Mutation,
subscription=Subscription,
extensions=[LocaleExtension],
)

View File

@ -45,6 +45,20 @@ class Localization(metaclass=SingletonMetaclass):
return self.locales[DEFAULT_LOCALE][string_id]
return string_id
def supported_locales(self) -> typing.List[str]:
"""Return a list of supported languages."""
return list(self.locales.keys())
def get_locale(self, locale: typing.Optional[str]) -> str:
"""Parse the value of Accept-Language header and return the most preferred supported locale."""
if locale is None:
return DEFAULT_LOCALE
for lang in locale.split(","):
lang = lang.split(";")[0]
if lang in self.locales:
return lang
return DEFAULT_LOCALE
def flatten_dict(
self, d: typing.Dict[str, typing.Any], parent_key: str = "", sep: str = "."
) -> typing.Dict[str, str]: