Add translation to FastAPI with gettext

Saeed Babashahi
2 min readJun 19, 2021

--

In this article we add support for translation to FastAPI. For this purpose we extract language from request Accept-Language Header by using middlewares.

Photo by Edurne Chopeitia on Unsplash

Lets start with creating FastAPI project. Install FastAPI with `pip install fastapi` and for asgi server install `pip install uvicorn[standard]`. Create a structure like below then we could start coding:

Project structure (venv dir is virtual env)

In i18n with the power of gettext we add 2 functions, trans func that translates messages and active_translation func which is used in middleware and sets requested language in _default_lang.

In our middleware we add get_accept_language to our app middleware. This function gets request accept-langauge header and calls active_translation with it.

Our end point simply returns a message that called with trans function from i18n.

In main we add our middleware and endpoint router.

At first install gettext on Ubuntu: ‍‍`apt install gettext‍‍‍‍`, now we need to create locales dir, for each of supported language of your project add this path to locales your-lang/LC_MESSAGES/base.po for example we have locales/en/LC_MESSAGES/base.po and locales/de/LC_MESSAGES/base.po. Also you need to add base.pot to locales dir.

Find your pygettext module, `whereis pygettext.py` which is usually located in `/usr/bin/pygettext3`. In the root of your project find all of your message with `/usr/bin/pygettext3 -d base -o locales/base.pot /` base.pot is now like:

Now for each language merge `base.pot` into `base.po` with this command: `msgmerge locales/de/LC_MESSAGES/base.po locales/base.pot -U`. Add tranlation to base.po files. After translation your file should look like:

At the end you should generate `mo` files with `msgfmt -o locales/de/LC_MESSAGES/base.mo locales/de/LC_MESSAGES/base` and now if we run project with `uvicorn main:app — reload — host 0.0.0.0 — port 8007` to check our endpoint.

Result of endpoint with out translation
Result of endpoint with translation to de

Hope it helped :), Feel free to mention any ideas for improvement.

--

--

Saeed Babashahi

Backend software engineer who loves to learn. I am experienced in Python, Django, DRF, Neo4j, PostgreSQL and I am a newbie gopher :).