Internationalization of FastAPI
There are a lot of solutions to attach gettext to FastAPI, for example, I used this article.
The problem is that they all translate the text immediately, but I need to store it in the pydantic model and translate it into the user's language at the time of serialization, i.e. lazy evaluation
I had to do a bit of cycling and this is what I came up with:
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
I don't like that for each line you have to build a whole model, I wanted to do it through pydantic string typesbut something didn’t work out right away.
Maybe someone can recommend a better solution? Fastapi-localization seems to have some kind of lazy wrapper, but I don't understand how to use it.