Simple implementation of multi-lingual models for Django. Django-admin integration works out of the box. Supports django-localeurl integration.


  • Django 1.5.+
  • Python 2.7.+, 3.3.+


Note, that Django 1.5 is required. Earlier versions are not supported.

  1. Installation

Latest stable version on PyPI:

$ pip install django-slim

Latest stable version on bitbucket:

$ pip install -e hg+

Latest stable version on github:

$ pip install -e git+
  1. Add slim to INSTALLED_APPS of you settings module.

Usage and examples

An extensive example project is available at directory.

Screenshots are present in documentation on PythonHosted (


In order to be able to quickly evaluate the django-slim, a demo app (with a quick installer) has been created (Debian only). Follow the instructions below for having the demo running within a minute.

Grab the latest

Create a new- or switch to existing- virtual environement, assign execute rights to the installer and run the

$ chmod +x

$ ./

Go to the front/back -end and test the app.

Let’s now step-by-step review our imaginary example app.

Add slim to installed apps.

>>>     # ...
>>>     'slim',
>>>     # ...
>>> )

Add languages.

>>>     ('en', gettext("English")), # Main language!
>>>     ('hy', gettext("Armenian")),
>>>     ('nl', gettext("Dutch")),
>>>     ('ru', gettext("Russian")),
>>> )


>>> from django.db import models
>>> from slim import LanguageField, Slim
>>> class FooItem(models.Model, Slim):
>>>     title = models.CharField(_("Title"), max_length=100)
>>>     slug = models.SlugField(unique=True, verbose_name=_("Slug"))
>>>     body = models.TextField(_("Body"))
>>>     language = LanguageField()


>>> from django.contrib import admin
>>> from slim.admin import SlimAdmin
>>> class FooItemAdmin(SlimAdmin):
>>>     list_display = ('title',)
>>>     fieldsets = (
>>>         (None, {
>>>             'fields': ('title', 'slug', 'body')
>>>         }),
>>>     )
>>>, FooItemAdmin)


We assume that language code is kept in the request object (django-localeurl behaviour, which you’re advised to use).

>>> from slim import get_language_from_request
>>> from example.models import FooItem
>>> def browse(request, template_name='foo/browse.html'):
>>>     language = get_language_from_request(request)
>>>     queryset = FooItem._default_manager.filter(language=language)
>>>     # The rest of the code

More on ORM filtering

>>> from example.models import FooItem
>>> foo = FooItem._default_manager.all()[0]
<FooItem: Lorem ipsum>

Let’s assume, we have such record and it has been translated to Armenian (am) and Dutch (nl). Original translation is named Lorem ipsum. Other translations have the language code appended to the title.

>>> armenian_foo = foo.get_translation_for('hy')
<FooItem: Lorem ipsum HY>
>>> dutch_foo = foo.get_translation_for('nl')
<FooItem: Lorem ipsum NL>

If we have a translated object, we can always get the main translation.

>>> armenian_foo.original_translation == foo

All available translations for foo:

>>> foo.available_translations()
[<FooItem: Lorem ipsum HY>, <FooItem: Lorem ipsum NL>]

All available translations for Armenian foo.

>>> armenian_foo.available_translations()
[<FooItem: Lorem ipsum>, <FooItem: Lorem ipsum NL>]

See directory for a working example.

django-localeurl integration


django-localeurl integration is fully supported for Python 2.6.* and 2.7.* and installs automatically when installing django-slim. If you are using Python 3, install a forked version of django-localeurl (since official version does not yet have support for Python 3).

Forked version from bitbucket:

$ pip install -e hg+


Use slim.models.decorators.auto_prepend_language decorator in order to have it working.

Example (have in mind our FooItem model.

>>> from django.core.urlresolvers import reverse
>>> from slim.models.decorators import auto_prepend_language
>>> class FooItem(models.Model):
>>>     # Some other code; have in mind previous pieces.
>>>     @auto_prepend_language
>>>     def get_absolute_url(self):
>>>         kwargs = {'slug': self.slug}
>>>         return reverse('foo.detail', kwargs=kwargs)

Do not forget to add the LocaleURLMiddleware to the MIDDLEWARE_CLASSES (as first).

>>>     'localeurl.middleware.LocaleURLMiddleware',
>>>     # The rest...
>>> )

