angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

Flask meertalige verwerking, overschakeling en de 404 pagina Niet gevonden uitzondering

In dit artikel bespreken we een aantal voorwaarden bij het verwerken van de taal in de url, het gebruik van een standaardtaal en het gebruik van een lijst van beschikbare talen.

13 november 2019 Bijgewerkt 15 november 2019
post main image
https://unsplash.com/@sadswim

Hoe Flask meertalig te implementeren wordt uitgelegd in de Flask docs, zie onderstaande links. Maar dit is slechts een beginpunt. U moet het proces beter begrijpen om speciale gevallen te kunnen behandelen, zoals terugvallen op een standaardtaal, taalwisseling en de uitzondering 404 Page Not Found.

Veronderstellingen

In de rest van dit bericht gebruiken we een taalcode, 'lang_code', die beschikbaar is in de url, het is het eerste deel van de url, bijvoorbeeld:

https://www.example.com/en

https://www.example.com/en/login

We gebruiken ook Flask-Babel voor de vertalingen. Ik gebruik blueprints en registreer ze als volgt in create_app():

    # authentication (shared)
    from shared.blueprints.auth.views import auth_blueprint
    app.register_blueprint(auth_blueprint, url_prefix='/<lang_code>/auth')

    # pages (shared)
    from shared.blueprints.pages.views import pages_blueprint
    app.register_blueprint(pages_blueprint, url_prefix='/<lang_code>')

We gebruiken g.lang_code als de waarde van de geselecteerde taal. Ik gebruik geen sessievariabele om de taal te onthouden, maar vertrouw op de beschikbaarheid van de taal bij elk verzoek.

Flask meertalige verwerking

De manier waarop Flask omgaat met meertaligheid bij een aanvraag is als volgt:

Eerst wordt url_value_preprocessor() aangeroepen om de taal uit het url. voorbeeld te halen:

@pages_blueprint.url_value_preprocessor
def pull_lang_code(endpoint, values):
    # pop lang_code from url and set g.lang_code
    ...
    if 'lang_code' in values:
        g.lang_code = values.pop('lang_code')

Vervolgens wordt Babels locale_selector() aangeroepen om de vertalingen voor de pagina te leveren, bijvoorbeeld:

@babel.localeselector
def get_locale():
    return g.get('lang_code')

Tenslotte wordt url_defaults() aangeroepen voordat de pagina wordt gebouwd om <lang_code> te vervangen door lang_code in de urls, bijvoorbeeld:

@pages_blueprint.url_defaults
def add_language_code(endpoint, values):
    # stuff g.lang_code in urls
    ...
    values.setdefault('lang_code', g.lang_code)

Dit is vrij eenvoudig, maar zoals je kunt zien, kunnen er omstandigheden optreden waarbij de taalcode wordt gewijzigd, niet beschikbaar of zelfs niet geldig is. Het belangrijkste is om ervoor te zorgen dat g.lang_code altijd op een geldige taal is ingesteld voordat localeselector() en url_defaults() worden aangeroepen. Hieronder wordt een aantal voorwaarden besproken.

Flask meertalige verwerking: bezoekers schakelen over naar een andere taal

Om over te schakelen naar een andere taal kunnen we een GET gebruiken om de huidige aanvraag met een extra lang_code parameter te wijzigen:

<a href="{{ request.script_root  +  request.path }}?lc=en">English</a>
<a href="{{ request.script_root  +  request.path }}?lc=de">Deutsch</a>

We moeten de functionaliteit van de url_value_preprocessor() uitbreiden om de taalswitch te ondersteunen. Vereenvoudigd, deze extra code lijkt op deze extra code:

@pages_blueprint.url_value_preprocessor
def pull_lang_code(endpoint, values):
    ...
    request_lang_code = request.args.get('lc')
    if request_lang_code:
        g.lang_code = request_lang_code
    ...

Flask meertalige verwerking: taal ontbreekt in url en standaardtaal.

