FunktionerPluginPriserRessourcer
Skift sprog
RessourcerSådan oversætter du Drupal .po-filer med AI

Sådan oversætter du Drupal .po-filer med AI

SimplePoTranslate Team6. juni 2026
Sådan oversætter du Drupal .po-filer med AI

De fleste forbinder .po-filer med WordPress, men gettext-formatet er årtier ældre end WordPress og driver grænsefladeoversættelse i hele open source-verdenen. Drupal er en af dets største brugere. Hvis du driver et flersproget Drupal-site, flyder alle menupunkter, feltbeskrivelser, fejlmeddelelser og modulstrenge gennem .po-filer, præcis som det gør i WordPress, blot med en anden placeholder-dialekt og en anden import-workflow. Og ligesom med WordPress, bliver manuel oversættelse af disse filer en flaskehals, så snart dit site vokser ud over en håndfuld strenge.

Denne guide handler om, hvordan du oversætter Drupal po-filer med AI uden at ødelægge det, der gør Drupal til Drupal. Vi gennemgår Drupals oversættelsessystem, hvor strengene faktisk kommer fra, den placeholder-syntaks, der adskiller sig fra WordPress og absolut skal bevares, og den fulde eksport-, oversæt- og genimport-cyklus, inklusive de drush-kommandoer, der gør den gentagelig.

Sådan fungerer Drupals oversættelsessystem

Drupal håndterer grænsefladeoversættelse via kerne-modulet locale (undertiden kaldet "Interface Translation" i moderne Drupal). Når det er aktiveret, administrerer det en databasetabel med kildestrenge og deres oversættelser pr. sprog, og det kan importere og eksportere disse oversættelser som standard gettext .po-filer.

Administratorgrænsefladen findes på /admin/config/regional/translate. Herfra kan du søge efter uoversatte strenge, redigere dem direkte og, afgørende, importere en .po-fil for at masseindlæse oversættelser eller eksportere den aktuelle tilstand til en .po-fil for offline redigering. Denne eksport-/redigerings-/importcyklus er den workflow, vi optimerer.

I modsætning til WordPress, hvor hvert plugin og tema leverer sine egne .po- og .mo-filer i en languages/-mappe, centraliserer Drupal grænsefladestrenge i sin database og behandler .po som udvekslingsformat. Du eksporterer, arbejder på filen og importerer den tilbage. Det kompilerede .mo-trin, som WordPress kræver, håndteres internt.

Hvor strengene kommer fra

Drupal-strenge stammer fra tre steder, og en komplet oversættelse skal dække dem alle:

  • Core leverer tusindvis af oversættelige strenge til admin UI, formularer og systemmeddelelser.
  • Contrib modules (Views, Webform, Commerce og resten) registrerer hver deres egne strenge via t()-funktionen.
  • Themes bidrager med skabelonstrenge, regionetiketter og beskrivelser af temaindstillinger.

Når du eksporterer fra /admin/config/regional/translate, kan du afgrænse eksporten til oversatte, uoversatte eller alle strenge. Ved en ny oversættelsesrunde giver eksport af kun uoversatte strenge dig en fokuseret .po-fil med præcis det arbejde, der mangler.

En praktisk konsekvens af denne tre-kildestruktur: dit oversættelsesarbejde er aldrig rigtig "færdigt". Hver gang du tilføjer et contrib module, aktiverer en ny funktion eller opdaterer Drupal core, vises en ny samling af uoversatte msgid-indgange i locale-tabellerne. Dette er grunden til, at Drupal-teams behandler oversættelse som en tilbagevendende pipeline snarere end en engangs-lanceringsopgave. Den samme eksport-, oversæt- og genimport-cyklus kører ved hver implementering, der rører moduler, og jo hurtigere den cyklus er, jo mindre oversættelsesgæld akkumuleres der mellem udgivelser.

