Skip to content

docs: pin manpage troff filename to the make target#4193

Open
grandixximo wants to merge 2 commits into
LinuxCNC:masterfrom
grandixximo:fix-manpage-troff-naming
Open

docs: pin manpage troff filename to the make target#4193
grandixximo wants to merge 2 commits into
LinuxCNC:masterfrom
grandixximo:fix-manpage-troff-naming

Conversation

@grandixximo

@grandixximo grandixximo commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Reported by @hdiethelm in #4178, where a translated man page rendered with the content of a sibling page and a rerun changed which page was affected.

Problem

asciidoctor's manpage backend names its output file from the page's == NAME section, not from the make target it was invoked for. The troff rule passed --destination-dir and trusted asciidoctor to pick the name. For the translated manpages that NAME line goes through po4a, so a translation that altered the command identifier redirected the troff to the wrong filename:

#: src/man/man3/hm2_pktuart_read.3.adoc:6
msgid  "hm2_pktuart_read - read data from a Hostmot2 UART buffer"
msgstr "hm2_uart_read - liest Daten aus einem Hostmot2 UART-Puffer"   # dropped "pkt"

de/.../hm2_pktuart_read.3.adoc then renders to a file named hm2_uart_read.3, colliding with the real hm2_uart_read page. Under -j the two recipes race for one output: the loser is never written, the winner is nondeterministic, so a rerun changes which page is corrupted.

Fix

Pass -o "$@" so the build graph, not the page text, decides each filename. Every target is produced exactly once at its own name, regardless of translation state. A wrong translation can still make a page's visible text wrong, but it can no longer misname a file, race, or drop a page.

NAME drift is still worth seeing, but the build is the wrong place to surface it (it disappears in the build log). So scripts/manpage-name-check.py scans the built man tree after the doc build and reports any page whose rendered .TH name disagrees with its filename. It is quiet when nothing drifted. When something has, it prints each page with the exact string to search in Weblate and its current value side by side, so the list is a ready worklist. It never fails the build: in CI it writes that same list to the job summary and emits one warning pointing at it (rather than one annotation per page). The NAME lines are translatable strings managed in Weblate, so fixes go there. The check is a convenience for translation cleanup, not load-bearing, so it is easy to drop or fold into the build later if maintainers prefer.

Verification

Full configured doc build with translations (--enable-build-documentation --enable-build-documentation-translation), po4a over all languages, German built through to HTML, then built a second time:

  • Race gone: the previously colliding pairs (hm2_uart_read/hm2_pktuart_read, hm2_bspi_set_read/set_write, rtapi_stdint/rtapi_string) are all produced as distinct troff with the correct title, and the man HTML renders.
  • Second build is a complete no-op (Nothing to be done), which also confirms no target is left missing and po4a is not re-run.
  • manpage-name-check.py over the built tree flags the drifted translated pages and is silent on the English tree.

Companion to #4175, which covers the same defect on the other output: that PR fixes the .so alias stubs of multi-name pages; this fixes the primary page filename. They are independent and land in parallel.

@grandixximo

Copy link
Copy Markdown
Contributor Author

@BsAtHome are we holding merges till sid is fixed?

@hdiethelm

Copy link
Copy Markdown
Contributor

Hmm, due to you can detect wrong translations: It would make sense to fix (or remove) them and fail if it happens ever again.
I dont see any warnings in the doc build, just to much text... ;-) I would have to search for it and probably no one except you will ever look out for these.

@BsAtHome

Copy link
Copy Markdown
Contributor

@BsAtHome are we holding merges till sid is fixed?

Currently only the independent doc package build fails. I was not at the dev-meeting yesterday, so I don't know whether the meeting took place or what was discussed.

@grandixximo

Copy link
Copy Markdown
Contributor Author

