0

I am trying to optimize internationalization for my django (wagtail) site.

I have a model which creates fields for the CMS that allow translation to different language:

from internationalization.translatedfield import TranslatedField

class BlogPage(Page):

    body_en = RichTextField(blank=True)
    body_fr = RichTextField(blank=True)

    body = TranslatedField(
        'body_en',
        'body_fr'
    )

    content_panels = Page.content_panels + [
        FieldPanel('body_en', classname="full"),
        FieldPanel('body_fr', classname="full"),
    ]

The translatedfield import just allows us to use a single variable name in our django template ('body'):

from django.utils import translation

class TranslatedField(object):
    def __init__(self, en_field, fr_field):
        self.en_field = en_field
        self.fr_field = fr_field

    def __get__(self, instance, owner):
        if translation.get_language() == 'fr':
            return getattr(instance, self.fr_field)
        else:
            return getattr(instance, self.en_field)

And in the template:

{{ page.body|richtext }}

All this allows the CMS user to input text for 'body_fr' and 'body_en' fields, and, based on the URL the visitor was at, output either the french or english translations (e.g. site.com/en/blog or site.com/fr/blog).

The problem is there could be potentially dozens of languages and dozens of fields, so you can see how this model could get very large. So what I'd like to do is dynamically create those self.en_fields and .fr fields in a loop.

So the TranslatedField import might look something like:

class TranslatedField(object):
    def __init__(self, field, languages):

where field would be, in this example, body and languages would be an array of languages we want to support for this field: ['en','fr'].

Then I would loop through that array, for language in languages and somehow return self.{language}_field = language, and in def __get__(self, instance, owner): somehow loop through all the languages again and say if translation.get_language() == language: return getattr(instance,self.{language_field}` (above being pseudocode).

How do I restructure the existing model and import to more effectively render the fields that I need? I'm guessing the answer might involve using a combination of loops and dictionaries, but I haven't had a ton of success with dynamically creating and implementing these so far.

mheavers
  • 29,530
  • 58
  • 194
  • 315

1 Answers1

0

This isn't a complete answer but hopefully it will get you on the right track.

The first think you could simplify is the construction of the TranslatedField and it's __get__ method like so:

class TranslatedField(object):
    def __init__(self, field_name, languages):
        self.field_name = field_name
        self.languages = languages

    def __get__(self, instance, owner):
        required_lang = translation.get_language()
        lang = required_lang if required_lang in self.languages else self.languages[0]
        translated_field_name = '%s_%s' % (self.field_name, lang)
        return getattr(instance, translated_field_name)

You will still need to create body_en, body_fr and so on but that's a start.

In order to not have to create all the body_xxx fields, and do something like this instead body = TranslatedField(field_type=RichText, field_args=None, fields_kwargs={'blank': True}, languages=['en', 'fr']), then you'll have to look at contribute_to_class.

Btw, there are some translation libraries out there for Wagtail which might be worth a look.

Loïc Teixeira
  • 1,404
  • 9
  • 19