Det er også værd at bemærke, at Drupal automatisk kan hente fællesskabsbidragne oversættelser fra localize.drupal.org til core og populære contrib-moduler. Disse dækker de almindelige strenge, men de dækker sjældent dine brugerdefinerede moduler, dit tema eller den projektspecifikke formulering, dit site faktisk bruger. Forskellen mellem fællesskabsoversættelsen og et fuldt lokaliseret site er præcis det arbejde, en AI-gennemgang hurtigt lukker.

Drupal-placeholdere er ikke WordPress-placeholdere

Her er den vigtigste ting at forstå, før du sender en Drupal .po-fil til en AI-oversætter: Drupal bruger ikke printf-stilens %s- og %1$s-placeholdere, der dominerer WordPress. Drupals t()-funktion bruger tre forskellige placeholder-præfikser, hver med forskellig escape-adfærd:

  • @variable — værdien er HTML-escapet, den sikre standard for brugerindtastet tekst.
  • %variable — værdien er escapet og omgivet af <em>-fremhævelse.
  • :placeholder — bruges til URL-attributter, kørt igennem URL-sanering.

En typisk Drupal-kildestreng ser sådan ud i den eksporterede .po-fil:

#: 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 ""

Hvis en oversætter ændrer @count til @cuenta, erstatter @name med det oversatte ord for "navn," eller indsætter et mellemrum, der gør @count til @ count, matcher placeholderen ikke længere det, t()-kaldet sender ind. Drupal udskriver derefter den bogstavelige token @count på siden i stedet for det faktiske nummer. Oversættelsen ser færdig ud, men sitet er synligt ødelagt.

Dette er den samme type fejl, der rammer WordPress %s-strenge, og vi dækker det generelle princip i dybden i hvordan man oversætter PO-filer uden at bryde kodevariabler. Drupal-forskellen er simpelthen, at der er tre placeholder-stilarter i stedet for én, og et oversættelsesværktøj skal genkende dem alle.

Hvorfor generiske oversættere fejler her

Indsæt den node.module-streng i en generisk maskinoversættelsesboks, og du vil ofte få @count ødelagt, den <em>-indbundne %date lokaliseret til en anden token, eller flertalsformerne kollapset til én. Ingen af disse værktøjer blev bygget med gettext-semantik i tankerne. De oversætter tekst; de forstår ikke, at @count er en kontrakt med applikationskoden.

En gettext-bevidst oversættelsespipeline med Syntax Locking behandler @variable, %variable og :placeholder som uforanderlige tokens. De låses før oversættelsen og genoprettes bagefter, så den omkringliggende sætning oversættes, mens placeholdere passerer uændret igennem. Den samme lås dækker WordPress %s og %1$s, i18next {{name}} og inline HTML, hvilket er grunden til, at et enkelt værktøj kan betjene et Drupal-, Symfony- eller Laravel-projekt lige så nemt som et WordPress-projekt. Drupal flertalsformer via msgid_plural bevares som flertalsformer snarere end udfladede, hvilket er vigtigt, fordi Drupal-sprog kan have alt fra én til seks flertalsvarianter.

Der er også en mere subtil fejltype, der er værd at nævne. Drupal-strenge indlejrer ofte inline-markup og links inde i den oversættelige tekst, f.eks. Read the <a href=":url">documentation</a>, hvor :url er en placeholder, og <a>-taggene skal overleve. En oversætter, der ikke forstår strukturen, kan oversætte href-attributten, udelade det afsluttende tag eller lokalisere placeholder-navnet. Context-Aware AI, der læser hele strengen som en enhed, kombineret med tokenlåsning, holder både markup og :url-kontrakten intakt, mens den kun oversætter den menneskelæsbare "documentation"-tekst imellem.

Eksport-, oversæt- og genimport-cyklussen

Den gentagelige workflow har tre trin, og drush gør eksport og import scriptbar, så du ikke behøver at klikke dig igennem admin UI hver gang.

Trin 1: Eksporter PO-filen

