5

I am working on a flask project (Python3). I have internationalization working fine in my project. This is the configuration method launched in the create_app factory:

def configure_languages(app):

    # flask-babel
    babel = Babel(app)

    @babel.localeselector
    def get_locale():
        languages = ['en', 'fr', 'de']
        lang = request.args.get('lang')
        if lang is None:
            return g.get('lang_code', app.config['BABEL_DEFAULT_LOCALE'])
        elif lang not in languages:
            return g.get('lang_code', app.config['BABEL_DEFAULT_LOCALE'])
        else:
            g.lang_code = lang
            return g.get('lang_code', app.config['BABEL_DEFAULT_LOCALE'])

    @app.before_request
    def ensure_lang_support():
        lang_code = g.get('lang_code', app.config['BABEL_DEFAULT_LOCALE'])
        if lang_code and lang_code not in app.config['SUPPORTED_LANGUAGES']:
            return abort(404)


    @app.url_defaults
    def set_language_code(endpoint, values):
        if 'lang_code' in values or not g.get('lang_code',
                                              app.config['BABEL_DEFAULT_LOCALE']):
            return
        if app.url_map.is_endpoint_expecting(endpoint, 'lang_code'):
            values['lang_code'] = g.get('lang_code',
                                          app.config['BABEL_DEFAULT_LOCALE'])

    @app.url_value_preprocessor
    def get_lang_code(endpoint, values):
        if values is not None:
            g.lang_code = values.pop('lang_code',
                                     app.config['BABEL_DEFAULT_LOCALE'])

This is how I define one of the blueprints:

frontend_blueprint = Blueprint('frontend', __name__, url_prefix='/<lang_code>')

The application is working fine. I can see the language codes in the url. For instance:

http://localhost:5000/en/posts
http://localhost:5000/fr/posts
http://localhost:5000/de/posts

The en is the default language in the config of my application.

Nevertheless, I've got a question:

How can I make the default language empty?

I want my web app by default not to show any language code If I am using it in English:

http://localhost:5000/posts
http://localhost:5000/about
http://localhost:5000/help

Only when I select some particular language like French or German the url should become like these:

http://localhost:5000/fr/posts
http://localhost:5000/fr/about
http://localhost:5000/fr/help

Or

http://localhost:5000/de/posts
http://localhost:5000/de/about
http://localhost:5000/de/help

How can I do that? I tried to set the default language code in the config from 'en' to '' but obviously it's not working.

David Buck
  • 3,752
  • 35
  • 31
  • 35
Nurjan
  • 5,889
  • 5
  • 34
  • 54

1 Answers1

0

You can use the following. This works by detecting the language from the url and stores it in the flask g request global, and it defaults to the browser setting if no language code has been set. Note that app.config['LANGUAGES]' must be a list containing supported languages such as ['en', 'de', 'fr].

@blueprint.url_defaults
def set_language_code(endpoint, values):
    if 'lang_code' in values or not g.get('lang_code', None):
        return
    # If endpoint expects lang_code, send it forward
    if current_app.url_map.is_endpoint_expecting(endpoint, 'lang_code'):
        values['lang_code'] = g.lang_code

@blueprint.url_value_preprocessor
def get_lang_code(endpoint, values):
    if values is not None:
        # If no language code has been set, get the best language from the browser settings
        default_lang = request.accept_languages.best_match(current_app.config['LANGUAGES'])
        g.lang_code = values.pop('lang_code', default_lang)

@babel.localeselector
def get_locale():
    lang = g.get('lang_code')
    if lang in current_app.config['LANGUAGES']:
        return lang
    else:
        return 'en'

And then mount the blueprint on your app two times:

app.register_blueprint(blueprint, url_prefix='/')
app.register_blueprint(blueprint, url_prefix='/<lang_code>')
user787267
  • 2,550
  • 1
  • 23
  • 32