If you're building a Django app that needs to support more than one language, Django's built-in internationalisation (i18n) is a decent start. But if you want to go further — like translating model fields, managing multilingual content, and switching language context dynamically — Django-parler is the tool you want.

This guide is aimed at beginners and covers everything from installation to usage, with best practices and practical examples.


🌍 Why Use Django-parler?

Django itself provides tools for translating strings in templates and Python code. Still, it doesn't offer a clean way to make database models translatable — to have fields that store multiple language versions.

Django-parler solves this with a well-designed API and seamless integration into Django admin and queries.


🔧 Installation and Basic Configuration

First, install the package:

pip install django-parler

Then, add it to your INSTALLED_APPS in settings.py:

INSTALLED_APPS = [
    ...
    'parler',
]

Set your supported languages:

LANGUAGE_CODE = 'en'

LANGUAGES = [
    ('en', 'English'),
    ('pl', 'Polski'),
]

PARLER_LANGUAGES = {
    None: (
        {'code': 'en'},
        {'code': 'pl'},
    ),
    'default': {
        'fallbacks': ['en'],
        'hide_untranslated': False,
    },
}

🧱 Making a Model Translatable

Let's say you want to create a Category model in which each language's name and slug should differ.

Here's how to do it with parler:

from django.db import models
from parler.models import TranslatableModel, TranslatedFields

class Category(TranslatableModel):
    translations = TranslatedFields(
        name=models.CharField(max_length=200),
        slug=models.SlugField(max_length=200, unique=True),
    )

    def __str__(self):
        return self.safe_translation_getter('name', any_language=True)

Key points:

  • Use TranslatableModel as your base class.
  • Define translatable fields inside TranslatedFields().
  • Use safe_translation_getter() to safely get the translated value.

🛠 Using Translations in the Admin

Django-parler provides an admin mixin to show translation tabs automatically:

from django.contrib import admin
from parler.admin import TranslatableAdmin
from .models import Category

@admin.register(Category)
class CategoryAdmin(TranslatableAdmin):
    list_display = ('__str__',)

You'll now see tabs for each language when editing an object in the admin.


🔍 Querying Translatable Models

To avoid duplicate entries or incorrect results, always use .translated() when querying:

from .models import Category

# Only get categories that are translated into the current language
Category.objects.translated('pl').filter(translations__is_published=True)

Or to get only those that exist in the current request's language:

from django.utils.translation import get_language

Category.objects.translated(get_language()).all()

⚠️ Avoid using .filter(translations__...) without .translated(...) or .distinct() — this can lead to duplicate rows in querysets.


🎯 Rendering Translations in Templates

Use safe_translation_getter() to access values in templates:

{{ category.safe_translation_getter:"name" }}

Or use the standard property (like category.name) if you're sure the model is correctly translated in the context.


🧪 Testing Translations

Use Django's override context to test translations:

from django.utils.translation import override

with override('pl'):
    category = Category.objects.first()
    print(category.name)  # Should be in Polish

🧹 Best Practices

  • Use safe_translation_getter to prevent NoneType errors.
  • Always use .translated() when filtering by translatable fields.
  • Never mix translated and untranslated queries unless you use .distinct().
  • Use admin mixins to have a smooth experience when editing translations.
  • Don't duplicate logic — define fallbacks and supported languages in one place (settings.py).

✅ Summary

Django-parler is a powerful tool for multilingual content in Django. With minimal configuration, you can:

  • Translate model fields.
  • Filter and fetch content in the current language.
  • Provide a seamless admin experience.

Stay tuned, and happy translating! 🌍