feat: internationalize claude-code error messages and fix tests

This commit is contained in:
hannesrudolph 2025-06-20 14:25:13 -05:00
parent df2e8b70d9
commit c7fbc1ebba
20 changed files with 100 additions and 24 deletions

View file

@ -10,6 +10,7 @@ import { ApiStreamUsageChunk, type ApiStream } from "../transform/stream"
import { runClaudeCode } from "../../integrations/claude-code/run"
import { ClaudeCodeMessage } from "../../integrations/claude-code/types"
import { BaseProvider } from "./base-provider"
import i18n from "../../i18n"
export class ClaudeCodeHandler extends BaseProvider implements ApiHandler {
private options: ApiHandlerOptions
@ -70,7 +71,10 @@ export class ClaudeCodeHandler extends BaseProvider implements ApiHandler {
if (exitCode !== null && exitCode !== 0) {
throw new Error(
`Claude Code process exited with code ${exitCode}.${errorOutput ? ` Error output: ${errorOutput.trim()}` : ""}`,
i18n.t("common:errors.claude_code_process_exited", {
exitCode,
errorOutput: errorOutput.trim(),
}),
)
}
@ -99,13 +103,13 @@ export class ClaudeCodeHandler extends BaseProvider implements ApiHandler {
if (message.stop_reason !== null && message.stop_reason !== "tool_use") {
const errorMessage =
message.content[0]?.text || `Claude Code stopped with reason: ${message.stop_reason}`
message.content[0]?.text ||
i18n.t("common:errors.claude_code_stopped", {
stopReason: message.stop_reason,
})
if (errorMessage.includes("Invalid model name")) {
throw new Error(
errorMessage +
`\n\nAPI keys and subscription plans allow different models. Make sure the selected model is included in your plan.`,
)
throw new Error(errorMessage + `\n\n` + i18n.t("common:errors.claude_code_invalid_model"))
}
throw new Error(errorMessage)

View file

@ -63,7 +63,10 @@
"condense_handler_invalid": "El gestor de l'API per condensar el context no és vàlid",
"condense_context_grew": "La mida del context ha augmentat durant la condensació; s'omet aquest intent",
"share_task_failed": "Ha fallat compartir la tasca. Si us plau, torna-ho a provar.",
"share_no_active_task": "No hi ha cap tasca activa per compartir"
"share_no_active_task": "No hi ha cap tasca activa per compartir",
"claude_code_process_exited": "El procés de Claude Code ha finalitzat amb el codi {{exitCode}}. Sortida d'error: {{errorOutput}}",
"claude_code_stopped": "Claude Code s'ha aturat per la raó: {{stopReason}}",
"claude_code_invalid_model": "Les claus API i els plans de subscripció permeten models diferents. Assegura't que el model seleccionat estigui inclòs en el teu pla."
},
"warnings": {
"no_terminal_content": "No s'ha seleccionat contingut de terminal",

View file

@ -59,7 +59,10 @@
"condense_handler_invalid": "API-Handler zum Verdichten des Kontexts ist ungültig",
"condense_context_grew": "Kontextgröße ist während der Verdichtung gewachsen; dieser Versuch wird übersprungen",
"share_task_failed": "Teilen der Aufgabe fehlgeschlagen. Bitte versuche es erneut.",
"share_no_active_task": "Keine aktive Aufgabe zum Teilen"
"share_no_active_task": "Keine aktive Aufgabe zum Teilen",
"claude_code_process_exited": "Claude Code Prozess beendet mit Code {{exitCode}}. Fehlerausgabe: {{errorOutput}}",
"claude_code_stopped": "Claude Code gestoppt mit Grund: {{stopReason}}",
"claude_code_invalid_model": "API-Schlüssel und Abonnementpläne erlauben verschiedene Modelle. Stelle sicher, dass das ausgewählte Modell in deinem Plan enthalten ist."
},
"warnings": {
"no_terminal_content": "Kein Terminal-Inhalt ausgewählt",

View file

@ -59,7 +59,10 @@
"condense_handler_invalid": "API handler for condensing context is invalid",
"condense_context_grew": "Context size increased during condensing; skipping this attempt",
"share_task_failed": "Failed to share task. Please try again.",
"share_no_active_task": "No active task to share"
"share_no_active_task": "No active task to share",
"claude_code_process_exited": "Claude Code process exited with code {{exitCode}}. Error output: {{errorOutput}}",
"claude_code_stopped": "Claude Code stopped with reason: {{stopReason}}",
"claude_code_invalid_model": "API keys and subscription plans allow different models. Make sure the selected model is included in your plan."
},
"warnings": {
"no_terminal_content": "No terminal content selected",

View file

@ -59,7 +59,10 @@
"condense_handler_invalid": "El manejador de API para condensar el contexto no es válido",
"condense_context_grew": "El tamaño del contexto aumentó durante la condensación; se omite este intento",
"share_task_failed": "Error al compartir la tarea. Por favor, inténtalo de nuevo.",
"share_no_active_task": "No hay tarea activa para compartir"
"share_no_active_task": "No hay tarea activa para compartir",
"claude_code_process_exited": "El proceso de Claude Code finalizó con el código {{exitCode}}. Salida de error: {{errorOutput}}",
"claude_code_stopped": "Claude Code se detuvo por la razón: {{stopReason}}",
"claude_code_invalid_model": "Las claves API y los planes de suscripción permiten diferentes modelos. Asegúrate de que el modelo seleccionado esté incluido en tu plan."
},
"warnings": {
"no_terminal_content": "No hay contenido de terminal seleccionado",

View file

@ -59,7 +59,10 @@
"condense_handler_invalid": "Le gestionnaire d'API pour condenser le contexte est invalide",
"condense_context_grew": "La taille du contexte a augmenté pendant la condensation ; cette tentative est ignorée",
"share_task_failed": "Échec du partage de la tâche. Veuillez réessayer.",
"share_no_active_task": "Aucune tâche active à partager"
"share_no_active_task": "Aucune tâche active à partager",
"claude_code_process_exited": "Le processus Claude Code s'est terminé avec le code {{exitCode}}. Sortie d'erreur : {{errorOutput}}",
"claude_code_stopped": "Claude Code s'est arrêté pour la raison : {{stopReason}}",
"claude_code_invalid_model": "Les clés API et les plans d'abonnement autorisent différents modèles. Assurez-vous que le modèle sélectionné est inclus dans votre plan."
},
"warnings": {
"no_terminal_content": "Aucun contenu de terminal sélectionné",

View file

@ -59,7 +59,10 @@
"condense_handler_invalid": "संदर्भ को संक्षिप्त करने के लिए API हैंडलर अमान्य है",
"condense_context_grew": "संक्षिप्तीकरण के दौरान संदर्भ का आकार बढ़ गया; इस प्रयास को छोड़ा जा रहा है",
"share_task_failed": "कार्य साझा करने में विफल। कृपया पुनः प्रयास करें।",
"share_no_active_task": "साझा करने के लिए कोई सक्रिय कार्य नहीं"
"share_no_active_task": "साझा करने के लिए कोई सक्रिय कार्य नहीं",
"claude_code_process_exited": "क्लाउड कोड प्रक्रिया कोड {{exitCode}} के साथ समाप्त हुई। त्रुटि आउटपुट: {{errorOutput}}",
"claude_code_stopped": "क्लाउड कोड इस कारण से रुका: {{stopReason}}",
"claude_code_invalid_model": "एपीआई कुंजी और सदस्यता योजनाएं विभिन्न मॉडलों की अनुमति देती हैं। सुनिश्चित करें कि चयनित मॉडल आपकी योजना में शामिल है।"
},
"warnings": {
"no_terminal_content": "कोई टर्मिनल सामग्री चयनित नहीं",

View file

@ -59,7 +59,10 @@
"condense_handler_invalid": "Handler API untuk mengompres konteks tidak valid",
"condense_context_grew": "Ukuran konteks bertambah saat mengompres; melewati percobaan ini",
"share_task_failed": "Gagal membagikan tugas. Silakan coba lagi.",
"share_no_active_task": "Tidak ada tugas aktif untuk dibagikan"
"share_no_active_task": "Tidak ada tugas aktif untuk dibagikan",
"claude_code_process_exited": "Proses Claude Code keluar dengan kode {{exitCode}}. Output error: {{errorOutput}}",
"claude_code_stopped": "Claude Code berhenti dengan alasan: {{stopReason}}",
"claude_code_invalid_model": "Kunci API dan paket langganan mengizinkan model yang berbeda. Pastikan model yang dipilih termasuk dalam paket Anda."
},
"warnings": {
"no_terminal_content": "Tidak ada konten terminal yang dipilih",

View file

@ -59,7 +59,10 @@
"condense_handler_invalid": "Il gestore API per condensare il contesto non è valido",
"condense_context_grew": "La dimensione del contesto è aumentata durante la condensazione; questo tentativo viene saltato",
"share_task_failed": "Condivisione dell'attività fallita. Riprova.",
"share_no_active_task": "Nessuna attività attiva da condividere"
"share_no_active_task": "Nessuna attività attiva da condividere",
"claude_code_process_exited": "Il processo Claude Code è terminato con il codice {{exitCode}}. Output errore: {{errorOutput}}",
"claude_code_stopped": "Claude Code si è fermato per il motivo: {{stopReason}}",
"claude_code_invalid_model": "Le chiavi API e i piani di abbonamento consentono modelli diversi. Assicurati che il modello selezionato sia incluso nel tuo piano."
},
"warnings": {
"no_terminal_content": "Nessun contenuto del terminale selezionato",

View file

@ -59,7 +59,10 @@
"condense_handler_invalid": "コンテキストを圧縮するためのAPIハンドラーが無効です",
"condense_context_grew": "圧縮中にコンテキストサイズが増加しました;この試行をスキップします",
"share_task_failed": "タスクの共有に失敗しました",
"share_no_active_task": "共有するアクティブなタスクがありません"
"share_no_active_task": "共有するアクティブなタスクがありません",
"claude_code_process_exited": "Claude Codeプロセスがコード{{exitCode}}で終了しました。エラー出力:{{errorOutput}}",
"claude_code_stopped": "Claude Codeは次の理由で停止しました{{stopReason}}",
"claude_code_invalid_model": "APIキーとサブスクリプションプランでは異なるモデルが許可されています。選択したモデルがプランに含まれていることを確認してください。"
},
"warnings": {
"no_terminal_content": "選択されたターミナルコンテンツがありません",

View file

@ -59,7 +59,10 @@
"condense_handler_invalid": "컨텍스트 압축을 위한 API 핸들러가 유효하지 않습니다",
"condense_context_grew": "압축 중 컨텍스트 크기가 증가했습니다; 이 시도를 건너뜁니다",
"share_task_failed": "작업 공유에 실패했습니다",
"share_no_active_task": "공유할 활성 작업이 없습니다"
"share_no_active_task": "공유할 활성 작업이 없습니다",
"claude_code_process_exited": "Claude Code 프로세스가 코드 {{exitCode}}로 종료되었습니다. 오류 출력: {{errorOutput}}",
"claude_code_stopped": "Claude Code가 다음 이유로 중지되었습니다: {{stopReason}}",
"claude_code_invalid_model": "API 키 및 구독 플랜은 다른 모델을 허용합니다. 선택한 모델이 플랜에 포함되어 있는지 확인하십시오."
},
"warnings": {
"no_terminal_content": "선택된 터미널 내용이 없습니다",

View file

@ -59,7 +59,10 @@
"condense_handler_invalid": "API-handler voor het comprimeren van context is ongeldig",
"condense_context_grew": "Contextgrootte nam toe tijdens comprimeren; deze poging wordt overgeslagen",
"share_task_failed": "Delen van taak mislukt",
"share_no_active_task": "Geen actieve taak om te delen"
"share_no_active_task": "Geen actieve taak om te delen",
"claude_code_process_exited": "Claude Code-proces afgesloten met code {{exitCode}}. Foutuitvoer: {{errorOutput}}",
"claude_code_stopped": "Claude Code gestopt met reden: {{stopReason}}",
"claude_code_invalid_model": "API-sleutels en abonnementsplannen staan verschillende modellen toe. Zorg ervoor dat het geselecteerde model in uw plan is opgenomen."
},
"warnings": {
"no_terminal_content": "Geen terminalinhoud geselecteerd",

View file

@ -59,7 +59,10 @@
"condense_handler_invalid": "Nieprawidłowy handler API do kondensowania kontekstu",
"condense_context_grew": "Rozmiar kontekstu wzrósł podczas kondensacji; pomijanie tej próby",
"share_task_failed": "Nie udało się udostępnić zadania",
"share_no_active_task": "Brak aktywnego zadania do udostępnienia"
"share_no_active_task": "Brak aktywnego zadania do udostępnienia",
"claude_code_process_exited": "Proces Claude Code zakończył się z kodem {{exitCode}}. Wyjście błędu: {{errorOutput}}",
"claude_code_stopped": "Claude Code zatrzymany z powodu: {{stopReason}}",
"claude_code_invalid_model": "Klucze API i plany subskrypcji zezwalają na różne modele. Upewnij się, że wybrany model jest uwzględniony w Twoim planie."
},
"warnings": {
"no_terminal_content": "Nie wybrano zawartości terminala",

View file

@ -63,7 +63,10 @@
"condense_handler_invalid": "O manipulador de API para condensar o contexto é inválido",
"condense_context_grew": "O tamanho do contexto aumentou durante a condensação; pulando esta tentativa",
"share_task_failed": "Falha ao compartilhar tarefa",
"share_no_active_task": "Nenhuma tarefa ativa para compartilhar"
"share_no_active_task": "Nenhuma tarefa ativa para compartilhar",
"claude_code_process_exited": "O processo Claude Code foi encerrado com o código {{exitCode}}. Saída de erro: {{errorOutput}}",
"claude_code_stopped": "Claude Code parou com o motivo: {{stopReason}}",
"claude_code_invalid_model": "Chaves de API e planos de assinatura permitem modelos diferentes. Certifique-se de que o modelo selecionado esteja incluído em seu plano."
},
"warnings": {
"no_terminal_content": "Nenhum conteúdo do terminal selecionado",

View file

@ -59,7 +59,10 @@
"condense_handler_invalid": "Обработчик API для сжатия контекста недействителен",
"condense_context_grew": "Размер контекста увеличился во время сжатия; пропускаем эту попытку",
"share_task_failed": "Не удалось поделиться задачей",
"share_no_active_task": "Нет активной задачи для совместного использования"
"share_no_active_task": "Нет активной задачи для совместного использования",
"claude_code_process_exited": "Процесс Claude Code завершился с кодом {{exitCode}}. Вывод ошибки: {{errorOutput}}",
"claude_code_stopped": "Claude Code остановлен по причине: {{stopReason}}",
"claude_code_invalid_model": "Ключи API и планы подписки разрешают использование различных моделей. Убедитесь, что выбранная модель включена в ваш план."
},
"warnings": {
"no_terminal_content": "Не выбрано содержимое терминала",

View file

@ -59,7 +59,10 @@
"condense_handler_invalid": "Bağlamı sıkıştırmak için API işleyicisi geçersiz",
"condense_context_grew": "Sıkıştırma sırasında bağlam boyutu arttı; bu deneme atlanıyor",
"share_task_failed": "Görev paylaşılamadı",
"share_no_active_task": "Paylaşılacak aktif görev yok"
"share_no_active_task": "Paylaşılacak aktif görev yok",
"claude_code_process_exited": "Claude Code işlemi {{exitCode}} koduyla çıktı. Hata çıktısı: {{errorOutput}}",
"claude_code_stopped": "Claude Code şu nedenle durduruldu: {{stopReason}}",
"claude_code_invalid_model": "API anahtarları ve abonelik planları farklı modellere izin verir. Seçilen modelin planınıza dahil olduğundan emin olun."
},
"warnings": {
"no_terminal_content": "Seçili terminal içeriği yok",

View file

@ -59,7 +59,10 @@
"condense_handler_invalid": "Trình xử lý API để nén ngữ cảnh không hợp lệ",
"condense_context_grew": "Kích thước ngữ cảnh tăng lên trong quá trình nén; bỏ qua lần thử này",
"share_task_failed": "Không thể chia sẻ nhiệm vụ",
"share_no_active_task": "Không có nhiệm vụ hoạt động để chia sẻ"
"share_no_active_task": "Không có nhiệm vụ hoạt động để chia sẻ",
"claude_code_process_exited": "Quá trình Claude Code thoát với mã {{exitCode}}. Lỗi đầu ra: {{errorOutput}}",
"claude_code_stopped": "Claude Code dừng với lý do: {{stopReason}}",
"claude_code_invalid_model": "Khóa API và gói đăng ký cho phép các mô hình khác nhau. Đảm bảo mô hình đã chọn được bao gồm trong gói của bạn."
},
"warnings": {
"no_terminal_content": "Không có nội dung terminal được chọn",

View file

@ -64,7 +64,10 @@
"condense_handler_invalid": "压缩上下文的API处理程序无效",
"condense_context_grew": "压缩过程中上下文大小增加;跳过此次尝试",
"share_task_failed": "分享任务失败。请重试。",
"share_no_active_task": "没有活跃任务可分享"
"share_no_active_task": "没有活跃任务可分享",
"claude_code_process_exited": "Claude Code 进程以代码 {{exitCode}} 退出。错误输出:{{errorOutput}}",
"claude_code_stopped": "Claude Code 因以下原因停止:{{stopReason}}",
"claude_code_invalid_model": "API 密钥和订阅计划允许不同的模型。请确保所选模型包含在您的计划中。"
},
"warnings": {
"no_terminal_content": "没有选择终端内容",

View file

@ -59,7 +59,10 @@
"condense_handler_invalid": "壓縮上下文的 API 處理程式無效",
"condense_context_grew": "壓縮過程中上下文大小增加;跳過此次嘗試",
"share_task_failed": "分享工作失敗。請重試。",
"share_no_active_task": "沒有活躍的工作可分享"
"share_no_active_task": "沒有活躍的工作可分享",
"claude_code_process_exited": "Claude Code 處理程序以代碼 {{exitCode}} 結束。錯誤輸出:{{errorOutput}}",
"claude_code_stopped": "Claude Code 因以下原因停止:{{stopReason}}",
"claude_code_invalid_model": "API 金鑰和訂閱方案允許不同的模型。請確保所選模型包含在您的方案中。"
},
"warnings": {
"no_terminal_content": "沒有選擇終端機內容",

View file

@ -32,6 +32,24 @@ vi.mock("../setup", () => ({
if (key === "notifications.error") {
return options?.message ? `Operation failed: ${options.message}` : "Operation failed"
}
if (key === "common:errors.claude_code_process_exited") {
return `Claude Code process exited with code ${options?.exitCode}. Error output: ${options?.errorOutput}`
}
if (key === "common:errors.claude_code_stopped") {
return `Claude Code stopped with reason: ${options?.stopReason}`
}
if (key === "common:errors.claude_code_invalid_model") {
return "API keys and subscription plans allow different models. Make sure the selected model is included in your plan."
}
if (key === "common:errors.claude_code_process_exited") {
return `Claude Code process exited with code ${options?.exitCode}. Error output: ${options?.errorOutput}`
}
if (key === "common:errors.claude_code_stopped") {
return `Claude Code stopped with reason: ${options?.stopReason}`
}
if (key === "common:errors.claude_code_invalid_model") {
return "API keys and subscription plans allow different models. Make sure the selected model is included in your plan."
}
return key
},
changeLanguage: vi.fn(),