Execute the following steps to prepare for multilingual models:
- In the core app, create model_fields.py with the following content:
# myproject/apps/core/model_fields.py
from django.conf import settings
from django.utils.translation import get_language
from django.utils import translation
class TranslatedField(object):
def __init__(self, field_name):
self.field_name = field_name
def __get__(self, instance, owner):
lang_code = translation.get_language()
if lang_code == settings.LANGUAGE_CODE:
# The fields of the default language are in the main
model
return getattr(instance, self.field_name)
else:
# The fields of the other languages are in the
translation
# model, but falls back to the main model
translations = instance.translations.filter(
language=lang_code,
).first() or instance
return getattr(translations, self.field_name)
- Add the admin.py file to the core app with the following content:
# myproject/apps/core/admin.py
from django import forms
from django.conf import settings
from django.utils.translation import gettext_lazy as _
class LanguageChoicesForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
LANGUAGES_EXCEPT_THE_DEFAULT = [
(lang_code, lang_name)
for lang_code, lang_name in settings.LANGUAGES
if lang_code != settings.LANGUAGE_CODE
]
super().__init__(*args, **kwargs)
self.fields["language"] = forms.ChoiceField(
label=_("Language"),
choices=LANGUAGES_EXCEPT_THE_DEFAULT,
required=True,
)
Now let's implement the multilingual models:
- First, set multiple languages in the settings for your project. Let's say, our website will support all official languages of European Union with English being the default language:
# myproject/settings/_base.py
LANGUAGE_CODE = "en"
# All official languages of European Union
LANGUAGES = [
("bg", "Bulgarian"), ("hr", "Croatian"),
("cs", "Czech"), ("da", "Danish"),
("nl", "Dutch"), ("en", "English"),
("et", "Estonian"), ("fi", "Finnish"),
("fr", "French"), ("de", "German"),
("el", "Greek"), ("hu", "Hungarian"),
("ga", "Irish"), ("it", "Italian"),
("lv", "Latvian"), ("lt", "Lithuanian"),
("mt", "Maltese"), ("pl", "Polish"),
("pt", "Portuguese"), ("ro", "Romanian"),
("sk", "Slovak"), ("sl", "Slovene"),
("es", "Spanish"), ("sv", "Swedish"),
]
- Then, let's create the Idea and IdeaTranslations models:
# myproject/apps/ideas/models.py
from django.db import models
from django.conf import settings
from django.utils.translation import gettext_lazy as _
from myproject.apps.core.model_fields import TranslatedField
class Idea(models.Model):
title = models.CharField(
_("Title"),
max_length=200,
)
content = models.TextField(
_("Content"),
)
translated_title = TranslatedField("title")
translated_content = TranslatedField("content")
class Meta:
verbose_name = _("Idea")
verbose_name_plural = _("Ideas")
def __str__(self):
return self.title
class IdeaTranslations(models.Model):
idea = models.ForeignKey(
Idea,
verbose_name=_("Idea"),
on_delete=models.CASCADE,
related_name="translations",
)
language = models.CharField(_("Language"), max_length=7)
title = models.CharField(
_("Title"),
max_length=200,
)
content = models.TextField(
_("Content"),
)
class Meta:
verbose_name = _("Idea Translations")
verbose_name_plural = _("Idea Translations")
ordering = ["language"]
unique_together = [["idea", "language"]]
def __str__(self):
return self.title
- Last, create the admin.py for the ideas app as follows:
# myproject/apps/ideas/admin.py
from django.contrib import admin
from django.utils.translation import gettext_lazy as _
from myproject.apps.core.admin import LanguageChoicesForm
from .models import Idea, IdeaTranslations
class IdeaTranslationsForm(LanguageChoicesForm):
class Meta:
model = IdeaTranslations
fields = "__all__"
class IdeaTranslationsInline(admin.StackedInline):
form = IdeaTranslationsForm
model = IdeaTranslations
extra = 0
@admin.register(Idea)
class IdeaAdmin(admin.ModelAdmin):
inlines = [IdeaTranslationsInline]
fieldsets = [
(_("Title and Content"), {
"fields": ["title", "content"]
}),
]