Skip to content

Configure a translation provider (Cloudflare Workers AI) to turn the translation workflow back on #141

Description

@darksidemilk

Automated translation has been off since GitHub retired GitHub Models on 30 July 2026 (every request now returns 410). The pipeline it was built on is intact — what is missing is a provider.

This is configuration, not code. .github/workflows/translate.yml is gated on the TRANSLATE_ENDPOINT repository variable: unset, every run skips cleanly. Setting it, plus TRANSLATE_MODEL and the TRANSLATE_API_KEY secret, turns the workflow on with no change to scripts/translate.mjs.

What to do

translations/README.md is the step-by-step — creating the Cloudflare account, minting a scoped API token, the curl smoke test, and the three repository settings. In short:

  • Secret TRANSLATE_API_KEY — the Cloudflare API token
  • Variable TRANSLATE_ENDPOINThttps://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/ai/v1/chat/completions
  • Variable TRANSLATE_MODEL@cf/zai-org/glm-4.7-flash

Cloudflare Workers AI is OpenAI-compatible and takes the same bearer header the script already sends, which is why no code changes.

Why Cloudflare and not something else

Two options look right and are not, both already investigated:

  • Azure Translator has the biggest free tier (F0, 2M characters/month) and cannot do this job. It takes no prompt, so the terminology glossary has nowhere to go, and its textType is plain/html only — wikilinks and fenced code do not survive, and checkStructure rejects essentially every page.
  • Azure Foundry Models would drop straight in but is pay-per-token with no free allowance.

An open-source project cannot carry a per-token bill, which is the constraint that picked Cloudflare: the Workers Free plan includes 10,000 Neurons/day, resetting 00:00 UTC.

The current backlog, and what the free tier can and cannot do

7 languages are configured in translations/languages.json. Only French is seeded:

Language Pages present --dry-run says would translate
fr French 99 28
es Spanish 0 104
de German 0 104
zh-cn Chinese (Simplified) 0 104
pt-br Portuguese (Brazil) 0 104
it Italian 0 104
ja Japanese 0 104

That is ~650 page-translations. 10,000 Neurons/day is enough to track changes to docs/, not to seed a language from nothing — which is what the script's request budget and the workflow's nightly drain are already shaped around. So the expected split is:

  1. Turn the workflow on so fr's 28 drifted pages are picked up and docs/ stops drifting further.
  2. Seed the six empty languages in bulk by hand. translations/SEEDING.md has the full recipe and its gotchas — it is how the French tree was built.

Note the six empty languages are not currently broken for readers: quartz/scripts/rtd-build.mjs lays each language over a copy of docs/, so an untranslated page falls back to English rather than 404ing. Each also needs its own Read the Docs project (same repo, same branch, differing only in the Language setting) before it is reachable.

Acceptance

  • Cloudflare account + scoped API token created, curl smoke test in translations/README.md returns a completion
  • The secret and two variables set on this repository
  • translate.yml runs green on a push touching docs/** and opens/updates its commit
  • node scripts/translate.mjs fr --verify no worse than before (see below)
  • A spot-check that the injected machine-translation banner and the gettext glossary are both being applied — the glossary is not cosmetic: FOG's French UI calls a Host a Machine, not an Hôte, and without it the docs name buttons that are not on the reader's screen

Note on --verify baseline

fr currently fails --verify on 20 pages (15 before #140, which changed English pages the French tree has not caught up with). That is the expected stale state, not a regression — those pages are queued in --dry-run and regenerate once a provider exists. Worth capturing the number before flipping the switch so the improvement is visible.

Everything that does not call a model still works today: --dry-run reports drift, and --verify/--relink are unaffected.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CVRiHn5P4C15Lu3LxGtN8g

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions