Чтобы прикрутить gettext к FastAPI есть куча решений, я, например, пользовался этой статьей.
Проблема в том, что все они переводят текст сразу, в мне нужно хранить его в pydantic модели переводить на язык пользователя в момент сериализации т.е. lazy evaluation
Пришлось немного повелосипедить. и вот к чему я пришел:
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 обертка но я не понял как ей польоваться.
ссылка на оригинал статьи https://habr.com/ru/articles/842340/
Добавить комментарий