We would like to use Flask-Babel for the internationalizing of our Flask application.
Our goal is to use a unique ID string like "example_demo_text" for msgid and translate this msgid in several languages. Our process works like this: use the unique msgid "example_demo_text" in gettext( .. ) function, the extract all gettext messages and write the associated message string (msgstr) in the .po file for our default locale (en).
The whole process works so far...
When a request wants the message string in a supported language, which is yet not fully translated (happens sadly a lot) and the msgstr is in this locale is empty, flask-babel returns the msgid, which should not shown to the user.
How can we configure flask-babel to use a fallback local (in our case en) if the msgstr in the requested locale is empty?
Here is how we implemented flask-babel in our flask application:
main.py
import ...
supported_locales = ("de", "en", "es", "fr", "hr", "it", "nl")
app = Flask(__name__)
app.register_blueprint(demos, url_prefix="/demos")
babel = Babel(app, configure_jinja=False, default_locale="en")
@babel.localeselector
def get_locale():
user_local = RequestHeader(request).get_user_local()
if user_local not in supported_locales:
user_local = current_app.config["BABEL_DEFAULT_LOCALE"]
return user_local
(RequestHeader()
is just a class to handle our headers, with a method to get the user locale, which is provided as header by our auth proxy.)
our example route file demos.py:
import ...
demos = Blueprint("demos", __name__)
@demos.route("/translation-demo")
def demo_translation():
first_translation = gettext("example_demo_text")
second_translation = gettext("example_demo_text_param")
third_translation = gettext("example_demo_text_paramtime")
return {"message1": first_translation, "message2": second_translation, "message3": third_translation}
/en/messages.po
#: rest/demos/demos.py:121
msgid "example_demo_text"
msgstr "I am an english text, which can be translated"
#: rest/demos/demos.py:122
msgid "example_demo_text_param"
msgstr "I am an english text with parameters: Today's date is ..."
#: rest/demos/demos.py:123
msgid "example_demo_text_paramtime"
msgstr "The time this request was received is ..."
(for example the msgstr for the msgid example_demo_text
in /de/message.po is empty, flask-babel should return msgstr for en.)
I think I found my answer.
Flask-Babel does not support our wished approach for Translations. The way we use to translate, forces us to use text strings as message ids (msgid) instead of id-strings. Even though, there are some approaches to get it working with id-strings as msgid, none of these approaches will fit our standard trnaslation behavior.
The first way would be to use id-strings as msgid and write the text-string direct in the extracted .po file. The problem here is that Flask-Babel searches in the requested language .po file, for the message string (msgstr). If there is no msgstr for this particular msgid, it will use the string for the msgid as fallback. So, this case is only usable if we translate every language before every release to 100%, which is not realistic for us. Otherwise, the user gets a gibberish string as response. Check this issue from the codebase of Babel.