A brief history

This package is inspired by django-hvad. When attempting to integrate multilingual support into django-fluent-pages using django-hvad this turned out to be really hard. The sad truth is that while django-hvad has a nice admin interface, table layout and model API, it also overrides much of the default behavior of querysets and model metaclasses. This prevents combining django-hvad with django-polymorphic or django-mptt for example.

When investigating other multilingual packages, they either appeared to be outdated, store translations in the same table (too inflexible for us) or only provided a model API. Hence, there was a need for a new solution, using a simple, crude but effective API.

To start multilingual support in our django-fluent-pages package, it was coded directly into the package itself. A future django-hvad transition was kept in mind. Instead of doing metaclass operations, the “shared model” just proxied all attributes to the translated model (all manually constructed). Queries just had to be performed using .filter(translations__title=..). This proved to be a sane solution and quickly it turned out that this code deserved a separate package, and some other modules needed it too.

This package is an attempt to combine the best of both worlds; the API simplicity of django-hvad with the crude, but effective solution of proxying translated attributes.

Added on top of that, the API-sugar is provided, similar to what django-hvad has. It’s possible to create the translations model manually, or let it be created dynamically when using the TranslatedFields field. This is to make your life easier - without loosing the freedom of manually using the API at your will.


Database schema

django-parler uses a separate table for storing translated fields. Each row stores the content for one language, using a language_code column.

django-parler database design

The same database layout is used by django-hvad, making a transition to django-parler rather easy.


  • Works with existing tools, such as the Django migration framework.
  • Unlimited languages can be supported
  • Languages can be added on the fly, no database migrations needed.


  • An extra database query is needed to fetch translated fields.
  • Filtering on translated fields should happen in a single .filter(..) call.


  • The extra database queries are mostly avoided by the caching mechanism, which can store the translated fields in memcached.
  • To query all languages, use .prefetch('translations') in the ORM query. The prefetched data will be read by django-parler.

Opposite design: django-modeltranslation

The classic solution for writing translatable fields is employed by django-modeltranslation. Each field has a separate column per language.

django-modeltranslation database design

The advantages are:

  • fast reading of all the data, everything is in a single table.
  • editing all fields at once is easy.

The disadvantages are:

  • The database schema is changed based on the project settings.
  • Third party packages can’t provide reasonable data migrations for translated fields.
  • For projects with a large number of languages, a lot of additional fields will be read with each query,

Package naming

The package name is rather easy to explain; “parler” is French for “to talk”.

And for our slogan, watch Dexter’s Laboratory episode “The Big Cheese”. ;-)