Wagtail Translated Navigation Menu
When handling multi-lingual content on your website, your navigation menu may not be displayed in the local language.
I recently ran into an issue when using the Wagtail Localize plugin to translate content into various languages. The pages were translated fine, but the top navigation menu always stayed in the default language.
After looking into that issue for way too long, I finally found a solution and wanted to document it in case anyone else runs into the same issue.
This was the content of base/templatetags/navigation_tags.py before:
from django import template
from wagtail.core.models import Page, Site
from mybase.base.models import FooterText
register = template.Library()
# https://docs.djangoproject.com/en/3.2/howto/custom-template-tags/
@register.simple_tag(takes_context=True)
def get_site_root(context):
# This returns a core.Page. The main menu needs to have the site.root_page
# defined else will return an object attribute error ('str' object has no
# attribute 'get_children')
return Site.find_for_request(context['request']).root_page
def has_menu_children(page):
# This is used by the top_menu property
# get_children is a Treebeard API thing
# https://tabo.pe/projects/django-treebeard/docs/4.0.1/api.html
return page.get_children().live().in_menu().exists()
...
And this was the content of templates/tags/top_menu.html:
{% load navigation_tags wagtailcore_tags %}
{% get_site_root as site_root %}
{% for menuitem in menuitems %}
<li class="presentation {{ menuitem.title|lower|cut:" " }}{% if menuitem.active %} active{% endif %}{% if menuitem.show_dropdown %} has-submenu{% endif %}">
{% if menuitem.show_dropdown %}
<a href="{% pageurl menuitem %}" class="allow-toggle">{{ menuitem.title }} <span><a class="caret-custom dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"></a></span></a>
{% top_menu_children parent=menuitem %}
{# Used to display child menu items #}
{% else %}
<a href="{% pageurl menuitem %}" role="menuitem">{{ menuitem.title }}</a>
{% endif %}
</li>
{% endfor %}
There might be other solutions, and as usual, the actual fix highly depends on your particular Wagtail implementation, but the fix for me was to change base/templatetags/navigation_tags.py to retrieve the page matching the request language:
from django import template
from wagtail.models import Page, Site
from mybase.base.models import FooterText
from wagtail.core.models import Locale
register = template.Library()
# https://docs.djangoproject.com/en/3.2/howto/custom-template-tags/
@register.simple_tag(takes_context=True)
def get_site_root(context):
# This returns a core.Page. The main menu needs to have the site.root_page
# defined else will return an object attribute error ('str' object has no
# attribute 'get_children')
request = context['request']
language = request.LANGUAGE_CODE
locale = Locale.objects.get(language_code=language)
return Site.find_for_request(context['request']).root_page.get_translation(locale)
...
Tagged with:
Wagtail