Чтобы прикрутить 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 обертка но я не понял как ей польоваться.
Buchachalo
А почему на https://qna.habr.com/ не спросили?