9. Release Notes

9.1. 1.8.0 - current release

Released on April 28, 2017

Python and Django versions supported:

  • Support for Django 1.10 was added.
  • Django 1.7 is no longer supported.
  • So, as a reminder, supported Django versions for this release are: 1.8 LTS, 1.9, 1.10.x (for x ≥ 1) and 1.11.

New features:

  • Automatic loading of translations on attribute access can now be disabled, by setting HVAD["AUTOLOAD_TRANSLATIONS"] to False. This will prevent hvad from initiating database queries. Accessing translatable attributes with no translation loaded will then raise an AttributeError.
  • It is possible to automatically install TranslationQueryset as the default queryset for all translatable models, by setting HVAD["USE_DEFAULT_QUERYSET"] to True. Specifically, it changes default_class to be a TranslationQueryset instead of a QuerySet. See the section about overriding the default queryset for advantages and caveats of doing so.
  • Field declaration for internal language_code attribute can be overriden. — #332.

Compatibility warnings:

  • All settings have been moved to a unique HVAD dictionary. Please update your django settings accordingly.

  • Deprecated class FallbackQueryset has been removed. Using it along with FallbackQueryset.use_fallbacks() did not work on Django 1.9 and newer and was deprecated on older versions. Using it without that method made it behave like a regular queryset. So as a summary,

    • Code using .untranslated().use_fallbacks() must be replaced with .language().fallbacks().
    • All other uses of FallbackQueryset can be safely replaced with a regular QuerySet.
  • Translated admin no longer shows objects lacking a translation. This was already the case on Django 1.9 and newer, and this behavior now extends to all Django versions. Such objects should not happen anyway, and throw a warning when encountered.


  • Increase speed of translated attribute access by ~30%, by avoiding a method call when a translation is loaded.
  • Attempting to use a reserved name for a translated field now raises an ImproperlyConfigured exception instead of silently ignoring the field.
  • Instances created by serializers using TranslatableModelMixin in normal, non-enforcing mode can no longer be created without a translation. — #322.

9.2. 1.7.0

Released on February 8, 2017

New features:

  • Support for defer() and only() was added. Note that deferring all translated fields will not result in translation being skipped, because 1) it needs to be inspected for language resolution and 2) loaded translation language must be fixed at query time. Support is limited to immediate fields at the moment, ie it is not possible to defer fields of additionals models loaded through select_related().

Compatibility warnings:

  • Internal admin method TranslatableAdmin.get_available_languages() is deprecated and will be removed. Use TranslatableModel.get_available_languages() instead.
  • Internal admin method TranslatableAdmin.get_language_tabs() signature changed.


  • Do not consider annotations when looking up translatable query fields. Fixes errors that could arise when using some annotation names. — #303.
  • Accept special value __all__ for form field list, as a synonym for None, meaning include all known fields. — #313.
  • Fix translation deletion links that were improperly generated when using inline change forms. — #317.

9.3. 1.6.0

Released on September 6, 2016

Python and Django versions supported:

  • Support for Django 1.10 was added. It requires version 1.10.1 or better.
  • So, as a reminder, supported Django versions for this release are: 1.7, 1.8 LTS, 1.9, 1.10.x (for x ≥ 1).


  • No longer set master to NULL before clearing translations when using delete_translations(). This only triggers one query instead of two, and allows enforcing non-null foreign key at the database level.
  • Django system checks are now run in the test suite in addition to hvad’s tests.

9.4. 1.5.1

Released on May 23, 2016


  • Filter out m2m and generic fields in update_translation() so it does not bite when using (unsupported) m2m fields or generic relations in a translation — #285.

9.5. 1.5.0

Released on February 2, 2016

Python and Django versions supported:

  • Django 1.4 LTS is no longer supported.
  • So, as a reminder, supported Django versions for this release are: 1.7, 1.8 LTS, 1.9.

