manpages: generate translated manpages at build time with po4a - #94
Merged
Merged
Conversation
Stop tracking the ~100 pre-rendered docs/man/*.{lang}.1.in and
src/utils/*/docs/*.{lang}.1.in. Generate them at build time from the
English masters + docs/man/po/manpages-*.po via po4a, then install
them under <prefix>/share/man/<lang>/man1/.
Why this matters:
Weblate edits docs/man/po/manpages-*.po but cannot run po4a, so every
Weblate translation PR left the tracked renders stale and turned the
manpages-sync CI red (PR amule-project#66). The stopgap commented the check out
entirely, which let the tracked renders deliberately lag behind the
translations.
Tracking generated files also forced CI to pin po4a 0.74 from
Debian trixie because po4a's output wrapping changes between versions
and any mismatch surfaced as spurious drift.
Pipeline
- docs/man/po4a.config.in: CMake-templated config; @CMAKE_*_DIR@
references resolve to absolute build-dir output paths at configure
time, so po4a writes straight into the build tree.
- docs/man/CMakeLists.txt:
* cmake_dependent_option(TRANSLATED_MANPAGES ... ON ENABLE_NLS OFF)
* find_program(po4a). If missing, install only English masters and
surface a STATUS message (po4a is an optional build dep).
* add_custom_command runs po4a once with DEPENDS on every
manpages-*.po, then a second custom_command per output runs
cmake/configure_translated_manpage.cmake to substitute @MAN_DATE@
and @PACKAGE_VERSION@ (po4a passes those through verbatim).
* The two-pass split is required because configure_file is
configure-time only; the rendered .1.in inputs don't exist yet
when CMakeLists.txt runs.
- cmake/configure_translated_manpage.cmake: tiny helper that
re-implements configure_file @only semantics via file(READ) +
string(CONFIGURE) + file(WRITE), invoked via cmake -P from the
custom_command at build time.
- scripts/update-manpages-po.sh: counterpart to scripts/update-po.sh
for translators. Runs po4a --no-translations against a temp
docs/man-relative config (so #: source refs land as relative paths,
not the developer's absolute fs path), regenerating manpages.pot
and merging into manpages-*.po.
- .github/workflows/i18n.yml: replace the disabled manpages-sync
with a manpages-pot-sync that re-runs update-manpages-po.sh and
diffs the result, matching the existing pot-sync job for the
application catalogs. Weblate can never break this one — Weblate
only edits .po files.
- .github/workflows/release.yml: new source-bundle job builds
aMule-<TAG>-src.tar.gz containing every tracked file plus the
freshly-rendered translated manpages, so downstream packagers can
consume a tarball that doesn't require po4a at build time. Attached
to the draft Release alongside the binary artifacts.
The mtime gotcha the disabled manpages-sync job documents goes away
once nothing rendered is in git: CMake's DEPENDS on the .po inputs
drives incremental rebuilds rather than po4a's own
"outputs up-to-date" check.
Closes amule-project#69.
6 tasks
Member
|
@got3nks |
4 tasks
Author
|
Fixed in #101 |
got3nks
added a commit
that referenced
this pull request
Jun 11, 2026
… tree PR #94's po4a invocation ran with no flags, so po4a did all three of its default operations on every cmake --build: 1. Regenerate docs/man/po/manpages.pot from English masters 2. Merge the new .pot into every docs/man/po/manpages-*.po 3. Render the translated *.lang.1.in into the build dir Only (3) is the build's job; (1) and (2) belong to scripts/update-manpages-po.sh which a translator runs explicitly. The side effect was that every plain cmake --build left docs/man/po/manpages.pot and 10x manpages-*.po showing as modified in git status, dirtying the working tree at minimum with a refreshed POT-Creation-Date timestamp. Pass --no-update to po4a in both the CMake custom_command and the release.yml source-bundle step. po4a then only renders translated manpages and leaves po/.pot/.po untouched. Reported by @ngosang on #94.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #69.
Summary
Stop tracking the ~100 pre-rendered
docs/man/*.{lang}.1.inandsrc/utils/*/docs/*.{lang}.1.in. Generate them at build time from the English masters +docs/man/po/manpages-*.povia po4a, then install them under<prefix>/share/man/<lang>/man1/.Why
Weblate edits
docs/man/po/manpages-*.pobut cannot run po4a, so every Weblate translation PR left the tracked renders stale and turned themanpages-syncCI red (e.g. #66). The stopgap was to comment that check out, which let the tracked renders deliberately lag behind the translations. Tracking generated files also forced CI to pin po4a 0.74 from Debian trixie because po4a's output wrapping changes between versions and any mismatch surfaced as spurious drift.Pipeline
docs/man/po4a.config.in— CMake-templated config.@CMAKE_*_DIR@references resolve to absolute build-dir output paths at configure time so po4a writes straight into the build tree.docs/man/CMakeLists.txt— addscmake_dependent_option(TRANSLATED_MANPAGES ... ON ENABLE_NLS OFF).find_program(po4a)— if missing, install only English masters and surface aSTATUSmessage; po4a is an optional build dep. A singleadd_custom_commandruns po4a withDEPENDSon everymanpages-*.po, then a per-outputadd_custom_commandrunscmake/configure_translated_manpage.cmaketo substitute@MAN_DATE@and@PACKAGE_VERSION@(po4a passes those through verbatim). The two-pass split is required becauseconfigure_fileis configure-time only; the rendered.1.ininputs don't exist yet when CMakeLists.txt runs.cmake/configure_translated_manpage.cmake— tiny helper that re-implementsconfigure_file @ONLYsemantics viafile(READ)+string(CONFIGURE)+file(WRITE), invoked viacmake -Pfrom the custom command at build time.scripts/update-manpages-po.sh— counterpart toscripts/update-po.shfor translators. Runspo4a --no-translationsagainst a tempdocs/man-relative config (so#:source refs land as relative paths, not the developer's absolute filesystem path), regeneratingmanpages.potand merging intomanpages-*.po..github/workflows/i18n.yml— replaces the disabledmanpages-syncwith amanpages-pot-syncthat re-runsupdate-manpages-po.shand diffs the result, matching the existingpot-syncjob for the application catalogs. Weblate can never break this one — Weblate only edits.pofiles..github/workflows/release.yml— newsource-bundlejob buildsaMule-<TAG>-src.tar.gzcontaining every tracked file plus the freshly-rendered translated manpages, attached to the draft Release alongside the binary artifacts. Downstream packagers can consume that tarball instead of the GitHub-generated "Source code" archive to avoid po4a as a build-time dependency.Mtime gotcha
The disabled
manpages-syncjob documented a po4a "outputs up-to-date" mtime check that broke on fresh checkouts. That goes away entirely once nothing rendered is in git: CMake'sDEPENDSon the.poinputs drives incremental rebuilds rather than po4a's own mtime check.Test plan
Executed on macOS ARM64 + Ubuntu 26.04 ARM64 (
amule-dev-vm).cmake -B buildconfigures cleanly withTRANSLATED_MANPAGES=ON(Mac + Linux),po4adiscovered,po4a.configmaterialised in build dir with absolute pathscmake --build build(ALL) renders 100.lang.1.invia po4a then substitutes into 100.lang.1files (verified inbuild/docs/man/andbuild/src/utils/)cmake --install buildlays them under<prefix>/share/man/<lang>/man1/<binary>.1amuled.1content correct:.TH AMULED 1 "June 2026" "aMule Daemon vGIT" "aMule Daemon", body has.SH NOM,"le client P2P eMule multiplateforme — version daemonisée"amuled.1has matching.THsubstitutionscripts/update-manpages-po.shis idempotent: produces only thePOT-Creation-Datetimestamp diff when run with no changes to the English masters#:source references in the regenerated.potare repo-relative (amule.1.in:1), not developer-absoluteTRANSLATION_<LANG>still works (only enabled langs install)Migration notes for maintainers
ENABLE_NLS=YES. Build hosts without po4a will skip translated manpages and emit aSTATUSnote. Pass-DTRANSLATED_MANPAGES=NOto opt out explicitly.Dingit status.