Package: django-parler
django-parlerSimple Django model translations without nasty hacks.Features:Nice admin integration.Access translated attributes like regular attributes.Automatic fallback to the default language.Separate table for translated fields, compatible withdjango-hvad.Plays nice with others, compatible withdjango-polymorphic,django-mpttand such:No ORM query hacks.Easy to combine with custom Manager or QuerySet classes.Easy to construct the translations model manually when needed.See thedocumentationfor more details.A brief overviewInstalling django-parlerThe package can be installed using:pipinstalldjango-parlerAdd the following settings:INSTALLED_APPS+=('parler',)Optionally, the admin tabs can be configured too:PARLER_LANGUAGES={None:({'code':'en',},{'code':'en-us',},{'code':'it',},{'code':'nl',},),'default':{'fallback':'en',# defaults to PARLER_DEFAULT_LANGUAGE_CODE'hide_untranslated':False,# the default; let .active_translations() return fallbacks too.}}ReplaceNonewith theSITE_IDwhen you run a multi-site project with the sites framework.
EachSITE_IDcan be added as additional entry in the dictionary.Make sure your project is configured for multiple languages.
It might be useful to limit theLANGUAGESsetting. For example:fromdjango.utils.translationimportgettext_lazyas_LANGUAGE_CODE='en'LANGUAGES=(('en',_("English")),('en-us',_("US English")),('it',_('Italian')),('nl',_('Dutch')),('fr',_('French')),('es',_('Spanish')),)By default, the fallback language is the same asLANGUAGE_CODE.
The fallback language can be changed in the settings:PARLER_DEFAULT_LANGUAGE_CODE='en'Creating modelsUsing theTranslatedFieldswrapper, model fields can be marked as translatable:fromdjango.dbimportmodelsfromparler.modelsimportTranslatableModel,TranslatedFieldsclassMyModel(TranslatableModel):translations=TranslatedFields(title=models.CharField(_("Title"),max_length=200))def__unicode__(self):returnself.titleAccessing fieldsTranslatable fields can be used like regular fields:>>>object=MyModel.objects.all()[0]>>>object.get_current_language()'en'>>>object.titleu'cheese omelet'>>>object.set_current_language('fr')# Only switches>>>object.title="omelette du fromage"# Translation is created on demand.>>>object.save()Internally, django-parler stores the translated fields in a separate model, with one row per language.Filtering translationsTo query translated fields, use the.translated()method:MyObject.objects.translated(title='cheese omelet')To access objects in both the current and possibly the fallback language, use:MyObject.objects.active_translations(title='cheese omelet')This returns objects in the languages which are considered “active”, which are:The current languageThe fallback language whenhide_untranslated=Falsein thePARLER_LANGUAGESsetting.Changing the languageThe queryset can be instructed to return objects in a specific language:>>>objects=MyModel.objects.language('fr').all()>>>objects[0].titleu'omelette du fromage'This only sets the language of the object.
By default, the current Django language is used.Useobject.get_current_language()andobject.set_current_language()to change the language on individual objects.
There is a context manager to do this temporary:fromparler.utils.contextimportswitch_languagewithswitch_language(model,'fr'):printmodel.titleAnd a function to query just a specific field:model.safe_translation_getter('title',language_code='fr')Advanced FeaturesThis package also includes:Creating theTranslatedFieldsModelmanually!Form classes for inline support.View classes for switching languages, creating/updating translatable objects.Template tags for language switching-buttons.ORM methods to handle the translated fields.Admin inlines support.See thedocumentationfor more details.Special notesUsingModelAdmin.prepopulated_fieldsdoesn’t work, but you can useget_prepopulated_fields()as workaround.Due toORM restrictionsqueries for translated fields should be performed in a single.translated(..)or.active_translations(..)call.The.active_translations(..)method typically needs to.distinct()call to avoid duplicate results of the same object.TODOThe list code currently performs one query per object. This needs to be reduced.Preferably, theTranslatedFieldproxy on the model should behave like aRelatedField,
if that would nicely with the ORM too.Please contribute your improvements or work on these area’s!ContributingThis module is designed to be generic. In case there is anything you didn’t like about it,
or think it’s not flexible enough, please let us know. We’d love to improve it!If you have any other valuable contribution, suggestion or idea,
please let us know as well because we will look into it.
Pull requests are welcome too. :-)