Skip to content

Translator Workflow

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

Translator Workflow

A walkthrough of the standard translator workflow for phpbbdocs-hugo, tying the individual commands in Script Reference together into the process you'd follow end to end. Read README.md and docs/phpbb-hugo-languages.md first for the project's own conventions (language codes, directory naming) before starting.

The shape of it

Both content families follow the same five-stage shape: only the command prefix and the catalog location differ.

Stage End-user docs Developer docs
1. Initialize/refresh catalogs init / update devdocs-init / devdocs-update
2. Translate hand-edit .po files hand-edit .po files
3. Validate check devdocs-check
4. Reconstruct build devdocs-build
5. Render the site phpbbdocs_hugo.sh phpbbdocs_hugo.sh

Every .po catalog you edit lives in the sibling phpbbdocs-languages repo, not in phpbbdocs-hugo itself. translations.sh resolves that repo's location from translation.conf (or a LANGUAGES_REPO environment variable override). Nothing under content/<lang>/chapters/ or site/content/<lang>/development/ is ever hand-edited directly; both are reconstructed from the PO catalogs by build/devdocs-build, so edits made straight to those generated files are silently overwritten on the next reconstruction.

Worked example: adding a brand-new language

Say you're adding Spanish (es). The two families are independent: you can do one, the other, or both, in either order.

1. Confirm the language code

Check docs/phpbb-hugo-languages.md for the real phpBB ISO code and register/variant (casual vs. formal address, script variant, spelling variant) before doing anything else. Getting this wrong means redoing every step below under the right code.

2. Initialize catalogs for both families

./translations.sh init es
./translations.sh devdocs-init es

Both prompt for language.toml details the first time a code is used (English name, native name, locale); answer once and both families share the same language.toml. init creates empty documentation/*.po catalogs (one per end-user chapter); devdocs-init creates empty development/**/*.po catalogs mirroring the real upstream RST tree file-for-file (55 files as of this writing). Neither overwrites existing work: re-running against an already-initialized language errors out on purpose and tells you to use update/devdocs-update instead.

3. Translate

Hand-translate the msgstr of every entry in:

  • <languages-repo>/es/documentation/*.po (7 files: the end-user chapters)
  • <languages-repo>/es/development/**/*.po (55 files: the dev-docs)

Plain text works, but see PO Editors for tools built for this file type (fuzzy/untranslated filtering, side-by-side source view).

Leave code samples, file paths, URLs, and RST/DocBook markup untouched; only the translatable prose changes. See docs/translation-process-prompt.md for the fuller writing-conventions guidance (internal named-reference handling, what to leave in English, etc.) and, once translated, that same doc's terminology-audit process for verifying quoted UI strings actually match the real phpBB software (the writeup goes in phpbbdocs-languages's own terminology/<code>/, not phpbbdocs-hugo; see step 7 below).

There's no requirement to finish both families, or finish either one in a single sitting: status/devdocs-status (next step) work correctly against partial progress at any point.

4. Check progress and validate

./translations.sh status es
./translations.sh devdocs-status es

./translations.sh check es
./translations.sh devdocs-check es       # can take >2 minutes on the full corpus

status/devdocs-status show translated/fuzzy/untranslated counts and a completion percentage. Check in on these anytime, not just at the end. check/devdocs-check are the gate: they validate PO syntax and that every catalog reconstructs to well-formed output, reporting a COMPLETE/INCOMPLETE verdict. Don't move to reconstruction until both come back clean.

5. Reconstruct and build

./translations.sh build es
./translations.sh devdocs-build es site/content/es/development

./phpbbdocs_hugo.sh all

build writes content/es/chapters/*.xml; devdocs-build writes site/content/es/development/* directly (the second argument is what makes this write into the real site tree instead of the disposable preview location at build/devdocs-preview/). Neither one runs hugo itself: phpbbdocs_hugo.sh all is the step that builds the site, for every language, from whatever's currently on disk.

One more manual step for the end-user docs specifically: proteus_doc_es.xml's <bookinfo> (title/abstract/authorgroup/copyright) is hand-maintained and never generated from the PO catalogs. Write it once, following the pattern in proteus_doc_en.xml.

6. Fill gaps and preview

./fill_translation_fallbacks.sh en es

If Spanish is missing pages another language already has (common for a brand-new language, or right after an upstream content sync), this copies the English version over with a fallback: true flag so the language switcher still links to something, clearly marked as untranslated, instead of just not showing a link at all. Safe to re-run anytime; never overwrites a real translation.

Preview locally with .claude/launch.json's hugo config (or plain hugo server --source site), then visit /es/ and /es/development/ and confirm the language switcher, chapter ordering, and rendered content all look right before committing.

7. Commit and open a PR

The .po catalogs live in phpbbdocs-languages, so that's the repo your commit goes in. From that repo's root:

git checkout -b add-es-devdocs-translation
git add es/
git commit -m "Add complete Spanish translation of dev-docs (development/)"
git push -u origin add-es-devdocs-translation
gh pr create --title "Add complete Spanish translation of dev-docs (development/)" --body "..."

Branch name: add-<code>-devdocs-translation for a new dev-docs language (add-de-devdocs-translation, add-da-it-devdocs-translation for a two-language PR); fix/<short-description> for a correction to existing catalogs (fix/de-upgrade-guide-grammar); maintenance/<short-description> for tooling/process changes. Translating the end-user chapters instead (or as well) follows the same shape, just without devdocs- in the branch name if you're doing both together.

PR title: Add complete <Language> translation of dev-docs (development/) for a new language. Match the exact phrasing above; this repo's merged PRs are consistent about it (see #8, #9, #10).

PR body: two sections, ## Summary and ## Verification. Summary is a few bullets: what got translated, how much (entry counts, not just "most of it"), and any technique worth flagging (e.g. a bulk-copy shortcut for a formal/casual variant). Verification quotes the actual devdocs-status/devdocs-check output, not just "all tests pass":

## Summary

- Translates all 55 Sphinx dev-docs PO catalogs (5498 msgid entries) to 100% completion for `es`.

## Verification

- `devdocs-status es`: 100.0% completion, 5498/5498 translated, 0 fuzzy, 0 untranslated.
- `devdocs-check es`: `Result: COMPLETE -- all 55 expected catalogs present and valid.`

This repo squash-merges: one commit lands on main per PR, so the individual commit message on your branch matters less than the PR title (GitHub uses the PR title as the squash commit's subject line by default).

Any terminology-audit writeup (terminology audit, human-review notes, supplementary glossary) is a separate commit in this same phpbbdocs-languages repo, under terminology/<code>/, not in phpbbdocs-hugo. See docs/translation-process-prompt.md (in phpbbdocs-hugo) for the conventions and terminology/README.md for the pattern to follow.

Ongoing workflow: updating an already-translated language

Once a language exists, the cycle is shorter: you're refreshing against upstream changes and filling in whatever a status check shows as gaps, not starting from nothing.

# 1. Pull the latest upstream English source first
./pull_upstream_docs.sh

# 2. Refresh both families' catalogs against it
./translations.sh update fr
./translations.sh devdocs-update fr

# 3. See what's now untranslated/fuzzy after the merge
./translations.sh status fr
./translations.sh devdocs-status fr

# 4. Translate the gaps (fuzzy entries especially -- these are
#    msgmerge's best-guess carry-forward from a similar old string,
#    and need a human read-through, not a rubber stamp)

# 5. Validate, reconstruct, build -- same as the new-language flow
./translations.sh check fr
./translations.sh devdocs-check fr
./translations.sh build fr
./translations.sh devdocs-build fr site/content/fr/development
./phpbbdocs_hugo.sh all

# 6. Fill any new gaps a fresh upstream pull introduced
./fill_translation_fallbacks.sh en fr

update/devdocs-update are the dev-docs-family's and documentation-family's own way of finding out that upstream drifted: each records the upstream commit it last synced against (phpbbdocs-languages/metadata/source.json), and status/devdocs-status flag when that recorded commit is stale relative to the current one (Source: DRIFTED).

What audit is for, and when to reach for it

translations.sh audit <lang> (documentation family only; there's no devdocs-audit yet, see docs/TODO/todo-sphinx-devdocs-spike.md's "What's still open") catches something check can't: content divergence between a PO catalog and the already-committed content/<lang>/chapters/*.xml, which can happen if one was hand-edited without the other being kept in sync, or if a shared error slipped into both identically. Run it after a build, or anytime you suspect the committed chapter file and its source catalog have drifted apart. docs/TODO/todo-po-roundtrip-audit.md has the full method and worked examples if a mismatch turns up.