angle-up arrow-clockwise arrow-counterclockwise arrow-down-up arrow-left at calendar card-list chat check envelope folder house info-circle pencil people person person-plus phone plus question-circle search tag trash x

Ajout de liens url_for() vers les Jinja modèles d'un site web Flask multilingue

15 septembre 2019 à côté de Peter

Dans un site web multilingue avec des limaces multilingues, nous ne pouvons plus utiliser <a href="{{ url_for('pages.about') }}">{{{ _('About') }}</a>.

post main image
unsplash.com/@andrewtneel
Avant de poursuivre votre lecture, vous voudrez peut-être lire mes articles précédents sur le multilinguisme et le repli linguistique, voir les liens ci-dessous. Quand je me suis donné la mission de développer et de mettre en place un site web multilingue Flask , SQLAlchemy je savais que les choses pouvaient devenir difficiles. Je n'ai pas vraiment pris le temps de tout concevoir avant, j'ai juste lu beaucoup de choses sur le multilinguisme sur Internet et j'ai fait confiance à mon expérience pour concevoir tout en écrivant du code qui pourrait être étendu sans trop d'efforts. Pourtant, parfois vous pouvez vous impliquer tellement dans le fonctionnement du code que vous oubliez des choses simples.

Le problème : url_for() dans les Jinja templates

Dans les pages blueprint vues.py j'avais défini les points finaux pour le contact, les conditions d'utilisation et la politique de confidentialité de la page :
@pages_blueprint.route('/contact')
def contact():
    return page_view('contact')


@pages_blueprint.route('/about')
def about():
    return page_view('about')

@pages_blueprint.route('/terms-of-use')
def terms_of_use():
    return page_view('terms-of-use')


@pages_blueprint.route('/privacy-policy')
def privacy_policy():
    return page_view('privacy-policy')

J'ai supprimé ces lignes pour que le seul point final restant pour les pages soit la fonction page_view :

@pages_blueprint.route('/<slug>', methods=['GET', 'POST'])
def page_view(slug):
    ...

Puis les pages ont cessé de fonctionner... bien sûr. À certains endroits dans les modèles, j'ai encore utilisé url_for() pour générer le lien vers une page. Par exemple, l'option'Lire la suite' était toujours spécifiée comme :

<a href="{{ url_for('pages.about') }}">{{ _('Read more') }}</a>

Et sur la page Registre, il y avait le lien :

* {{ _('See our') }} <a href="{{ url_for('pages.privacy_policy') }}" class="link">{{ _('privacy policy') }}</a> {{ _('how we process and protect your personal data.') }}

Les deux ont échoué avec le célèbre :

werkzeug.routing.BuildError: Could not build url for endpoint ...

Rien de spécial et oui, on l'attendait, mais comment résoudre cela et surtout, comment résoudre cela de manière multilingue ?

La solution : un dict imbriqué pour chaque langue sélectionnée

La solution n'est pas très difficile, comme je l'ai mentionné dans les billets précédents, nous avons deux tableaux :

ContentItem ContentItem
ContentItemTranslation

ContentItem contient un nom'commun'. Par exemple, la page A propos a un nom commun'A propos', puis les enregistrements ContentItemTranslation contiennent le titre de la page traduite, pour la langue néerlandaise c'est'Over ons' et la balise dérivée est'over-ons'. Pour pouvoir fournir les données appropriées à la fonction url_for() nous devons créer un dictionnaire ayant la structure suivante :

{
    'About': { 'title': title, 'slug': slug },
    'Privacy policy': { 'title': title, 'slug': slug },
    ... 
}

Ensuite, nous avons besoin du processeur de contexte pour obtenir ce dictionnaire dans le modèle, ici j'utilise app_template_slug comme nom du dictionnaire. Dans le Jinja modèle, nous pouvons l'utiliser de la manière suivante :

* {{ _('See our') }} <a href="{{ url_for('pages.page_view', slug=app_template_slug['Privacy policy']['slug']) }}" class="link">{{ app_template_slug['Privacy policy']['title'] }}</a> {{ _('how we process and protect your personal data.') }}

Nous utilisons le nom " commun " pour obtenir le titre et le slug appropriés, donc rien ne dépend de la langue ici. Comme pour les autres fonctionnalités, j'ai créé l'objet qui prend en charge la génération du dictionnaire imbriqué dans la fonction create_app.

Liens / crédits

Multilanguage fallback revisited and a page footer with multilanguage links
/en/blog/multilanguage-fallback-revisited-and-a-page-footer-with-multilanguage-links

Refining multilanguage: adding language fallback as an option
/en/blog/refining-multilanguage-adding-language-fallback-as-an-option

Laissez un commentaire

Commentez anonymement ou connectez-vous pour commenter.

Commentaires

Laissez une réponse

Répondez de manière anonyme ou connectez-vous pour répondre.