"""Locale helpers for Homebase MCP tool metadata."""

from __future__ import annotations

from copy import deepcopy
from dataclasses import dataclass
from typing import Any

DEFAULT_LOCALE = "en"
SUPPORTED_LOCALES = ("en", "de", "es", "zh", "ja", "ru")

ALIASES = {
    "en-us": "en",
    "en-gb": "en",
    "de-de": "de",
    "de-at": "de",
    "de-ch": "de",
    "es-es": "es",
    "es-mx": "es",
    "zh-cn": "zh",
    "zh-hans": "zh",
    "ja-jp": "ja",
    "ru-ru": "ru",
    "ru-by": "ru",
    "zh-sg": "zh",
    "zh-hk": "zh",
    "zh-tw": "zh",
    "es-419": "es",
    "es-ar": "es",
    "es-cl": "es",
    "es-co": "es",
}

DEFAULT_SCHEMA_DESCRIPTIONS: dict[str, str] = {
    "args": "Optional argument object.",
    "agent_id": "Agent identifier for provenance or filtering.",
    "battery": "Test battery name.",
    "category": "Category filter or category to store.",
    "chain": "Automation chain name.",
    "chunks": "Task chunks to assign across workers.",
    "confidence": "Confidence score from 0 to 1.",
    "connector": "Connector name.",
    "constraints": "Optional routing constraints such as provider, model, speed, cost, or token budget.",
    "content": "Content text.",
    "description": "Optional description.",
    "dry_run": "Preview the operation without applying changes.",
    "focus": "Optional topic focus.",
    "format": "Output format.",
    "id": "Numeric entry ID.",
    "input": "Input payload for the operation.",
    "key": "Entry key.",
    "limit": "Maximum number of results to return.",
    "max_tokens": "Approximate token budget.",
    "message": "Message text.",
    "path": "Local filesystem path.",
    "plugin": "Plugin name.",
    "priority": "Task priority.",
    "prompt": "Prompt text to analyze or route.",
    "probe_id": "Probe result ID.",
    "quality": "Quality rating from 0 to 1.",
    "question": "Question to evaluate by consensus.",
    "query": "Search query.",
    "route_id": "Routing decision ID.",
    "run_id": "Automation run ID.",
    "source": "Source URL or file path.",
    "status": "Status filter.",
    "strategies": "Discovery strategies to use.",
    "subtasks": "Optional subtasks for hierarchy planning.",
    "tags": "List of tags.",
    "target": "Connector target, channel, or chat ID.",
    "task": "Task description.",
    "task_id": "Task ID.",
    "test": "Optional single test name.",
    "title": "Task title.",
    "type": "Memory type.",
    "url": "URL to inspect.",
    "value": "Entry value.",
    "voters": "Number of independent voters to plan.",
    "workers": "Number of parallel workers to plan.",
    "iterations": "Number of coordination iterations to plan.",
}

