Skip to content

Multi-Language Support

Ways runs in one of two modes, decided by a single switch. English is the source of truth; localization is adopter-run — a non-English speaker opts in and the framework translates itself, validated against the English root (ADR-139). This page is the reference; the lifecycle and rationale live in the localization explanation pages (01.009.E–01.013.E) and the evidence record ADR-183.

The two modes

The switch is the resolved Config.language:

Mode When What runs
English (default) language is en / auto / unset English corpus + English (384-dim) matching only. The 127MB multilingual model is never downloaded or loaded. No locale tuning. The intl pipeline is dormant — zero cost.
Localized language is a specific non-English code (e.g. es) The multilingual corpus is built with the English root as anchor, the 768-dim multilingual lane runs as a second lane, and ways tune locale --lang audits the localization.

Both modes match by the same rule (see matching.md and engine-reference.md). The difference is the model, not the method.

Setting the switch — two configs

There are two different language settings; conflating them is the common mistake:

Config Controls Set by
language in ~/.config/agent-ways/config.yaml the ways intl mode + the output-language directive ways-localize
language in Claude Code settings.json (a NAME, e.g. "spanish") Claude Code's response language the operator (or ways-localize)

The effective switch is the user-scope config.yaml language (default auto; ways.language in ways settings), the layer ways-localize writes. Setting Claude Code's settings.json language alone does nothing to ways, and nothing reports the mismatch. To localize ways, the operator asks for it, which invokes the ways-localize skill.

Localizing — the ways-localize skill

Localization is one operation, run on demand:

"set up ways in Spanish"  →  ways-localize skill

It interviews for the language, gets consent (the model download + all-ways pass is heavy), flips the switch, fetches the multilingual model on demand (make -C tools/way-embed model-multilingual), translates every way's description+vocabulary against the English root, rebuilds the corpus, runs ways tune locale --lang <code> until clean, and sets Claude Code's own language. See the skill (skills/ways-localize/) and scenario 01.011.E.

The embedding models

Model File Size Role
all-MiniLM-L6-v2 minilm-l6-v2.gguf 21MB English lane (384-dim) — always present
paraphrase-multilingual-MiniLM-L12-v2 multilingual-minilm-l12-v2-q8.gguf 127MB Multilingual lane (768-dim, 52 langs) — on-demand, localized mode only

An install fetches only the English model. The multilingual model is fetched by ways-localize (or make -C tools/way-embed model-multilingual) when an adopter localizes — English installs never pay for it.

The English-root anchor

In localized mode, each way contributes two kinds of entry to the multilingual corpus:

  • the English root — the way's English description+vocabulary, embedded with the multilingual model. This is the per-way anchor, the source of truth in multilingual space.
  • the locale aliases — one .locales.jsonl line per localized language, generated by ways-localize.

Every alias is scored against the root, never against sibling translations — which is what keeps a multilingual install from drifting into a free-for-all with no fixed meaning. A localized way matches a native-language prompt via its alias; the way's English body is still injected (the guidance text — Claude reads it in any language).

Locale stub format

One .locales.jsonl file per way, co-located with its .md, one line per language:

{"lang":"es","description":"seguridad general, codificación segura","vocabulary":"seguridad vulnerable defensa owasp"}

Just lang, description, vocabulary — no per-stub threshold, and no per-way threshold anywhere: firing is the global τ_s / τ_k on the calibrated g(s), never a per-node or per-locale threshold (see engine-reference.md). A full native-language way can override a stub by existing as security.es.md. New/edited ways are authored English-only; ways-localize derives the locale layer.

Tuning — the acceptance gate

ways tune locale is the localized-mode acceptance gate. Fidelity is alignment to the English root; discrimination is non-collision with other ways. It is never invoked in English mode.

ways tune locale                    # audit the active localized language
ways tune locale --lang es          # scope to one language
ways tune locale --way security     # scope to one way
ways tune locale --json

Re-author flagged stubs and re-run until clean. See the meta/knowledge/optimization/tuning way for the failure modes and fixes.

Output language

The effective Config.language also drives the output-language directive injected by core.md: in localized mode the agent writes commit messages, comments, and prose in that language. Way content stays English (the guidance text); only generated output changes.

Checking status

ways tune language          # resolved language, model availability, per-way locale coverage
ways tune language --json   # machine-readable (resolved_language, models, locales_found)

Architecture

  • ADR-139 — adopter-run localization (the two modes, the shelve, root-anchoring)
  • ADR-125 — the coordinate-alias model (description+vocabulary as embedding-space alias)
  • ADR-107 — original locale support and the dual-model approach (superseded in part)
  • ADR-183 — the tuning mechanics (evidence record)