New features:

  • It is now possible to specify a custom translation base model, allowing advanced translation manipulation, such as controlling their loading with from_db().
  • Translated model’s save() method now accepts translated field names in update_fields. Also, if only translated fields, or only untranslated fields are specified in update_fields, the extra query will be skipped.
  • Support for third parameter on ModelAdmin‘s get_object() method was added.
  • Experimental support for using language(‘all’) together with select_related() is being introduced. Please check the generated queries if you use it. Feedback is appreciated.

Compatibility Warnings:

  • Saving of translations now happens in the model’s save() method. It used to happen in the post_save signal.
  • TranslationsMixin now splits the update into update and update_translation methods. The former is called once per save, and uses the latter as many times as required to update all translations.


  • Translation deletion URIs are no longer broken on Django 1.9 — #279.
  • REST framework translation support now uses update_fields to reduce the number of queries when updating an object.
  • REST framework translation support no longer breaks when using PrimaryKeyRelatedField and TranslationsMixin together — #278.
  • Admin no longer uses deprecated patterns function — #268.

9.6. 1.4.0

Released on November 10, 2015

Python and Django versions supported:

  • Support for Python 3.5 was added.
  • Support for Django 1.9 was added.
  • Django 1.6 is no longer officially supported.
  • Django 1.4 LTS has reached its end of life, and support will be dropped in hvad 1.5.
  • So, as a reminder, supported versions for this release are: 1.4 LTS, 1.7, 1.8 LTS, 1.9.

Compatibility Warnings:

  • As a result of the annotations fix (see below), applications that worked around annotate()‘s shortcomings on translation querysets are likely to break, as annotate() has been fixed. The workarounds should be simply removed.
  • Method FallbackQueryset.use_fallbacks() is not supported on Django 1.9 and newer (and deprecated on other versions, see below). Please use TranslationQueryset.fallbacks() instead.
  • Translated admin no longer shows objects lacking a translation, starting from Django 1.9. This behavior will be extended to all Django versions in the next release. Such objects should not happen anyway, and throw a warning when encountered.
  • Translation model building has been refactored. It is functionally equivalent to its previous implementation (it passes the exact same test suite), but code depending on the internals and inner implementation details could break.

Deprecation List:

  • Method FallbackQueryset.use_fallbacks() is now deprecated on Django 1.6 and newer. The plan is to completely drop FallbackQueryset in the near future, and let TranslationManager.untranslated() default to returning a plain Django queryset, thus enabling MyModel.objects.untranslated() to give access to all features a plain Django queryset supports.

    For queries that need fallbacks, the use_fallbacks() method has long been superseded by TranslationQueryset.fallbacks(), which is better tested, uses simpler code yet supports more features. Please update your queries accordingly.

    MyModel.objects.untranslated().use_fallbacks('en', 'ja', 'fr') should be rewritten as MyModel.objects.language('en').fallbacks('ja', 'fr'), or even MyModel.objects.language().fallbacks() to have the query use your application’s language settings automatically.


  • Annotations added to a TranslationQueryset using the annotate() method no longer end up on the translation cache with a master__ prefix.
  • Specifying translation fields in unique_together on translatable models no longer causes Django to generate incorrect migrations. — #260.
  • When no Meta options are set on a TranslatableModelForm, the auto-created one now correctly inherits that of its first base class that has one set — #262.
  • Using language('all') together with values() no longer breaks — #264.

9.7. 1.3.0

Released on July 29, 2015

This release is a collection of fixes and improvements, some of which may introduce minor compatibility issues. Please make sure you fix any deprecation warnings before upgrading to avoid those issues.

Python and Django versions supported:

  • Django 1.5 is no longer officially supported.
  • Django 1.6 has reached its end of life, and support will be dropped in hvad 1.4.
  • As a reminder, Django 1.4 is still supported, so supported versions for this release are: 1.4, 1.6, 1.7, 1.8.

New Features:

  • Russian and Latvian translations are now included, thanks to Juris Malinens — #248.

