3

I am new to wagtail and i am working with a custom menu. I set up a custom menu class and use a tag to display the menu-items in the templates. This works fine, however i would need to create different menus depending on what language my site is used in. (i know wagtailmenus exists, however i could not find a satisfying way to create translated menus there either)

I wanted to create a similar translation experience like wagtail-localize does with pages. Is this possible or do i have to take a different approach?

I already tried to use wagtails TranslatableMixin to simply create duplicates of my menu with different translations, however this does not seem to work, because the translate option (like it is done with pages) is missing.

Classes:

class Menu(TranslatableMixin, ClusterableModel):    
    title = models.CharField(max_length=100)
    logo = models.ForeignKey("wagtailimages.Image", blank=True, null=True, on_delete=models.SET_NULL, related_name="menu_logo")
    image = models.ForeignKey("wagtailimages.Image", blank=True, null=True, on_delete=models.SET_NULL, related_name="menu_image")
    slug = AutoSlugField(populate_from="title", editable=True)

    panels = [
        MultiFieldPanel(
            [
                FieldPanel("title"),
                FieldPanel("slug"),
                ImageChooserPanel("logo"),
                ImageChooserPanel("image"),
            ],
            heading="Menu",
        ),
        InlinePanel("menu_items", label="Menu Item"),
    ]

    def __str__(self):
        return self.title

    class Meta(TranslatableMixin.Meta):
        verbose_name = "Menu"



class MenuItem(ClusterableModel, AbstractMenuItem):
    page = ParentalKey("Menu", related_name="menu_items")

    class Meta:
        verbose_name = "Menu Item"

Templatetags:

@register.simple_tag()
def get_menu(slug, authencicated):
    menu = Menu.objects.get(slug=slug)
    all_menu_items = menu.menu_items.all()
    menu_items = []
    for item in all_menu_items:
        if item.show(authencicated):
            menu_items.append(item)
    return {"logo": menu.logo, "image": menu.image, "items": menu_items}

template:

{% get_menu "main-menu" request.user.is_authenticated as menu%}
Schmella
  • 71
  • 4

1 Answers1

0

Here are ways to approach this "manually" without additional packages. First of all please double check your configuration.

On the one hand you could add a translated title to the page models that you are listing in these menus. Call it title_en, for example.

On the other hand you could add these field directly to your MenuItem class:

class MenuItem(ClusterableModel, AbstractMenuItem):
    page = ParentalKey("Menu", related_name="menu_items")
    title_en = models.CharField(max_length=32, verbose_name="English Title")
    title_zh = models.CharField(max_length=32, verbose_name="Chinese Title")

    class Meta:
        verbose_name = "Menu Item"

In the template you can identify the current language and choose the menu accordingly. This also works via a template tag (by passing the language code over or getting the language code within the template tag).

{% load i18n %}

{% get_current_language as current_language_code %}


# You could either pass the current_language_code to your template tag:
{% get_menu('slug', current_language_code) %}


# Or use multiple template tags:
{% if current_language_code == 'zh' %}
    {% get_chinese_menu %}
{% else %}
    {% get_english_fallback_menu %}
{% endif %}

You can also get the current language code in your templatetags.py:

from django.utils.translation import get_language

@register.simple_tag()
def get_menu(slug, ...):
    current_language_code = get_language()
    if current_language_code == 'zh':
        ...
    else:
        ... 

You could use an additional custom template tag to translate the menu items if the structure of the menu is identical:

from django.utils.translation import get_language

@register.simple_tag()
def get_translated_title(item):
    current_language_code = get_language()
    if current_language_code == 'zh':
        return item.title_zh
    return item.title_en  # fallback
Fuchsi
  • 127
  • 5
  • This is not exactly what i've searched for, but thanks for the reply. I searched for a possibility to translate the menu like wagtail-localize allows me to do with pages and snippets. As a workaround i registered my Menus as snippets and there i can transalte them using the "wagtail-localize" approach. However, my initial desire to make a model (registered to the admin sidebar) translatable is sadly not supported in wagtail-localize as of now. – Schmella Dec 13 '21 at 10:53
  • I’ve used [Wagtail Modeltranslation](https://github.com/infoportugal/wagtail-modeltranslation) for that before. Maybe worth a look. – Fuchsi Dec 13 '21 at 16:51
  • can you show me your code with Menus as snippets please?! – Omerta Omerta Apr 17 '22 at 16:08