SCHEMA_TRANSLATIONS: dict[str, dict[str, str]] = {
    "de": {
        "args": "Optionales Argumentobjekt.",
        "agent_id": "Agentenkennung für Herkunft oder Filterung.",
        "battery": "Name der Test-Batterie.",
        "category": "Kategoriefilter oder zu speichernde Kategorie.",
        "chain": "Name der Automatisierungskette.",
        "chunks": "Task-Abschnitte, die auf Worker verteilt werden.",
        "confidence": "Konfidenzwert von 0 bis 1.",
        "connector": "Name des Connectors.",
        "constraints": "Optionale Routing-Vorgaben wie Provider, Modell, Tempo, Kosten oder Token-Budget.",
        "content": "Inhaltstext.",
        "description": "Optionale Beschreibung.",
        "dry_run": "Operation nur vorab anzeigen, ohne Änderungen anzuwenden.",
        "focus": "Optionaler Themenfokus.",
        "format": "Ausgabeformat.",
        "id": "Numerische Eintrags-ID.",
        "input": "Eingabedaten für die Operation.",
        "key": "Eintragsschlüssel.",
        "limit": "Maximale Anzahl zurückzugebender Ergebnisse.",
        "max_tokens": "Ungefähres Token-Budget.",
        "message": "Nachrichtentext.",
        "path": "Lokaler Dateisystempfad.",
        "plugin": "Plugin-Name.",
        "priority": "Task-Priorität.",
        "prompt": "Prompt-Text, der analysiert oder geroutet werden soll.",
        "probe_id": "ID des Probe-Ergebnisses.",
        "quality": "Qualitätsbewertung von 0 bis 1.",
        "question": "Frage, die per Konsens bewertet werden soll.",
        "query": "Suchanfrage.",
        "route_id": "ID der Routing-Entscheidung.",
        "run_id": "ID des Automatisierungslaufs.",
        "source": "Quell-URL oder Dateipfad.",
        "status": "Statusfilter.",
        "strategies": "Zu verwendende Discovery-Strategien.",
        "subtasks": "Optionale Teilaufgaben für die Hierarchieplanung.",
        "tags": "Liste von Tags.",
        "target": "Connector-Ziel, Kanal oder Chat-ID.",
        "task": "Task-Beschreibung.",
        "task_id": "Task-ID.",
        "test": "Optionaler Einzeltestname.",
        "title": "Task-Titel.",
        "type": "Memory-Typ.",
        "url": "Zu prüfende URL.",
        "value": "Eintragswert.",
        "voters": "Anzahl unabhängiger Voter, die geplant werden sollen.",
        "workers": "Anzahl paralleler Worker, die geplant werden sollen.",
        "iterations": "Anzahl geplanter Koordinationsiterationen.",
    },
    "es": {
        "args": "Objeto opcional de argumentos.",
        "agent_id": "Identificador del agente para procedencia o filtrado.",
        "battery": "Nombre de la batería de pruebas.",
        "category": "Filtro de categoría o categoría a guardar.",
        "chain": "Nombre de la cadena de automatización.",
        "chunks": "Fragmentos de la tarea para asignar entre trabajadores.",
        "confidence": "Puntuación de confianza de 0 a 1.",
        "connector": "Nombre del conector.",
        "constraints": "Restricciones opcionales de enrutamiento, como proveedor, modelo, velocidad, coste o presupuesto de tokens.",
        "content": "Texto del contenido.",
        "description": "Descripción opcional.",
        "dry_run": "Vista previa sin aplicar cambios.",
        "focus": "Enfoque temático opcional.",
        "format": "Formato de salida.",
        "id": "ID numérico de la entrada.",
        "input": "Datos de entrada para la operación.",
        "key": "Clave de la entrada.",
        "limit": "Número máximo de resultados.",
        "max_tokens": "Presupuesto aproximado de tokens.",
        "message": "Texto del mensaje.",
        "path": "Ruta local del sistema de archivos.",
        "plugin": "Nombre del plugin.",
        "priority": "Prioridad de la tarea.",
        "prompt": "Texto del prompt que se debe analizar o enrutar.",
        "probe_id": "ID del resultado de exploración.",
        "quality": "Valoración de calidad de 0 a 1.",
        "question": "Pregunta que se debe evaluar por consenso.",
        "query": "Consulta de búsqueda.",
        "route_id": "ID de la decisión de enrutamiento.",
        "run_id": "ID de la ejecución de automatización.",
        "source": "URL de origen o ruta de archivo.",
        "status": "Filtro de estado.",
        "strategies": "Estrategias de descubrimiento a usar.",
        "subtasks": "Subtareas opcionales para la planificación jerárquica.",
        "tags": "Lista de etiquetas.",
        "target": "Destino, canal o chat del conector.",
        "task": "Descripción de la tarea.",
        "task_id": "ID de la tarea.",
        "test": "Nombre opcional de una prueba individual.",
        "title": "Título de la tarea.",
        "type": "Tipo de memoria.",
        "url": "URL a inspeccionar.",
        "value": "Valor de la entrada.",
        "voters": "Número de votantes independientes que se deben planificar.",
        "workers": "Número de trabajadores paralelos que se deben planificar.",
        "iterations": "Número de iteraciones de coordinación que se deben planificar.",
    },
    "zh": {
        "args": "可选参数对象。",
        "agent_id": "用于来源记录或过滤的智能体标识。",
        "battery": "测试集名称。",
        "category": "类别过滤器或要保存的类别。",
        "chain": "自动化链名称。",
        "chunks": "要分配给工作者的任务片段。",
        "confidence": "0 到 1 的置信度分数。",
        "connector": "连接器名称。",
        "constraints": "可选路由约束，例如提供方、模型、速度、成本或 token 预算。",
        "content": "内容文本。",
        "description": "可选描述。",
        "dry_run": "仅预览操作，不应用更改。",
        "focus": "可选主题焦点。",
        "format": "输出格式。",
        "id": "数字条目 ID。",
        "input": "操作输入数据。",
        "key": "条目键。",
        "limit": "返回结果的最大数量。",
        "max_tokens": "近似 token 预算。",
        "message": "消息文本。",
        "path": "本地文件系统路径。",
        "plugin": "插件名称。",
        "priority": "任务优先级。",
        "prompt": "要分析或路由的提示文本。",
        "probe_id": "探测结果 ID。",
        "quality": "0 到 1 的质量评分。",
        "question": "要通过共识评估的问题。",
        "query": "搜索查询。",
        "route_id": "路由决策 ID。",
        "run_id": "自动化运行 ID。",
        "source": "来源 URL 或文件路径。",
        "status": "状态过滤器。",
        "strategies": "要使用的发现策略。",
        "subtasks": "用于层级规划的可选子任务。",
        "tags": "标签列表。",
        "target": "连接器目标、频道或聊天 ID。",
        "task": "任务描述。",
        "task_id": "任务 ID。",
        "test": "可选单项测试名称。",
        "title": "任务标题。",
        "type": "记忆类型。",
        "url": "要检查的 URL。",
        "value": "条目值。",
        "voters": "要规划的独立投票者数量。",
        "workers": "要规划的并行工作者数量。",
        "iterations": "要规划的协调迭代次数。",
    },
    "ja": {
        "args": "任意の引数オブジェクト。",
        "agent_id": "来歴または絞り込み用のエージェント ID。",
        "battery": "テストバッテリー名。",
        "category": "カテゴリフィルター、または保存するカテゴリ。",
        "chain": "自動化チェーン名。",
        "chunks": "ワーカーに割り当てるタスクの分割単位。",
        "confidence": "0 から 1 の信頼度スコア。",
        "connector": "コネクタ名。",
        "constraints": "プロバイダー、モデル、速度、コスト、トークン予算などの任意のルーティング制約。",
        "content": "内容テキスト。",
        "description": "任意の説明。",
        "dry_run": "変更を適用せずに操作をプレビューします。",
        "focus": "任意のトピック焦点。",
        "format": "出力形式。",
        "id": "数値のエントリ ID。",
        "input": "操作への入力データ。",
        "key": "エントリキー。",
        "limit": "返す結果の最大数。",
        "max_tokens": "おおよそのトークン予算。",
        "message": "メッセージ本文。",
        "path": "ローカルファイルシステムパス。",
        "plugin": "プラグイン名。",
        "priority": "タスク優先度。",
        "prompt": "分析またはルーティングするプロンプト本文。",
        "probe_id": "探査結果 ID。",
        "quality": "0 から 1 の品質評価。",
        "question": "コンセンサスで評価する質問。",
        "query": "検索クエリ。",
        "route_id": "ルーティング判断 ID。",
        "run_id": "自動化実行 ID。",
        "source": "ソース URL またはファイルパス。",
        "status": "ステータスフィルター。",
        "strategies": "使用する検出戦略。",
        "subtasks": "階層計画用の任意のサブタスク。",
        "tags": "タグの一覧。",
        "target": "コネクタの宛先、チャンネル、またはチャット ID。",
        "task": "タスク説明。",
        "task_id": "タスク ID。",
        "test": "任意の単体テスト名。",
        "title": "タスクタイトル。",
        "type": "メモリ種別。",
        "url": "確認する URL。",
        "value": "エントリ値。",
        "voters": "計画する独立投票者数。",
        "workers": "計画する並列ワーカー数。",
        "iterations": "計画する協調イテレーション数。",
    },
    "ru": {
        "args": "Необязательный объект аргументов.",
        "agent_id": "Идентификатор агента для происхождения или фильтрации.",
        "battery": "Название набора тестов.",
        "category": "Фильтр категории или категория для сохранения.",
        "chain": "Название цепочки автоматизации.",
        "chunks": "Фрагменты задачи для распределения между исполнителями.",
        "confidence": "Оценка уверенности от 0 до 1.",
        "connector": "Название коннектора.",
        "constraints": "Необязательные ограничения маршрутизации: провайдер, модель, скорость, стоимость или бюджет токенов.",
        "content": "Текст содержимого.",
        "description": "Необязательное описание.",
        "dry_run": "Предпросмотр операции без применения изменений.",
        "focus": "Необязательный тематический фокус.",
        "format": "Формат вывода.",
        "id": "Числовой ID записи.",
        "input": "Входные данные для операции.",
        "key": "Ключ записи.",
        "limit": "Максимальное количество результатов.",
        "max_tokens": "Примерный бюджет токенов.",
        "message": "Текст сообщения.",
        "path": "Локальный путь файловой системы.",
        "plugin": "Название плагина.",
        "priority": "Приоритет задачи.",
        "prompt": "Текст prompt для анализа или маршрутизации.",
        "probe_id": "ID результата probe.",
        "quality": "Оценка качества от 0 до 1.",
        "question": "Вопрос для оценки через консенсус.",
        "query": "Поисковый запрос.",
        "route_id": "ID решения маршрутизации.",
        "run_id": "ID запуска автоматизации.",
        "source": "Исходный URL или путь к файлу.",
        "status": "Фильтр статуса.",
        "strategies": "Стратегии обнаружения.",
        "subtasks": "Необязательные подзадачи для иерархического планирования.",
        "tags": "Список тегов.",
        "target": "Цель коннектора, канал или chat ID.",
        "task": "Описание задачи.",
        "task_id": "ID задачи.",
        "test": "Необязательное имя отдельного теста.",
        "title": "Заголовок задачи.",
        "type": "Тип памяти.",
        "url": "URL для проверки.",
        "value": "Значение записи.",
        "voters": "Количество независимых участников голосования для плана.",
        "workers": "Количество параллельных исполнителей для плана.",
        "iterations": "Количество планируемых итераций координации.",
    },
}

