A way to implement models with translatable content.
The translatable field of the default language has no extension, like "title" and the translations have extensions postfixes "_<two-letter language code>", like "title_la" or "title_mn". Method get_title() in this case returns the translation of the currently chosen language or the title of the default language, if the translation is not set.
The class XFieldList overrides the default list class and is used for modifying ordering and list_display settings according the chosen language. For example, when the German language is chosen, the list of translatable content objects will be ordered by German titles (not English).
*At the time when the list of field names is assigned to ordering or list_display (at the import of the model), the currently chosen language is still not known. But the language is known when ordering and list_display lists are used in contributed administration or elsewhere.*
The XFieldList returns the modified values of the passed-in list, when its methods/properties are triggered. XFieldList transforms field names ending "_" (except the ones beginning with "__", like "__str__") to appropriate translations according the currently chosen language. For example ['title_', 'content_', 'is_published'] will be changed to ['title', 'content', 'is_published'] for the English language and to ['title_lt', 'content_lt', 'is_published'] for the Lithuanian language.
*The best practice is to put XFieldList into a separate file and import it from different apps whenever needed.*
It's worth mentioning that one implementing this should also know about [Django internationalization](http://www.djangoproject.com/documentation/i18n/).
- i18n
- l10n
- translations
- multilingual
Together with my mentor, Dusty Phillips, I have developed a simple class that dynamically adds two fields to its subclasses.
This is useful in cases when a single piece of content is divided into translatable and non-translatable fields, connected by a 1-to-many relationship.
## Update 2009/03/30
Since its inception, this snippet has grown into a significantly more powerful solution for translatable content (I use it myself with great joy :). The project is now hosted on github:
[project page](http://github.com/foxbunny/django-i18n-model/tree/master)
## Update 2008/07/09
It is now possible to define `i18n_common_model` attribute in `class Meta` section. Here's an example:
class Meta:
i18n_common_model = "MyCommonModel"
As you can see, it has to be a string, not the real class, and it is case-sensitive.
## Example
class Article(models.Model):
author = models.CharField(max_length = 40)
class Admin:
pass
class ArticleI18N(I18NModel):
title = models.CharField(max_length = 120)
body = models.TextField()
class Admin:
pass
# optionally, you can specify the base class
# if it doesn't follow the naming convention:
#
# class Meta:
# i18m_common_model = "Article"
When the ArticleI18N class is created, it automatically gains two new fields. `lang` field is a CharField with choices limited to either `settings.LANGUAGES` or `django.conf.global_settings.LANGUAGES`. The other field is `i18n_common` field which is a ForeignKey to Article model.
## The conventions
* call the translation model `SomeBaseModelI18N`, and the non-translation model SomeBaseModel (i.e., the translation model is called basename+"I18N")
* the first convention can be overriden by specifying the base model name using the `i18n_common_model` attribute in `Meta` section of the `I18N` model
* I18N model is a subclass of `I18NModel` class
## Original blog post
[http://blog.papa-studio.com/2008/07/04/metaclasses-and-translations/](http://blog.papa-studio.com/2008/07/04/metaclasses-and-translations/)
- models
- i18n
- metaclass
- translated-content