Localization for Flask Applications


Learn how to localize your Flask app with Flask-Babel and add new translations. Flask, the lightweight Python microframework for creating web apps and PhraseApp translation management work great together.

This post will guide you through the process of localizing your Flask application using Flask-Babel and PhraseApp.

Flask-Babel is a Flask extension that adds internationalization (i18n) and localization (l10n) support to any Flask application. PhraseApp is a translation management tool that features a powerful in-context-editor, making the process of translating more convenient.

Get Started With Flask-Babel

Let’s begin by installing the required dependencies:

This will install Flask-Babel, aswell as the pybabel command-line tool.

Next, import Flask-Babel and hook it to your app like so:

In your configuration, add a dictionary named LANGUAGES. In this example, we add two locales, english (‘en’) and german (‘de’).

We will use this dictionary for a little helper function that Babel offers:

This convenient tool will automatically choose the best matching locale, based on the Accept-Language header from the incoming request.

Hint: for testing purposes, you can directly return a language code, for example: return ‘de’

One more thing! Create a config file for Babel. We will chew through the details later on, but for now, simply create a file named babel.cfg in the top-level directory of you app:

Tagging Strings

Now it’s time to tag all the Strings you want to translate. In a typical Flask app, there will be two types of Strings that require translating. One being hard-coded Strings in your .py files, the other being Strings in your .html Jinja2 templates.

Tag them by adding a gettext(‘String’) call to them, like so:


For your Jinja2 templates, this is also very straightforward, for example:


Hint: you can use _() as a shortcut for gettext().

Note that the english string is also the key (msgid) that gettext will use for when looking up the corosponding Translation value (msgstr).

Building Locales

When all strings are tagged, it is time to build a catalog for the Locales we want to create. Run:

This checks all files specified in babel.cfg and searches thru them to find tagged strings and outputs them to messages.pot.

Next, run:

This will use the index from messages.pot to build a german (‘de’) locale in our translations directory. Don’t worry, if the directory doesn’t exist yet, pybabel will create it for you.

Finally it is time to translate the Strings.

With your favorite text editor, open ‘translations/de/LC_MESSAGES/messages.po’. You can now start translating the msgstr values. When you are done editing, there is only one step left, compile all .po files in your translation directory:

Done! Start playing around with your app. Remember, the locale is chosen based on the Accept-Language Header that is being sent by your Browser.

Check out our full Flask-Babel example app, a modified version of Flaskr, the official Flask demo app.

Get Translations With PhraseApp

PhraseApp provides tools for software translation management. Its WYSIWYG In-Context-Editor (Demo) enables you and your copywriters or translators to change translations on your website in any web browser.

Let’s integrate the In-Context Editor in our example from above.

In order to expose your tagged Strings to the In-Context-Editor, we will be using theFlask-Phrase, a package that you can install via:

Next, we hook our app to Flask-Phrase and import the gettext provided by Flask-Phrase. Extending the example from above, this would look like this:

Hint: the gettext provided by flask_phrase will simply proxy the call to Flask-Babel when not in editing mode.

Next, add the following to your Flask app config:

Almost done. In your .html Jinja2 templates, add this JavaScript snippet along with the Project-ID that can be found in the PhraseApp Translation Center:

That’s it. Make sure PHRASEAPP_ENABLED is set to ‘True’ so that your strings will be rendered in a special format for the PhraseApp editor. Check out our full example appwith Flask-Babel and PhraseApp built in.

Hint: Need support integrating PhraseApp? Feel free to contact us any time.

Further Reading

Be sure to subscribe and receive all updates from the PhraseApp blog straight to your inbox. You’ll receive localization best practices, about cultural aspects of breaking into new markets, guides and tutorials for optimizing software translation and other industry insights and information. Don’t miss out!

Also published on Medium.