Search code examples
pythonflaskmultilingualpython-babel

How can I choose the language, using Flask + Babel?


Now I'm developing a project, which should support two languages: English, as default, and Russian. It's pretty easy to do, using HTTP_ACCEPT_LANGUAGE header, the code is bellow:

babel = Babel(app)

@babel.localeselector
def get_locale():
    return request.accept_languages.best_match(app.config["LANGUAGES"].keys())

Languages are hardcoded in application config file:

LANGUAGES = {
    'en': 'English',
    'ru': 'Russian'
}

But I also want to add a button, like Switch language to English. What is the best practice to realise it?


Solution

  • This is the solution I came across:

    First you set a route that will handle the language change and will store the selected language on the session:

    @app.route('/language/<language>')
    def set_language(language=None):
        session['language'] = language
        return redirect(url_for('index'))
    

    Secondly, you have to modify a little the code you have to get the selected language from the session:

    @babel.localeselector
    def get_locale():
        # if the user has set up the language manually it will be stored in the session,
        # so we use the locale from the user settings
        try:
            language = session['language']
        except KeyError:
            language = None
        if language is not None:
            return language
        return request.accept_languages.best_match(app.config['LANGUAGES'].keys())
    

    You have also to be able to access the CURRENT_LANGUAGE from the templates, so you can inject it:

    @app.context_processor
        def inject_conf_var():
            return dict(
                        AVAILABLE_LANGUAGES=app.config['LANGUAGES'],
                        CURRENT_LANGUAGE=session.get('language',request.accept_languages.best_match(app.config['LANGUAGES'].keys())))
    

    Finally, on the template you can choose the the language you want:

    {% for language in AVAILABLE_LANGUAGES.items() %}
         {% if CURRENT_LANGUAGE == language[0] %}
             {{ language[1] }}
         {% else %}
             <a href="{{ url_for('set_language', language=language[0]) }}" >{{ language[1] }}</a>
         {%  endif %}
    {% endfor %}
    

    Application config.py includes the following constant:

    LANGUAGES = {
      'en': 'English',
      'es': 'Spanish'
    }
    

    Hope this helps!