Skip to main content
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 under i18n/fr/ with the original paths preserved.

The shape

The file

localization-factory.nika.yaml

How it works

1

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.
2

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.
3

The mirror tree comes out the other end

The final fan-out writes ./i18n/fr/<original path> with create_dirs: true. Path templating is plain ${{ }} interpolation inside a string.

Constructs you just used

Make it yours

  • All your locales: wrap the lang in a list and run per locale, or lift const.lang to 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 glob with exec: git diff --name-only and 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.