Adding a language: what Bahasa Melayu taught, and who the script is actually for
Four additions, all from doing ms (24th locale) rather than from theory.
WHO THE SCRIPT IS FOR. The page reproduced a Claude Code workflow as though it
were the process. It is not: Workflow/agent/pipeline are harness APIs, so a
contributor without Claude Code could not run a line of it, and it carried the
maintainer's own machine path. Now split explicitly -- the PROMPT and the
VERIFICATION are the reusable artefacts and work for a human translator, another
tool or an agency; the orchestration is one maintainer's tooling. Paths
generalised.
MODEL GUIDANCE. Run the agents on Sonnet, not Opus: the failure modes that matter
are instruction-following, and step 3 catches every one mechanically, so the
larger model buys quality where it cannot show. ms was done this way with zero
structural faults. And use ONE model for the whole locale -- mixing them risks an
inconsistent register within a single language, which is worse than either alone.
TICKETS IS TOO BIG FOR ONE AGENT. At ~1,550 keys a single agent spent twenty
minutes WITHOUT EVER ATTEMPTING A WRITE -- it read the source, then went grepping
its sibling locale files to see how "Save" and "Delete" had already been
translated, then started a task list about terminology. Not a crash, not a hang,
not a truncated file: the transcript kept growing, and the tell was writes=0
after twenty minutes while its siblings finished in two. The fix is three
changes, all needed: split by top-level section into six chunks that write
fragments; HAND the agent lang/<code>/common.php as the only consistency
reference so there is nothing to go looking for; and tell it plainly not to
research, naming the failure.
CHECK 5 — SIBLING-LANGUAGE DRIFT. New, and no structural check can ever catch it:
a translator drifts between closely related languages while the file parses, every
key is present and every placeholder survives. Applies to ms/id, nb/nn, and any
Iberian or Serbo-Croatian variants added later. The defence is a word list used
twice -- as a "use this NOT that" table in the prompt, and as a grep afterwards.
For ms/id the decisive marker is bisa vs boleh: ms came out 432 boleh, zero bisa.
Also records banning false friends outright -- "kereta" is car in Malay and train
in Indonesian, the class of error that produces confident nonsense.
Plus two smaller ones in step 4: update the README language count (a number in
prose, so nothing reports it stale), and register the locale LAST on a live
install, because a file mid-write is unparseable and a registered locale with an
unparseable file is a fatal rather than a fallback.
Add the 'Adding a Language' developer guide, and refresh the locale list
The workflow script that translated all 23 modules into pt-BR lived in a session
temp directory and was deleted with that session, so the next language had to
start by rewriting it from memory. The script is now reproduced in full, along
with the two non-obvious decisions in it (no StructuredOutput, because it failed
silently on files over ~350 keys; pt-BR as a structural template only) and the
four verification checks — the placeholder one especially, since a key can pass
both the count and the set check and still be broken.
Internationalisation: the locale table said 20 and had never listed uk. Now 23,
with nb and nn added.