T3 fan-out · product / content / i18n — three chained fan-outs
(read-all → translate-all → write-all) with jq transpose zipping
paths back to texts between stages. The masterclass file for
collections.
The job
« Can we have the docs in French? » is weeks of copy-paste, or it’s this file: glob finds every markdown file, the texts are read and translated in parallel (rate-limited so the provider doesn’t choke), and the mirror tree appears underi18n/fr/ with the original paths preserved.
The shape
The file
t3-localization-factory.nika.yaml
How it works
The filesystem is the collection
nika:glob returns the file list at runtime — add a doc tomorrow,
it’s in the next run. exclude: keeps node_modules out.transpose zips parallel arrays
Two fan-outs produce two aligned arrays (paths, texts). The jq
transpose | map({path: .[0], text: .[1]}) zip turns them into
[{path, text}] — and ${{ item.path }} works, because loop-locals
are full objects.Constructs you just used
Make it yours
- All your locales: wrap the lang in a list and run per locale — or lift
vars.langto a typed required input and call the workflow per language. - Glossary discipline: interpolate your terminology table into the translate prompt so product names never drift.
- Only what changed: replace
globwithexec: git diff --name-onlyand translate the delta (PR review fan-out starts the same way).
Next · Config drift sentinel
RFC 7396 merge-patch + RFC 6902 diff — jq decides, the model only
explains.