mirror of
https://github.com/Hopiu/django-modeltranslation.git
synced 2026-05-24 20:23:45 +00:00
General documentation touchups. Used wikir compatible syntax for literal blocks. Fixed internal links.
This commit is contained in:
parent
951b0699cb
commit
ab03291848
1 changed files with 127 additions and 88 deletions
|
|
@ -1,16 +1,8 @@
|
|||
.. _ref-topics-modeltranslation:
|
||||
|
||||
==================
|
||||
Modeltranslation
|
||||
==================
|
||||
|
||||
.. admonition:: About this document
|
||||
|
||||
This document provides an introduction to the modeltranslation application.
|
||||
|
||||
.. currentmodule:: modeltranslation.models
|
||||
.. moduleauthor:: Peter Eschler <peschler@googlemail.com>,
|
||||
Dirk Eschler <eschler@gmail.com>
|
||||
================
|
||||
Modeltranslation
|
||||
================
|
||||
|
||||
The modeltranslation application can be used to translate dynamic content of
|
||||
existing models to an arbitrary number of languages without having to change
|
||||
|
|
@ -23,6 +15,11 @@ models on a per-project basis. You can use the same app in different projects,
|
|||
may they use translations or not, and you never have to touch the original
|
||||
model class.
|
||||
|
||||
*Authors*
|
||||
|
||||
- Peter Eschler <peschler@googlemail.com>
|
||||
- Dirk Eschler <eschler@gmail.com>
|
||||
|
||||
.. contents::
|
||||
|
||||
|
||||
|
|
@ -66,7 +63,9 @@ The following variables have to be added to or edited in the project's
|
|||
**settings.INSTALLED_APPS**
|
||||
|
||||
Make sure that the ``modeltranslation`` app is listed in your
|
||||
``INSTALLED_APPS`` variable::
|
||||
``INSTALLED_APPS`` variable:
|
||||
|
||||
::
|
||||
|
||||
INSTALLED_APPS = (
|
||||
...
|
||||
|
|
@ -85,7 +84,9 @@ first language is treated as the *default language*.
|
|||
The modeltranslation application uses the list of languages to add localized
|
||||
fields to the models registered for translation. To use the languages ``de``
|
||||
and ``en`` in your project, set the settings.LANGUAGES variable like this
|
||||
(where ``de`` is the default language)::
|
||||
(where ``de`` is the default language):
|
||||
|
||||
::
|
||||
|
||||
gettext = lambda s: s
|
||||
LANGUAGES = (
|
||||
|
|
@ -101,6 +102,7 @@ modeltranslation app, but rather required for Django to be able to
|
|||
**settings.MODELTRANSLATION_DEFAULT_LANGUAGE**
|
||||
|
||||
*New in development version*
|
||||
|
||||
To override the default language as described in settings.LANGUAGES, define
|
||||
``MODELTRANSLATION_DEFAULT_LANGUAGE``. Note that the value has to be in
|
||||
settings.LANGUAGES, otherwise an exception will be raised.
|
||||
|
|
@ -111,10 +113,34 @@ In order to be able to import the project's ``translation.py`` registration
|
|||
file the ``MODELTRANSLATION_TRANSLATION_REGISTRY`` must be set to a value in
|
||||
the form ``<PROJECT_MODULE>.translation``. E.g. if your project is located in a
|
||||
folder named ``myproject`` the ``MODELTRANSLATION_TRANSLATION_REGISTRY`` must
|
||||
be set like this::
|
||||
be set like this:
|
||||
|
||||
::
|
||||
|
||||
MODELTRANSLATION_TRANSLATION_REGISTRY = "myproject.translation"
|
||||
|
||||
**settings.MODELTRANSLATION_CUSTOM_FIELDS**
|
||||
|
||||
*New in development version*
|
||||
|
||||
``Modeltranslation`` officially supports ``CharField`` and ``TextField``.
|
||||
|
||||
In most cases subclasses of these fields will work fine, too. Other fields
|
||||
aren't supported and will throw an ``ImproperlyConfigured`` exception.
|
||||
|
||||
The list of supported fields can be extended. Just define a tuple of field
|
||||
names in your settings.py like this:
|
||||
|
||||
::
|
||||
|
||||
MODELTRANSLATION_CUSTOM_FIELDS = ('MyField', 'MyOtherField',)
|
||||
|
||||
.. note:: This just prevents ``modeltranslation`` from throwing an
|
||||
``ImproperlyConfigured`` exception. Any non text-like field will most
|
||||
likely fail in one way or another. The feature is considered
|
||||
experimental and might be replaced by a more sophisticated mechanism
|
||||
in future versions.
|
||||
|
||||
|
||||
Registering models and their fields for translation
|
||||
---------------------------------------------------
|
||||
|
|
@ -143,12 +169,13 @@ option class must be registered with the
|
|||
|
||||
.. note:: In contrast to the Django admin application which looks for
|
||||
``admin.py`` files in the project **and** application directories,
|
||||
the modeltranslation app looks only for one ``translation.py`` file in
|
||||
the project directory.
|
||||
the modeltranslation app looks only for one ``translation.py`` file in the project directory.
|
||||
|
||||
To illustrate this let's have a look at a simple example using a ``News``
|
||||
model. The news in this example only contains a ``title`` and a ``text`` field.
|
||||
Instead of a news, this could be any Django model class::
|
||||
Instead of a news, this could be any Django model class:
|
||||
|
||||
::
|
||||
|
||||
class News(models.Model):
|
||||
title = models.CharField(max_length=255)
|
||||
|
|
@ -156,7 +183,9 @@ Instead of a news, this could be any Django model class::
|
|||
|
||||
In order to tell the ``modeltranslation`` app to translate the ``title`` and
|
||||
``text`` field, create a ``translation.py`` file in your project directory and
|
||||
add the following::
|
||||
add the following:
|
||||
|
||||
::
|
||||
|
||||
from modeltranslation.translator import translator, TranslationOptions
|
||||
from some.news.models import News
|
||||
|
|
@ -175,10 +204,13 @@ At this point you are mostly done and the model classes registered for
|
|||
translation will have been added some auto-magical fields. The next section
|
||||
explains how things are working under the hood.
|
||||
|
||||
|
||||
Changes automatically applied to the model class
|
||||
------------------------------------------------
|
||||
After registering the ``News`` model for transaltion an SQL dump of the
|
||||
News app will look like this::
|
||||
News app will look like this:
|
||||
|
||||
::
|
||||
|
||||
$ ./manage.py sqlall news
|
||||
BEGIN;
|
||||
|
|
@ -229,7 +261,9 @@ Accessing translated and translation fields
|
|||
===========================================
|
||||
The ``modeltranslation`` app changes the behaviour of the translated fields. To
|
||||
explain this consider the News example again. The original ``News`` model
|
||||
looked like this::
|
||||
looked like this:
|
||||
|
||||
::
|
||||
|
||||
class News(models.Model):
|
||||
title = models.CharField(max_length=255)
|
||||
|
|
@ -288,7 +322,9 @@ on the current language setting. "Language setting" is referring to the Django
|
|||
`set_language`_ view and the corresponding ``get_lang`` function.
|
||||
|
||||
Assuming the current language is ``de`` in the News example from above, the
|
||||
translated ``title`` field will return the value from the ``title_de`` field::
|
||||
translated ``title`` field will return the value from the ``title_de`` field:
|
||||
|
||||
::
|
||||
|
||||
# Assuming the current language is "de"
|
||||
n = News.objects.all()[0]
|
||||
|
|
@ -303,28 +339,10 @@ the ``django.utils.i18n.get_language`` function to determine the current
|
|||
language.
|
||||
|
||||
|
||||
Supported fields
|
||||
----------------
|
||||
``Modeltranslation`` officially supports CharField and TextField.
|
||||
|
||||
*New in development version*
|
||||
In most cases subclasses of these fields will work fine, too. Other fields
|
||||
aren't supported and will throw an ``ImproperlyConfigured`` exception.
|
||||
|
||||
The list of supported fields can be extended. Just define a tuple of field
|
||||
names in your settings.py like this::
|
||||
|
||||
MODELTRANSLATION_CUSTOM_FIELDS = ('MyField', 'MyOtherField',)
|
||||
|
||||
*Note:* This just prevents ``modeltranslation`` from throwing an
|
||||
``ImproperlyConfigured`` exception. Any non text-like field will most likely
|
||||
fail in one way or another. The feature is considered experimental and might be
|
||||
replaced by a more sophisticated mechanism in future versions.
|
||||
|
||||
|
||||
Set a default value
|
||||
-------------------
|
||||
*New in development version*
|
||||
|
||||
TODO
|
||||
|
||||
|
||||
|
|
@ -333,7 +351,9 @@ Django admin backend integration
|
|||
In order to be able to edit the translations via the admin backend you need to
|
||||
register a special admin class for the translated models. The admin class must
|
||||
derive from ``modeltranslation.admin.TranslationAdmin`` which does some funky
|
||||
patching on all your models registered for translation::
|
||||
patching on all your models registered for translation:
|
||||
|
||||
::
|
||||
|
||||
from django.contrib import admin
|
||||
from modeltranslation.admin import TranslationAdmin
|
||||
|
|
@ -357,21 +377,27 @@ following:
|
|||
the default translation field required instead.
|
||||
|
||||
|
||||
TranslationAdmin in combination with other admin classes
|
||||
--------------------------------------------------------
|
||||
.. _translationadmin_in_combination_with_other_admin_classes:
|
||||
|
||||
!TranslationAdmin in combination with other admin classes
|
||||
---------------------------------------------------------
|
||||
If there already exists a custom admin class for a translated model and you
|
||||
don't want or can't edit that class directly there is another solution.
|
||||
|
||||
Taken the News example let's say there is a ``NewsAdmin`` class defined by the
|
||||
News app itself. This app is not yours or you don't want to touch it at all,
|
||||
but it has this nice admin class::
|
||||
but it has this nice admin class:
|
||||
|
||||
::
|
||||
|
||||
class NewsAdmin(model.Admin):
|
||||
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||
# does some funky stuff with the formfield here
|
||||
|
||||
So a first attempt might be to create your own admin class which subclasses
|
||||
``NewsAdmin`` and ``TranslationAdmin`` to combine stuff like so::
|
||||
``NewsAdmin`` and ``TranslationAdmin`` to combine stuff like so:
|
||||
|
||||
::
|
||||
|
||||
class MyTranslatedNewsAdmin(NewsAdmin, TranslationAdmin):
|
||||
pass
|
||||
|
|
@ -382,7 +408,9 @@ Python must make a decision and it chooses the first class ``NewsAdmin``. The
|
|||
functionality from ``TranslationAdmin`` will not be executed and translation in
|
||||
the admin will not work for this class.
|
||||
|
||||
But don't panic, here's a solution::
|
||||
But don't panic, here's a solution:
|
||||
|
||||
::
|
||||
|
||||
class MyTranslatedNewsAdmin(NewsAdmin, TranslationAdmin):
|
||||
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||
|
|
@ -404,6 +432,7 @@ custom admin class and that's done in the example above. After that the
|
|||
Inlines
|
||||
-------
|
||||
*New in 0.2*
|
||||
|
||||
Support for tabular and stacked inlines, common and generic ones.
|
||||
|
||||
A translated inline must derive from one of the following classes:
|
||||
|
|
@ -420,67 +449,71 @@ patching.
|
|||
For our example we assume that there is new model called Image. It's
|
||||
definition is left out for simplicity. Our News model inlines the new model:
|
||||
|
||||
{{{
|
||||
from django.contrib import admin
|
||||
from modeltranslation.admin import TranslationTabularInline
|
||||
::
|
||||
|
||||
class ImageInline(TranslationTabularInline):
|
||||
model = Image
|
||||
from django.contrib import admin
|
||||
from modeltranslation.admin import TranslationTabularInline
|
||||
|
||||
class NewsAdmin(admin.ModelAdmin):
|
||||
list_display = ('title',)
|
||||
inlines = [ImageInline,]
|
||||
class ImageInline(TranslationTabularInline):
|
||||
model = Image
|
||||
|
||||
admin.site.register(News, NewsAdmin)
|
||||
}}}
|
||||
class NewsAdmin(admin.ModelAdmin):
|
||||
list_display = ('title',)
|
||||
inlines = [ImageInline,]
|
||||
|
||||
*Note:* In this example only the Image model is registered in translation.py.
|
||||
It's not a requirement that `NewsAdmin` derives from `TranslationAdmin` in
|
||||
order to inline a model which is registered for translation.
|
||||
admin.site.register(News, NewsAdmin)
|
||||
|
||||
.. note:: In this example only the Image model is registered in translation.py.
|
||||
It's not a requirement that `NewsAdmin` derives from
|
||||
`TranslationAdmin` in order to inline a model which is registered for
|
||||
translation.
|
||||
|
||||
In this more complex example we assume that the News and Image models are
|
||||
registered in translation.py. The News model has an own custom admin class and
|
||||
the Image model an own generic stacked inline class. It uses the technique
|
||||
described in [InstallationAndUsage#TranslationAdmin_in_combination_with_other_admin_classes TranslationAdmin in combination with other admin classes].:
|
||||
described in `TranslationAdmin in combination with other admin classes`__.:
|
||||
|
||||
{{{
|
||||
from django.contrib import admin
|
||||
from modeltranslation.admin import TranslationAdmin, TranslationGenericStackedInline
|
||||
__ translationadmin_in_combination_with_other_admin_classes_
|
||||
|
||||
class TranslatedImageInline(ImageInline, TranslationGenericStackedInline):
|
||||
model = Image
|
||||
::
|
||||
|
||||
class TranslatedNewsAdmin(NewsAdmin, TranslationAdmin):
|
||||
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||
field = super(TranslatedNewsAdmin, self).formfield_for_dbfield(db_field, **kwargs)
|
||||
self.patch_translation_field(db_field, field, **kwargs)
|
||||
return field
|
||||
from django.contrib import admin
|
||||
from modeltranslation.admin import TranslationAdmin, TranslationGenericStackedInline
|
||||
|
||||
inlines = [TranslatedImageInline,]
|
||||
class TranslatedImageInline(ImageInline, TranslationGenericStackedInline):
|
||||
model = Image
|
||||
|
||||
admin.site.register(News, NewsAdmin)
|
||||
}}}
|
||||
class TranslatedNewsAdmin(NewsAdmin, TranslationAdmin):
|
||||
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||
field = super(TranslatedNewsAdmin, self).formfield_for_dbfield(db_field, **kwargs)
|
||||
self.patch_translation_field(db_field, field, **kwargs)
|
||||
return field
|
||||
|
||||
inlines = [TranslatedImageInline,]
|
||||
|
||||
admin.site.register(News, NewsAdmin)
|
||||
|
||||
|
||||
Using tabbed translation fields
|
||||
-------------------------------
|
||||
*New in development version*
|
||||
|
||||
Modeltranslation supports separation of translation fields via jquery-ui tabs.
|
||||
The proposed way to include it is through the inner `Media` class of a
|
||||
`TranslationAdmin` class like this:
|
||||
|
||||
{{{
|
||||
class NewsAdmin(TranslationAdmin):
|
||||
class Media:
|
||||
js = (
|
||||
'/static/modeltranslation/js/force_jquery.js',
|
||||
'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js',
|
||||
'/static/modeltranslation/js/tabbed_translation_fields.js',
|
||||
)
|
||||
css = {
|
||||
'screen': ('/static/modeltranslation/css/tabbed_translation_fields.css',),
|
||||
}
|
||||
}}}
|
||||
::
|
||||
|
||||
class NewsAdmin(TranslationAdmin):
|
||||
class Media:
|
||||
js = (
|
||||
'/static/modeltranslation/js/force_jquery.js',
|
||||
'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js',
|
||||
'/static/modeltranslation/js/tabbed_translation_fields.js',
|
||||
)
|
||||
css = {
|
||||
'screen': ('/static/modeltranslation/css/tabbed_translation_fields.css',),
|
||||
}
|
||||
|
||||
The `force_jquery.js` script is necessary when using Django's built-in
|
||||
`django.jQuery` object. This and the static urls used are just an example and
|
||||
|
|
@ -499,7 +532,9 @@ Unfortunately the newly added translation fields on the model will be empty
|
|||
then, and your templates will show the translated value of the fields (see
|
||||
Rule 1 below) which will be empty in this case. To correctly initialize the
|
||||
default translation field you can use the ``update_translation_fields``
|
||||
command::
|
||||
command:
|
||||
|
||||
::
|
||||
|
||||
manage.py update_translation_fields
|
||||
|
||||
|
|
@ -517,7 +552,9 @@ populated with initial data.
|
|||
|
||||
Caveats
|
||||
=======
|
||||
Consider the following example (assuming the default lanuage is ``de``)::
|
||||
Consider the following example (assuming the default lanuage is ``de``):
|
||||
|
||||
::
|
||||
|
||||
>>> n = News.objects.create(title="foo")
|
||||
>>> n.title
|
||||
|
|
@ -531,7 +568,9 @@ normally updates the associated default translation field (``title_de``) is not
|
|||
called. Therefor the call to ``n.title_de`` returns an empty value.
|
||||
|
||||
Now assign the title, which triggers the descriptor and the default translation
|
||||
field is updated::
|
||||
field is updated:
|
||||
|
||||
::
|
||||
|
||||
>>> n.title = 'foo'
|
||||
>>> n.title_de
|
||||
|
|
|
|||
Loading…
Reference in a new issue