Skip to content

Script Reference

William Jacoby edited this page Sep 17, 2026 · 2 revisions

Script & Command Reference

Every script in phpbbdocs-hugo, with a runnable example for each command, not just the abstract <placeholder> form. All commands are run from the repo root unless noted otherwise. Real per-language examples below use fr (French) for the end-user docs and de_x_sie (German Formal) for the dev-docs, since those are currently 100% translated in this project. Swap in any other language code from docs/phpbb-hugo-languages.md.

This page is a command-by-command reference, not a workflow. See Build & Publish Workflow for rebuilding and publishing the whole site, or Translator Workflow for one language's translation process end to end, to see these commands chained together in order.


translations.sh: end-user docs ("documentation" family)

Hand-authored end-user chapters (content/en/chapters/*.xml), translated via gettext PO catalogs stored in the sibling phpbbdocs-languages repo (itstool-based). One subcommand per lifecycle stage:

Command What it does
extract Regenerate the English .pot templates (maintainer-only — run automatically by init/update)
init <lang> Create empty PO catalogs for a brand-new language
update <lang> Refresh an existing language's catalogs against the latest English source
status <lang> Show translated/fuzzy/untranslated counts and completion %
check <lang> Validate PO syntax and that reconstruction round-trips cleanly
audit <lang> Diff a fresh reconstruction against the committed content/<lang>/chapters/*.xml, catching real content drift check can't see
build <lang> Reconstruct content/<lang>/chapters/*.xml from the PO catalogs
# Create catalogs for a brand-new language (prompts for language.toml
# details the first time: English name, native name, locale)
./translations.sh init es

# See how far along French is
./translations.sh status fr

# Refresh French's catalogs after the English source changed upstream
./translations.sh update fr

# Validate every catalog compiles and reconstructs to well-formed XML
./translations.sh check fr

# Catch real content drift check can't see (PO vs. the committed XML)
./translations.sh audit fr

# Reconstruct content/fr/chapters/*.xml from the translated catalogs
./translations.sh build fr

build only reconstructs the chapter XML. It does not run hugo itself. Follow it with ./phpbbdocs_hugo.sh fr (see below) to build the site, and hand-maintain proteus_doc_fr.xml's <bookinfo> separately (title/abstract/authorgroup/copyright, never generated from the PO catalogs).


translations.sh: developer docs ("development" / dev-docs family)

Upstream Sphinx/RST developer docs (pulled from upstream-phpbb-documentation/development/, a separate checkout from the end-user docs' own), translated the same PO-catalog way, with an identical six-subcommand shape prefixed devdocs-:

Command What it does
devdocs-extract Regenerate .pot templates from the real upstream RST (maintainer-only)
devdocs-init <lang> Create empty dev-docs PO catalogs mirroring the RST tree file-for-file
devdocs-update <lang> Refresh an existing language's dev-docs catalogs
devdocs-status <lang> Show dev-docs translation completion
devdocs-check <lang> Validate every catalog and its Markdown reconstruction
devdocs-build <lang> [target_dir] Reconstruct translated dev-docs Markdown into [target_dir]
# Create catalogs for a brand-new dev-docs language
./translations.sh devdocs-init es

# Same-language case: en gets real catalogs too, msginit auto-fills
# msgstr = msgid at creation time -- no separate "English" code path
./translations.sh devdocs-init en

# Check completion
./translations.sh devdocs-status de_x_sie

# Validate every catalog (this one can take >2 minutes on the full
# 55-file corpus -- run it in the background if your shell supports it)
./translations.sh devdocs-check de_x_sie

# Write into the disposable preview location (no second argument) --
# useful for eyeballing a translation before trusting it in the real site
./translations.sh devdocs-build de_x_sie

# Write into the REAL site content tree -- this is what the live site
# actually reads, since the live-site cutover (2026-09-17)
./translations.sh devdocs-build de_x_sie site/content/de_x_sie/development

Unlike the documentation family's build, devdocs-build never runs hugo either, for the same reason. Follow it with ./phpbbdocs_hugo.sh all to fold the result into a real build.


Build & sync scripts

pull_upstream_docs.sh: sync end-user docs source from upstream

./pull_upstream_docs.sh

No arguments. Syncs content/en/chapters/ and content/en/images/ from the official phpbb/documentation repo, overwriting local changes. Only touches en: content/da/, content/fr/, etc. are unaffected (they're generated from PO catalogs by translations.sh build, not synced from upstream directly). Run this before translations.sh update <lang> so the refreshed catalogs reflect current upstream content.

phpbbdocs_hugo.sh: build the Hugo site

# Build every language into the default site/public
./phpbbdocs_hugo.sh all

# Build just French into a custom destination
./phpbbdocs_hugo.sh fr /tmp/fr-preview

# Build just English (destination defaults to site/public)
./phpbbdocs_hugo.sh en

language defaults to all; destination_dir defaults to site/public. This is what actually invokes hugo; neither translations.sh build nor devdocs-build do.

fill_translation_fallbacks.sh: fill translation gaps

# Fill every language's gaps from English, using every other
# content/<lang>/ directory found as the target list
./fill_translation_fallbacks.sh en

# Fill gaps for just French and the two German variants
./fill_translation_fallbacks.sh en fr de de_x_sie

source_lang is required; target_lang defaults to every other content/<lang>/ directory found. Safe to re-run anytime: a translation already at that path is never overwritten, only pages still flagged fallback: true get refreshed. Run this last, after whichever build step you just ran.


Maintainer / one-off tools

These aren't part of the normal per-translation-cycle workflow. Reach for them only in the specific situation each one describes.

fix_csv_table_headers.py: CSV-table delimiter fix

# Report what would change, without writing anything
python3 fix_csv_table_headers.py upstream-phpbb-documentation/development --dry-run

# Actually fix a real checkout in place
python3 fix_csv_table_headers.py upstream-phpbb-documentation/development

Fixes a Sphinx content-loss bug (a .. csv-table:: directive with a custom :delim: whose :header: line doesn't match it). Idempotent. You normally never run this directly: devdocs-build/devdocs-* already run it automatically against a disposable copy of the upstream checkout before every conversion. Only useful standalone if you want to inspect or hand-fix the upstream RST tree directly.

translations/align_existing_translation.py: migrate an existing hand-translation into a PO catalog

# One-time migration, e.g. for a language whose end-user chapters were
# hand-translated before the PO-catalog pipeline existed
itstool -o /tmp/en.pot content/en/chapters/admin_guide.xml
itstool -o /tmp/fr.pot content/fr/chapters/admin_guide.xml
python3 translations/align_existing_translation.py \
    /tmp/en.pot /tmp/fr.pot /tmp/admin_guide.po \
    fr content/en/chapters/admin_guide.xml content/fr/chapters/admin_guide.xml

A one-off historical tool (used to migrate da/fr's originally hand-translated chapters into PO catalogs). Not needed for a brand-new language: init already starts you with empty catalogs, no existing hand-translation to align against.

translations/align_glossary_by_term.py: glossary-specific alignment

python3 translations/align_glossary_by_term.py \
    content/en/chapters/glossary.xml \
    content/da/chapters/glossary.xml \
    /home/william/Desktop/repos/phpbbdocs-languages/da/documentation/glossary.po \
    --dry-run

Companion to the tool above, specifically for glossary.xml: some languages (Danish) resort the glossary alphabetically by the translated term, which breaks the positional pairing align_existing_translation.py relies on everywhere else. Matches terms by name instead. Drop --dry-run to actually write the catalog; add --overwrite to also replace entries that already have a translation (off by default).


Internal workers (invoked automatically, not run directly)

You won't normally call these yourself; they're documented here because every script gets an entry, and knowing they exist helps when reading translations.sh's own source or a stack trace.

# translations/sphinx_to_hugo.py -- one file, invoked once per page by
# devdocs-build/devdocs-check internally
python3 translations/sphinx_to_hugo.py \
    --source-root build/devdocs-source-copy \
    auth/authentication.rst \
    /home/william/Desktop/repos/phpbbdocs-languages/de_x_sie/development/auth/authentication.po \
    --language de_x_sie \
    --output /tmp/authentication.md \
    --weight 1 \
    --translation-key development-auth-authentication

# translations/devdocs_toc_order.py -- reads the real upstream toctree
# structure to determine chapter/page order; invoked once per
# devdocs-build run
python3 translations/devdocs_toc_order.py upstream-phpbb-documentation/development
  • translations/preserve_authorship_metadata.py — patches a reconstructed chapter in place so authorship/attribution blocks aren't silently overwritten by the English source's. Invoked by both check <lang> and build <lang>.
  • translations/audit_roundtrip.py — paragraph-by-paragraph diff used internally by audit <lang>; run ./translations.sh audit fr instead of calling this directly.