Compatibility Warnings: deprecated features pending removal in 1.3 have been removed. Most notably:

  • Calling save() on an invalid form now raises an assertion exception.
  • Classes TranslatableModelBase, TranslationFallbackManager, TranslatableBaseView and method TranslationManager.using_translations() no longer exist.
  • Deprecated view methods and context modifiers now raise an assertion exception.


  • Lift Django restrictions on translated fields in Meta.unique_together and Meta.index_together#252.
  • Properly forward model validation methods to translation validation methods, so that model validation detects constraint violations on the translation as well. Fixes duplicate detection in admin for unique constraints on translations — #251.
  • Detect name clash between translated and non-translated fields — #240.
  • Validate that at least one translation is provided when deserializing objects in TranslationsMixin#256.
  • Fix handling of model edition from an admin popup in Django 1.7 and newer — #253.
  • Generate proper ORM structures for fallbacks. Avoids table relabeling breaking queries, for instance when using update() or feeding a queryset to another queryset — #250.

9.8. 1.2.2

Released on June 3, 2015


  • Properly handle language_code in Meta.unique_together and Meta.index_together#244.

9.9. 1.2.1

Released on April 29, 2015


  • Make passing the model argument to queryset’s __init__ optional. Still allow it to be passed either as a positional or named argument — #241.

9.10. 1.2.0

Released on March 19, 2015

This is a feature release, to push REST framework support onto the main package.

Python and Django versions supported:

  • Due to this version being released early, end of support for Django 1.5 has been postponed until next release.

New features:

  • Support for Django REST framework is now included. It requires REST framework version 3.1 or newer — #220.

9.11. 1.1.1

Released on March 5, 2015


  • Backwards compatibility issue in get_field implementation — #233.
  • Admin no longer breaks on models using another pk field than id#231.

9.12. 1.1.0

Released on February 17, 2015

Python and Django versions supported:

  • hvad now supports Django 1.8.
  • Django 1.5 has reached its end of life, and support will be dropped in hvad 1.2. Note however that Django 1.4 will still be supported.

New features:

  • It is now possible to use translated fields in the unique_together and index_together settings on TranslatableModel. They cannot be mixed in a single constraint though, as table-spanning indexes are not supported by SQL databases.
  • The annotate() method is now supported. Support is still basic for now: annotations may not access more than one level of relation.

Compatibility warnings:

  • Internal module hvad.fieldtranslator was no longer used, and was incompatible with Django 1.8. It has been removed.
  • Deprecated using_translations() has been removed. It can be safely replaced by language().
  • Deprecated TranslationFallbackManager has been removed. Please use manager’s untranslated() method instead.
  • Deprecated TranslatableModelBase metaclass has been removed. Since release 0.5, hvad does not trigger metaclass conflicts anymore – #188.
  • Overriding the language in QuerySet.get() and QuerySet.filter() was deprecated in release 0.5, and has now been removed. Either use the language() method to set the correct language, or specify language('all') to filter manually through get and filter#182.
  • TranslatableModel‘s Internal attribute _shared_field_names has been removed.

Deprecation list:

  • Passing unique_together or index_together as a meta option on TranslatedFields is now deprecated and will be unsupported in release 1.3. Put them in the model’s Meta instead, alongside normal fields.
  • Calling save() on an invalid TranslatableModelForm is a bad practice and breaks on regular Django forms. This is now deprecated, and relevant checks will be removed in release 1.3. Please check the form is valid before saving it.
  • Generic views in hvad.views have been refactored to follow Django generic view behaviors. As a result, several non-standard methods are now deprecated. Please replace them with their Django equivalents — check #225.

9.13. 1.0.0

Released on December 19, 2014

Python and Django versions supported:

  • Django 1.3 is no longer supported.
  • Python 2.6 is no longer supported. Though it is likely to work for the time being, it has been dropped from the tested setups.

New features:

  • TranslatableModelForm has been refactored to make its behavior more consistent. As a result, it exposes two distinct language selection modes, normal and enforce, and has a clear API for manually overriding the language — #221.
  • The new features of modelform_factory() introduced by Django 1.6 and 1.7 are now available on translatable_modelform_factory as well — #221.
  • TranslationQueryset now has a fallbacks() method when running on Django 1.6 or newer, allowing the queryset to use fallback languages while retaining all its normal functionalities – #184.
  • Passing additional select items in method extra() is now supported. — #207.
  • It is now possible to use TranslationQueryset as default queryset for translatable models. — #207.
  • A lot of tests have been added, hvad now has 100% coverage on its core modules. Miscellaneous glitches found in this process were fixed.
  • Added MySQL to tested database backends on Python 2.7.

