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>.
El problema: url_for() en Jinja plantillas
@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
Leer más
Flask Jinja2 Multilanguage
Recientes
- Cómo ocultar las claves primarias de la base de datos UUID de su aplicación web
- Don't Repeat Yourself (DRY) con Jinja2
- SQLAlchemy, PostgreSQL, número máximo de filas por user
- Mostrar los valores en filtros dinámicos SQLAlchemy
- Transferencia de datos segura con cifrado de Public Key y pyNaCl
- rqlite: una alternativa de alta disponibilidad y dist distribuida SQLite
Más vistos
- Usando Python's pyOpenSSL para verificar los certificados SSL descargados de un host
- Usando UUIDs en lugar de Integer Autoincrement Primary Keys con SQLAlchemy y MariaDb
- Conectarse a un servicio en un host Docker desde un contenedor Docker
- Usando PyInstaller y Cython para crear un ejecutable de Python
- SQLAlchemy: Uso de Cascade Deletes para eliminar objetos relacionados
- Flask RESTful API validación de parámetros de solicitud con esquemas Marshmallow