Localize: Source to Native-Sounding Translations

Workflow

Transcreates content into every requested language, working each one in its destination file in-place (or inline when none is given), loops fix and audit until each passes native-fluency review, then ends with a per-language summary.

Usage

echo "<your request>" | octomind workflow localize

Reads your request from stdin. Add --dry-run to validate and print the plan without running any steps.

Pipeline

  1. 1 brief Sequential content:translate

    Read the request below and produce a compact work brief containing ONLY: 1. Every requested target language, with locale variant (es-ES not es; infer the most likely variant if only a language name is given), one `<lang…

  2. 2 facts Sequential content:translate

    Build a source fact ledger from the brief below. This is a preservation artifact, not an edit. If the brief lists source file path(s), read every source file now. If it carries pasted content inline, use that content di…

  3. 3 transcreate Sequential content:translate

    Work from the brief below. For EACH requested language: if it's the source's own language, pass the content through with only obvious mechanical fixes (typos, broken syntax) — the loop after this step owns the real AI-s…

  4. 4 polish Loop max 3×
    • fix content:editor continue

      Surgically edit every language in the brief — no scope confirmation needed. A language with a destination path lives in that file: read it, edit it in-place (git-aware, no suffixed copies), and report what changed. An `…

    • audit content:translate fresh

      Audit EVERY language in the brief independently. Read each language's current text from its destination file listed in the brief — that file is the draft under audit; the fix report below only says what changed. An `inl…

  5. 5 deliver Sequential content:translate

    The loop is finished. Every language with a destination path in the brief is already on disk — transcreate wrote it and each fix round edited it in-place — so write nothing, re-edit nothing, and never make editorial dec…

Definition

# Title: Localize: Source to Native-Sounding Translations
#
# Public workflow: transcreate every requested language (parsed from the input
# at runtime — no hardcoded language list), then run a genuine fix <-> audit
# loop, same evaluator-optimizer shape as `develop.toml` / `content.toml`,
# until every language reports PASS or the iteration cap is hit. Finally,
# deliver: return inline any language that has no destination, plus a
# per-language change summary of what was fixed and each language's final
# audit verdict.
#
# One turn covers ALL languages (as N `<lang>`-marked blocks), not a branch
# per language: `loop` cannot dynamically fan out per item (`match` is a
# `parallel`-only feature), and a convergence loop that re-checks its own work
# is worth more than parallel speed here. Add a language by asking for it in
# the input — nothing to edit in this file. Add per-language calibration by
# dropping a new `content-locale-humanize-<code>` skill.
#
# File-first: the `brief` step resolves a destination per language (the path
# the request names or implies, else `inline`). Every later step works on that
# file directly — transcreate writes it, fix edits it in-place, audit reads it
# back — so article text never round-trips through the conversation and each
# step's output is a short report, not the content. Only languages with no
# destination are carried inline and returned by `deliver`.
#
# Include the source's OWN language in the requested list (e.g. source is
# English, ask for "English, Chinese, and Russian") to also run an AI-slop
# check-and-fix pass on the source itself via content-voice/content-humanize —
# every prompt detects the same-language case per-language and switches rubric.
#
# Roles: `content:editor` owns the fix step (diagnose-then-edit specialist —
# surgical fixes per findings is exactly its identity, and the tap's own
# content.toml uses it in the same loop position). `content:translate` owns
# brief/transcreate (cross-language rendering), audit (NATIVE-AUDIT mode), and
# deliver (inline languages plus the per-language summary).
#
# Note: `max_iterations = 3` is a safety ceiling, not the target — research on
# iterative LLM self-refinement (TEaR, Self-Refine) finds quality peaks early
# and can decline with more automated rounds, so this should usually exit via
# `ALL-PASS` well before the cap. If it's still failing at the cap, that's a
# signal to look at the findings, not to raise the cap.
#
# Note: `retries = 4` on every step guards against transient provider or
# network errors — a multi-step pipeline shouldn't lose completed work to one
# failed call.
#
# Input shape: state the target language(s) in plain language, then the source
# content — a file path, multiple file paths, or pasted text, one article or
# several — and a destination path per language. Destinations are optional;
# a language without one comes back inline. Example:
#   Localize into Chinese and Russian:
#   content/english/blog/my-post/index.md
#   Chinese -> content/chinese/blog/my-post/index.md
#   Russian -> content/russian/blog/my-post/index.md
#
# Public roles only.

name        = "localize"
description = "Transcreates content into every requested language, working each one in its destination file in-place (or inline when none is given), loops fix and audit until each passes native-fluency review, then ends with a per-language summary."