Compatibility warnings:

  • TranslatableModelForm has been refactored to make its behavior more consistent. The core API has not changed, but edge cases are now clearly specified and some inconsistencies have disappeared, which could create issues, especially:
    • Direct use of the form class, without passing through the factory method. This used to have an unspecified behavior regarding language selection. Behavior is now well-defined. Please ensure it works the way you expect it to.


9.14. 0.5.2

Released on November 8, 2014


  • Admin does not break anymore on M2M fields on latest Django versions. — #212.
  • Related fields’s clear() method now works properly (it used to break on MySQL, and was inefficient on other engines) — #212.

9.15. 0.5.1

Released on October 24, 2014


  • Ecountering a regular (un-translatable) model in a deep select_related does not break anymore. — #206.
  • Language tabs URI are now correctly generated when changelist filters are used. — #203.
  • Admin language tab selection is no longer lost when change filters are active. — #202.

9.16. 0.5.0

Released on September 11, 2014

New features:

  • New translationformset_factory and its companion BaseTranslationFormSet allow building a formset to work on an instance’s translations. Please have at look at its detailed documentation#157.
  • Method language() now accepts the special value 'all', allowing the query to consider all translations – #181.
  • Django 1.6+’s new datetimes() method is now available on TranslationQueryset too – #175.
  • Django 1.6+’s new earliest() method is now available on TranslationQueryset.
  • Calls to language(), passing None to use the current language now defers language resolution until the query is evaluated. It can now be used in form definitions directly, for instance for passing a custom queryset to ModelChoiceField#171.
  • Similarly, use_fallbacks() can now be passed None as one of the fallbacks, and it will be replaced with current language at query evaluation time.
  • All queryset classes used by TranslationManager can now be customized thanks to the new fallback_class and default_class attributes.
  • Abstract models are now supported. The concrete class must still declare a TranslatedFields instance, but it can be empty – #180.
  • Django-hvad messages are now available in Italian – #178.
  • The Meta.ordering model setting is now supported on translatable models. It accepts both translated and shared fields – #185, #12.
  • The select_related() method is no longer limited to 1 level depth – #192.
  • The select_related() method semantics is now consistent with that of regular querysets. It supports passing None to clear the list and mutiple calls mimic Django behavior. That is: cumulative starting from Django 1.7 and substitutive before – #192.

Deprecation list:

  • The deprecated nani module was removed.
  • Method using_translations() is now deprecated. It can be safely replaced by language() with no arguments.
  • Setting NANI_TABLE_NAME_SEPARATOR was renamed to HVAD_TABLE_NAME_SEPARATOR. Using the old name will still work for now, but issue a deprecation warning, and get removed in next version.
  • CSS class nani-language-tabs in admin templates was renamed to hvad-language-tabs. Entities will bear both classes until next version.
  • Private _real_manager and _fallback_manager attributes of TranslationQueryset have been removed as the indirection served no real purpose.
  • The TranslationFallbackManager is deprecated and will be removed in next release. Please use manager’s untranslated() method instead.
  • The TranslatableModelBase metaclass is no longer necessary and will be removed in next release. hvad no longer triggers metaclass conflicts and TranslatableModelBase can be safely dropped – #188.
  • Overriding the language in QuerySet.get() and QuerySet.filter() is now deprecated. Either use the language() method to set the correct language, or specify language('all') to filter manually through get and filter#182.


  • Method latest() now works when passed no field name, properly getting the field name from the model’s Meta.get_latest_by option.
  • FallbackQueryset now leverages the better control on queries allowed in Django 1.6 and newer to use only one query to resolve fallbacks. Old behavior can be forced by adding HVAD_LEGACY_FALLBACKS = True to your settings.
  • Assigning value to translatable foreign keys through its _id field no longer results in assigned value being ignored – #193.
  • Tests were refactored to fully support PostgreSQL – #194

