Übersetzungs-Pipeline
Wie übersetzbare Strings vom Quellcode bis zur Laufzeit fließen (xgettext → Weblate → PO → PHP)
Das Modul bringt seine eigenen Übersetzungen über die Standard-gettext-Kette ein, gehostet auf Codeberg Weblate.
Ablauf
flowchart TB
subgraph Extraction["1️⃣ Quellcode → POT"]
direction LR
PHP["📝 src/*.php"] -->|npx gulp updatepo| POT["📄 messages.pot"]
end
subgraph Translation["2️⃣ Übersetzung"]
direction LR
WEBLATE["🌐 Weblate"] -->|download| PO["🗝 <lang>.po"]
end
subgraph Rendering["3️⃣ Webtrees"]
direction LR
PHPARR["📦 lang.php"] -->|I18N| RENDER["✅ Rendering"]
end
POT -->|upload| Translation
PO -->|npx gulp po2php| Rendering
classDef sourceStyle fill:#e3f2fd,stroke:#1565C0,stroke-width:2px
classDef fileStyle fill:#e8f5e9,stroke:#2E7D32,stroke-width:2px
classDef weblateStyle fill:#f3e5f5,stroke:#7B1FA2,stroke-width:2px
classDef renderStyle fill:#fce4ec,stroke:#C2185B,stroke-width:2px
class PHP sourceStyle
class POT,PO,PHPARR fileStyle
class WEBLATE weblateStyle
class RENDER renderStyle
Strings extrahieren
update-po-files.sh
führt xgettext über jede *.php / *.phtml aus, außer util/, vendor/, node_modules/ und tests/:
xgettext -L PHP \
--keyword=translate --keyword=plural:1,2 --keyword=translateContext:1c,2 \
--add-comments=I18N --from-code=utf-8 \
--output=resources/lang/messages.pot …
Zwei Marker-Helfer steuern, was extrahiert wird:
I18N::translate()/MoreI18N::translate()— modulspezifische Strings.translateist ein xgettext-Keyword, daher werden diese aufgenommen.MoreI18N::xlate()— Strings, die bereits vom webtrees-Core-POT abgedeckt sind. Gleiches Laufzeit-Verhalten, anderer Name, daher unsichtbar für xgettext. Nach einem Core-Updatemessages.potmit dem Core-POT vergleichen und neu abgedeckte msgids aufxlate()umstellen.
/* I18N: … */-Kommentare geben Übersetzern Kontext (über --add-comments=I18N aufgenommen).
PO → PHP
.po-Dateien werden nicht lokal gemergt — das ist Weblates Aufgabe, um Konflikte zu vermeiden. Sobald Weblate aktualisierte .po-Dateien liefert, kompilieren:
npx gulp po2php
Hinweis: ein früherer
.po→.mo-Schritt ist überflüssig (Formatwechsel bei den Übersetzungen, Issue #88).