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

от автора

Чтобы прикрутить 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/