9.17. 0.4.1

Released on June 1, 2014


9.18. 0.4.0

Released on May 19, 2014

New Python and Django versions supported:

  • django-hvad now supports Django 1.7 running on Python 2.7, 3.3 and 3.4.
  • django-hvad now supports Django 1.6 running on Python 2.7 and 3.3.

New features:

  • TranslationManager‘s queryset class can now be overriden by setting its queryset_class attribute.
  • Proxy models can be used with django-hvad. This is a new feature, please use with caution and report any issue on github.
  • TranslatableAdmin‘s list display now has direct links to each available translation.
  • Instance’s translated fields are now available to the model’s save() method when saving a TranslatableModelForm.
  • Accessing a translated field on an untranslated instance will now raise an AttributeError with a helpful message instead of letting the exception bubble up from the ORM.
  • Method in_bulk() is now available on TranslationQueryset.

Deprecation list:

  • Catching ObjectDoesNotExist when accessing a translated field on an instance is deprecated. In case no translation is loaded and none exists in database for current language, an AttributeError is raised instead. For the transition, both are supported until next release.

Removal of the old 'nani' aliases was postponed until next release.


  • Fixed an issue where TranslatableAdmin could overwrite the wrong language while saving a form.
  • lazy_translation_getter() now tries translations in LANGUAGES order once it has failed with current language and site’s main LANGUAGE_CODE.
  • No more deprecation warnings when importing only from hvad.
  • TranslatableAdmin now generates relative URLs instead of absolute ones, enabling it to work behind reverse proxies.
  • django-hvad does not depend on the default manager being named ‘objects’ anymore.
  • Q objects now work properly with TranslationQueryset.

9.19. 0.3

New Python and Django versions supported:

  • django-hvad now supports Django 1.5 running on Python 2.6 and 2.6.

Deprecation list:

  • Dropped support for django 1.2.
  • In next release, the old ‘nani’ module will be removed.

9.20. 0.2

The package is now called ‘hvad’. Old imports should result in an import error.

Fixed django 1.4 support

Fixed a number of minor issues

9.21. 0.1.4 (Alpha)

Released on November 29, 2011

9.22. 0.1.3 (Alpha)

Released on November 8, 2011

  • A new setting was introduced to configure the table name separator, NANI_TABLE_NAME_SEPARATOR.


    If you upgrade from an earlier version, you’ll have to rename your tables yourself (the general template is appname_modelname_translation) or set NANI_TABLE_NAME_SEPARATOR to the empty string in your settings (which was the implicit default until 0.1.0)

9.23. 0.0.4 (Alpha)

9.24. 0.0.3 (Alpha)

Released on May 26, 2011.

  • Replaced our ghetto fallback querying code with a simplified version of the logic used in Bert Constantins django-polymorphic, all credit for our now better FallbackQueryset code goes to him.
  • Replaced all JSON fixtures for testing with Python fixtures, to keep tests maintainable.
  • Nicer language tabs in admin thanks to the amazing help of Angelo Dini.
  • Ability to delete translations from the admin.
  • Changed hvad.admin.TranslatableAdmin.get_language_tabs signature.
  • Removed tests from egg.
  • Fixed some tests possibly leaking client state information.
  • Fixed a critical bug in hvad.forms.TranslatableModelForm where attempting to save a translated model with a relation (FK) would cause IntegrityErrors when it’s a new instance.
  • Fixed a critical bug in hvad.models.TranslatableModelBase where certain field types on models would break the metaclass. (Many thanks to Kristian Oellegaard for the fix)
  • Fixed a bug that prevented abstract TranslatableModel subclasses with no translated fields.

9.25. 0.0.2 (Alpha)

Released on May 16, 2011.

  • Removed language code field from admin.
  • Fixed admin ‘forgetting’ selected language when editing an instance in another language than the UI language in admin.

9.26. 0.0.1 (Alpha)

Released on May 13, 2011.

  • First release, for testing purposes only.