TRANSLATIONS: dict[str, dict[str, str]] = {
    "de": {
        "tool.hb_mem_store": "Speichert einen Fakt, eine Lektion oder einen Working-Memory-Eintrag.",
        "tool.hb_mem_query": "Sucht Memory-Einträge per Schlüsselwort.",
        "tool.hb_mem_context": "Erzeugt kompakten Kontext für Prompt-Injektion.",
        "tool.hb_mem_merge": "Confidence-basierte Zusammenführung doppelter Memories (dry_run zeigt Vorschau; dry_run=false wendet an).",
        "tool.hb_mem_consolidate": "Senkt die Memory-Confidence und entfernt Einträge mit niedriger Confidence (dry_run zeigt Vorschau; dry_run=false wendet an).",
        "tool.hb_route_select": "Analysiert einen Prompt und empfiehlt Modell oder Provider.",
        "tool.hb_route_evaluate": "Speichert Qualitätsfeedback für eine Routing-Entscheidung.",
        "tool.hb_route_stats": "Gibt Routing-Statistiken und Lernfortschritt aus.",
        "tool.hb_kb_search": "Sucht in der Knowledge-Datenbank.",
        "tool.hb_kb_ingest": "Nimmt neues Wissen als Text, URL oder Dateiinhalte auf.",
        "tool.hb_kb_get": "Ruft einen Knowledge-Eintrag mit Metadaten ab.",
        "tool.hb_kb_list": "Listet Tags in der Knowledge-Datenbank.",
        "tool.hb_swarm_parallel": "Teilt eine Aufgabe in Chunks und verarbeitet sie parallel.",
        "tool.hb_swarm_consensus": "Holt eine Mehrheitsentscheidung mehrerer unabhängiger Agenten ein.",
        "tool.hb_swarm_hierarchy": "Nutzt ein Boss-Worker-Delegationsmuster.",
        "tool.hb_swarm_stigmergy": "Koordiniert indirekt über geteilten Zustand.",
        "tool.hb_state_mem_get": "Ruft State-Memory-Einträge ab.",
        "tool.hb_state_mem_set": "Speichert einen State-Memory-Eintrag.",
        "tool.hb_state_task_list": "Listet Tasks mit optionalem Statusfilter.",
        "tool.hb_state_task_create": "Erstellt einen neuen Task.",
        "tool.hb_state_task_update": "Aktualisiert Status, Beschreibung oder Priorität eines Tasks.",
        "tool.hb_state_dispatch": "Gibt den Status eines Connector-Dispatchs zurück.",
        "tool.hb_garden_find": "Sucht im kleinen Garden-Store.",
        "tool.hb_garden_get": "Ruft einen Garden-Eintrag per Schlüssel ab.",
        "tool.hb_garden_put": "Speichert oder aktualisiert einen Garden-Eintrag.",
        "tool.hb_garden_run": "Führt einen gespeicherten Befehl aus, wenn Ausführung aktiviert ist.",
        "tool.hb_api_probe": "Prüft eine URL mit API-Discovery-Strategien.",
        "tool.hb_api_discover": "Erkennt API-Schemata aus einer Basis-URL.",
        "tool.hb_api_export": "Exportiert Probe-Ergebnisse als Markdown oder JSON.",
        "tool.hb_api_history": "Listet frühere Probe-Ergebnisse.",
        "tool.hb_test_list": "Listet verfügbare Test-Batterien.",
        "tool.hb_test_run": "Führt eine Test-Batterie oder einen Einzeltest aus.",
        "tool.hb_test_results": "Ruft Ergebnisse des letzten Testlaufs ab.",
        "tool.hb_auto_list_chains": "Listet lokale Automatisierungsketten.",
        "tool.hb_auto_run": "Stellt einen lokalen Planlauf ohne externe Backend-Ausführung in die Queue.",
        "tool.hb_auto_status": "Prüft den Status eines lokalen Planlaufs.",
        "tool.hb_auto_result": "Ruft das protokollierte Ergebnis eines lokalen Planlaufs ab.",
        "tool.hb_conn_list": "Listet konfigurierte Connectors.",
        "tool.hb_conn_send": "Stellt eine Nachricht für einen Connector in die Queue (kein Netzwerkversand).",
        "tool.hb_conn_receive": "Ruft neue Nachrichten eines Connectors ab.",
        "tool.hb_conn_status": "Prüft den Zustand eines Connectors.",
        "tool.hb_plug_list": "Listet installierte Plugins.",
        "tool.hb_plug_info": "Ruft Plugin-Metadaten ab.",
        "tool.hb_plug_run": "Protokolliert einen Plugin-Dry-run ohne Plugin-Code auszuführen.",
        "tool.hb_plug_discover": "Sucht neue Plugins in einem Verzeichnis.",
        "error.unknown_tool": "Unbekanntes Homebase-Tool: {name}",
    },
    "es": {
        "tool.hb_mem_store": "Guarda un dato, una lección o una entrada de memoria de trabajo.",
        "tool.hb_mem_query": "Busca entradas de memoria por palabra clave.",
        "tool.hb_mem_context": "Genera contexto compacto para inyección en prompts.",
        "tool.hb_mem_merge": "Fusiona memorias duplicadas basándose en la confianza (dry_run muestra vista previa; dry_run=false aplica la fusión).",
        "tool.hb_mem_consolidate": "Reduce la confianza de las memorias y elimina las entradas de baja confianza (dry_run muestra vista previa; dry_run=false aplica).",
        "tool.hb_route_select": "Analiza un prompt y recomienda el mejor modelo o proveedor.",
        "tool.hb_route_evaluate": "Califica una respuesta para el bucle de retroalimentación de routing (aprendizaje epsilon-greedy).",
        "tool.hb_route_stats": "Obtiene estadísticas de routing y progreso de aprendizaje.",
        "tool.hb_kb_search": "Busca en la base de conocimiento.",
        "tool.hb_kb_ingest": "Añade conocimiento nuevo como texto, URL o archivo.",
        "tool.hb_kb_get": "Obtiene una entrada de conocimiento con metadatos.",
        "tool.hb_kb_list": "Lista etiquetas en la base de conocimiento.",
        "tool.hb_swarm_parallel": "Divide una tarea en chunks y los procesa en paralelo.",
        "tool.hb_swarm_consensus": "Obtiene una votación mayoritaria de múltiples agentes independientes.",
        "tool.hb_swarm_hierarchy": "Utiliza un patrón de delegación jefe-trabajador.",
        "tool.hb_swarm_stigmergy": "Coordina indirectamente a través de estado compartido.",
        "tool.hb_state_mem_get": "Obtiene entradas de memoria de estado.",
        "tool.hb_state_mem_set": "Almacena una entrada de memoria de estado.",
        "tool.hb_state_task_list": "Lista tareas con filtro de estado opcional.",
        "tool.hb_state_task_create": "Crea una tarea nueva.",
        "tool.hb_state_task_update": "Actualiza una tarea (estado, descripción, prioridad).",
        "tool.hb_state_dispatch": "Devuelve el estado de un conector dispatch.",
        "tool.hb_garden_find": "Busca en el Garden.",
        "tool.hb_garden_get": "Obtiene una entrada del Garden por clave.",
        "tool.hb_garden_put": "Guarda o actualiza una entrada del Garden.",
        "tool.hb_garden_run": "Ejecuta un comando almacenado si la ejecución está explícitamente habilitada.",
        "tool.hb_api_probe": "Prueba una URL con todas las estrategias (OpenAPI, wordlist, patrón, HATEOAS).",
        "tool.hb_api_discover": "Detecta automáticamente esquemas de API desde una URL base.",
        "tool.hb_api_export": "Exporta resultados de probe como Markdown o JSON.",
        "tool.hb_api_history": "Lista resultados anteriores de probe.",
        "tool.hb_test_list": "Lista baterías de prueba disponibles.",
        "tool.hb_test_run": "Ejecuta una batería de prueba o un test individual.",
        "tool.hb_test_results": "Obtiene resultados de la última ejecución de prueba.",
        "tool.hb_auto_list_chains": "Lista definiciones de cadenas de automatización locales.",
        "tool.hb_auto_run": "Pone en cola un plan de cadena de automatización local sin ejecutar backends externos.",
        "tool.hb_auto_status": "Comprueba el estado de ejecución de una automatización local.",
        "tool.hb_auto_result": "Obtiene el resultado registrado de una ejecución de automatización local.",
        "tool.hb_conn_list": "Lista conectores configurados.",
        "tool.hb_conn_send": "Pone en cola un mensaje para un conector sin entrega por red.",
        "tool.hb_conn_receive": "Obtiene mensajes recientes de bandeja de entrada local de un conector.",
        "tool.hb_conn_status": "Comprueba el estado local de un conector y el número de mensajes en cola.",
        "tool.hb_plug_list": "Lista plugins locales descubiertos.",
        "tool.hb_plug_info": "Obtiene metadatos de plugin local.",
        "tool.hb_plug_run": "Registra un dry-run de plugin sin ejecutar código del plugin.",
        "tool.hb_plug_discover": "Escanea un directorio local en busca de metadatos de plugin.",
        "error.unknown_tool": "Herramienta Homebase desconocida: {name}",
    },
    "zh": {
        "tool.hb_mem_store": "保存事实、经验或工作记忆条目。",
        "tool.hb_mem_query": "按关键词搜索记忆条目。",
        "tool.hb_mem_context": "生成用于提示注入的紧凑上下文。",
        "tool.hb_mem_merge": "基于置信度合并重复的记忆条目（dry_run 预览，dry_run=false 应用合并）。",
        "tool.hb_mem_consolidate": "降低记忆的置信度并清除低置信度的条目（dry_run 预览，dry_run=false 应用）。",
        "tool.hb_route_select": "分析提示并推荐最佳模型或提供商。",
        "tool.hb_route_evaluate": "为路由反馈循环给响应评分（epsilon-greedy 学习）。",
        "tool.hb_route_stats": "获取路由统计信息和学习进度。",
        "tool.hb_kb_search": "搜索知识库。",
        "tool.hb_kb_ingest": "接收文本、URL 或文件形式的新知识。",
        "tool.hb_kb_get": "获取带元数据的单条知识条目。",
        "tool.hb_kb_list": "列出知识库中的标签。",
        "tool.hb_swarm_parallel": "将任务拆分为多个块并并行处理。",
        "tool.hb_swarm_consensus": "获取多个独立代理的多数投票结果。",
        "tool.hb_swarm_hierarchy": "采用 Boss-Worker 委派模式。",
        "tool.hb_swarm_stigmergy": "通过共享状态实现间接协调（blackboard 模式）。",
        "tool.hb_state_mem_get": "获取状态记忆条目。",
        "tool.hb_state_mem_set": "保存一条状态记忆条目。",
        "tool.hb_state_task_list": "列出任务，可按状态筛选。",
        "tool.hb_state_task_create": "创建新任务。",
        "tool.hb_state_task_update": "更新任务（状态、描述、优先级）。",
        "tool.hb_state_dispatch": "返回连接器分发状态。",
        "tool.hb_garden_find": "搜索 Garden。",
        "tool.hb_garden_get": "按键获取指定的 Garden 条目。",
        "tool.hb_garden_put": "保存或更新 Garden 条目。",
        "tool.hb_garden_run": "仅在显式启用执行时运行已保存的命令。",
        "tool.hb_api_probe": "使用所有策略（OpenAPI、词表、模式、HATEOAS）探测 URL。",
        "tool.hb_api_discover": "从基础 URL 自动检测 API schema。",
        "tool.hb_api_export": "将探测结果导出为 Markdown 或 JSON。",
        "tool.hb_api_history": "列出以往的探测结果。",
        "tool.hb_test_list": "列出可用的测试套件。",
        "tool.hb_test_run": "运行一个测试套件或单个测试。",
        "tool.hb_test_results": "获取上次测试运行的结果。",
        "tool.hb_auto_list_chains": "列出可用的本地自动化链定义。",
        "tool.hb_auto_run": "将本地自动化链计划加入队列，但不执行外部后端。",
        "tool.hb_auto_status": "查看本地自动化运行的状态。",
        "tool.hb_auto_result": "获取已记录的本地自动化运行结果。",
        "tool.hb_conn_list": "列出已配置的连接器。",
        "tool.hb_conn_send": "将消息加入连接器队列，但不进行网络投递。",
        "tool.hb_conn_receive": "获取某个连接器最近的本地收件箱消息。",
        "tool.hb_conn_status": "查看本地连接器的健康状况和队列数量。",
        "tool.hb_plug_list": "列出已发现的本地插件。",
        "tool.hb_plug_info": "获取本地插件元数据。",
        "tool.hb_plug_run": "记录一次插件 dry-run，但不执行插件代码。",
        "tool.hb_plug_discover": "扫描本地目录以查找插件元数据。",
        "error.unknown_tool": "未知 Homebase 工具：{name}",
    },
    "ja": {
        "tool.hb_mem_store": "事実、学習内容、作業メモリの項目を保存します。",
        "tool.hb_mem_query": "キーワードでメモリ項目を検索します。",
        "tool.hb_mem_context": "プロンプト注入用の短いコンテキストを生成します。",
        "tool.hb_mem_merge": "確信度に基づいて重複するメモリをマージします（dry_runはプレビュー表示、dry_run=falseで適用されます）。",
        "tool.hb_mem_consolidate": "メモリの確信度を減衰させ、低確信度のエントリを削除します（dry_runはプレビュー表示、dry_run=falseで適用されます）。",
        "tool.hb_route_select": "プロンプトを分析し、最適なモデルまたはプロバイダを推奨します。",
        "tool.hb_route_evaluate": "ルーティングのフィードバックループのために応答を評価します（epsilon-greedy学習）。",
        "tool.hb_route_stats": "ルーティング統計と学習の進捗状況を取得します。",
        "tool.hb_kb_search": "ナレッジベースを検索します。",
        "tool.hb_kb_ingest": "テキスト、URL、ファイルから新しい知識を取り込みます。",
        "tool.hb_kb_get": "メタデータを含む単一のナレッジエントリを取得します。",
        "tool.hb_kb_list": "ナレッジベース内のタグを一覧表示します。",
        "tool.hb_swarm_parallel": "タスクをチャンクに分割し、並列処理します。",
        "tool.hb_swarm_consensus": "複数の独立したエージェントから多数決を取得します。",
        "tool.hb_swarm_hierarchy": "ボス・ワーカー型の委任パターンを使用します。",
        "tool.hb_swarm_stigmergy": "共有状態を介して間接的に調整します（ブラックボードパターン）。",
        "tool.hb_state_mem_get": "ステートメモリのエントリを取得します。",
        "tool.hb_state_mem_set": "ステートメモリのエントリを保存します。",
        "tool.hb_state_task_list": "オプションのステータスフィルタでタスクを一覧表示します。",
        "tool.hb_state_task_create": "新しいタスクを作成します。",
        "tool.hb_state_task_update": "タスクのステータス、説明、優先度を更新します。",
        "tool.hb_state_dispatch": "コネクタのディスパッチ状態を返します。",
        "tool.hb_garden_find": "Gardenを検索します。",
        "tool.hb_garden_get": "キーで特定の Garden エントリを取得します。",
        "tool.hb_garden_put": "Garden エントリを保存または更新します。",
        "tool.hb_garden_run": "実行が明示的に有効になっている場合、保存済みのコマンドを実行します。",
        "tool.hb_api_probe": "すべての戦略（OpenAPI、ワードリスト、パターン、HATEOAS）を使用してURLを調査します。",
        "tool.hb_api_discover": "ベースURLからAPIスキーマを自動検出します。",
        "tool.hb_api_export": "プローブ結果をMarkdownまたはJSONとしてエクスポートします。",
        "tool.hb_api_history": "過去のプローブ結果を一覧表示します。",
        "tool.hb_test_list": "利用可能なテストバッテリーを一覧表示します。",
        "tool.hb_test_run": "テストバッテリーまたは単一のテストを実行します。",
        "tool.hb_test_results": "直近のテスト実行の結果を取得します。",
        "tool.hb_auto_list_chains": "利用可能なローカル自動化チェーン定義を一覧表示します。",
        "tool.hb_auto_run": "外部バックエンドを実行せずに、ローカル自動化チェーンの計画をキューに入れます。",
        "tool.hb_auto_status": "ローカル自動化実行のステータスを確認します。",
        "tool.hb_auto_result": "記録されたローカル自動化実行の結果を取得します。",
        "tool.hb_conn_list": "設定済みのコネクタを一覧表示します。",
        "tool.hb_conn_send": "ネットワーク配信せずに、コネクタ宛てのメッセージをキューに入れます。",
        "tool.hb_conn_receive": "コネクタのローカル受信箱にある最近のメッセージを取得します。",
        "tool.hb_conn_status": "ローカルコネクタの稼働状況とキュー件数を確認します。",
        "tool.hb_plug_list": "検出されたローカルプラグインを一覧表示します。",
        "tool.hb_plug_info": "ローカルプラグインのメタデータを取得します。",
        "tool.hb_plug_run": "プラグインコードを実行せずに、プラグインのdry-runを記録します。",
        "tool.hb_plug_discover": "プラグインのメタデータについてローカルディレクトリをスキャンします。",
        "error.unknown_tool": "不明な Homebase ツール: {name}",
    },
    "ru": {
        "tool.hb_mem_store": "Сохраняет факт, урок или запись рабочей памяти.",
        "tool.hb_mem_query": "Ищет записи памяти по ключевому слову.",
        "tool.hb_mem_context": "Создает компактный контекст для вставки в prompt.",
        "tool.hb_mem_merge": "Объединяет дублирующиеся memories на основе уверенности (dry_run показывает предпросмотр; dry_run=false применяет объединение).",
        "tool.hb_mem_consolidate": "Снижает уверенность memories и удаляет записи с низкой уверенностью (dry_run показывает предпросмотр; dry_run=false применяет).",
        "tool.hb_route_select": "Анализирует prompt и рекомендует лучшую модель или провайдера.",
        "tool.hb_route_evaluate": "Оценивает ответ для цикла обратной связи маршрутизации (epsilon-greedy обучение).",
        "tool.hb_route_stats": "Выводит статистику маршрутизации и прогресс обучения.",
        "tool.hb_kb_search": "Ищет в базе знаний.",
        "tool.hb_kb_ingest": "Добавляет новое знание из текста, URL или файла.",
        "tool.hb_kb_get": "Получает запись знаний с метаданными.",
        "tool.hb_kb_list": "Перечисляет теги в базе знаний.",
        "tool.hb_swarm_parallel": "Разделяет задачу на части и обрабатывает их параллельно.",
        "tool.hb_swarm_consensus": "Получает голос большинства от нескольких независимых агентов.",
        "tool.hb_swarm_hierarchy": "Использует паттерн делегирования Boss-Worker.",
        "tool.hb_swarm_stigmergy": "Координирует косвенно через общее состояние.",
        "tool.hb_state_mem_get": "Получает записи state-памяти.",
        "tool.hb_state_mem_set": "Сохраняет запись state-памяти.",
        "tool.hb_state_task_list": "Перечисляет задачи с опциональной фильтрацией по статусу.",
        "tool.hb_state_task_create": "Создает новую задачу.",
        "tool.hb_state_task_update": "Обновляет статус, описание или приоритет задачи.",
        "tool.hb_state_dispatch": "Выводит статус диспетчера коннектора.",
        "tool.hb_garden_find": "Ищет в Garden.",
        "tool.hb_garden_get": "Получает запись Garden по ключу.",
        "tool.hb_garden_put": "Сохраняет или обновляет запись Garden.",
        "tool.hb_garden_run": "Выполняет сохраненную команду, если выполнение явно включено.",
        "tool.hb_api_probe": "Проверяет URL всеми стратегиями (OpenAPI, wordlist, pattern, HATEOAS).",
        "tool.hb_api_discover": "Автоматически определяет API-схему из базового URL.",
        "tool.hb_api_export": "Экспортирует результаты проверки как Markdown или JSON.",
        "tool.hb_api_history": "Перечисляет предыдущие результаты проверок.",
        "tool.hb_test_list": "Перечисляет доступные наборы тестов.",
        "tool.hb_test_run": "Запускает набор тестов или отдельный тест.",
        "tool.hb_test_results": "Получает результаты последнего запуска тестов.",
        "tool.hb_auto_list_chains": "Перечисляет доступные локальные определения цепочек автоматизации.",
        "tool.hb_auto_run": "Ставит в очередь локальный план цепочки без выполнения внешних бэкендов.",
        "tool.hb_auto_status": "Проверяет статус локального запуска автоматизации.",
        "tool.hb_auto_result": "Получает результат локального запуска автоматизации.",
        "tool.hb_conn_list": "Перечисляет настроенные коннекторы.",
        "tool.hb_conn_send": "Ставит сообщение в очередь для коннектора без сетевой доставки.",
        "tool.hb_conn_receive": "Получает последние сообщения из локального входящего ящика коннектора.",
        "tool.hb_conn_status": "Проверяет локальное состояние коннектора и количество сообщений в очереди.",
        "tool.hb_plug_list": "Перечисляет обнаруженные локальные плагины.",
        "tool.hb_plug_info": "Получает метаданные локального плагина.",
        "tool.hb_plug_run": "Записывает dry-run плагина без выполнения кода.",
        "tool.hb_plug_discover": "Сканирует локальный каталог на наличие плагинов.",
        "error.unknown_tool": "Неизвестный инструмент Homebase: {name}",
    },
}


