FunctiesPluginPrijzenBronnen
Taal wijzigen
BronnenHoe Drupal .po-bestanden te vertalen met AI

Hoe Drupal .po-bestanden te vertalen met AI

SimplePoTranslate Team6 juni 2026
Hoe Drupal .po-bestanden te vertalen met AI

De meeste mensen associëren .po-bestanden met WordPress, maar het gettext-formaat is tientallen jaren ouder dan WordPress en drijft interfacevertalingen aan in de hele open-sourcewereld. Drupal is een van de grootste gebruikers ervan. Als je een meertalige Drupal-site beheert, loopt elk menulabel, veldbeschrijving, foutmelding en module-string via .po-bestanden, precies zoals in WordPress, alleen met een ander placeholder-dialect en een andere importworkflow. En net als bij WordPress, zodra je site meer dan een handvol strings omvat, wordt het handmatig vertalen van die bestanden de bottleneck.

Deze gids gaat over hoe je Drupal .po-bestanden met AI vertaalt zonder de dingen kapot te maken die Drupal Drupal maken. We behandelen Drupal's vertaalsysteem, waar de strings vandaan komen, de placeholder-syntax die verschilt van WordPress en absoluut moet worden behouden, en de volledige export-, vertaal- en re-importlus inclusief de drush-commando's die het herhaalbaar maken.

Hoe Drupal's vertaalsysteem werkt

Drupal beheert interfacevertalingen via de kern locale-module (soms ook wel "Interface Translation" genoemd in modern Drupal). Eenmaal ingeschakeld beheert het een databasetabel met bronstrings en hun vertalingen per taal, en het kan die vertalingen importeren en exporteren als standaard gettext .po-bestanden.

De admin-interface bevindt zich op /admin/config/regional/translate. Van daaruit kun je onvertaalde strings zoeken, ze inline bewerken en, cruciaal, een .po-bestand importeren om vertalingen in bulk te laden of de huidige staat exporteren naar een .po-bestand voor offline bewerking. Die export/bewerk/import-cyclus is de workflow die we optimaliseren.

In tegenstelling tot WordPress, waar elke plugin en thema zijn eigen .po- en .mo-bestanden in een languages/-directory levert, centraliseert Drupal interfacestrings in zijn database en behandelt het .po als het uitwisselingsformaat. Je exporteert, werkt aan het bestand en importeert het terug. De gecompileerde .mo-stap die WordPress vereist, wordt intern afgehandeld.

Waar de strings vandaan komen

Drupal-strings zijn afkomstig van drie plaatsen, en een complete vertaling moet ze allemaal bestrijken:

  • Core levert duizenden vertaalbare strings voor de admin-UI, formulieren en systeemberichten.
  • Contrib modules (Views, Webform, Commerce, en de rest) registreren elk hun eigen strings via de t()-functie.
  • Themes dragen template-strings, regio-labels en themainstellingsbeschrijvingen bij.

Wanneer je exporteert vanuit /admin/config/regional/translate, kun je de export richten op vertaalde, onvertaalde of alle strings. Voor een nieuwe vertaalronde levert het exporteren van alleen onvertaalde strings een gericht .po-bestand op met precies het werk dat nog gedaan moet worden.

Een praktisch gevolg van deze drievoudige bronstructuur: je vertaalwerk is nooit echt "klaar". Elke keer dat je een contrib-module toevoegt, een nieuwe functie inschakelt of Drupal core bijwerkt, verschijnt er een nieuwe reeks onvertaalde msgid-vermeldingen in de locale-tabellen. Daarom behandelen Drupal-teams vertaling als een terugkerende pijplijn in plaats van een eenmalige lanceringstaak. Dezelfde export-, vertaal- en re-importlus draait bij elke deployment die modules aanraakt, en hoe sneller die lus is, hoe minder vertaalachterstand zich ophoopt tussen releases.

Het is ook vermeldenswaard dat Drupal automatisch door de gemeenschap bijgedragen vertalingen kan ophalen van localize.drupal.org voor core en populaire contrib-modules. Die bestrijken de gangbare strings, maar ze dekken zelden je aangepaste modules, je thema, of de projectspecifieke formulering die je site daadwerkelijk gebruikt. De kloof tussen de gemeenschapsvertaling en een volledig gelokaliseerde site is precies het werk dat een AI-ronde snel dicht.

