Интернационализация FastAPI

241e759d05eb85f0d3c27e2841b9a24e.jpg

Чтобы прикрутить gettext к FastAPI есть куча решений, я, например, пользовался этой статьей.

Проблема в том, что все они переводят текст сразу, в мне нужно хранить его в pydantic модели переводить на язык пользователя в момент сериализации т.е. lazy evaluation

Пришлось немного повелосипедить. и вот к чему я пришел:

class LazyGettext (BaseModel):
message: str
params: dict = Field (default_factory=dict, exclude=True)
syntax: str = None

class LazyGettext(BaseModel):
    message: str
    params: dict = Field(default_factory=dict, exclude=True)
    syntax: str = None

    def __mod__(self, params):
        self.params = params
        self.syntax = 'mod'
        return self

    def format(self, **kwargs):
        self.params = kwargs
        self.syntax = 'format'
        return self

    def __repr__(self) -> str:
        return self.__str__()

    def __str__(self) -> str:
        wrapper = TranslationWrapper()  # класс из статьи, ссылка на кот-орую выше
        tpl = wrapper.translations.gettext(self.message)
        if self.syntax == 'mod':
            tpl = tpl % self.params
        elif self.syntax == 'format':
            tpl = tpl.format(**self.params)
        return tpl

    @model_serializer
    def serialize(self):
        return self.__str__()

      
def _(message: str) -> LazyGettext:
    return LazyGettext(message=message)

# Пример использования

class Event(BaseModel):
    message: str | LazyGettext


events = [
    Event(messag=_('User {user} woke up').format(user='test')),
    Event(messag=_('User {user} commuted suicide').format(user='test')),
]

@router.get("/events/")
async def game_events(
) -> List[Event]:
    # С соотв. middleware будет выдавать текст на нужно языке в зависимости
    # от http заголовками
    return events

      

Мне не нравится, что для каждой строчки надо городить целую модель, хотел сделать это через pydantic string types, но что-то сходу не получи-лось.

Может кто-то посоветует решение лучше? В fastapi-localization как будто есть какая-то lazy обертка, но я не понял как ей польоваться.

© Habrahabr.ru