# ── 1. Brief — languages, source, and one destination per language ──────────
[[steps]]
name    = "brief"
role    = "content:translate"
session = "fresh"
retries = 4
prompt  = """
Read the request below and produce a compact work brief containing ONLY:

1. Every requested target language, with locale variant (es-ES not es; infer
   the most likely variant if only a language name is given), one
   `<lang>code</lang>` marker per language. Include the source's own language
   too if it's explicitly requested.
2. The source: if the request references file path(s), list the path(s)
   verbatim; if the content is pasted inline, reproduce it in full, unchanged.
3. One destination per language (and per source file, if several): the path
   the request names for that language, or implies (the source file itself
   when the request asks to overwrite it, or when the source's own language
   is requested in-place); otherwise the word `inline`. Never invent a path —
   an unstated destination is `inline`, not a guess.
4. Any reference material the request points at (documentation directories,
   manuals, glossaries) — list those paths verbatim; they ground terminology
   and facts for the later steps. Also check whether THAT reference material
   has variants matching each target language (sibling directories or files
   named by language or locale next to the reference path) and list, per
   language, whichever actually exist — never invent paths you didn't verify.
   This variant discovery applies ONLY to the reference material: the source
   content file and any destination content paths (and their language
   siblings) are NOT reference material — existing translations of the
   content are never a baseline, a draft, or a source of truth; the pipeline
   always produces fresh work from the source.
5. One line naming the content domain (technical, legal, marketing, academic,
   casual, ...), judged from the source.

Do not translate or analyze anything yet. No meta-commentary.

<request>
{{input}}
</request>
"""

# ── 2. Source fact ledger — stable preservation target for every later step ─
[[steps]]
name    = "facts"
role    = "content:translate"
session = "fresh"
retries = 4
prompt  = """
Build a source fact ledger from the brief below. This is a preservation
artifact, not an edit.

If the brief lists source file path(s), read every source file now. If it
carries pasted content inline, use that content directly. Do not use
destination files, existing translations, web search, or general knowledge as
source truth.

Extract EVERY factual data point that must survive localization:
- all numbers, percentages, ranges, dates, versions, counts, measurements,
  prices, durations, limits, and identifiers
- named studies, cited sources, benchmark names, standards, tools, product
  names, people, organizations, URLs, and quoted/cited claims
- multi-part facts as one exact item when the parts depend on each other
  (for example, keep "73% to 83%" as one range, not two loose numbers)

Do not judge whether a fact is "important"; if it is factual, include it.
For each item, preserve the exact source surface form and enough nearby
context to identify where it belongs. If the source contains no factual data
points, output `<source_facts>NONE</source_facts>`.

Output ONLY:
<source_facts>
- F001 | exact: "..." | type: ... | context: ...
- F002 | exact: "..." | type: ... | context: ...
</source_facts>

<brief>
{{brief}}
</brief>
"""

# ── 3. Transcreate every requested language — straight into its file ────────
[[steps]]
name    = "transcreate"
role    = "content:translate"
session = "fresh"
retries = 4
prompt  = """
Work from the brief below. For EACH requested language: if it's the source's
own language, pass the content through with only obvious mechanical fixes
(typos, broken syntax) — the loop after this step owns the real AI-slop pass,
don't duplicate that work here. Otherwise transcreate directly and cleanly
into that language, as a native speaker would write it from scratch — never
literal. Calibrate register and terminology to the brief's content domain.
If the brief lists reference material (documentation, glossaries), consult it
for domain terminology before coining your own renderings. Preserve meaning,
voice, and structure; keep code, placeholders, and URLs verbatim. Carry over
EVERY factual data point from the source — numbers, statistics, percentages,
dates, measurements, named studies, and cited claims — verbatim into every
language; a dropped statistic is a content loss, not a style choice. Use the
source fact ledger below as the explicit preservation checklist: every ledger
item must appear in each requested language with the same numeric bounds,
dates, identifiers, names, and claim meaning. If a fact cannot be rendered
naturally, preserve the exact source form and keep moving; never drop it. If the
brief lists source file path(s), read them; if it carries the content inline,
use it directly; if there are multiple articles/files, process every one.

Delivery, per language: if the brief lists a destination path, write that
language's full transcreation to that file now — the file's new content IS
the transcreation, whole, replacing whatever the file held (in-place,
git-aware: git is the undo history; no `.new`, `.bak`, or suffixed copies).
Never read or reuse what the destination currently holds — the work is fresh
from the source. If the destination is `inline`, output the block in the
conversation instead.

<brief>
{{brief}}
</brief>

<source_fact_ledger>
{{facts}}
</source_fact_ledger>

Output one line per language written to a file — `<lang>code</lang> written:
<path>` — and, for inline languages only, the full block starting with its own
`<lang>code</lang>` marker on its own line. Never paste a written file's
content into the output. No meta-commentary about your own process,
methodology, or tool use.
"""