Du kan eksportere fra UI på /admin/config/regional/translate ved at vælge et sprog og et eksportomfang, eller gøre det fra kommandolinjen. locale-modulet eksponerer eksport via Drupals oversættelsestjenester, og de fleste teams scripter det. Et typisk drush-kald til at udløse en oversættelsesimport (det omvendte, som vi bruger i trin tre) ser sådan ud:

# 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

Hvad eksportsiden angår, producerer admin-eksportformularen .po-filen; mange teams pakker locale-eksporttjenesten ind i en lille brugerdefineret Drush-kommando for fuld automatisering. Uanset hvad ender du med en standard gettext .po-fil, der indeholder dine uoversatte msgid-indgange.

Trin 2: Oversæt filen

Dette er det trin, hvor AI erstatter timer med manuel redigering. Upload den eksporterede .po-fil til en skybaseret oversætter, vælg dit målsprog, og lad den behandle. Fordi Drupal .po-filer til et stort site rutinemæssigt overstiger 10MB, når core, contrib og temaer er kombineret, er Smart Batching vigtigt her: filen deles i bidder, oversættes og samles igen, uden at du manuelt splitter den eller rammer størrelsesgrænser. Resultatet er en komplet .po-fil med alle msgstr udfyldt, og hver @count-, %date- og :url-placeholder præcis, hvor den startede.

Trin 3: Genimportér til Drupal

Importér den oversatte fil tilbage via /admin/config/regional/translate eller via drush locale:import-kommandoen vist ovenfor, og genopbyg derefter cachen. Drupal fletter oversættelserne ind i sine locale-tabeller, og strengene vises med det samme på hele sitet. Gentag cyklussen, hver gang du tilføjer et modul eller opdaterer core, da hver af dem medfører nye uoversatte strenge.

En importdetalje at få styr på: --override-flagget styrer, om indkommende oversættelser erstatter eksisterende. Brug --override=all, når du ønsker, at den AI-oversatte fil skal være autoritativ, eller en mere konservativ indstilling, hvis du har finjusteret bestemte strenge i Drupal UI, som du ikke ønsker overskrevet. For de fleste automatiserede pipelines holder det systemet forudsigeligt at behandle .po-filen som sandhedskilden og overskrive alt: filen i versionskontrol er, hvad sitet viser, punktum.

For flersprogede sites med flere målsprog kører cyklussen én gang per sprog. Eksporter det uoversatte sæt, oversæt det til tysk, importér det; eksporter igen, oversæt til spansk, importér det; og så videre. Fordi hvert sprog er en uafhængig .po-fil, kan du køre dem parallelt, og en skybaseret oversætter, der behandler dem samtidigt, forvandler det, der plejede at være en uge med konsulentarbejde, til en eftermiddag.

Drupal PO er et af flere formater

Det er værd at bemærke, at gettext .po ikke er den eneste måde, Drupal håndterer oversættelse på. Konfigurations- og indholds-enheder kan også udveksles som XLIFF, hvilket er standarden, som Translation Management Tool (TMGMT)-modulet benytter til professionelle oversættelsesleverandør-workflows. Hvis din Drupal-lokalisering kører gennem XLIFF snarere end interface .po-filer, er principperne for placeholder-bevaring identiske, men filstrukturen er forskellig, og vi dækker denne vej i oversættelse af XLIFF-filer til Drupal, Symfony og Angular.

For grænsefladeoversættelseslaget forbliver .po dog arbejdshesten. Eksport-, AI-oversæt- og genimport-cyklussen forvandler en flerdages manuel opgave til få minutters behandling, og så længe det værktøj, du bruger, oprigtigt forstår gettext-placeholdere, forbliver dine @variable-kontrakter intakte, og dit Drupal-site forbliver ubeskadiget på alle de sprog, du leverer.

Klar til at oversætte dine Drupal .po-filer uden at ødelægge en eneste @variable? Prøv SimplePoTranslate gratis — intet kreditkort påkrævet. Den gratis version håndterer standard gettext .po- og .pot-filer med fuld Syntax Locking, så dine Drupal-placeholdere passerer igennem præcis som koden forventer.