Flask multilingual application

Viewed 70

I need to make a flask based website multilingual.
My site needs to acts as follows:

example.com     -> Italian
example.com/it/ -> redirects to example.com
example.com/en/ -> English

This is my current implementation:
app.py

from flask import Flask, render_template
app = Flask(__name__)

@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html', navbar={}), 404

# blueprints
from blueprints.www import www
app.register_blueprint(www, name='default_locale_www', url_defaults={'locale': 'it'})
app.register_blueprint(www, name='www', url_prefix='/<locale>')

blueprints/www.py

from flask import render_template, Blueprint, abort, redirect, url_for

www = Blueprint('www', __name__)

all_locales = ['it', 'en']
default_locale = 'it'

@www.url_value_preprocessor
def manage_locales(endpoint, values):
    if values['locale'] not in all_locales:
        values['locale'] = default_locale

@www.route('/')
def homepage(locale):
    return render_template('homepage.html', locale=locale)

@www.route('/test')
def test(locale):
    return render_template('test.html', locale=locale)

@www.route('/{slug}')
def slug(locale, slug):
    return render_template('slug.html', locale=locale, slug=slug)

But have some issues:

  • example.com/it dose not redirect to example.com
  • example.com/foo shows the homepage in Italian, but it should return 404
  • example.com/it/foo should match the slug route, but returns 404
  • example.com/en/foo should match the slug route, but returns 404
  • example.com/foo/test should return 404, but match the test route

How would I go about doing this? Any information would be appreciated. Thanks in advance.

1 Answers

First of all, there is a typo in your slug route:

@www.route('/{slug}')

should be:

@www.route('/<slug>')

(with '<>' instead of '{}')

It will fix your 404 errors on /it/foo and /en/foo.

Regarding the locale part, I do not have a full answer, just a few points which can maybe help:

/foo and /foo/test can't redirect to the homepage and /test respectively because of the condition:

    if values['locale'] not in all_locales:
        values['locale'] = default_locale

which will force the locale to "it" when the "locale" (i.e. the first part of the URL) is not a known locale. You can try and tune your condition to make it work in most cases, but I don't know how to make it work in ALL cases. Especially, it will be difficult to match both the conditions: /it/test -> /test and /foo/test -> 404. For this, I tend to agree with the comment of @MSalters that it would be nicer to redirect all routes without locale to Italian by default (if I remember properly, it is also better in terms of SEO, but to be checked).

Related