hack/check-i18n.sh exits 1 on a clean checkout of main, so the i18n lint workflow fails on every pull request that touches content/** — including pull requests that change nothing about translations.
Reproducing it
git worktree add --detach /tmp/wsmain origin/main
cd /tmp/wsmain && ./hack/check-i18n.sh; echo "exit=$?"
Exit code is 1 and the output carries four ::error::stale translation lines, all for the same English source:
content/en/blog/2026-05-19-introducing-cozystack-wizard/index.md
The recorded digest is sha256:6f37e3e1… and the current one is sha256:2d13272f…, for the de, ru, zh-cn and one further translation of that post.
Mechanism
The English source was edited by 4b5d1ad ("chore(blog): repair front matter, links and bundle names"), which is an ancestor of main. Editing an English page changes its digest, so every recorded translation digest for that page goes stale until either the translations are refreshed or the digests are updated.
.github/workflows/i18n-lint.yml runs on pull_request with paths: content/**, so any content change picks up a red check for a break it did not introduce. The same workflow also runs on push to main, which is where this first became visible.
Impact
Every content pull request currently shows a failing required-looking check, and the failure names files the author never touched. The cost is not the red mark itself — it is that a genuinely stale translation introduced by a later pull request is indistinguishable from this pre-existing noise, so the check stops carrying information exactly where it was supposed to.
Fix shape
Two halves, and they are not interchangeable.
The honest fix is to refresh the four translations against the current English source and then run hack/check-i18n.sh update-digests, which is what the script's own hint tells the author to do.
Running update-digests alone would turn the check green while leaving the translations stale — it records that the current state is approved. That is available as a deliberate decision if the edits in 4b5d1ad were cosmetic enough not to affect the translated text, but it should be taken knowingly and said out loud in the commit, not reached for because it is the one-line option.
hack/check-i18n.shexits 1 on a clean checkout ofmain, so thei18n lintworkflow fails on every pull request that touchescontent/**— including pull requests that change nothing about translations.Reproducing it
Exit code is 1 and the output carries four
::error::stale translationlines, all for the same English source:The recorded digest is
sha256:6f37e3e1…and the current one issha256:2d13272f…, for thede,ru,zh-cnand one further translation of that post.Mechanism
The English source was edited by
4b5d1ad("chore(blog): repair front matter, links and bundle names"), which is an ancestor ofmain. Editing an English page changes its digest, so every recorded translation digest for that page goes stale until either the translations are refreshed or the digests are updated..github/workflows/i18n-lint.ymlruns onpull_requestwithpaths: content/**, so any content change picks up a red check for a break it did not introduce. The same workflow also runs on push tomain, which is where this first became visible.Impact
Every content pull request currently shows a failing required-looking check, and the failure names files the author never touched. The cost is not the red mark itself — it is that a genuinely stale translation introduced by a later pull request is indistinguishable from this pre-existing noise, so the check stops carrying information exactly where it was supposed to.
Fix shape
Two halves, and they are not interchangeable.
The honest fix is to refresh the four translations against the current English source and then run
hack/check-i18n.sh update-digests, which is what the script's own hint tells the author to do.Running
update-digestsalone would turn the check green while leaving the translations stale — it records that the current state is approved. That is available as a deliberate decision if the edits in4b5d1adwere cosmetic enough not to affect the translated text, but it should be taken knowingly and said out loud in the commit, not reached for because it is the one-line option.