Flask babel not workinf since revamped project with blueprints

27 views Asked by At

I have an app working well and translating with flask babel.

Then, I started to split the code in modules and generating blueprints instead of still writing all code inside the same .py file.

This is my project structure:

Project structure

Then, this is the code from main file: FinMapper.py

from app import create_app

app = create_app('default')

Code of app/init.py

from flask import Flask
from flask_babel import Babel
from config import config


def register_blueprints(app):
    from .file_import import file_import_blueprint
    app.register_blueprint(file_import_blueprint)


def get_locale():
    return 'es'


babel = Babel()


def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(config[config_name])
    config[config_name].init_app(app)
    register_blueprints(app)
    babel.init_app(app)

    return app

Code on forms.py:

class MovementFileForm(FlaskForm):
    type = SelectField(lazy_gettext('Type'), choices=[('default', 'DEFAULT'), ('bbva', 'BBVA')])
    file = FileField(lazy_gettext('File'),
                     validators=[DataRequired(),
                                 FileAllowed(['csv'], message='FileExtensionNotAllowed')],
                     render_kw={"class": "form-control"})

The calls to lazy_gettext('text') was working until refactoring to create blueprints.

And here an example of base.html with the navbar:

<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
    <div class="container-fluid">
        <a class="navbar-brand" href="#"><b>FinMapper</b></a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
                aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                <li class="nav-item">
                    <a class="nav-link active" aria-current="page" href="#">{{ _('Dashboard') }}</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link active" aria-current="page" href="#">{{ _('Categories') }}</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link active" aria-current="page" href="#">{{ _('Categorize') }}</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link active" aria-current="page" href="{{ url_for('file_import_blueprint.load') }}">{{ _('Load') }}</a>
                </li>
            </ul>
        </div>
    </div>
</nav>

Like lazy_gettext, the call of method _('text') was working until create blueprints.

My main doubt is if this code in the app factory is correct, I think that here is the problem:

Babel declaration detail

This is the first version of the code, working well without blueprints:

Project vanilla no blueprints

I don't know how must be instantiated or declared Babel to be able to use in all blueprints. Now, my translations are not working.

Update

I'm able to call locale selector, but still without translations. If I configure babel like this:

babel = babel()

def create_app(config_name):
    app = Flask(__name)
    babel.init(app, locale_selector=gel_locale()
    # more coding

Putting a print inside get_locale function, it works, is being called. But translations still not working

2

There are 2 answers

0
UrbanoJVR On BEST ANSWER

Solved moving translations folder inside app.

You can see the 1st photo uploaded with old project estructure.

Now, this is the new project structure:

New project structure

0
Augustin BAR On

Short answer :

You referenced a call of your function, not the function itself.

And you probably did a typo on init_app.

Please change :

babel.init(app, locale_selector=gel_locale())

to

babel.init_app(app, locale_selector=gel_locale)

Explanations

If you're using Flask-Babel 4.0.x, the @localeselector decorator doesn't exist anymore and you should reference a function as a localselector argument when creating your babel instance.

However, if you're using the app factory pattern (creating your app in a function and not directly in the file), you should declare the local_selector function in your init_app and not in your Babel instanciation.

Eg :

from flask import Flask
from flask_babel import Babel
from config import my_config

babel = Babel()

def get_locale():
    # put your code to manage your user favorite language here
    # I recommend using flask session in order to maintain persistence between requests 

    return "en"

def create_app():
    app = Flask(__name__)
    app.config.from_object(my_config)
    babel.init_app(app, locale_selector=get_locale)
    
    return app