AGPL-3.0-or-later · forever.

showcase · tier 3 · content

Localization factory

glob finds every doc, two fan-outs read + translate in parallel, jq zips the mirror tree back.

“Can we have the docs in French?” Yes, by lunch, with the original paths preserved. · conformance-gated in nika-spec ↗ · re-proven at every push

The whole file

6 tasks · 6 waves · the plan falls out of the bindings, nothing is scheduled by hand.

t3-localization-factory.nika.yamlsource
nika: v1workflow:  id: localization-factory  description: "glob docs → parallel read → parallel translate → mirror tree"model: ollama/qwen3.5:4b   # local default · swap for mistral/mistral-large (EU model for EU locales)vars:  lang: "fr"  source_glob: "./docs/**/*.md"tasks:  files:    invoke:      tool: "nika:glob"      args:        pattern: "${{ vars.source_glob }}"        exclude: ["**/node_modules/**"]  texts:    with:      files: ${{ tasks.files.output }}    for_each: ${{ with.files }}    max_parallel: 8    invoke:      tool: "nika:read"      args: { path: "${{ item }}" }  pairs:    with:      files: ${{ tasks.files.output }}      texts: ${{ tasks.texts.output }}    invoke:      tool: "nika:jq"      args:        input: ["${{ with.files }}", "${{ with.texts }}"]        expression: "transpose | map({path: .[0], text: .[1]})"  translated:    with:      pairs: ${{ tasks.pairs.output }}    for_each: ${{ with.pairs }}    max_parallel: 3                    # rate-limit the provider    fail_fast: false                   # finish the batch · a failed file yields null at its index    on_error:      recover: null                    # null keeps the transpose zip aligned (order preserved)    infer:      prompt: |        Translate to ${{ vars.lang }} · keep markdown structure, code blocks        untouched, and the original tone ·        ${{ item.text }}  bundle:    with:      pairs: ${{ tasks.pairs.output }}      translated: ${{ tasks.translated.output }}    invoke:      tool: "nika:jq"      args:        input: ["${{ with.pairs }}", "${{ with.translated }}"]        expression: "transpose | map(select(.[1] != null)) | map({path: .[0].path, text: .[1]})"  mirror:    with:      bundle: ${{ tasks.bundle.output }}    for_each: ${{ with.bundle }}    max_parallel: 8    invoke:      tool: "nika:write"      args:        path: "./i18n/${{ vars.lang }}/${{ item.path }}"        content: "${{ item.text }}"        create_dirs: trueoutputs:  files:    value: ${{ tasks.files.output }}    description: "Every source file that was mirrored"

nika inspect · engine 0.105.0 · vendored graph, never re-derived

7 declared edges · 6 waves · the plan falls out of the bindings