Drupal-placeholders zijn geen WordPress-placeholders

Dit is het allerbelangrijkste om te begrijpen voordat je een Drupal .po-bestand naar een AI-vertaler stuurt: Drupal gebruikt niet de printf-stijl %s en %1$s-placeholders die WordPress domineren. De t()-functie van Drupal gebruikt drie verschillende placeholder-prefixen, elk met een ander escaping-gedrag:

  • @variable — de waarde wordt HTML-escaped, de veilige standaard voor door de gebruiker ingevoerde tekst.
  • %variable — de waarde wordt escaped en omwikkeld met <em> nadruk-markup.
  • :placeholder — gebruikt voor URL-attributen, door URL-sanitization gehaald.

Een typische Drupal-bronstring ziet er zo uit in het geëxporteerde .po-bestand:

#: core/modules/node/node.module
msgid "@count comments"
msgid_plural "@count comments"
msgstr[0] ""
msgstr[1] ""

#: core/modules/user/user.module
msgid "Welcome @name, you last logged in on %date."
msgstr ""

Als een vertaler @count wijzigt naar @cuenta, @name vervangt door het vertaalde woord voor "naam", of een spatie invoegt waardoor @count verandert in @ count, komt de placeholder niet langer overeen met wat de t()-oproep doorgeeft. Drupal print dan de letterlijke token @count op de pagina in plaats van het daadwerkelijke getal. De vertaling lijkt klaar, maar de site is zichtbaar kapot.

Dit is dezelfde klasse van bugs die WordPress %s-strings treft, en we behandelen het algemene principe uitgebreid in hoe je PO-bestanden vertaalt zonder codevariabelen te breken. De Drupal-draai is simpelweg dat er drie placeholder-stijlen zijn in plaats van één, en een vertaaltool ze allemaal moet herkennen.

Waarom generieke vertalers hier falen

Plak die node.module-string in een consumenten machinevertalingsbox en je zult vaak zien dat @count verminkt wordt, de <em>-gebonden %date gelokaliseerd wordt naar een andere token, of dat de meervoudsvormen worden samengevoegd tot één. Geen van deze tools is gebouwd met gettext-semantiek in gedachten. Ze vertalen tekst; ze begrijpen niet dat @count een contract is met de applicatiecode.

Een gettext-bewuste vertaalpijplijn met Syntax Locking behandelt @variable, %variable en :placeholder als onveranderlijke tokens. Ze worden voor vertaling vergrendeld en daarna hersteld, zodat de omringende zin wordt vertaald terwijl de placeholders onaangetast blijven. Dezelfde vergrendeling omvat WordPress %s en %1$s, i18next {{name}}, en inline HTML, vandaar dat één tool een Drupal-, Symfony- of Laravel-project net zo gemakkelijk kan bedienen als een WordPress-project. Drupal meervoudsvormen via msgid_plural worden behouden als meervoudsvormen in plaats van afgevlakt, wat belangrijk is omdat Drupal-talen overal van één tot zes meervoudsvarianten kunnen hebben.

Er is ook een subtielere faalmodus die het waard is om te benoemen. Drupal-strings bevatten vaak inline-markup en links binnen de vertaalbare tekst, zoals Lees de <a href=":url">documentatie</a> waarbij :url een placeholder is en de <a>-tags moeten blijven bestaan. Een vertaler die de structuur niet begrijpt, kan het href-attribuut vertalen, de sluitende tag weglaten of de placeholder-naam lokaliseren. Context-Aware AI die de hele string als een eenheid leest, gecombineerd met token locking, houdt zowel de markup als het :url-contract intact terwijl alleen de menselijk leesbare "documentatie"-tekst ertussenin wordt vertaald.

De export-, vertaal- en re-importlus

De herhaalbare workflow heeft drie fasen, en drush maakt de export en import scriptbaar, zodat je niet elke keer door de admin-UI hoeft te klikken.

Stap 1: Exporteer het .po-bestand

Je kunt exporteren vanuit de UI op /admin/config/regional/translate door een taal en een exportbereik te kiezen, of het vanaf de commandoregel doen. De locale-module exposeert export via Drupal's vertaaldiensten, en de meeste teams scripten dit. Een typische drush-aanroep om een vertaalimport te activeren (het omgekeerde, dat we in stap drie gebruiken) ziet er zo uit:

