Guide des Traductions
Documentation complète du système de traduction multilingue du CMS EUROMA.
Modèle Dictionnaire
Stocke toutes les traductions avec ContentType générique
Modèle Language
Définit les langues disponibles sur le site
TranslatableMixin
Mixin pour rendre n'importe quel modèle traduisible
Comment ça marche ?
Le contenu original est stocké en français dans les modèles.
Les traductions sont stockées séparément dans la table Dictionnaire.
Quand un utilisateur change de langue, le système charge automatiquement les traductions correspondantes.
Architecture
traduction/ ├── models.py # Language, Dictionnaire ├── registry.py # TRANSLATABLE_MODELS ├── helpers.py # TranslatableMixin, prefetch_translations() ├── middleware.py # LanguageMiddleware ├── admin_mixins.py # TranslatableAdminMixin ├── templatetags/ │ └── traduction_tags.py # translate, trans_text, etc. └── context_processors.py # current_language_code
Middleware
LanguageMiddleware intercepte chaque requête et :
- Détecte le paramètre
?lang=xx - Stocke la langue en session
- Ajoute
request.current_language_code
Registry
TRANSLATABLE_MODELS définit les champs traduisibles :
'news.newsarticle': [
'title',
'content',
],
Modèles traduisibles
Application Core
| Modèle | Champs traduisibles |
|---|---|
CarouselSlide |
title, subtitle, button_text |
ProgramStatistic |
label, description |
Partner |
name, description |
Application CMS
| Modèle | Champs traduisibles |
|---|---|
Page |
title, description |
Section |
title, description |
MenuItem |
title |
Setting |
value |
PageSectionFieldValue |
text_value |
Application News
| Modèle | Champs traduisibles |
|---|---|
NewsCategory |
name, description |
NewsArticle |
title, content, meta_description |
EventType |
name, description |
Event |
title, short_description, description, location |
Application Universities
| Modèle | Champs traduisibles |
|---|---|
University |
name, short_name, description, academic_info |
Department |
name, description |
Application Team
| Modèle | Champs traduisibles |
|---|---|
Person |
bio, research_interests |
Professor |
courses_taught, awards |
PhDStudent |
thesis_title, thesis_description |
MasterStudent |
thesis_title, current_position |
Application Research
| Modèle | Champs traduisibles |
|---|---|
ResearchArea |
name, description, key_topics |
ResearchProject |
title, description, objectives, methodology, expected_outcomes |
Publication |
title, abstract |
Application Program
| Modèle | Champs traduisibles |
|---|---|
Semester |
name, description, learning_outcomes |
Course |
name, description, objectives, prerequisites |
Specialization |
name, description, career_opportunities |
FAQ |
question, answer |
Ajouter des traductions dans l'admin
Méthode 1 : Via l'onglet Traductions
Ouvrez un objet dans l'admin
Ex: Article, Menu Item, Slide
Cliquez sur l'onglet "Traductions"
En haut du formulaire
Entrez les traductions
Pour chaque champ et chaque langue
Enregistrez
Les traductions sont sauvegardées automatiquement
Exemple visuel
Astuce
Pour les sections CMS, utilisez le Gestionnaire de sections (Admin > CMS > Gestionnaire de sections) qui offre une interface plus pratique avec les champs de traduction intégrés.
Utilisation dans les templates
Méthode 1 : Accès direct
Quand les objets sont chargés via le context processor, les champs contiennent déjà les valeurs traduites :
{# Les valeurs sont déjà traduites automatiquement #}
{{ article.title }}
{{ slide.subtitle }}
{{ menu_item.title }}
{{ event.description }}
Méthode 2 : Filtre |translate
Pour les cas où l'objet n'a pas été pré-traduit :
{% load traduction_tags %}
{{ article|translate:'title' }}
{{ category|translate:'name' }}
{{ person|translate:'bio' }}
Méthode 3 : Textes statiques
Pour traduire des textes codés en dur dans les templates :
{% load traduction_tags %}
{% trans_text 'Accueil' 'Home' 'Startseite' %}
{% trans_text 'Lire la suite' 'Read more' 'Weiterlesen' %}
{% trans_text 'Contactez-nous' 'Contact us' 'Kontaktieren Sie uns' %}
{# Format: {% trans_text 'FR' 'EN' 'DE' %} #}
Variables de contexte disponibles
{# Langue courante #}
{{ current_language_code }} {# ex: 'en' #}
{{ current_language }} {# objet Language complet #}
{{ current_language.name }} {# ex: 'English' #}
{# Toutes les langues actives #}
{% for lang in available_languages %}
{{ lang.code }} - {{ lang.name }}
{% endfor %}
Sélecteur de langue
{% load traduction_tags %}
{# Sélecteur complet (inclusion tag) #}
{% language_selector %}
{# Ou manuellement #}
{% get_languages as languages %}
{% for lang in languages %}
{{ lang.name }}
{% endfor %}
Utilisation en Python
Pré-charger les traductions
Méthode optimisée pour charger les traductions d'une liste d'objets en une seule requête :
from traduction.helpers import prefetch_translations
# Charger les articles
articles = list(NewsArticle.objects.filter(is_published=True)[:10])
# Appliquer les traductions (modifie les objets en place)
prefetch_translations(articles, language_code='en')
# Maintenant article.title contient la version anglaise
for article in articles:
print(article.title) # Affiche le titre en anglais
Récupérer une traduction unique
from traduction.helpers import get_translated_value
# Récupérer la traduction d'un champ spécifique
title_en = get_translated_value(article, 'title', language_code='en')
title_de = get_translated_value(article, 'title', language_code='de')
# Avec fallback automatique si traduction inexistante
title = get_translated_value(article, 'title', language_code='en', fallback=True)
Définir une traduction
from traduction.models import Dictionnaire, Language
# Récupérer la langue
english = Language.objects.get(code='en')
# Définir/mettre à jour la traduction
Dictionnaire.set_translation(
obj=article,
field='title',
language=english,
translation='My Article Title in English'
)
# La méthode crée ou met à jour automatiquement
Dans une vue (Class-Based View)
from django.views.generic import ListView
from traduction.helpers import TranslatedViewMixin, prefetch_translations
class ArticleListView(TranslatedViewMixin, ListView):
model = NewsArticle
template_name = 'news/list.html'
translate_fields = ['title', 'content']
def get_queryset(self):
queryset = NewsArticle.objects.filter(is_published=True)
# translate_queryset applique automatiquement les traductions
return self.translate_queryset(queryset)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
lang_code = self.get_current_language_code()
# Traduire d'autres objets manuellement
categories = list(NewsCategory.objects.all())
prefetch_translations(categories, language_code=lang_code)
context['categories'] = categories
return context
Utiliser TranslatableMixin sur un modèle
# Dans le modèle avec TranslatableMixin
article = NewsArticle.objects.get(pk=1)
# Méthode get_translated() du mixin
title = article.get_translated('title') # Langue par défaut
title_en = article.get_translated('title', language_code='en')
# Vérifier si une traduction existe
has_en = article.has_translation('title', language_code='en')
Rendre un nouveau modèle traduisible
Ajouter le mixin au modèle
# myapp/models.py
from django.db import models
from traduction.helpers import TranslatableMixin
class Product(TranslatableMixin, models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
# name et description seront traduisibles
# price ne sera pas traduit (nombre)
Enregistrer dans le registre
# traduction/registry.py
TRANSLATABLE_MODELS = {
# ... autres modèles existants ...
'myapp.product': [
'name',
'description',
],
}
Configurer l'admin
# myapp/admin.py
from django.contrib import admin
from traduction.admin_mixins import TranslatableAdminMixin
from .models import Product
@admin.register(Product)
class ProductAdmin(TranslatableAdminMixin, admin.ModelAdmin):
list_display = ['name', 'price']
search_fields = ['name', 'description']
# L'onglet "Traductions" apparaîtra automatiquement
Appliquer les traductions (vue ou context processor)
# Dans un context processor ou une vue
from traduction.helpers import prefetch_translations
def get_products(language_code):
products = list(Product.objects.filter(is_active=True))
prefetch_translations(products, language_code=language_code)
return products
# Dans le template, {{ product.name }} affichera le nom traduit
C'est tout !
Votre modèle est maintenant traduisible. Vous pouvez ajouter des traductions via l'interface admin et elles seront automatiquement chargées selon la langue de l'utilisateur.
Fonctionnement technique
Flux de traduction
1. Utilisateur clique sur "English" ou ?lang=en ↓ 2. LanguageMiddleware détecte et stocke en session ↓ 3. request.current_language_code = 'en' ↓ 4. Context processor charge les données ↓ 5. prefetch_translations() récupère les traductions ↓ 6. Les champs des objets sont remplacés par les traductions ↓ 7. Template affiche {{ object.field }} → valeur traduite
Structure de la table Dictionnaire
CREATE TABLE traduction_dictionnaire (
id INT PRIMARY KEY AUTO_INCREMENT,
content_type_id INT NOT NULL, -- FK vers ContentType (ex: 'news.newsarticle')
object_id INT NOT NULL, -- ID de l'objet traduit
field VARCHAR(100), -- Nom du champ (ex: 'title')
language_id INT NOT NULL, -- FK vers Language
translation TEXT, -- Le texte traduit
created_at DATETIME,
updated_at DATETIME,
UNIQUE KEY unique_translation (content_type_id, object_id, field, language_id)
);
Exemple de données
| content_type | object_id | field | language | translation |
|---|---|---|---|---|
| newsarticle | 1 | title | en | My First Article |
| newsarticle | 1 | title | de | Mein erster Artikel |
| newsarticle | 1 | content | en | Article content in English... |
| menuitem | 5 | title | en | Home |
| menuitem | 5 | title | de | Startseite |
Dépannage
Les traductions ne s'affichent pas
1. Vérifier que la traduction existe
from traduction.models import Dictionnaire
from django.contrib.contenttypes.models import ContentType
from news.models import NewsArticle
ct = ContentType.objects.get_for_model(NewsArticle)
article = NewsArticle.objects.get(pk=1)
translations = Dictionnaire.objects.filter(
content_type=ct,
object_id=article.pk
)
for t in translations:
print(f"{t.field} ({t.language.code}): {t.translation[:50]}")
2. Vérifier la langue courante
# Dans une vue ou template
print(request.current_language_code) # Devrait afficher 'en', 'de', etc.
3. Vider le cache
python manage.py shell -c "from django.core.cache import cache; cache.clear()"
Les menus ne sont pas traduits
Assurez-vous d'utiliser le tag {% get_menu %} qui applique automatiquement les traductions :
{% load cms_tags %}
{# ✅ Correct - utilise get_menu #}
{% get_menu 'front-menu' as nav_menu %}
{% for item in nav_menu.get_root_items %}
{{ item.title }} {# Traduit automatiquement #}
{% endfor %}
{# ❌ Incorrect - accès direct sans traduction #}
{% for item in menu.items.all %}
{{ item.title }} {# NON traduit #}
{% endfor %}
Performance : Éviter les requêtes N+1
❌ Mauvais (N+1 requêtes)
for article in articles:
# Fait une requête par article !
title = get_translated_value(
article, 'title', 'en'
)
✅ Bon (2 requêtes max)
# Une seule requête pour toutes les traductions
prefetch_translations(articles, language_code='en')
for article in articles:
title = article.title # Déjà traduit
Fallback automatique
Si une traduction n'existe pas pour la langue demandée, le système retourne automatiquement la valeur originale (français). Ce n'est pas une erreur.
Commandes utiles
# Vider le cache des traductions
python manage.py shell -c "from django.core.cache import cache; cache.clear()"
# Lister les traductions d'un modèle
python manage.py shell -c "
from traduction.models import Dictionnaire
from django.contrib.contenttypes.models import ContentType
from cms.models import MenuItem
ct = ContentType.objects.get_for_model(MenuItem)
for t in Dictionnaire.objects.filter(content_type=ct):
print(f'{t.object_id} | {t.field} | {t.language.code} | {t.translation[:50]}')"
# Vérifier les langues actives
python manage.py shell -c "
from traduction.models import Language
for lang in Language.objects.filter(is_active=True):
print(f'{lang.code} - {lang.name} (default: {lang.is_default})')"
# Compter les traductions par langue
python manage.py shell -c "
from traduction.models import Dictionnaire
from django.db.models import Count
stats = Dictionnaire.objects.values('language__code').annotate(count=Count('id'))
for s in stats:
print(f\"{s['language__code']}: {s['count']} traductions\")"
Résumé rapide
| Action | Code / Méthode |
|---|---|
| Traduire dans template | {{ obj.field }} (si prefetch) ou {{ obj|translate:'field' }} |
| Texte statique | {% trans_text 'FR' 'EN' 'DE' %} |
| Charger menu traduit | {% get_menu 'slug' as menu %} |
| Pré-charger traductions | prefetch_translations(objects, language_code='en') |
| Définir traduction | Dictionnaire.set_translation(obj, 'field', lang, 'text') |
| Langue courante (Python) | request.current_language_code |
| Langue courante (Template) | {{ current_language_code }} |
| Changer langue | ?lang=en dans l'URL |