Agreed the warning is easy to miss in the build log, and detection without enforcement is weak. I would get to a hard gate in steps rather than flip to fail now:

  1. Land this as warn. With -o "$@" the build is already safe (no race, no missing page), so a bad translation only degrades a page's text, it cannot break the build. That removes the urgency and lets this merge today.

  2. Clear the current backlog in Weblate: 12 German strings plus a few in other languages. These are translatable strings, so the fix belongs in Weblate; a direct .po edit gets overwritten on the next sync.

  3. Once the tree is clean, add enforcement as a dedicated CI check, not a build failure. A build-level fail would fail every PR that builds docs while any translation is wrong, not just the offending one, and it lives in the 18 minute htmldocs job where it is as easy to miss as the warning. A small standalone check (scan the rendered manpages for NAME != stem) is fast, shows up as its own red status, and can be made a required check.

One caveat for that to actually gate translations: Weblate currently lands both via PR and via direct branch merges (the recent Merge remote-tracking branch 'weblate/...'). A required check only blocks the PR path, so Weblate would need to go through PRs for it to truly stop a bad string reaching master.

So: warn now, clean Weblate, then a required standalone check. Same end state you are after, sequenced so we can merge today without wedging other PRs.

@BsAtHome

Copy link
Copy Markdown
Contributor

You cannot enforce CI on weblate translations. People who translate do not usually look at CI. Translations are a tricky business and they are not well organized. It is also one-big-pile-of-text that is very hard to handle. Merges are ad-hoc and breaks are regular. It is hard to enforce structural changes to the translations as long as there is no real plan as how they are supposed to work and be organized.

@grandixximo

Copy link
Copy Markdown
Contributor Author

Fair, no enforcement then. Not a gate, a warning: a separate CI step runs the name check, never fails, and emits the mismatches as GitHub annotations plus a job-summary table. It shows up in the Checks tab instead of buried in the build log, and blocks nothing. Translators keep working as they do; whoever merges a weblate batch just gets a visible list of what drifted. That gives @hdiethelm the visibility without putting a gate on translations. Acceptable?

@BsAtHome

Copy link
Copy Markdown
Contributor

Yes, that should be enough for now.

@grandixximo grandixximo force-pushed the fix-manpage-troff-naming branch from 6e26517 to 5f0cad1 Compare June 22, 2026 08:17
@grandixximo

Copy link
Copy Markdown
Contributor Author

Updated per the discussion, folded the CI warning in rather than opening another PR. The -o "$@" pin is the actual fix and stands alone; the build no longer warns inline (it just buried in the log). Instead scripts/manpage-name-check.sh reports NAME drift as a non-blocking CI warning, annotations plus a job summary, which gives @hdiethelm the visibility without a gate on translations per @BsAtHome.

I fixed the current drift in Weblate, but that batch has not merged here yet, so the check will still flag those pages until the next Weblate sync lands. Since it only warns, that is harmless, and it shows the check doing its job in the meantime.

@grandixximo grandixximo force-pushed the fix-manpage-troff-naming branch from 5f0cad1 to bab6d1e Compare June 22, 2026 08:38
@hdiethelm

Copy link
Copy Markdown
Contributor

I like your approach with CI workflow commands and the summary. But it's a bit much:
https://github.com/LinuxCNC/linuxcnc/actions/runs/27940236294?pr=4193
Might be remove the warnings and only show the summary? It looks like there are less warnings than entry's in the summary. Probably the warnings are limited by github, so a summary is probably better. Or just one warning at the end that you should check the summary.

BTW: Here is the doc how to do this if others want this to: https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-commands

asciidoctor names the troff from the page's NAME section, not the make
target. po4a translates that NAME, so a translation that altered a command
identifier (hm2_pktuart_read rendered as hm2_uart_read) misnames the troff;
two pages then race for one output under -j, one going missing.

Pass -o "$@" so the build graph sets each filename, produced once at its own
name regardless of translation.
@grandixximo grandixximo force-pushed the fix-manpage-troff-naming branch from bab6d1e to 8dc405f Compare June 23, 2026 00:15
@grandixximo