Dit kan geen fout zijn omdat u misschien wilt dat de bezoeker uw domeinnaam url intypt en naar de standaard taalpagina's wordt 'omgeleid'. Maar dit kan ook gebeuren als een bezoeker een verkeerde url intypt, een (zoek)bot belt een verkeerde url. Ook dit kunnen we in de url_value_preprocessor() verwerken. In dit geval stellen we de lang_code in op de lang_code van de standaardtaal:

@pages_blueprint.url_value_preprocessor
def pull_lang_code(endpoint, values):
    ...
    if g.get('lang_code') is  None:
        g.lang_code = default_lang_code

Flask meertalige verwerking: taal is geen ondersteunde taal.

Onze applicatie ondersteunt slechts een beperkt aantal talen, bijv:

    available_lang_codes = ['en', 'de']

Ook hier kunnen we het ongeldige taalgeval in de url_value_preprocessor() behandelen. Als de taal niet geldig is, stellen we de lang_code in op de lang_code van de standaardtaal:

@pages_blueprint.url_value_preprocessor
def pull_lang_code(endpoint, values):
    ...
    if 'lang_code' in values:
        lang_code = values.pop('lang_code')
        if lang_code not in available_lang_codes:
            g.lang_code = default_lang_code

Flask meertalige verwerking: Pagina niet gevonden (404) fout (404)

Deze gaf me wat hoofdpijn, het kostte me wat debugging om te zien dat de stroom in dit geval anders is. Wat hier gebeurt is dat als geen van de blueprints 's overeenkomt met de aanvraag url, url_value_preprocessor() NOOIT wordt aangeroepen. Bijvoorbeeld, met de blueprints eerder getoond, is dit een geldige url:

http://127.0.0.1:8000/en/auth/login

maar deze url geeft een 404 uitzondering:

http://127.0.0.1:8000/en/auth/login/something

Wat te doen hier? Het antwoord is om deze voorwaarde te verwerken in de Flask @before_request. Op een normale flow before_request() wordt url_value_preprocessor (!) genoemd:

    @pages_blueprint.url_value_preprocessor
    def pull_lang_code(endpoint, values):
        ....

    @app.before_request
    def before_request():
        ....

In het geval van een 404 uitzondering wordt url_value_preprocessor() NIET aangeroepen maar before_request() wordt nog steeds aangeroepen:

    @app.before_request
    def before_request():
        ....

Normaal gesproken zal url_value_preprocessor() g.lang_code instellen op een waarde, een taalcode. Maar op een 404 wordt url_value_preprocessor() niet aangeroepen en is g.lang_code niet ingesteld. In before_request() controleren we de waarde van g.lang_code. Als het niet is ingesteld kunnen we het verzoek zelf in behandeling nemen. Als het eerste deel een geldige taalcode is, gaan we ervan uit dat we deze nodig hebben en stellen we g.lang_code in. Anders stellen we g.lang_code in op de standaard taal. Wanneer vervolgens de 404 handler wordt aangeroepen, kan de pagina in de juiste taal worden weergegeven.

Samenvatting

Ik heb geen sessievariabele gebruikt om de geselecteerde taal op te slaan, maar in plaats daarvan vertrouw ik op de taal in de url. Dit werkt prima als we met allerlei omstandigheden omgaan, zoals een ontbrekende taal. Het belangrijkste is om de taal in g in te stellen alvorens alle andere bewerkingen uit te voeren.

Links / credits

Flask Series: Internationalization
https://damyanon.net/post/flask-series-internationalization/

Flask-Babel
https://pythonhosted.org/Flask-Babel/

Using URL Processors
https://flask.palletsprojects.com/en/1.1.x/patterns/urlprocessors/

Laat een reactie achter

Reageer anoniem of log in om commentaar te geven.

Opmerkingen

Laat een antwoord achter

Antwoord anoniem of log in om te antwoorden.