docs: add explicit anchors for sections referenced by auto-generated ids - #4339
Conversation
These five sections are linked to via their auto-generated ids (_normal_download, _alternate_install_methods, _latency_tuning, _ini_settings, _commands). Translations change the section titles, which changes the generated id and breaks every such link in the translated HTML (flagged by the CI checklink run for de, es, ru, uk and nb). Pinning the id with an explicit anchor makes the targets translation-proof. English output is unchanged since the explicit id matches the auto-generated one.
scripts/docs-anchor-check.py, wired warn-only into the htmldocs CI job, flags <<_derived>> xrefs and link:...html#_derived URLs whose target has no explicit [[anchor]] in docs/src. Derived ids come from section titles, so such references break when a title is translated or retitled. Pin the target with an explicit anchor instead. Also pins the remaining lint hits, all same-page links in untranslated man pages (_subcommands, _mbccs_file_format, _modbus_functions, _modbus_types, _hal_types). Explicit ids match the auto-generated ones, so output is unchanged. Turns clean once PR LinuxCNC#4339 lands.
scripts/docs-anchor-check.py, wired warn-only into the htmldocs CI job, flags <<_derived>> xrefs and link:...html#_derived URLs whose target has no explicit [[anchor]] in docs/src. Derived ids come from section titles, so such references break when a title is translated or retitled. Pin the target with an explicit anchor instead. Also pins the remaining lint hits, all same-page links in untranslated man pages (_subcommands, _mbccs_file_format, _modbus_functions, _modbus_types, _hal_types). Explicit ids match the auto-generated ones, so output is unchanged. Turns clean once PR LinuxCNC#4339 lands.
|
But isn't this a general problem, every time a translation alters a header then the link name changes? |
|
Agreed, fixing instances alone is whack-a-mole. That is why this PR is paired with #4340, which adds a CI lint ( On "add the target consistently vs generate automatically": automatic generation is the current state and is precisely what breaks, because the generated id derives from the title text and translations change titles. There is no translation-stable automatic scheme short of asciidoctor inventing language-independent ids, which it does not do. So the convention has to be explicit anchors, and the lint is there to make "consistently" enforceable. The lint starts warn-only for burn-in and can flip to |
|
Yes, and that is what I mean, autogenerate the anchors in the 'en' docs before you put them through translation. Currently, the docs/src for 'en' is just copied (I think), while the translations are built from the docs/src. I suggest to process the 'en' source docs to add the anchors and make the translations use that version. |
|
I looked at autogenerating anchors into the en tree before po4a. It works mechanically, but it has two structural hazards that tipped me toward the lint instead. First, duplicate titles. docs/src has 4,720 sections but only 2,598 distinct derived ids; 173 ids occur in multiple files ( Second, fidelity and churn: the injector must reproduce asciidoctor's id derivation exactly (including duplicate suffixing) or the en build breaks, which practically means driving asciidoctor to compute them; and po4a masters becoming generated files rewrites every The lint in #4340 covers every reference form ( If the preference is still generated anchors, the variant I would pick is a one-time bulk injection into docs/src itself (asciidoctor-computed ids, verified by diffing rendered en html before/after) rather than a build-time stage. That avoids the po4a master churn, but it still needs the resolver same-file preference fix and adds anchor lines to ~2,600 sections. |
|
Ok, the po pollution problem settles it. That just means we have to keep looking at the lint results. Maybe even start to fail eventually when we are stable (can/should we, with translations?). |
|
These are caught before translation |
|
The mechanism, in order:
So a translation can never introduce this class of breakage; it can only inherit already-pinned anchors. That is also what makes failing the build on the lint safe with respect to translations: the lint reads only docs/src, never .po content, so nothing Weblate does can trip it. The failure class that does live inside translations (anchors mangled in msgstr strings) stays with checklink in htmlcheck.sh, which remains warn-only. |
|
I don't think we should ever hard fail on translations, because as far as I understand, to actually fix anything and have it come back here from Weblate, we have to merge what came from Weblate first, before a new push arrives from there. Therefore if we enforce, we will have to merge and break the tree, and the merge the fix, which is not something I think we ever want to do. |
|
You are right. We cannot fail on translation breakage because the fix has to go through weblate. Not a path we want to have because it introduces a third party dependency. |
scripts/docs-anchor-check.py, wired into the htmldocs CI job with --enforce, flags <<_derived>> xrefs and link:...html#_derived URLs whose target has no explicit [[anchor]] in docs/src. Derived ids come from section titles, so such references break when a title is translated or retitled. Pin the target with an explicit anchor instead. The lint reads only the English sources, so translations cannot trip it. Also pins the remaining lint hits, all same-page links in untranslated man pages (_subcommands, _mbccs_file_format, _modbus_functions, _modbus_types, _hal_types). Explicit ids match the auto-generated ones, so output is unchanged. With the five anchors from LinuxCNC#4339 merged, the lint reports the tree clean.
The CI htmldocs job (
scripts/htmlcheck.sh -w, W3C checklink) currently warns about broken URI fragments in the translated HTML docs. One class of those failures comes from sections that are linked to via their auto-generated AsciiDoc id rather than an explicit anchor.Auto-generated ids are derived from the section title (
=== Normal Downloadbecomes_normal_download). When a translation translates the title, the derived id changes (_normales_herunterladen) and every link using the English-derived id breaks in that language. This currently affects the de, es, ru, uk and nb builds:<<_normal_download,...>>and<<_alternate_install_methods,...>>in getting-linuxcnc.adoc<<_latency_tuning>>in latency-test.adoclink:../gui/qtvcp.html#_ini_settings[...]in qtplasmac.adoclink:../man/man1/halcmd.1.html#_commands[...]in qtvcp-widgets.adocThis PR pins the five ids with explicit
[[...]]anchors. The explicit id is identical to the previously auto-generated one, so the English output is unchanged and all existing references (including external deep links) keep working. po4a treats standalone anchor lines as structural and passes them through untranslated, so all translations inherit the stable id without any .po changes.I verified locally that the rendered HTML for all five pages emits the same ids as before. The remaining CI link warnings are mangled anchors inside translated strings in the .po files and have to be fixed on Weblate