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

Añadir enlaces url_for() a las Jinja plantillas de un sitio web Flask multilingüe

En un sitio web multilingüe con slugs multilingües ya no podemos usar <a href="{{ url_for('pages.about') }}">{{ _('Acerca de') }}</a>.

15 septiembre 2019
post main image
unsplash.com/@andrewtneel
Antes de seguir leyendo, puede que quieras leer mis artículos anteriores sobre el multilenguaje y el respaldo del lenguaje, ver los enlaces de abajo. Cuando me encargué de desarrollar e implementar un sitio web multilingüe Flask , SQLAlchemy supe que las cosas podrían ponerse difíciles. Realmente no me tomé el tiempo de diseñar todo de antemano, sólo leí mucho sobre el multilenguaje en Internet y confié en mi experiencia para diseñar mientras escribía código que pudiera ser expandido sin mucho esfuerzo. Aún así, a veces puedes involucrarte tanto en conseguir que el código funcione que te olvides de cosas simples.

El problema: url_for() en Jinja plantillas

En las páginas blueprint views.py he definido los puntos finales de la página de contacto, acerca de, términos de uso y política de privacidad:
@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')

Eliminé estas líneas para que el único punto final que quedara para las páginas fuera la función page_view:

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

Entonces las páginas dejaron de funcionar.... por supuesto. En algunos lugares de las plantillas todavía utilizaba url_for() para generar el enlace a una página. Por ejemplo, el `Leer más' seguía estando especificado como:

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

Y en la página de Registro estaba el enlace:

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

Ambos fracasaron con el famoso:

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

Nada especial y sí se esperaba, pero ¿cómo resolver esto y más importante aún, cómo resolver esto de forma multilingüe?

La solución: un dictador anidado para cada idioma seleccionado

La solución no es muy difícil, como mencioné en los posts anteriores tenemos dos tablas:

ContenidoItem
ContenidoItemItemTraducción

ContentItem contiene un nombre"común". Por ejemplo, la página Acerca de tiene un nombre común 'Acerca de' y los registros ContentItemTranslation contienen el título de la página traducida, para el idioma holandés esto es 'Over ons' y el slug derivado es 'over-ons' Para poder proporcionar los datos adecuados a la función url_for() necesitamos crear un diccionario con la siguiente estructura:

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

Luego necesitamos el procesador de contexto para llevar este diccionario a la plantilla, aquí uso app_template_slug como nombre del diccionario. En la Jinja plantilla podemos usar esto de la siguiente manera:

* {{ _('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.') }}

Usamos el nombre"común" para obtener el título y la bala adecuados, por lo que no hay nada que dependa del idioma aquí. Como con otras funcionalidades he creado el objeto que se encarga de la generación del diccionario anidado en la función create_app.

Enlaces / créditos

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

Deje un comentario

Comente de forma anónima o inicie sesión para comentar.

Comentarios

Deje una respuesta.

Responda de forma anónima o inicie sesión para responder.