Skip to content

Allow overriding how the locale is set#50

Open
aceisace wants to merge 1 commit intoAnbarryprojects:mainfrom
aceisace:main
Open

Allow overriding how the locale is set#50
aceisace wants to merge 1 commit intoAnbarryprojects:mainfrom
aceisace:main

Conversation

@aceisace
Copy link
Copy Markdown

@aceisace aceisace commented Feb 9, 2025

Analog to the flask-babel locale_selector, these small, but effective changes provide a much higher user-comfort as they are not restricted to only the integrated locale-selection method.

For instance, some users may want to save the locale of a logged-in-user which has a preferred locale in the request session or even as a cookie. Currently, it is not possible except to override the locale inside a view function like this:

from app.main import babel
async def some_function(abc: str):
    babel.locale = "de"

Which is fairly un-pythonic and adds a lot of repetitive code when you have a lot of view functions. Instead of this, one can, optionally override this behaviour like this:

In main.py:

# code omitted before
...

def get_locale_from_session(request: Request) -> str:
    # If user logged in, we stored locale in session:
    session_locale = request.session.get("locale")
    print(f"session_locale: {session_locale}")
    if session_locale and session_locale in settings.SUPPORTED_LANGUAGES:
        return session_locale

    # Fallback to Accept-Language header, or Babel default locale
    accept_language = request.headers.get("accept-language", "")

    if accept_language:
        languages = [lang.split(";")[0] for lang in accept_language.split(",")]

        # Check if any of the user's preferred languages match supported ones
        for lang in languages:
            if lang in settings.SUPPORTED_LANGUAGES:
                print("get_locale: ", lang)
                return lang

    return babel.default_locale  # Fallback if no match is found

# before 
app.add_middleware(BabelMiddleware, babel_configs=babel_configs, jinja2_templates=templates)
# after
app.add_middleware(BabelMiddleware, babel_configs=babel_configs, jinja2_templates=templates, locale_selector=get_locale_from_session)

Which does the following;
if a user is logged in, take their preferred locale to set the babel locale. If no user was found (i.e. not logged in), use the accept-language header instead. Of course, the user is free to set the locale in whichever way they want, e.g. database queries, cookies, sessions etc.

On my end, I have done some testing with some fairly good results. I kindly ask to merge the changes into main after doing some tests on your end too and having these changes available in the next release in the near future.

Allow providing locale_selector for more flexibility
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant