Internationalization (i18n)

Architect CLI supports English (default) and Spanish for all system-generated messages: human logs, agent prompts, reports, guardrails, and evaluations.

v1.1.0: System messages are now in English by default. You can switch to Spanish via configuration.


Configuration

Via YAML

# config.yaml (or .architect.yaml)
language: es   # "en" (default) | "es"

Via environment variable

export ARCHITECT_LANGUAGE=es

Via code (for extensions)

from architect.i18n import set_language, get_language

set_language("es")
print(get_language())  # "es"

Precedence

1. Code defaults → "en"

2. YAML file → language: es

3. Environment variable → ARCHITECT_LANGUAGE=es

What changes with language

ComponentAffected by languageEN ExampleES Example
HUMAN Logs (stderr)YesStep 1 → LLM callPaso 1 → Llamada al LLM
Agent prompts (system)YesYou are a careful executor...Eres un ejecutor cuidadoso...
Reports (markdown/JSON)Yes## Code Health Delta## Delta de Salud del Código
Guardrails messagesYesSensitive file blocked...Archivo sensible bloqueado...
Close instructionsYesYour budget is exhausted...Tu presupuesto se ha agotado...
Context summariesYes[Summary of previous steps][Resumen de pasos anteriores]
Self-evaluator promptsYesOriginal task:Tarea original:
Ralph Loop progressYes# Ralph Loop — Progress# Ralph Loop — Progreso
CLI help/flagsNo--mode yolo--mode yolo
User promptsNo(no change)(no change)
Error messages (CLI)No(always English)(always English)

What does NOT change

  • CLI help text: architect --help, architect run --help, etc. are always in English.
  • User prompts: the text the user writes is not translated.
  • Skills and .architect.md: project file content is not translated.
  • File names: SKILL.md, memory.md, etc. keep their names.
  • JSON output format: JSON keys (status, final_output, etc.) do not change.

Architecture

Module src/architect/i18n/

src/architect/i18n/
├── __init__.py    # Public API: t(), set_language(), get_language(), get_prompt()
├── registry.py    # LanguageRegistry — thread-safe singleton with fallback chain
├── en.py          # English strings (canonical, ~160 keys)
└── es.py          # Spanish strings (~160 keys)

Public API

FunctionDescription
t(key, **kwargs)Translate a key with optional interpolation
get_prompt(key)Get a multiline prompt for the current language
set_language(lang)Set the active language ("en" or "es")
get_language()Return the current language code

Fallback chain

When looking up a key, the registry follows this chain:

current language → English (fallback) → raw key (last resort)

This guarantees the application never breaks even if a translation is missing: if a key doesn’t exist in Spanish, the English version is used. If it doesn’t exist in English either, the key is returned as a string.

Lazy resolution

All translations are resolved at runtime, not at import-time. This is critical because set_language() is called after modules are imported (when the user’s configuration is loaded).

Lazy mechanisms include:

  • _PromptProxy in agents/prompts.py: DEFAULT_PROMPTS["build"] resolves via get_prompt() on each access.
  • _LazyAgentDict in agents/registry.py: DEFAULT_AGENTS["build"] builds the AgentConfig with the current language’s prompt.
  • _LazyPrompt and _LazyStr: wrappers for REVIEW_SYSTEM_PROMPT and BUILD_PROMPT that resolve on .format() or str().

Key namespaces

The ~160 keys are organized into 14 namespaces:

NamespaceKeysWhat it covers
human.*~41HumanFormatter: step logs, tools, safety nets, pipeline, ralph, reviewer, parallel, competitive, context
competitive.*~17Competitive evaluation report: headers, ranking, details
ralph.*~16Iteration progress, specification prompts
eval.*~15Self-evaluator: system prompt, labels, corrections
health.*~14Code health delta: title, headers, metrics
dispatch.*~13Sub-agents: prompts, instructions, types
guardrail.*~10Block messages: sensitive, protected, commands, limits
context.*~9Context summary, headers, omission messages
pipeline.*~7Pipeline YAML validation: errors
close.*~5Close instructions: budget, max_steps, timeout, context_full, interrupt
prompt.*~5Agent system prompts: build, plan, resume, review
reviewer.*~5Auto-reviewer: system prompt, labels
dryrun.*~3Dry-run summary: headers, labels
misc.*Skills headers, pipeline labels

Usage examples

Change language in config

# config.yaml
language: es

llm:
  model: gpt-4o
architect run "analyze the project" --mode yolo
# Logs on stderr are shown in Spanish:
# 🔄 Paso 1 → Llamada al LLM (5 mensajes)
#    ✓ LLM respondió con 2 tool calls
# ...
# ✅ Agente completado (3 pasos)

Change language with env var

ARCHITECT_LANGUAGE=es architect run "analyze the project" --mode yolo

Verify language via code

from architect.i18n import t, set_language

# English (default)
print(t("human.llm_call", step=1, messages=5))
# → "\n🔄 Step 1 → LLM call (5 messages)"

set_language("es")
print(t("human.llm_call", step=1, messages=5))
# → "\n🔄 Paso 1 → Llamada al LLM (5 mensajes)"

Adding a new language

To add support for a third language (for example, French):

1. Create the strings file

# src/architect/i18n/fr.py
"""French language strings for architect-cli."""

STRINGS: dict[str, str] = {
    "human.llm_call": "\n🔄 Étape {step} → Appel LLM ({messages} messages)",
    "human.llm_response_tools": "   ✓ LLM a répondu avec {count} appel{s} d'outil",
    # ... all ~160 keys
}

2. Register in the registry

# src/architect/i18n/registry.py — in _load_defaults()
def _load_defaults(self):
    from . import en, es, fr
    self._languages["en"] = en.STRINGS
    self._languages["es"] = es.STRINGS
    self._languages["fr"] = fr.STRINGS

3. Update the config schema

# src/architect/config/schema.py
class AppConfig(BaseModel):
    language: Literal["en", "es", "fr"] = "en"

4. Verify key parity

from architect.i18n.en import STRINGS as EN
from architect.i18n.fr import STRINGS as FR

missing = set(EN) - set(FR)
extra = set(FR) - set(EN)
assert not missing, f"Missing in FR: {missing}"
assert not extra, f"Extra in FR: {extra}"

FileRole
src/architect/i18n/__init__.pyPublic API
src/architect/i18n/registry.pyLanguageRegistry singleton
src/architect/i18n/en.pyEnglish strings (~160 keys)
src/architect/i18n/es.pySpanish strings (~160 keys)
src/architect/config/schema.pylanguage: Literal["en", "es"] field in AppConfig
src/architect/config/loader.pyARCHITECT_LANGUAGE env var reading
src/architect/cli.pyset_language(config.language) at startup
tests/test_i18n/test_i18n.py~25 tests for the i18n system