# ── 4. Fix <-> audit loop — every language together, each round, until clean ─
[[steps]]
name           = "polish"
loop           = true
max_iterations = 3
exit_when      = { output = "audit", matches = '(?m)^ALL-PASS' }

  [[steps.run]]
  name    = "fix"
  role    = "content:editor"
  session = "continue"
  retries = 4
  prompt  = """
Surgically edit every language in the brief — no scope confirmation needed.
A language with a destination path lives in that file: read it, edit it
in-place (git-aware, no suffixed copies), and report what changed. An
`inline` language is edited in the conversation and output in full.

Work ONE language at a time, and between languages take a grounding pause:
before starting each language's edit, view the brief's source file (or the
relevant reference material) to re-anchor terminology and meaning for that
language — then finish that language (file edited, or inline block emitted),
then move to the NEXT language and repeat until every language is done. The
per-language grounding reads come first, every time. Completeness contract:
your final output MUST contain exactly one entry for EVERY language in the
brief — finishing after only some languages is a broken response; before
ending, count your entries against the brief's language list.

THIS round (no auditor findings exist yet): diagnose and fix in one pass,
self-directed. Run the `content-humanize` 7-pass rewrite on the source's own
language, and `content-locale-humanize`'s fix-passes (plus whichever
per-language calibration skill matches) on every other language — interference
and calques first, then frequency outliers, rhythm, register. Edit what the
rubrics actually flag; don't rewrite what already reads native.

LATER rounds: you receive the auditor's findings directly — resolve every
one, criticals first, without reintroducing anything already fixed. A
language the auditor reported no findings against is left untouched (report
it as `unchanged`; an inline language is re-output as is).

Before shortening or varying ANY repeated word: decide whether it NAMES
something (a product, brand, protocol, command, field, person — a referential
word) or is a STYLE choice (an adjective/verb an AI overuses for emphasis).
Only style choices get varied or cut for repetition. A name must repeat
exactly, verbatim, as many times as the content needs it — never shortened,
abbreviated, or swapped for a synonym, no matter how often it appears.

Preserve each language's locale punctuation conventions exactly while
editing — full-width punctuation in CJK text stays full-width; never let an
edit swap in ASCII punctuation where the locale uses its own.

Fact ledger lock: before editing each language and again before outputting it,
check the source fact ledger below. Every listed item must still be present in
that language with the same numeric bounds, dates, identifiers, names, and
claim meaning. Humanization, repetition cleanup, concision, and rhythm edits
are not allowed to remove or blur a ledger item. If the current draft dropped
one, restore it in the closest source-matching location before doing any style
polish.

Match the SOURCE's register: natural and human, never overshooting into
slang or colloquialisms the source doesn't carry — a neutral technical
sentence stays neutral in the target, just native. And render recurring
constructions (mode names, repeated patterns like "in X mode") the same way
every time — one form, used consistently.

Ground every terminology or factual choice in the brief's source and
reference material (read them) — never fill a gap from imagination, and never
justify a rendering by documentation, official usage, or search results you
did not actually open in this session: fabricated authority is a critical
defect, while an honest "unverified" is acceptable. For headings and
recurring domain terms whose target rendering isn't the plainly established
standard, verification is a duty, not a judgment call — check the brief's
language-matching reference material if listed, otherwise run
`content-locale-humanize`'s phrase-verification (exact quoted-phrase
websearch: real native usage found means keep it, nothing found means
rephrase). Feeling certain doesn't waive it. For ordinary prose, verify only
when genuinely unsure — a handful of lookups at most.

<brief>
{{brief}}
</brief>

<source_fact_ledger>
{{facts}}
</source_fact_ledger>

<drafts>
{{transcreate}}
</drafts>

Output, per language: for a file destination, `<lang>code</lang> edited:
<path>` (or `unchanged: <path>`) followed by a short list of what changed;
for an inline language, the full edited block starting with its own
`<lang>code</lang>` marker. Never paste a file's content into the output. No
meta-commentary about your own process.
"""

  [[steps.run]]
  name    = "audit"
  role    = "content:translate"
  session = "fresh"
  retries = 4
  prompt  = """
Audit EVERY language in the brief independently. Read each language's
current text from its destination file listed in the brief — that file is the
draft under audit; the fix report below only says what changed. An `inline`
language's text is the block in the fix report. Judge each against ONLY its
own text, using the brief's source (read the source file if the brief lists a
path) to verify accuracy and completeness, and the brief's reference material
to verify domain terminology. For the source's own language, run the
`content-humanize` 8-dimension diagnostic. For every other language,
NATIVE-AUDIT mode via `content-locale-humanize` (plus whichever per-language
calibration skill matches that language) — never by matching an English
AI-word list. Pick exactly one rubric per language, never both. Check locale
punctuation conventions too (full-width in CJK, target-locale quotation
marks). This step is read-only — report, never edit files.

PHRASE-VERIFICATION PASS (per non-source language, the core naturalness
check): pick the handful of collocations and turns of phrase in that language
you're least sure a native tech reader would actually use — the suspicious
calques, unnatural verb-object pairs, nominal chains, borderline term
renderings. For EACH, run an exact quoted-phrase websearch per
`content-locale-humanize`'s phrase-verification technique (quotes for exact
match; scope to a native-language platform the audience uses when you can;
also try unscoped). Real native hits → the phrase is fine, do NOT flag it.
Zero / no results → it's a genuine finding: report it with a natural
replacement, and verify that replacement the same way before proposing it.
Do not flag a phrase as unnatural on intuition alone once you have a tool to
check — and never claim a search verdict you didn't actually run. In each
language's section list the phrases you verified with their verdict
(found / not found + the query), so the pass is auditable.

FACTUAL-COMPLETENESS PASS (every language, before fluency scoring): use the
source fact ledger below as the canonical checklist. For each language's draft,
verify every ledger item is present with the same numeric bounds, dates,
identifiers, names, and claim meaning. Do not re-decide which facts matter
during audit; the ledger already did that once from the source. A missing or
altered item (e.g. ledger says "73% to 83%" but the draft drops one bound or
the whole range) is a Critical finding — report it with the exact ledger value
and the missing/changed form in the draft. This pass runs on the source's own
language too: the humanize pass can drop data just as easily as translation
can. A language with a missing ledger item cannot PASS, regardless of fluency
score. If the ledger says `<source_facts>NONE</source_facts>`, say so and skip
only this factual-completeness pass.

<brief>
{{brief}}
</brief>

<source_fact_ledger>
{{facts}}
</source_fact_ledger>

<fix_report>
{{fix}}
</fix_report>

FIRST, before any quality judgment, run the completeness check: every
language listed in the brief must have its text present — its destination
file exists and holds that language's content, or its inline block is in the
fix report. A language from the brief with neither gets an automatic
`<code>: FAIL (missing draft)` — no quality audit can rescue an absent text.

For each language present: list findings (severity-ordered, with quotes and
fix direction) if any, then close that language's section with exactly one
line — `<code>: PASS` or `<code>: FAIL`. PASS requires the native-fluency
score in the Pass band AND zero Critical or Moderate findings — a language
with a Moderate finding still listed is a FAIL, because a PASS ends the loop
and whatever you listed would never get applied. Minor polish-level findings
alone don't block a PASS.

Then derive the final line MECHANICALLY against the BRIEF's language list:
if and only if EVERY language in the brief has a verdict line saying PASS,
end the WHOLE response with exactly `ALL-PASS`; otherwise (any FAIL, or any
brief language without a verdict) end with exactly `CONTINUE`. Nothing after
that line.
"""

# ── 5. Deliver — inline languages + per-language summary; files are done ────
[[steps]]
name    = "deliver"
role    = "content:translate"
session = "fresh"
retries = 4
prompt  = """
The loop is finished. Every language with a destination path in the brief is
already on disk — transcreate wrote it and each fix round edited it in-place
— so write nothing, re-edit nothing, and never make editorial decisions of
your own: the loop already made them all. For each `inline` language, output
its final block from `<final>` verbatim, whole.

<brief>
{{brief}}
</brief>

<final>
{{fix}}
</final>

<final_audit>
{{audit}}
</final_audit>

Then give a brief per-language change summary: what was fixed (criticals
first, in plain terms), what was deliberately left unchanged, the language's
final audit verdict (PASS, or FAIL with the top outstanding finding if the
loop hit its cap), and where the final text landed — the destination path,
or "inline". Attribute a choice to reference documentation only if that
material was actually consulted in this pipeline — never assert doc support
that wasn't verified.
"""