9

I'm using django modeltranslation for a multi-language site.

Language fallback works good when reading attributes directly. For example, if current language is German and I print object.title, if the German title is not defined I'll see the english title.

I would expect fallback to work also on queries, but that's not true. In fact, if i do something like

results = MyModel.objects.filter(title = 'hello')

this will get no results if the German title is not set, while I would like it to return the object with english title "hello".

How can I make this work?

Thanks in advance.

sabrina
  • 1,567
  • 2
  • 12
  • 15
  • have you read the documentation? http://django-modeltranslation.readthedocs.org/en/latest/usage.html#fallback-languages – Hedde van der Heide Dec 11 '14 at 09:28
  • 2
    Sure, the section Fallback languages explain the how to set the fallback order. And it works when accessing fields or using values(), as explained in the documentation. The problem is that fallback doesn't apply when using querysets for filtering. there's nothing about this need in the documentation, so I was asking if there is a way to achieve this. – sabrina Dec 11 '14 at 11:37
  • Also the MODELTRANSLATION_AUTO_POPULATE setting doesn't seem to work. I set it to true, but when saving objects with TranslationModelForm translated fields are not populated :( – sabrina Dec 11 '14 at 11:40
  • 1
    Thanks for asking, I have the same issue! Couldn't find anything in the docs either. Have you found a way to solve this yet? – steps Apr 14 '15 at 12:36

3 Answers3

3

Unfortunately answers above are wrong. The way to handle this case correct is

    queryset = queryset.filter(
        Q(
            Q(Q(title_fr_fr__icontains=search) & ~Q(title_fr_fr=""))
            |
            Q(Q(title_en_gb__icontains=search) & Q(title_fr_fr=""))
        )        
    )

Where fr-fr - is language we are working with now and en-gb - is our default language. This means get us those rows where title on target language contains searchable string AND title on target language is FILLED (not empty) OR where title on default language contains searchable string AND title on target language is empty.

So whole example will be looks like this:

from django.db.models import Q
###
default_lang = settings.LANGUAGE_CODE.replace("-", "_")
current_lang = get_language().replace("-", "_")

queryset = queryset.filter(
    Q(
        Q(Q(**{f'title_{current_lang}__icontains': search}) & ~Q(**{f'title_{current_lang}': ""}))
        |
        Q(Q(**{f'title_{default_lang}__icontains': search}) & Q(**{f'title_{current_lang}': ""}))
        )
    )

azuax answer gives wrong results in some cases. Suppose title_de = 'ABC', title_en = 'DEF' and current language de. And for search string "DEF" we get this row but shouldn't because user see "ABC"

Слава
  • 71
  • 3
0

The thing to do here is to explicitly query the desire language. In your case:

from django.db.models import Q
# ...
# define your query like this: 
results = MyModel.objects.filter(Q(title_de = 'hello') | Q(title_en = 'hello'))
# supposing you have German and English languages set

Why this work? Because when you query the specific language, ModelTranslation keep it. Otherwise it use the current language.

I hope it helps!

azuax
  • 465
  • 1
  • 6
  • 15
0

You must ensure that your model is registered in translation.py

from modeltranslation.translator import register, TranslationOptions
@register(YourModel)
class YourModel(TranslationOptions):
    pass

In this way all the queries that are done will return the appropriate field depending on the language in which it is, this because to register it is created a MultilingualManager