grandixximo commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

https://github.com/LinuxCNC/linuxcnc/actions/runs/27993036704
How is that? also working on a script to actually get more details about what actually needs fixing, worth it?
To be run manually.

@hdiethelm

Copy link
Copy Markdown
Contributor

Looks nice! Not to much warnings, so you see the relevant ones and a good sumary.

@hdiethelm

Copy link
Copy Markdown
Contributor

I did not look into translations yet, still new to linuxcnc. So you know probably better how much info is needed to fix it. It might be already good eneught.

At least way better than before, a lot was broken and no one took notice.

To much code has always the issue that someone needs to maintain and fix it sometimes in the future.

@grandixximo

grandixximo commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

I mean it gives you the gist of what the issue might be, but for example the mb2hal
you would not know what was wrong with that, seems to match.

image

but actually

[de] mb2hal   (Plain text)
    search:  mb2hal - HAL non-realtime component for Modbus
    current: *mb2hal* - HAL Nicht-Echtzeit-Komponente für Modbus

But getting these info out is intensive, it's not worth it to have it in all the builds IMO, so a separate script, which I can have some instructions about, and a mention in the sumamry, that runs locally on demand, and stdout the needed info from a built docs tree, I think is more reasonable, after you get those info it is trivial to find and fix it in weblate, even if you don't understand the language that needs fixing.

@hdiethelm

Copy link
Copy Markdown
Contributor

Ok, why not. The example above would be hard to spot manually.

@grandixximo

grandixximo commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

I'm not sure I like it that much, it works....
@BsAtHome How would you like this to look?

Edit:
I'm not happy with this, Reshaping into a single script.

@grandixximo grandixximo marked this pull request as draft June 23, 2026 07:08
@grandixximo grandixximo force-pushed the fix-manpage-troff-naming branch from f6fe989 to 91a8850 Compare June 23, 2026 07:44
@BsAtHome

Copy link
Copy Markdown
Contributor

I'm not sure I like it that much, it works.... @BsAtHome How would you like this to look?

Very informative list of mismatches. Most, if not all, you'd not need to know the language to fix the translation.

BTW, why is the dash vs em-dash a problem? Is there some processing step that can't handle it? It might have been introduced by auto- or assisted-translation.

@grandixximo

grandixximo commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

asciidoctor's manpage backend derives the page name by splitting the NAME line on the literal ASCII " - ". An em-dash or en-dash is not that separator, so it folds the volume into the name (io renders as io.1), which before the -o pin could collide with a real page. You might be right about it being automated translation swapping the hyphen for a typographic dash. I already fixed in Weblate by putting " - " back.

@grandixximo grandixximo force-pushed the fix-manpage-troff-naming branch from 91a8850 to 7374946 Compare June 23, 2026 08:50
@grandixximo grandixximo marked this pull request as ready for review June 23, 2026 08:56
@grandixximo

grandixximo commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

I simplified the columns, I think the "search" col is all you really need to find it in weblate, and the "current" col is just to confirm what we see on this end, I already fixed all 65 warning in weblate, will have to wait for next weblate cycle to see if we get more, or if I missed any.

I'm happy with it now 😊

Comment thread scripts/manpage-name-check.py Outdated
After the doc build, scripts/manpage-name-check.py scans the built man
tree for pages whose rendered .TH name disagrees with their filename, the
sign of a translated NAME line that drifted from the command identifier.

Quiet when nothing drifted.  When something has, it prints each page with
the string to search in Weblate and its current value side by side, so the
output is a ready worklist.  Never fails the build: in CI it writes that
list to the job summary and emits one warning pointing at it.  The NAME
lines are managed in Weblate, so fixes go there.
@grandixximo grandixximo force-pushed the fix-manpage-troff-naming branch from 7374946 to d91856b Compare June 23, 2026 11:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants