Flask-Babel localized strings within js Flask-Babel localized strings within js flask flask

Flask-Babel localized strings within js


I have finally found a solution, although I am not sure it is the way to go. The idea is to wrap the javascript code within an html template, which is interpretated by Jinja2 before it is rendered and apply a custom Jinja2 filter to get rid of some minor issues. I tried to keep js files separately but it did not work.

It seems that gettext function can be used like so:

var helloWorld = {{gettext('Hello, world')}};

But then, no quotes are inserted, and hence, js interpreter throws an error:

var helloWorld = Hello, world;

That's why I have finally applied a custom filter. A working example would be as follows.

hello_world.html:

<script type="text/javascript">   var x = {{gettext('Hello, world')|generate_string|safe}};   console.log(x);    //logs the localized hello world message</script>

app.py:

#Jinja2 filtersfrom jinja2 import evalcontextfilter, Markup#Mind the hack! Babel does not work well within js code@app.template_filter()@evalcontextfilterdef generate_string(eval_ctx, localized_value):    if localized_value is None:        return ""    else:        return Markup("\"" + localized_value + "\"").unescape()

Hope this helps!


Providing translations in rendered JavaScript is a bit fragile. Also, I usually do not generate JavaScript using Jinja because it uses the same type of brackets and easily turns into mess when abused (it's always possible to have dynamic data and static JavaScript).

Alternative lightweight approach is to do the same JSON trick, but using data-attributes:

<div id="view-i18n" data-i18n='{{ view_i18n|tojson }}'> ... </div>

(NB: single quotes!)

But it's also good for a limited number of translations.

Perhaps, the most solid approach is to have the same translations in JavaScript as there are in the Flask app.

With a help of a utility called pojson it is possible to convert po-files to json (see https://github.com/ZeWaren/flask-i18n-example for an example) as part of the build process (for instance, right after making mo-files). Translations can be easily added to some unique enough global namespace variable by prepending the output of pojson with var some_unique_name = to have access to it. Or put the file under static into locale-specific file (eg static/view-es.json , static/view-fr.json, etc) and get it with ajax call.

Some things to consider though. You may need to break your translation domain into separate Python and Javascript by controlling babel extraction options if you really want to make JSON smaller. Also, having all translation strings in Javascript has security aspects. Maybe, you do not want to expose certain phrases only admins see to be open to other category of users. But then more translation domains are needed for different levels of access. Also header information may need to be removed to prevent leaking translator's emails and whatnot. This, of course, complicates the build process somewhat, but the more translation JavaScript side needs with time, the more automation pays itself off.