# Re-import a translated PO file for Spanish, overwriting customized strings
drush locale:import es /var/www/translations/es-untranslated.po \
  --type=customized --override=all

# Rebuild caches so the new strings render immediately
drush cache:rebuild

Voor de export produceert het admin-exportformulier het .po-bestand; veel teams verpakken de locale-exportservice in een klein aangepast Drush-commando voor volledige automatisering. Hoe dan ook, je eindigt met een standaard gettext .po-bestand dat je onvertaalde msgid-vermeldingen bevat.

Stap 2: Vertaal het bestand

Dit is de fase waarin AI uren handmatige bewerking vervangt. Upload het geëxporteerde .po-bestand naar een cloud-vertaler, kies je doeltaal en laat het verwerken. Omdat Drupal .po-bestanden voor een grote site routinematig meer dan 10MB beslaan zodra core, contrib en thema's gecombineerd zijn, is Slimme Batchverwerking hier van belang: het bestand wordt opgesplitst, vertaald en opnieuw samengesteld zonder dat je het handmatig hoeft te splitsen of tegen groottelimieten aanloopt. De uitvoer is een compleet .po-bestand met elke msgstr gevuld en elke @count, %date en :url placeholder precies waar het begon.

Stap 3: Re-importeer naar Drupal

Importeer het vertaalde bestand terug via /admin/config/regional/translate of via het hierboven getoonde drush locale:import-commando, en herbouw vervolgens de cache. Drupal voegt de vertalingen samen in zijn locale-tabellen, en de strings verschijnen onmiddellijk op de site. Voer de lus opnieuw uit wanneer je een module toevoegt of de core bijwerkt, aangezien elk nieuwe onvertaalde strings met zich meebrengt.

Eén importdetail om goed te doen: de --override-vlag bepaalt of inkomende vertalingen bestaande vertalingen vervangen. Gebruik --override=all wanneer je wilt dat het door AI vertaalde bestand autoritair is, of een conservatievere instelling als je bepaalde strings in de Drupal UI handmatig hebt afgestemd die je niet wilt overschrijven. Voor de meeste geautomatiseerde pijplijnen, het behandelen van het .po-bestand als de bron van waarheid en alles overschrijven, houdt het systeem voorspelbaar: het bestand in versiebeheer is wat de site toont, punt uit.

Voor meertalige sites met meerdere doeltalen, draait de lus één keer per taal. Exporteer de onvertaalde set, vertaal deze naar het Duits, importeer het; exporteer opnieuw, vertaal naar het Spaans, importeer het; enzovoort. Omdat elke taal een onafhankelijk .po-bestand is, kun je ze parallel uitvoeren, en een cloud-vertaler die ze gelijktijdig verwerkt, verandert wat vroeger een week van aannemerstijd was in een middag.

Drupal .po is een van de verschillende formaten

Het is vermeldenswaard dat gettext .po niet de enige manier is waarop Drupal vertalingen afhandelt. Configuratie- en contententiteiten kunnen ook worden uitgewisseld als XLIFF, wat de standaard is waarop de Translation Management Tool (TMGMT)-module leunt voor professionele vertaalbureausworkflows. Als je Drupal-lokalisatie via XLIFF loopt in plaats van interface .po-bestanden, zijn de principes voor het behoud van placeholders identiek, maar de bestandsstructuur verschilt, en we behandelen dat pad in XLIFF-bestanden vertalen voor Drupal, Symfony en Angular.

Voor de interface-vertaallaag blijft .po echter het werkpaard. De export-, AI-vertaal-, re-importlus verandert een meerdaagse handmatige klus in enkele minuten verwerking, en zolang de tool die je gebruikt gettext-placeholders echt begrijpt, blijven je @variable-contracten intact en blijft je Drupal-site ongeschonden in elke taal die je levert.

Klaar om je Drupal .po-bestanden te vertalen zonder een enkele @variable te breken? Probeer SimplePoTranslate gratis — geen creditcard nodig. De gratis tier verwerkt standaard gettext .po- en .pot-bestanden met volledige Syntax Locking, zodat je Drupal-placeholders exact doorgegeven worden zoals de code verwacht.