wagtail

Wagtail internationalization for form fields


How can the internationalization support be implemented for field label, help text and so on. The standard multiplication of fields seems not working e.g. the example given in the doc for creating contact form. I tried to add extra fields for the other languages (the first approach described in the doc)

  from django.db import models

  from wagtail.core.models import Page
  from modelcluster.fields import ParentalKey
  from wagtail.admin.edit_handlers import (
    FieldPanel, FieldRowPanel,
    InlinePanel, MultiFieldPanel
  )

  from wagtail.core.fields import RichTextField
  from wagtail.contrib.forms.models import (
    AbstractEmailForm, AbstractForm, AbstractFormField
  )
  from wagtail.contrib.forms.edit_handlers import FormSubmissionsPanel
  from dimaplus.languages import TranslatedField
  # Create your models here.

  class FormField(AbstractFormField):
    page = ParentalKey(
        'FormPage',
        on_delete=models.CASCADE,
        related_name='form_fields',
    )
    label_fa = models.CharField(max_length=255)
    label_ru = models.CharField(max_length=255)
    label_ar = models.CharField(max_length=255)

    tr_label_tag = TranslatedField(
      'label',
      'label_fa',
      'label_ar',
      'label_ru',
    )
    panels = AbstractFormField.panels + [
        FieldPanel('label_fa'),
        FieldPanel('label_ru'),
        FieldPanel('label_ar'),
    ]
  class FormPage(AbstractEmailForm, Page):

    intro = RichTextField(blank=True)
    intro_fa = RichTextField(blank=True)
    intro_ar = RichTextField(blank=True)
    intro_ru = RichTextField(blank=True)

    thank_you_text = RichTextField(blank=True)
    thank_you_text_fa = RichTextField(blank=True)
    thank_you_text_ar = RichTextField(blank=True)
    thank_you_text_ru = RichTextField(blank=True)

    # 'body',
    # 'body_fa',
    # 'body_ar',
    # 'body_ru',
    tr_intro = TranslatedField(
        'intro',
        'intro_fa',
        'intro_ar',
        'intro_ru'
    )
    tr_thank_you_text = TranslatedField(
        'thank_you_text',
        'thank_you_text_fa',
        'thank_you_text_ar',
        'thank_you_text_ru'
    )

    content_panels = AbstractEmailForm.content_panels + [
        FormSubmissionsPanel(),
        FieldPanel('intro_fa', classname='full'),
        InlinePanel('form_fields', label="Form fields"),
        FieldPanel('thank_you_text_fa', classname="full"),
        MultiFieldPanel([
            FieldPanel('intro'),
            FieldPanel('thank_you_text'),
            FieldPanel('intro_ar'),
            FieldPanel('thank_you_text_ar'),
            FieldPanel('intro_ru'),
            FieldPanel('thank_you_text_ru'),
        ]),
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('from_address', classname="col6"),
                FieldPanel('to_address', classname="col6"),
            ]),
            FieldPanel('subject'),
        ], "Email"),
    ]

The 'TranslatedField' class is simply given in the doc:

from django.utils import translation
from django.utils.translation import gettext_lazy as _

#translation class
class TranslatedField:
    def __init__(self,
                 en_field,
                 fa_field,
                 ar_field,
                 ru_field):
        self.en_field = en_field
        self.fa_field = fa_field
        self.ar_field = ar_field
        self.ru_field = ru_field

    def __get__(self, instance, owner):
        lang = translation.get_language()
        if lang == 'fa':
            return getattr(instance, self.fa_field)
        elif lang == 'ar':
            return  getattr(instance, self.ar_field)
        elif lang == 'ru':
            return  getattr(instance, self.ru_field)
        else:
            return getattr(instance, self.en_field)

Solution

  • In case someone stumbles upon this. It's possible to do this with the example from the docs. You have to use the label field itself for the translation because that's the field wagtail uses to build the form. Just override it with the translated field.

    class FormField(AbstractFormField):
        label_en = models.CharField(max_length=250)
        label_de = models.CharField(max_length=250)
        label_fr = models.CharField(max_length=250)
        label_ru = models.CharField(max_length=250)
    
        label = TranslatedField(
            'label_en',
            'label_de',
            'label_fr',
            'label_ru'
        )
    
        # this is to remove the original label from the field panels
        # you could also just copy the panels from the AbstractFormFieldClass
        # wagtail will throw an error otherwise
        AbstractFormField.panels.remove(next((x for x in AbstractFormField.panels if x.field_name == 'label'), None))
    
        content_panels = AbstractFormField._panels + [                 
            FieldPanel('label_en'),
            FieldPanel('label_de'),
            FieldPanel('label_fr'),
            FieldPanel('label_ru'),
        ]
    

    With the helptext field it would be the same. Those are the fields the class uses:

    panels = [
        FieldPanel('label'),
        FieldPanel('help_text'),
        FieldPanel('required'),
        FieldPanel('field_type', classname="formbuilder-type"),
        FieldPanel('choices', classname="formbuilder-choices"),
        FieldPanel('default_value', classname="formbuilder-default"),
    ]