pythonflaskpython-babel

How to pass to url_for default params?


I develops multi language web site. Pages have URI's like this:

/RU/about

/EN/about

/IT/about

/JP/about

/EN/contacts

and in jinja2 templates I write:

<a href="{{ url_for('about', lang_code=g.current_lang) }}">About</a>

I have to write lang_code=g.current_lang in all url_for calls.

Is it possible to pass lang_code=g.current_lang to url_for implicitly? And write only {{ url_for('about') }}

My routers looks like:

@app.route('/<lang_code>/about/')
def about():
...

Solution

  • Use app.url_defaults to provide default values when building a url. Use app.url_value_preprocessor to extract values from a url automatically. This is described in the docs about url processors.

    @app.url_defaults
    def add_language_code(endpoint, values):
        if 'lang_code' in values:
            # don't do anything if lang_code is set manually
            return
    
        # only add lang_code if url rule uses it
        if app.url_map.is_endpoint_expecting(endpoint, 'lang_code'):
            # add lang_code from g.lang_code or default to RU
            values['lang_code'] = getattr(g, 'lang_code', 'RU')
    
    @app.url_value_preprocessor
    def pull_lang_code(endpoint, values):
        # set lang_code from url or default to RU
        g.lang_code = values.pop('lang_code', 'RU')
    

    Now url_for('about') will produce /RU/about, and g.lang_code will be set to RU automatically when visiting the url.


    Flask-Babel provides more powerful support for handling languages.