Also, add localeurl to INSTALLED_APPS.

>>>     # Some apps...
>>>     'localeurl',
>>>     # Some more apps...
>>> )


GPL 2.0/LGPL 2.1


For any issues contact me at the e-mail given in the Author section.


Artur Barseghyan <>



List view:


Edit view for main language:


Edit view for translated item:


models Package

class slim.models.__init__.Slim[source]

Bases: object

Add this class to all your multi-lingual Django models, where you use slim.models.fields.LanguageField. Alternatively, you may use the slim.models.SlimBaseModel.


Returns available translations.

Return interable:
 At this moment a list of objects.
available_translations_admin(*args, **kwargs)[source]

Gets a HTML with all available translation URLs for current object if available. For admin use.

Return str:
available_translations_exclude_current_admin(*args, **kwargs)[source]

Same as available_translations_admin but does not include itself to the list.

Return str:
get_original_translation(*args, **kwargs)[source]

Gets original translation of current object.

Return obj:Object of the same class as the one queried.

Find an acceptable redirect target. If this is a local link, then try to find the page this redirect references and translate it according to the user’s language. This way, one can easily implement a localized “/”-url to welcome page redirection.


Get translation article in given language.

Parameters:language (str) – Which shall be one of the languages specified in LANGUAGES in
Return obj:Either object of the same class as or None if no translations are available for the given language.
is_multilingual None[source]

Simple flat to use on objects to find our wheither they are multilinugal or not

Return bool:Always returns boolean True
original_translation None[source]

Property for get_original_translation method.

Return obj:Object of the same class as the one queried.
translation_admin(*args, **kwargs)[source]

Gets a HTML with URL to the original translation of available. For admin use.

Return str:
class slim.models.__init__.SlimBaseModel(*args, **kwargs)[source]

Bases: django.db.models.base.Model, slim.models.__init__.Slim

An abstract Django model.

class Meta[source]
abstract = False

fields Module

class slim.models.fields.LanguageField(*args, **kwargs)[source]

Bases: django.db.models.fields.CharField

LanguageField model. Stores language string in a CharField field.

Using contrib_to_class melthod adds translation_of field, which is simply a ForeignKey to the same class.

contribute_to_class(cls, name)[source]

Returns best form field to represent this model field

validate(value, model_instance)[source]

Validating the field.

We shall make sure that there are double translations for the same language for the same object. That’s why, in case if model is not yet saved (translated_object does not yet have a primary key), we check if there are already translations of the same object in the language we specify now.

Otherwise, if model_instance already has a primary key, we anyway try to get a translated_object and compare it with our model_instance. In case if translated_object exists and not equal to our model_instance we raise an error.

