Multilingual slug with django-translated-fields

524 Views Asked by At

I am trying to implement a multilingual Django website with help of django-translated-fields.

The project I am working on is based on cookiecutter-django and Docker.

The translation works fine for my model fields – except the slug filed. Actually translation of slug works as well but I am not able to take slug field for getting one single entry.

Excerpt of voting model:

class Voting(models.Model):
    slug =  TranslatedField(
        models.SlugField(
            max_length=80,
            unique=True,
            verbose_name="Voting URL slug",
            blank=True
        ),
        {
            "de": {"blank": True},
            "fr": {"blank": True},
            "it": {"blank": True},
            "rm": {"blank": True},
            "en": {"blank": True},
        },
    )

Full voting model of project can be seen here.

Excerpt of view:

def voting(request, slug):
    voting = get_object_or_404(Voting, slug=slug)
    context = {
        'voting': voting
    }
    return render(request, 'votes/single.html', context)

Full view can be seen here

Since Django translated fields creates slug_en, slug_de and so on I cannot find a solution for getting the slug in corresponding language.

It should be obvious since documentation of Django-translated fields says:

No model field is actually created. The TranslatedField instance is a descriptor which by default acts as a property for the current language's field.

Unfortunately, don’t get it anyway. Any idea how I can change voting model for getting the entry in the specific language?

2

There are 2 best solutions below

1
On BEST ANSWER
from translated_fields import to_attribute

def voting(request, slug):
    voting = get_object_or_404(Voting, **{to_attribute(name='slug'): slug})
    context = {
        'voting': voting
    }
    return render(request, 'votes/single.html', context)

If necessary, you can add language_code=request.LANGUAGE_CODE to the call to to_attribute, but usually this is not necessary:

    voting = get_object_or_404(Voting, **{to_attribute(name='slug', language_code=request.LANGUAGE_CODE): slug})
3
On

Not sure if this is the right way but with help of Django Documentation “How Django discovers language preference” I came to following solution.

Changing the voting view as follows:

def voting(request, slug):
    '''Takes slug of single voting and returns that voting object in
    corresponding language.
    '''
    if request.LANGUAGE_CODE == 'de':
        voting = get_object_or_404(Voting, slug_de=slug)
    elif request.LANGUAGE_CODE == 'fr':
        voting = get_object_or_404(Voting, slug_fr=slug)
    elif request.LANGUAGE_CODE == 'it':
        voting = get_object_or_404(Voting, slug_it=slug)
    elif request.LANGUAGE_CODE == 'rm':
        voting = get_object_or_404(Voting, slug_rm=slug)
    elif request.LANGUAGE_CODE == 'en':
        voting = get_object_or_404(Voting, slug_en=slug)
    context = {
        'voting': voting
    }
    return render(request, 'votes/single.html', context)