I haven't thought of a nice way to remove #, fuzzy from the files. I think process_babel_file might possibly become its own module, but on the other hand, having all methods in one script is quite nice for the mean time. I expect there to be bugs, although it works for the languages I've tried.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

Generate and manipulate translation files for a flask app.
Assumes areas in jinja2 templates are marked with {% trans %}..{% endtrans %}
or gettext, _, or other gettext variants.
Related: flask, flask-babel, pybabel, jinja2, i18n, gobabslate
    1. Run pybabel with extract option
        pybabel extract -F babel.cfg -o messages.pot .
    2. Run pybabel with init option for each language
        pybabel init -i messages.pot -d translations -l fr
        pybabel init -i messages.pot -d translations -l de
    3. Pull translations from Google Translate API into babel files
    4. Remove #fuzzy from message.po files.
    5. Run pybabel with compile option
        pybabel compile -d translations
import sys
import codecs
from subprocess import Popen
from goslate import Goslate

pybabel_extract = ['pybabel', 'extract', '-F' 'babel.cfg',
                                         '-o' 'messages.pot', '.']
pybabel_init_lang = ['pybabel', 'init', '-i', 'messages.pot',
                                        '-d', 'translations', '-l']
pybabel_compile = ['pybabel', 'compile', '-d', 'translations']

def get_language_codes():
        from config import LANGUAGES, LANGUAGE_DEFAULT
        return [lang for lang in LANGUAGES.keys() if lang != LANGUAGE_DEFAULT]
        return ['fr', 'de']

def return_code(args):
    return Popen(args).communicate()[0]

def process_babel_file(lang, remove_fuzzy=False):
    gs = Goslate()
    filename = 'translations/' + lang + '/LC_MESSAGES/messages.po'
    file_stream = codecs.open(filename,          'r', 'utf-8')
    file_output = codecs.open(filename + '.tmp', 'w', 'utf-8')
    finding_input, data = False, u''
    for line in file_stream:
        if finding_input is True and line == u'msgstr ""\n':
            finding_input = False
            new_text = gs.translate(data, lang).replace('"', '\\"')
            file_output.write(u'msgstr "' + new_text + u'"\n')
        elif finding_input is True:
            data += line.replace('\n', ' ').replace('\\n"', ' ').strip('"')\
                        .replace('\\"', '"')
        elif line == u'msgid ""\n' or line[:7] == u'msgid "':
            finding_input = True
            data = u'' if line == u'msgid ""\n' else line[7:].strip()\
                .strip('"').replace('\\"', '"')
        elif line == '#, fuzzy\n' and remove_fuzzy:
    Popen(['cp', filename + '.tmp', filename]).communicate()

def main():
    if return_code(pybabel_extract) is not None:
        sys.exit('pybabel failed to extract translations')
    for language_code in get_language_codes():
        if return_code(pybabel_init_lang + [language_code]) is not None:
            print('Failed to add language: %s', language_code)
        process_babel_file(language_code, remove_fuzzy=True)
    if return_code(pybabel_compile) is not None:
        sys.exit('pybabel was unable to compile translations')

if __name__ == '__main__':

1 Answer 1


Nice script! Found it very helpful to get started and test flask babel and see first translations.

A few "bugs" I discovered for your consideration

  • Any string with a ' will cause problems
  • Same with other special characters, e.g. ()

The resulting po file mixes entries later on and generates strings like:

#: dedri/templates/contact.html:29
msgid "Your email"
msgstr "Aboutmsgstr \"about (modificado por Raimundo)\" #: dedri / templates / about.html:            13 msgid \"Aquí añadimos unas pocas palabras acerca de cada uno de nosotros.\" msgstr \"Aquí añadimos Unas Palabras Sobre CADA UNO de Nosotros here.\" #: Dedri / templates / contact.html: 29 msgid \"Your email\"" 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.