# Django: het verschil tussen gettext en gettext_lazy afklaring (evaluatiepunt begrijpen) Wanneer je Django i18n gebruikt, schommelt je vaak tussen `gettext()` en `gettext_lazy()` door. De meeste verwarring ontstaat doordat je probeert de "verschillen" als termen te onthouden. Het kernpunt is simpel. * **`gettext` vertaalt nu (direct evalueren, eager)** * **`gettext_lazy` vertaalt later (lazy evaluatie, lazy)** Met dit ene evaluatiepunt kun je bijna alle gevallen ordenen. --- ## Waarom bepaalt het "wanneer" vertalen belangrijk? {#sec-cd5e4068943f} Django verandert meestal de taal per verzoek (request). ![Vergelijking van vertaalmomenten in Django](/media/editor_temp/6/29f9dbe8-44b7-47ed-bef6-4cc0cc62bb79.png) * Middleware kijkt naar het verzoek en activeert `activate("ko")` / `activate("en")` om de huidige thread/context-taal te activeren. * Bij het renderen van templates, formulieren of admin-schermen moet de vertaling in die taal plaatsvinden. Met andere woorden, **het moment waarop je een string vertaalt** bepaalt het resultaat. --- ## `gettext()` : "nu" vertalen en een string teruggeven {#sec-9ff53b7dc3ad} ```python from django.utils.translation import gettext as _ def view(request): message = _("Welcome") # vertaald op het moment dat deze regel wordt uitgevoerd return HttpResponse(message) ``` * Wordt aangeroepen binnen een functie/view (runtime) werkt het meestal zoals verwacht. * Wordt echter aangeroepen op module-importtijd, kan het problemen veroorzaken. ### Veelgemaakte valkuil: `gettext()` gebruiken in module-constanten {#sec-7c331db329fb} ```python # app/constants.py from django.utils.translation import gettext as _ WELCOME = _("Welcome") # ❌ kan vast blijven op de taal van de serverstart/import ``` In dit geval blijft `WELCOME` een vaste vertaalde string, zelfs als de taal later verandert (vooral in omgevingen waar import slechts één keer gebeurt). --- ## `gettext_lazy()` : een proxy die later vertaald wordt {#sec-a90df9111315} ```python from django.utils.translation import gettext_lazy as _ WELCOME = _("Welcome") # ✅ een object dat pas vertaald wordt wanneer nodig ``` `gettext_lazy()` levert meestal een "lazy object (proxy)". * Bij het renderen van formulieren/templates/admin wordt het vertaald. * Het gebeurt op het moment dat de string als tekst wordt gerenderd. > Samenvatting: **In plekken waar de taal bij het renderen wordt bepaald, is lazy vaak de juiste keuze.** --- ## Praktische regels: waar wat gebruiken? {#sec-4a8a3cbed930} ### 1) "Maak nu een scherm/antwoord" → `gettext` {#sec-197c23c83765} * In views of service-logica die direct een string maken voor een antwoord of log. ```python from django.utils.translation import gettext as _ def signup_done(request): return JsonResponse({"message": _("Signup completed.")}) ``` ### 2) "Definitie die bij import geëvalueerd kan worden" → `gettext_lazy` {#sec-b545464ef5b7} * `verbose_name`, `help_text` van modellen * `label`, `help_text` van formuliervelden * `label` van DRF serializer velden (vergelijkbare reden) * Beschrijvingen in admin `list_display` (definitie vooraf, render later) ```python from django.db import models from django.utils.translation import gettext_lazy as _ class Article(models.Model): title = models.CharField(_("title"), max_length=100) status = models.CharField( _("status"), max_length=20, choices=[ ("draft", _("Draft")), ("published", _("Published")), ], help_text=_("Visibility of the article."), ) ``` ### 3) "Module‑niveau constant/choices" → meestal `gettext_lazy` {#sec-9ea28af08fa3} * **Herbruikbare constanten** zijn het veiligst als lazy. ```python from django.utils.translation import gettext_lazy as _ STATUS_CHOICES = [ ("draft", _("Draft")), ("published", _("Published")), ] ``` ### 4) "String naar externe systemen (log, derde‑partij API, header, etc.)" → `gettext` of force-evaluatie van lazy {#sec-f04525bb1d99} * Een lazy object rechtstreeks doorgeven kan onverwachte types/serialisatieproblemen veroorzaken. ```python from django.utils.translation import gettext_lazy as _ from django.utils.encoding import force_str msg = _("Welcome") logger.info(force_str(msg)) # ✅ converteert naar echte string ``` ### 5) "String samenvoegen/formatteren" → overweeg speciale lazy‑hulpmiddelen {#sec-67d42a88924b} * Het mengen van lazy berichten met f‑strings of `str.format()` kan het evaluatiepunt verwarren. Django biedt `format_lazy` voor dit doel. ```python from django.utils.translation import gettext_lazy as _ from django.utils.text import format_lazy title = format_lazy("{}: {}", _("Error"), _("Invalid token")) ``` Of gebruik de oude `%`‑formattering voor eenvoudiger beheer. ```python from django.utils.translation import gettext as _ message = _("Hello, %(name)s!") % {"name": user.username} ``` --- ## De drie meest voorkomende fouten {#sec-273d53d27224} ### Fout 1) `gettext()` gebruiken bij module‑import → vaste vertaling {#sec-7f4b5a25d9d0} * Bij constanten/choices overweeg altijd lazy. ### Fout 2) Lazy object rechtstreeks in JSON/ log plaatsen {#sec-7a741de5c1d8} * Converteer eerst met `force_str()`. ### Fout 3) f‑string gebruiken om een vertaalde string te bouwen {#sec-76316b53a754} ```python # ❌ niet aanbevolen _("Hello") + f" {user.username}" ``` * De vertaalde eenheid wordt opgesplitst (taal‑specifieke woordvolgorde) en het evaluatiepunt wordt complexer. * **Gebruik variabele vervanging binnen de vertaalde string**. ```python # ✅ aanbevolen _("Hello, %(name)s!") % {"name": user.username} ``` --- ## Tips om verwarring te verminderen {#sec-79205bb8a9a7} De meest effectieve manier om verwarring te verminderen is om de betekenis van `_` te uniformeren per bestandstype. * In `models.py`, `forms.py`, `admin.py` (definitie eerst): `from django.utils.translation import gettext_lazy as _` * In `views.py`, `services.py` (uitvoering eerst): `from django.utils.translation import gettext as _` Op deze manier ontstaat een basisregel: **"Hier is lazy de standaard"**, waardoor fouten afnemen. --- ## Samenvatting {#sec-3aa43e207283} * **Directe evaluatie veilig bij runtime‑logica**: `gettext` * **Later gerenderd (definitie/metadata/constanten/labels)**: `gettext_lazy` * **Extern naar buiten**: gebruik `force_str` indien nodig * **Lazy + format**: `format_lazy` of variabele vervanging binnen de vertaalde string Met deze richtlijnen kun je de verwarring rond gettext en gettext_lazy minimaliseren en automatisch de juiste keuze maken. --- **Gerelateerde artikelen** - [Problemen bij het gebruik van gettext_lazy als JSON‑sleutel en oplossingen](/ko/whitedec/2025/4/26/gettext-lazy-json-key-problem-solution/)