NOTE: This has nothing to do with unique fields in the original model_instance. Make sure you have properly specified all unique attributes with respect to LanguageField` of your original ``model_instance if you need those records to be unique.

class slim.models.fields.SimpleLanguageField(*args, **kwargs)[source]

Bases: django.db.models.fields.CharField

SimpleLanguageField model. Stores language string in a CharField field.


Returns best form field to represent this model field

decorators Module

slim.models.decorators.prepend_language(func, language_field='language')[source]

Prepends the language from the model to the path resolved.

slim.models.decorators.localeurl_prepend_language(func, language_field='language')[source]

Prepends the language from the model to the path resolved when django-localeurl package is used.

slim.models.decorators.auto_prepend_language(func, language_field='language')

Prepends the language from the model to the path resolved.

admin Module

class slim.admin.SlimAdmin(model, admin_site)[source]

Bases: django.contrib.admin.options.ModelAdmin


list_view_primary_only - if set to True, onlt primary language items would be shown in the list view. Default value is False.

language_field - name of the language field defined in your model. Default value language.

auto_add_edit_view - if set to True, extra fields for language editing are added to the list view. Do NOT set this value to False!

collapse_slim_fieldset if set to True, the language fieldset is shown collapsed.

auto_add_edit_view = True
auto_add_list_view = True
collapse_slim_fieldset = True
declared_fieldsets None
get_list_display(*args, **kwargs)[source]
get_list_filter(*args, **kwargs)[source]
get_readonly_fields(*args, **kwargs)[source]
language_field = 'language'
list_view_primary_only = False
media None
queryset(*args, **kwargs)[source]

conf Module

slim.conf.get_setting(setting, override=None)[source]

Get a setting from slim conf module, falling back to the default.

If override is not None, it will be used instead of the setting.

helpers Module


Gets default language.

Return str:

Gets available languages.

Return iterable:

Returns just languages keys.

Return list:
slim.helpers.get_language_from_request(request, default='af')[source]

Gets language from HttpRequest

  • django.http.HttpRequest
  • default (str) –
Return str:

Returns just languages dict.

Return dict:
slim.helpers.admin_change_url(app_label, module_name, object_id, extra_path='', url_title=None)

Gets an admin change URL for the object given.

  • app_label (str) –
  • module_name (str) –
  • object_id (int) –
  • extra_path (str) –
  • url_title (str) – If given, an HTML a tag is returned with url_title as the tag title. If left to None just the URL string is returned.
Return str:
slim.helpers.admin_add_url(app_label, module_name, extra_path='', url_title=None)

Gets an admin edit URL for the object given.

  • app_label (str) –
  • module_name (str) –
  • extra_path (str) –
  • url_title (str) – If given, an HTML a tag is returned with url_title as the tag title. If left to None just the URL string is returned.
Return str:
slim.helpers.smart_resolve(var, context)[source]

Resolves variable from context in a smart way. First trying to resolve from context and when result is None checks if variable is not None and returns just variable when not. Otherwise returns None.

  • var (str) –
  • context (Context) –
Return mixed:

utils Module


Checks if localeurl is installed in the Django project.

Return bool:

translations Module


Extracts the short language code from its argument (or return the default language code).

Parameters:code (str) –
Return str:

from django.conf import settings >>> short_language_code(‘de’) ‘de’ >>> short_language_code(‘de-at’) ‘de’


Returns true if current or passed language is the primary language for this site. (The primary language is defined as the first language in settings.LANGUAGES.)

Parameters:language (str) –
Return bool:

slim_tags Module

slim.templatetags.slim_tags.get_translated_object_for(parser, token)[source]

Gets translated object for the object given.

{% get_translated_object_for [object] language=[language] as [var_name] %}
Example usage::
{% get_translated_object_for article as translated_article %} {% get_translated_object_for article language=ru as translated_article %}
slim.templatetags.slim_tags.get_translated_objects_for(parser, token)[source]

Gets translations available for the given object.

{% get_translated_objects_for [object] as [var_name] %}
Example usage::
{% get_translated_objects_for article as translated_article %}
slim.templatetags.slim_tags.set_language(parser, token)[source]

Sets current language code.

FIXME: This is actually a hack.

{% set_language [language] %}
{% set_language ru %}
slim.templatetags.slim_tags.multiling_is_enabled(parser, token)[source]

Checks if multiling shall be enabled (in templates). Simply, if LANGUAGES tuple contains more than one language, we return boolean True; otherwise - boolean False.

{% multiling_is_enabled as [var_name] %}
{% multiling_is_enabled as multiling_is_enabled %}

Not all languages are available in Django yet. It might happen that support for your own precious language is not yet available in Django and many apps rely on languages list defined in django.conf.global_settings module.

Thus, to have translations for your own language available, the following approach is introduced: - Pick the language code closest to your language but name it differently: ((‘ar’, ugettext(‘Armenian’)),). - Instead of using Django’s language_name filter (of i18n module) use slim_language_name filter just the

same way.

This filter would get your item tranlation based on your project translations.

Parameters:lang_code (str) –
Return str:

Indices and tables