def normalize_locale(locale: str | None) -> str:
    if not locale:
        return DEFAULT_LOCALE
    normalized = locale.strip().lower().replace("_", "-")
    normalized = ALIASES.get(normalized, normalized.split("-", 1)[0])
    if normalized in SUPPORTED_LOCALES:
        return normalized
    return DEFAULT_LOCALE


@dataclass(frozen=True)
class I18n:
    locale: str = DEFAULT_LOCALE

    def __post_init__(self) -> None:
        object.__setattr__(self, "locale", normalize_locale(self.locale))

    def t(self, key: str, default: str | None = None) -> str:
        if self.locale == DEFAULT_LOCALE:
            return default or key
        return TRANSLATIONS.get(self.locale, {}).get(key) or default or key

    def localize_schema(self, schema: dict[str, Any]) -> dict[str, Any]:
        """Return a copy of a JSON schema with localized property descriptions."""
        localized = deepcopy(schema)
        properties = localized.get("properties")
        if isinstance(properties, dict):
            for name, property_schema in properties.items():
                if not isinstance(property_schema, dict):
                    continue
                description = self._schema_description(name, property_schema.get("description"))
                if description:
                    property_schema["description"] = description
        return localized

    def _schema_description(self, name: str, default: str | None = None) -> str | None:
        fallback = default or DEFAULT_SCHEMA_DESCRIPTIONS.get(name)
        if self.locale == DEFAULT_LOCALE:
            return fallback
        return SCHEMA_TRANSLATIONS.get(self.locale, {}).get(name) or fallback
