From f26e328d4018f66082cb36917edee69265d0beee Mon Sep 17 00:00:00 2001 From: Kayvan Sylvan Date: Mon, 16 Feb 2026 13:10:00 -0800 Subject: [PATCH 1/2] feat: internationalize file manager, Vertex AI, and Copilot error messages via i18n - Replace hardcoded error strings in `file_manager.go` with i18n translation keys - Add file manager, Vertex AI, and Copilot i18n keys to all 10 locale files - Internationalize Copilot plugin error messages and debug logs - Internationalize Vertex AI model fetching error messages - Fix JSON trailing comma syntax errors across all locale files - Normalize German locale JSON indentation from tabs to spaces - Use `AddSetupQuestionWithEnvName` for Bedrock AWS region setup --- internal/domain/file_manager.go | 22 +- internal/i18n/locales/de.json | 853 +++++++++++++------------ internal/i18n/locales/en.json | 31 +- internal/i18n/locales/es.json | 31 +- internal/i18n/locales/fa.json | 31 +- internal/i18n/locales/fr.json | 31 +- internal/i18n/locales/it.json | 31 +- internal/i18n/locales/ja.json | 31 +- internal/i18n/locales/pt-BR.json | 31 +- internal/i18n/locales/pt-PT.json | 31 +- internal/i18n/locales/zh.json | 31 +- internal/plugins/ai/bedrock/bedrock.go | 4 +- internal/plugins/ai/copilot/copilot.go | 23 +- internal/plugins/ai/vertexai/models.go | 13 +- 14 files changed, 724 insertions(+), 470 deletions(-) diff --git a/internal/domain/file_manager.go b/internal/domain/file_manager.go index 64753e4b..316e52c9 100644 --- a/internal/domain/file_manager.go +++ b/internal/domain/file_manager.go @@ -7,6 +7,8 @@ import ( "path/filepath" "slices" "strings" + + "github.com/danielmiessler/fabric/internal/i18n" ) // FileChangesMarker identifies the start of a file changes section in output @@ -37,7 +39,7 @@ func ParseFileChanges(output string) (changeSummary string, changes []FileChange // Find the first [ after the file changes marker jsonArrayStart := strings.Index(output[jsonStart:], "[") if jsonArrayStart == -1 { - return output, nil, fmt.Errorf("invalid %s format: no JSON array found", FileChangesMarker) + return output, nil, fmt.Errorf(i18n.T("file_manager_invalid_format_no_json_array"), FileChangesMarker) } jsonStart += jsonArrayStart @@ -57,7 +59,7 @@ func ParseFileChanges(output string) (changeSummary string, changes []FileChange } if bracketCount != 0 { - return output, nil, fmt.Errorf("invalid %s format: unbalanced brackets", FileChangesMarker) + return output, nil, fmt.Errorf(i18n.T("file_manager_invalid_format_unbalanced_brackets"), FileChangesMarker) } // Extract the JSON string and fix escape sequences @@ -75,7 +77,7 @@ func ParseFileChanges(output string) (changeSummary string, changes []FileChange jsonStr = fixInvalidEscapes(jsonStr) err = json.Unmarshal([]byte(jsonStr), &fileChanges) if err != nil { - return changeSummary, nil, fmt.Errorf("failed to parse %s JSON: %w", FileChangesMarker, err) + return changeSummary, nil, fmt.Errorf(i18n.T("file_manager_failed_parse_json"), FileChangesMarker, err) } } @@ -83,22 +85,22 @@ func ParseFileChanges(output string) (changeSummary string, changes []FileChange for i, change := range fileChanges { // Validate operation if change.Operation != "create" && change.Operation != "update" { - return changeSummary, nil, fmt.Errorf("invalid operation for file change %d: %s", i, change.Operation) + return changeSummary, nil, fmt.Errorf(i18n.T("file_manager_invalid_operation"), i, change.Operation) } // Validate path if change.Path == "" { - return changeSummary, nil, fmt.Errorf("empty path for file change %d", i) + return changeSummary, nil, fmt.Errorf(i18n.T("file_manager_empty_path"), i) } // Check for suspicious paths (directory traversal) if strings.Contains(change.Path, "..") { - return changeSummary, nil, fmt.Errorf("suspicious path for file change %d: %s", i, change.Path) + return changeSummary, nil, fmt.Errorf(i18n.T("file_manager_suspicious_path"), i, change.Path) } // Check file size if len(change.Content) > MaxFileSize { - return changeSummary, nil, fmt.Errorf("file content too large for file change %d: %d bytes", i, len(change.Content)) + return changeSummary, nil, fmt.Errorf(i18n.T("file_manager_file_content_too_large"), i, len(change.Content)) } } @@ -174,15 +176,15 @@ func ApplyFileChanges(projectRoot string, changes []FileChange) error { // Create directories if necessary dir := filepath.Dir(absPath) if err := os.MkdirAll(dir, 0755); err != nil { - return fmt.Errorf("failed to create directory %s for file change %d: %w", dir, i, err) + return fmt.Errorf(i18n.T("file_manager_failed_create_directory"), dir, i, err) } // Write the file if err := os.WriteFile(absPath, []byte(change.Content), 0644); err != nil { - return fmt.Errorf("failed to write file %s for file change %d: %w", absPath, i, err) + return fmt.Errorf(i18n.T("file_manager_failed_write_file"), absPath, i, err) } - fmt.Printf("Applied %s operation to %s\n", change.Operation, change.Path) + fmt.Printf(i18n.T("file_manager_applied_operation")+"\n", change.Operation, change.Path) } return nil diff --git a/internal/i18n/locales/de.json b/internal/i18n/locales/de.json index 24ed62af..0bbab897 100644 --- a/internal/i18n/locales/de.json +++ b/internal/i18n/locales/de.json @@ -1,417 +1,416 @@ { - "html_readability_error": "verwende ursprüngliche Eingabe, da HTML-Lesbarkeit nicht angewendet werden kann", - "vendor_not_configured": "Anbieter %s ist nicht konfiguriert", - "vendor_no_transcription_support": "Anbieter %s unterstützt keine Audio-Transkription", - "transcription_model_required": "Transkriptionsmodell ist erforderlich (verwende --transcribe-model)", - "youtube_not_configured": "YouTube ist nicht konfiguriert, bitte führen Sie die Einrichtung durch", - "spotify_not_configured": "Spotify ist nicht konfiguriert, bitte führen Sie die Einrichtung durch", - "spotify_label": "Spotify", - "spotify_setup_description": "Spotify - um Podcast-/Show-Metadaten von Spotify abzurufen", - "spotify_invalid_url": "Ungültige Spotify-URL, kann Show- oder Episoden-ID nicht abrufen: '%s'", - "spotify_error_getting_metadata": "Fehler beim Abrufen der Spotify-Metadaten: %v", - "spotify_no_show_found": "Keine Show mit ID gefunden: %s", - "spotify_no_episode_found": "Keine Episode mit ID gefunden: %s", - "spotify_url_help": "Spotify-Podcast- oder Episoden-URL zum Abrufen von Metadaten und Senden an den Chat", - "youtube_api_key_required": "YouTube API-Schlüssel erforderlich für Kommentare und Metadaten. Führen Sie 'fabric --setup' zur Konfiguration aus", - "youtube_ytdlp_not_found": "yt-dlp wurde nicht in PATH gefunden. Bitte installiere yt-dlp, um die YouTube-Transkript-Funktionalität zu nutzen", - "youtube_invalid_url": "ungültige YouTube-URL, kann keine Video- oder Playlist-ID abrufen: '%s'", - "youtube_url_is_playlist_not_video": "URL ist eine Playlist, kein Video", - "youtube_no_video_id_found": "keine Video-ID in URL gefunden", - "youtube_rate_limit_exceeded": "YouTube-Ratenlimit überschritten. Versuche es später erneut oder verwende andere yt-dlp-Argumente wie '--sleep-requests 1', um Anfragen zu verlangsamen.", - "youtube_auth_required_bot_detection": "YouTube erfordert Authentifizierung (Bot-Erkennung). Verwende --yt-dlp-args='--cookies-from-browser BROWSER' wobei BROWSER chrome, firefox, brave usw. sein kann.", - "youtube_ytdlp_stderr_error": "Fehler beim Lesen von yt-dlp stderr", - "youtube_invalid_ytdlp_arguments": "ungültige yt-dlp-Argumente: %v", - "youtube_failed_create_temp_dir": "temporäres Verzeichnis konnte nicht erstellt werden: %v", - "youtube_no_transcript_content": "kein Transkriptinhalt in VTT-Datei gefunden", - "youtube_no_vtt_files_found": "keine VTT-Dateien im Verzeichnis gefunden", - "youtube_failed_walk_directory": "Verzeichnis konnte nicht durchlaufen werden: %v", - "youtube_error_getting_video_details": "Fehler beim Abrufen der Videodetails: %v", - "youtube_invalid_duration_string": "ungültige Dauer-Zeichenfolge: %s", - "youtube_error_getting_metadata": "Fehler beim Abrufen der Video-Metadaten: %v", - "youtube_error_parsing_duration": "Fehler beim Parsen der Videodauer: %v", - "youtube_error_getting_comments": "Fehler beim Abrufen der Kommentare: %v", - "youtube_error_saving_csv": "Fehler beim Speichern der Videos in CSV: %v", - "youtube_no_video_found_with_id": "kein Video mit ID gefunden: %s", - "youtube_invalid_timestamp_format": "ungültiges Zeitstempel-Format: %s", - "youtube_empty_seconds_string": "leere Sekunden-Zeichenfolge", - "youtube_invalid_seconds_format": "ungültiges Sekundenformat %q: %w", - "error_fetching_playlist_videos": "Fehler beim Abrufen der Playlist-Videos: %w", - "openai_api_base_url_not_configured": "API-Basis-URL für Anbieter %s nicht konfiguriert", - "openai_failed_to_create_models_url": "Modell-URL konnte nicht erstellt werden: %w", - "openai_unexpected_status_code_with_body": "unerwarteter Statuscode: %d von Anbieter %s, Antwort: %s", - "openai_unexpected_status_code_read_error_partial": "unerwarteter Statuscode: %d von Anbieter %s (Fehler beim Lesen: %v), teilweise Antwort: %s", - "openai_unexpected_status_code_read_error": "unerwarteter Statuscode: %d von Anbieter %s (Fehler beim Lesen der Antwort: %v)", - "openai_unable_to_parse_models_response": "Modell-Antwort konnte nicht geparst werden; rohe Antwort: %s", - "openai_warning_model_no_image_generation": "Warnung: Modell '%s' unterstützt keine Bildgenerierung. Unterstützte Modelle: %s. Erwägen Sie die Verwendung von -m gpt-5.2 für Bildgenerierung.\n", - "openai_model_no_image_generation": "Modell '%s' unterstützt keine Bildgenerierung. Unterstützte Modelle: %s", - "scraping_not_configured": "Scraping-Funktionalität ist nicht konfiguriert. Bitte richte Jina ein, um Scraping zu aktivieren", - "could_not_determine_home_dir": "konnte Benutzer-Home-Verzeichnis nicht bestimmen: %w", - "could_not_stat_env_file": "konnte .env-Datei nicht überprüfen: %w", - "could_not_create_config_dir": "konnte Konfigurationsverzeichnis nicht erstellen: %w", - "could_not_create_env_file": "konnte .env-Datei nicht erstellen: %w", - "could_not_copy_to_clipboard": "konnte nicht in die Zwischenablage kopieren: %v", - "file_already_exists_not_overwriting": "Datei %s existiert bereits, wird nicht überschrieben. Benenne die vorhandene Datei um oder wähle einen anderen Namen", - "error_creating_file": "Fehler beim Erstellen der Datei: %v", - "error_writing_to_file": "Fehler beim Schreiben in die Datei: %v", - "error_creating_audio_file": "Fehler beim Erstellen der Audio-Datei: %v", - "error_writing_audio_data": "Fehler beim Schreiben von Audio-Daten in die Datei: %v", - "tts_model_requires_audio_output": "TTS-Modell '%s' benötigt Audio-Ausgabe. Bitte gib eine Audio-Ausgabedatei mit dem -o Flag an (z.B., -o output.wav)", - "audio_output_file_specified_but_not_tts_model": "Audio-Ausgabedatei '%s' angegeben, aber Modell '%s' ist kein TTS-Modell. Bitte verwende ein TTS-Modell wie gemini-2.5-flash-preview-tts", - "file_already_exists_choose_different": "Datei %s existiert bereits. Bitte wähle einen anderen Dateinamen oder entferne die vorhandene Datei", - "no_notification_system_available": "kein Benachrichtigungssystem verfügbar", - "cannot_convert_string": "kann String %q nicht zu %v konvertieren", - "unsupported_conversion": "nicht unterstützte Konvertierung von %v zu %v", - "invalid_config_path": "ungültiger Konfigurationspfad: %w", - "config_file_not_found": "Konfigurationsdatei nicht gefunden: %s", - "error_reading_config_file": "Fehler beim Lesen der Konfigurationsdatei: %w", - "error_parsing_config_file": "Fehler beim Parsen der Konfigurationsdatei: %w", - "error_reading_piped_message": "Fehler beim Lesen der weitergeleiteten Nachricht von stdin: %w", - "image_file_already_exists": "Bilddatei existiert bereits: %s", - "invalid_image_file_extension": "ungültige Bilddatei-Erweiterung '%s'. Unterstützte Formate: .png, .jpeg, .jpg, .webp", - "image_parameters_require_image_file": "Bildparameter (--image-size, --image-quality, --image-background, --image-compression) können nur mit --image-file verwendet werden", - "invalid_image_size": "ungültige Bildgröße '%s'. Unterstützte Größen: 1024x1024, 1536x1024, 1024x1536, auto", - "invalid_image_quality": "ungültige Bildqualität '%s'. Unterstützte Qualitäten: low, medium, high, auto", - "invalid_image_background": "ungültiger Bildhintergrund '%s'. Unterstützte Hintergründe: opaque, transparent", - "image_compression_jpeg_webp_only": "Bildkomprimierung kann nur mit JPEG- und WebP-Formaten verwendet werden, nicht %s", - "image_compression_range_error": "Bildkomprimierung muss zwischen 0 und 100 liegen, erhalten: %d", - "transparent_background_png_webp_only": "transparenter Hintergrund kann nur mit PNG- und WebP-Formaten verwendet werden, nicht %s", - "available_transcription_models": "Verfügbare Transkriptionsmodelle:", - "tts_audio_generated_successfully": "TTS-Audio erfolgreich generiert und gespeichert unter: %s\n", - "fabric_command_complete": "Fabric-Befehl abgeschlossen", - "fabric_command_complete_with_pattern": "Fabric: %s abgeschlossen", - "command_completed_successfully": "Befehl erfolgreich abgeschlossen", - "output_truncated": "Ausgabe: %s...", - "output_full": "Ausgabe: %s", - "choose_pattern_from_available": "Wähle ein Muster aus den verfügbaren Mustern", - "pattern_variables_help": "Werte für Mustervariablen, z.B. -v=#role:expert -v=#points:30", - "choose_context_from_available": "Wähle einen Kontext aus den verfügbaren Kontexten", - "choose_session_from_available": "Wähle eine Sitzung aus den verfügbaren Sitzungen", - "attachment_path_or_url_help": "Anhangspfad oder URL (z.B. für OpenAI-Bilderkennungsnachrichten)", - "run_setup_for_reconfigurable_parts": "Setup für alle rekonfigurierbaren Teile von Fabric ausführen", - "set_temperature": "Temperatur festlegen", - "set_top_p": "Top P festlegen", - "stream_help": "Streaming", - "set_presence_penalty": "Präsenzstrafe festlegen", - "use_model_defaults_raw_help": "Verwende die Standardwerte des Modells, ohne Chat-Optionen (temperature, top_p usw.) zu senden. Gilt nur für OpenAI-kompatible Anbieter. Anthropic-Modelle verwenden stets eine intelligente Parameterauswahl, um modell-spezifische Anforderungen einzuhalten.", - "set_frequency_penalty": "Häufigkeitsstrafe festlegen", - "list_all_patterns": "Alle Muster auflisten", - "list_all_available_models": "Alle verfügbaren Modelle auflisten", - "list_all_contexts": "Alle Kontexte auflisten", - "list_all_sessions": "Alle Sitzungen auflisten", - "update_patterns": "Muster aktualisieren", - "messages_to_send_to_chat": "Nachrichten zum Senden an den Chat", - "copy_to_clipboard": "In Zwischenablage kopieren", - "choose_model": "Modell wählen", - "specify_vendor_for_model": "Anbieter für das ausgewählte Modell angeben (z.B., -V \"LM Studio\" -m openai/gpt-oss-20b)", - "model_context_length_ollama": "Modell-Kontextlänge (betrifft nur ollama)", - "output_to_file": "Ausgabe in Datei", - "output_entire_session": "Gesamte Sitzung (auch eine temporäre) in die Ausgabedatei ausgeben", - "number_of_latest_patterns": "Anzahl der neuesten Muster zum Auflisten", - "change_default_model": "Standardmodell ändern", - "youtube_url_help": "YouTube-Video oder Playlist-\"URL\" zum Abrufen von Transkript und Kommentaren und Senden an Chat oder Ausgabe in Konsole und Speichern in Ausgabedatei", - "prefer_playlist_over_video": "Playlist gegenüber Video bevorzugen, wenn beide IDs in der URL vorhanden sind", - "grab_transcript_from_youtube": "Transkript von YouTube-Video abrufen und an Chat senden (wird standardmäßig verwendet).", - "grab_transcript_with_timestamps": "Transkript von YouTube-Video mit Zeitstempeln abrufen und an Chat senden", - "grab_comments_from_youtube": "Kommentare von YouTube-Video abrufen und an Chat senden", - "output_video_metadata": "Video-Metadaten ausgeben", - "additional_yt_dlp_args": "Zusätzliche Argumente für yt-dlp (z.B. '--cookies-from-browser brave')", - "specify_language_code": "Sprachencode für den Chat angeben, z.B. -g=en -g=zh -g=pt-BR -g=pt-PT", - "scrape_website_url": "Website-URL zu Markdown mit Jina AI scrapen", - "search_question_jina": "Suchanfrage mit Jina AI", - "seed_for_lmm_generation": "Seed für LMM-Generierung", - "wipe_context": "Kontext löschen", - "wipe_session": "Sitzung löschen", - "print_context": "Kontext ausgeben", - "print_session": "Sitzung ausgeben", - "convert_html_readability": "HTML-Eingabe in eine saubere, lesbare Ansicht konvertieren", - "apply_variables_to_input": "Variablen auf Benutzereingabe anwenden", - "disable_pattern_variable_replacement": "Mustervariablenersetzung deaktivieren", - "show_dry_run": "Zeige, was an das Modell gesendet würde, ohne es tatsächlich zu senden", - "serve_fabric_rest_api": "Fabric REST API bereitstellen", - "serve_fabric_api_ollama_endpoints": "Fabric REST API mit ollama-Endpunkten bereitstellen", - "address_to_bind_rest_api": "Adresse zum Binden der REST API", - "api_key_secure_server_routes": "API-Schlüssel zum Sichern der Server-Routen", - "path_to_yaml_config": "Pfad zur YAML-Konfigurationsdatei", - "print_current_version": "Aktuelle Version ausgeben", - "list_all_registered_extensions": "Alle registrierten Erweiterungen auflisten", - "register_new_extension": "Neue Erweiterung aus Konfigurationsdateipfad registrieren", - "remove_registered_extension": "Registrierte Erweiterung nach Name entfernen", - "choose_strategy_from_available": "Strategie aus den verfügbaren Strategien wählen", - "list_all_strategies": "Alle Strategien auflisten", - "list_all_vendors": "Alle Anbieter auflisten", - "output_raw_list_shell_completion": "Rohe Liste ohne Kopfzeilen/Formatierung ausgeben (für Shell-Vervollständigung)", - "enable_web_search_tool": "Web-Such-Tool für unterstützte Modelle aktivieren (Anthropic, OpenAI, Gemini)", - "set_location_web_search": "Standort für Web-Suchergebnisse festlegen (z.B., 'America/Los_Angeles')", - "save_generated_image_to_file": "Generiertes Bild in angegebenem Dateipfad speichern (z.B., 'output.png')", - "image_dimensions_help": "Bildabmessungen: 1024x1024, 1536x1024, 1024x1536, auto (Standard: auto)", - "image_quality_help": "Bildqualität: low, medium, high, auto (Standard: auto)", - "compression_level_jpeg_webp": "Komprimierungslevel 0-100 für JPEG/WebP-Formate (Standard: nicht gesetzt)", - "background_type_help": "Hintergrundtyp: opaque, transparent (Standard: opaque, nur für PNG/WebP)", - "suppress_thinking_tags": "In Denk-Tags eingeschlossenen Text unterdrücken", - "start_tag_thinking_sections": "Start-Tag für Denk-Abschnitte", - "end_tag_thinking_sections": "End-Tag für Denk-Abschnitte", - "disable_openai_responses_api": "OpenAI Responses API deaktivieren (Standard: false)", - "audio_video_file_transcribe": "Audio- oder Video-Datei zum Transkribieren", - "model_for_transcription": "Modell für Transkription (getrennt vom Chat-Modell)", - "split_media_files_ffmpeg": "Audio/Video-Dateien größer als 25MB mit ffmpeg aufteilen", - "tts_voice_name": "TTS-Stimmenname für unterstützte Modelle (z.B., Kore, Charon, Puck)", - "list_gemini_tts_voices": "Alle verfügbaren Gemini TTS-Stimmen auflisten", - "list_transcription_models": "Alle verfügbaren Transkriptionsmodelle auflisten", - "send_desktop_notification": "Desktop-Benachrichtigung senden, wenn Befehl abgeschlossen ist", - "custom_notification_command": "Benutzerdefinierter Befehl für Benachrichtigungen (überschreibt eingebaute Benachrichtigungen)", - "set_reasoning_thinking_level": "Reasoning/Thinking-Level festlegen (z.B., off, low, medium, high, oder numerische Token für Anthropic oder Google Gemini)", - "set_debug_level": "Debug-Level festlegen (0=aus, 1=grundlegend, 2=detailliert, 3=Trace)", - "usage_header": "Verwendung:", - "application_options_header": "Anwendungsoptionen:", - "help_options_header": "Hilfe-Optionen:", - "help_message": "Diese Hilfenachricht anzeigen", - "options_placeholder": "[OPTIONEN]", - "available_vendors_header": "Verfügbare Anbieter:", - "available_models_header": "Verfügbare Modelle", - "no_items_found": "Keine %s", - "no_description_available": "Keine Beschreibung verfügbar", - "i18n_download_failed": "Fehler beim Herunterladen der Übersetzung für Sprache '%s': %v", - "i18n_load_failed": "Fehler beim Laden der Übersetzungsdatei: %v", - "setup_welcome_header": "🎉 Willkommen bei Fabric! Lass uns mit der Einrichtung beginnen.", - "setup_step_downloading_patterns": "📥 Schritt 1: Patterns werden heruntergeladen (erforderlich für Fabric)...", - "setup_step_downloading_strategies": "📥 Schritt 2: Strategien werden heruntergeladen (erforderlich für Fabric)...", - "setup_step_configure_ai_provider": "🤖 Schritt 3: KI-Anbieter konfigurieren", - "setup_ai_provider_required": "Fabric benötigt mindestens einen KI-Anbieter.", - "setup_add_more_providers_later": "Sie können später weitere Anbieter mit 'fabric --setup' hinzufügen", - "setup_step_setting_defaults": "⚙️ Schritt 4: Standard-Anbieter und -Modell werden festgelegt...", - "setup_complete_header": "✅ Einrichtung abgeschlossen! Sie können Fabric jetzt verwenden.", - "setup_next_steps": "Nächste Schritte:", - "setup_list_patterns": "• Verfügbare Patterns auflisten: fabric -l", - "setup_try_pattern": "• Ein Pattern ausprobieren: echo 'Ihr Text' | fabric --pattern summarize", - "setup_configure_more": "• Weitere Einstellungen konfigurieren: fabric --setup", - "setup_failed_download_patterns": "Fehler beim Herunterladen der Patterns: %w", - "setup_failed_download_strategies": "Fehler beim Herunterladen der Strategien: %w", - "setup_failed_set_defaults": "Fehler beim Festlegen des Standard-Anbieters und -Modells: %w", - "setup_no_ai_provider_selected": "Kein KI-Anbieter ausgewählt - mindestens einer ist erforderlich", - "setup_invalid_selection": "Ungültige Auswahl: %s", - "setup_available_ai_providers": "Verfügbare KI-Anbieter:", - "setup_enter_ai_provider_number": "KI-Anbieter-Nummer", - "setup_available_plugins": "Verfügbare Plugins:", - "setup_plugin_number": "Plugin-Nummer", - "setup_plugin_prompt": "Geben Sie die Nummer des Plugins ein, das eingerichtet werden soll", - "setup_required_configuration_header": "━━━ ERFORDERLICHE KONFIGURATION ━━━\n\nKI-Anbieter [mindestens einer erforderlich]", - "setup_required_tools": "Erforderliche Werkzeuge", - "setup_optional_configuration_header": "━━━ OPTIONALE KONFIGURATION ━━━\n\nOptionale Werkzeuge", - "setup_validation_header": "Konfigurationsstatus:", - "setup_validation_ai_provider_configured": "✓ KI-Anbieter konfiguriert", - "setup_validation_ai_provider_missing": "✗ KI-Anbieter nicht konfiguriert - Erforderlich für Fabric", - "setup_validation_defaults_configured": "✓ Standard-Anbieter/-Modell festgelegt: %s/%s", - "setup_validation_defaults_missing": "✗ Standard-Anbieter/-Modell nicht festgelegt - Erforderlich für Fabric", - "setup_validation_patterns_configured": "✓ Patterns heruntergeladen", - "setup_validation_patterns_missing": "✗ Patterns nicht gefunden - Erforderlich für Fabric", - "setup_validation_strategies_configured": "✓ Strategien heruntergeladen", - "setup_validation_strategies_missing": "✗ Strategien nicht gefunden - Erforderlich für Fabric", - "setup_validation_incomplete_warning": "⚠️ Einrichtung unvollständig! Erforderliche Komponenten fehlen.", - "setup_validation_incomplete_help": "Führen Sie 'fabric --setup' erneut aus, um fehlende Elemente zu konfigurieren,\noder 'fabric -U', um Patterns und Strategien herunterzuladen.", - "setup_validation_complete": "✓ Alle erforderlichen Komponenten konfiguriert!", - "patterns_not_found_header": "⚠️ Keine Patterns gefunden!", - "patterns_required_to_work": "Patterns sind erforderlich, damit Fabric funktioniert. Um dies zu beheben:", - "patterns_option_run_setup": "Option 1 (Empfohlen): Setup ausführen, um Patterns herunterzuladen", - "patterns_option_run_setup_command": "fabric --setup", - "patterns_option_run_update": "Option 2: Patterns direkt herunterladen/aktualisieren", - "patterns_option_run_update_command": "fabric -U", - "pattern_not_found_no_patterns": "Pattern '%s' nicht gefunden.\n\nKeine Patterns installiert! Um dies zu beheben:\n • Führen Sie 'fabric --setup' aus, um Patterns zu konfigurieren und herunterzuladen\n • Oder führen Sie 'fabric -U' aus, um Patterns direkt herunterzuladen/zu aktualisieren", - "pattern_not_found_list_available": "Pattern '%s' nicht gefunden. Führen Sie 'fabric -l' aus, um verfügbare Patterns anzuzeigen", - "plugin_configured": " ✓", - "plugin_not_configured": " ⚠️ NICHT KONFIGURIERT", - "defaults_setup_description": "Standard-KI-Anbieter und -Modell", - "defaults_model_question": "Geben Sie den Index oder den Namen Ihres Standardmodells ein", - "defaults_model_context_length_question": "Geben Sie die Kontextlänge des Modells ein", - "custom_patterns_label": "Benutzerdefinierte Patterns", - "custom_patterns_setup_description": "Benutzerdefinierte Patterns - Verzeichnis für Ihre benutzerdefinierten Patterns festlegen", - "custom_patterns_directory_question": "Geben Sie den Pfad zu Ihrem benutzerdefinierten Pattern-Verzeichnis ein", - "jina_label": "Jina AI", - "jina_setup_description": "Jina AI Service - zum Erfassen einer Webseite als sauberer, LLM-freundlicher Text", - "youtube_label": "YouTube", - "youtube_setup_description": "YouTube - zum Erfassen von Video-Transkripten (via yt-dlp) und Kommentaren/Metadaten (via YouTube API)", - "language_label": "Sprache", - "language_setup_description": "Sprache - Standard-Ausgabesprache des AI-Anbieters", - "language_output_question": "Geben Sie Ihre Standard-Ausgabesprache ein (zum Beispiel: zh_CN)", - "optional_marker": "(optional)", - "required_marker": "[erforderlich]", - "patterns_loader_label": "Pattern-Loader", - "patterns_setup_description": "Patterns – lädt Patterns herunter", - "patterns_git_repo_url_label": "Git Repo URL", - "patterns_git_repo_url_question": "Geben Sie die Standard-Git-Repository-URL für die Patterns ein", - "patterns_git_repo_folder_label": "Git Repo Patterns Ordner", - "patterns_git_repo_folder_question": "Geben Sie den Standardordner im Git-Repository an, in dem die Patterns gespeichert sind", - "patterns_failed_create_temp_folder": "Fehler beim Erstellen des temporären Pattern-Ordners: %w", - "patterns_downloading": "Lade Patterns herunter und befülle %s...\\n", - "patterns_failed_download_from_git": "Fehler beim Herunterladen der Patterns aus dem Git-Repository: %w", - "patterns_saving_updated_configuration": "💾 Aktualisierte Konfiguration wird gespeichert (Pfad geändert von '%s' zu '%s')...\\n", - "patterns_failed_move_patterns": "Fehler beim Verschieben der Patterns in das Konfigurationsverzeichnis: %w", - "patterns_download_success": "✅ Patterns erfolgreich nach %s heruntergeladen und installiert\\n", - "patterns_failed_unique_file": "Fehler beim Erstellen der Datei mit eindeutigen Patterns: %w", - "patterns_failed_access_directory": "Fehler beim Zugriff auf den Pattern-Ordner '%s': %w", - "patterns_preserve_warning": "Warnung: Benutzerdefiniertes Pattern '%s' konnte nicht erhalten werden: %v\\n", - "patterns_preserved_custom_pattern": "Benutzerdefiniertes Pattern beibehalten: %s\\n", - "patterns_failed_create_temp_dir": "Fehler beim Erstellen des temporären Verzeichnisses: %w", - "patterns_cloning_repository": "Repository %s wird geklont (Pfad: %s)...\\n", - "patterns_failed_download_from_repo": "Fehler beim Herunterladen der Patterns von %s: %w", - "patterns_failed_read_temp_directory": "Fehler beim Lesen des temporären Pattern-Verzeichnisses: %w", - "patterns_no_patterns_migration_failed": "Keine Patterns im Repository unter Pfad %s gefunden und Migration fehlgeschlagen: %w", - "patterns_downloaded_temp": "%d Patterns in temporäres Verzeichnis heruntergeladen\\n", - "patterns_detected_old_path": "🔄 Alter Pattern-Pfad 'patterns' erkannt, versuche Migration zu 'data/patterns'...", - "patterns_warning_remove_test_folder": "Warnung: Der temporäre Testordner '%s' konnte nicht entfernt werden: %v\\n", - "patterns_found_new_path": "✅ %d Patterns im neuen Pfad '%s' gefunden, Konfiguration wird aktualisiert...\\n", - "patterns_failed_move_test_patterns": "Fehler beim Verschieben der Test-Patterns in den temporären Ordner: %w", - "patterns_unable_to_find_or_migrate": "Keine Patterns im aktuellen Pfad '%s' gefunden oder Migration auf neue Struktur fehlgeschlagen", - "patterns_failed_read_directory": "Fehler beim Lesen des Pattern-Verzeichnisses: %w", - "patterns_debug_included_custom_directory": "📂 Auch Patterns aus dem benutzerdefinierten Verzeichnis aufgenommen: %s\\n", - "patterns_warning_custom_directory": "Warnung: Benutzerdefiniertes Pattern-Verzeichnis %s konnte nicht gelesen werden: %v\\n", - "patterns_no_patterns_found_in_directories": "Keine Patterns in den Verzeichnissen %s und %s gefunden", - "patterns_no_patterns_found_in_directory": "Keine Patterns im Verzeichnis %s gefunden", - "patterns_failed_write_unique_file": "Fehler beim Schreiben der Datei mit eindeutigen Patterns: %w", - "patterns_unique_file_created": "📝 Datei mit eindeutigen Patterns mit %d Einträgen erstellt\\n", - "patterns_no_patterns_copied": "Keine Patterns wurden erfolgreich nach %s kopiert", - "patterns_failed_loaded_marker": "Marker-Datei '%s' konnte nicht erstellt werden: %w", - "strategies_label": "Prompt-Strategien", - "strategies_setup_description": "Strategien – lädt Prompt-Strategien herunter (z. B. Chain of Thought)", - "strategies_git_repo_url_label": "Git Repo URL", - "strategies_git_repo_url_question": "Geben Sie die Standard-Git-Repository-URL für die Strategien ein", - "strategies_git_repo_folder_label": "Git Repo Strategien Ordner", - "strategies_git_repo_folder_question": "Geben Sie den Standardordner im Git-Repository an, in dem Strategien gespeichert sind", - "strategies_downloading": "Lade Strategien herunter und befülle %s...\\n", - "strategies_download_success": "✅ Strategien erfolgreich nach %s heruntergeladen und installiert\\n", - "strategies_home_dir_error": "Startverzeichnis konnte nicht ermittelt werden: %v", - "strategies_failed_create_directory": "Strategie-Verzeichnis konnte nicht erstellt werden: %w", - "strategies_cloning_repository": "Repository %s wird geklont (Pfad: %s)...\\n", - "strategies_failed_download": "Fehler beim Herunterladen der Strategien: %w", - "strategies_downloaded_count": "%d Strategien heruntergeladen\\n", - "strategies_home_dir_fallback": "Startverzeichnis konnte nicht ermittelt werden: %v, verwende stattdessen aktuelles Verzeichnis", - "strategy_not_found": "Strategie %s nicht gefunden. Führen Sie 'fabric --liststrategies' aus, um eine Liste zu erhalten", - "strategies_none_found": "Keine Strategien gefunden. Führen Sie 'fabric --setup' aus, um Strategien herunterzuladen", - "strategies_available_header": "Verfügbare Strategien:", - "plugin_enter_value": "Geben Sie Ihren %v %v ein", - "plugin_enable_bool_question": "%v %v aktivieren (true/false)", - "plugin_setup_skipped": "[%v] übersprungen\\n", - "plugin_question_bool": "%v%v (true/false, leer lassen für '%s' oder '%v' eingeben, um den Wert zu entfernen):", - "plugin_question_with_default": "%v%v (leer lassen für '%s' oder '%v' eingeben, um den Wert zu entfernen):", - "plugin_question_optional": "%v%v (leer lassen zum Überspringen):", - "plugin_invalid_boolean_value": "Ungültiger Boolescher Wert: %v", - "plugin_setting_not_valid": "%v=%v ist nicht gültig", - "plugin_invalid_bool": "Ungültiger boolescher Wert: %q", - "ollama_num_ctx_must_be_finite": "num_ctx muss eine endliche Zahl sein", - "ollama_num_ctx_must_be_integer": "num_ctx muss eine Ganzzahl sein, erhielt Float mit Nachkommastellen", - "ollama_num_ctx_value_out_of_range": "num_ctx Wert außerhalb des Bereichs", - "ollama_num_ctx_must_be_positive": "num_ctx muss positiv sein, erhalten: %d", - "ollama_num_ctx_value_too_large": "num_ctx Wert zu groß: %d", - "ollama_num_ctx_must_be_valid_number": "num_ctx muss eine gültige Zahl sein", - "ollama_num_ctx_must_be_valid_number_got": "num_ctx muss eine gültige Zahl sein, erhalten: %s", - "ollama_num_ctx_invalid_type": "num_ctx muss eine Zahl sein, ungültiger Typ erhalten", - "ollama_num_ctx_exceeds_maximum": "num_ctx überschreitet den maximal zulässigen Wert von %d", - "ollama_error_reading_body": "Fehler beim Lesen des Bodys: %v", - "ollama_error_endpoint": "Endpunkt wird getestet", - "ollama_error_unmarshalling_body": "Fehler beim Unmarshalling des Bodys: %v", - "ollama_invalid_num_ctx_in_request": "Ungültiger num_ctx in Anfrage: %v", - "ollama_warning_parse_variables": "Warnung: Fehler beim Parsen von options.variables als JSON: %v", - "ollama_error_marshalling_body": "Fehler beim Marshalling des Bodys: %v", - "ollama_error_building_chat_url": "Fehler beim Erstellen der /chat URL: %v", - "ollama_error_creating_chat_request": "Fehler beim Erstellen der /chat Anfrage: %v", - "ollama_failed_create_request": "Fehler beim Erstellen der Anfrage", - "ollama_error_getting_chat_body": "Fehler beim Abrufen des /chat Bodys: %v", - "ollama_upstream_non_2xx_body_unreadable": "Upstream Fabric Server hat nicht-2xx Status %d zurückgegeben und Body konnte nicht gelesen werden: %v", - "ollama_upstream_non_2xx": "Upstream Fabric Server hat nicht-2xx Status %d zurückgegeben: %s", - "ollama_upstream_returned_status": "Upstream Fabric Server hat Status %d zurückgegeben", - "ollama_error_prefix": "Fehler: %s", - "ollama_error_parse_upstream_response": "Fehler: Upstream-Antwort konnte nicht geparst werden", - "ollama_failed_unmarshal_fabric_response": "Fehler beim Unmarshalling der Fabric Antwort", - "ollama_error_writing_response": "Fehler beim Schreiben der Antwort: %v", - "ollama_error_scanning_body": "Fehler beim Scannen des Bodys: %v", - "ollama_failed_scan_sse_stream": "Fehler beim Scannen des SSE Response Streams: %v", - "ollama_sse_buffer_limit": "SSE Zeile überschreitet 1MB Puffer-Limit - Datenzeile zu groß", - "ollama_warning_no_content": "Warnung: Kein Inhalt vom Upstream Fabric Server erhalten", - "ollama_no_content_from_upstream": "Kein Inhalt vom Upstream Fabric Server erhalten", - "ollama_empty_address": "Leere Adresse", - "ollama_invalid_address": "Ungültige Adresse: %w", - "ollama_invalid_address_missing_host": "Ungültige Adresse: Host fehlt", - "ollama_invalid_address_missing_hostname": "Ungültige Adresse: Hostname fehlt", - "ollama_invalid_address_path_not_allowed": "Ungültige Adresse: Pfadkomponente in bloßer Adresse nicht zulässig", - "extension_registry_not_initialized": "Erweiterungsregistrierung nicht initialisiert", - "extension_name_label": "Erweiterung: %s\n", - "extension_status_disabled": " Status: DEAKTIVIERT - Hash-Überprüfung fehlgeschlagen: %v\n", - "extension_config_path_label": " Konfigurationspfad: %s\n\n", - "extension_status_enabled": " Status: AKTIVIERT\n", - "extension_executable_label": " Programmdatei: %s\n", - "extension_type_label": " Typ: %s\n", - "extension_timeout_label": " Zeitlimit: %s\n", - "extension_description_label": " Beschreibung: %s\n", - "extension_version_label": " Version: %s\n", - "extension_operations_label": " Operationen:\n", - "extension_command_template_label": " Befehlsvorlage: %s\n", - "extension_file_config_label": " Dateikonfiguration:\n", - "extension_invalid_config_path": "ungültiger Konfigurationspfad: %w", - "extension_failed_read_config": "Konfigurationsdatei konnte nicht gelesen werden: %w", - "extension_failed_parse_config": "Konfigurationsdatei konnte nicht geparst werden: %w", - "extension_failed_register": "Erweiterung konnte nicht registriert werden: %w", - "extension_invalid_timeout": "ungültiger Zeitlimit-Wert '%s': muss eine Dauer wie '30s' oder '1m' sein: %w", - "extension_registered_success": "Erweiterung erfolgreich registriert:\n", - "extension_name_detail_label": "Name: %s\n", - "extension_failed_remove": "Erweiterung konnte nicht entfernt werden: %w", - "lmstudio_api_url_question": "Geben Sie Ihre %v URL ein (zur Erinnerung, sie ist normalerweise %v)", - "lmstudio_failed_create_request": "Anfrage konnte nicht erstellt werden: %w", - "lmstudio_failed_send_request": "Anfrage konnte nicht gesendet werden: %w", - "lmstudio_unexpected_status_code": "Unerwarteter Statuscode: %d", - "lmstudio_failed_decode_response": "Antwort konnte nicht dekodiert werden: %w", - "lmstudio_failed_marshal_payload": "Nutzlast konnte nicht serialisiert werden: %w", - "lmstudio_error_reading_response": "Fehler beim Lesen der Antwort: %w", - "lmstudio_invalid_response_missing_choices": "Ungültiges Antwortformat: Auswahlmöglichkeiten fehlen oder sind leer", - "lmstudio_invalid_response_missing_message": "Ungültiges Antwortformat: Nachricht in der ersten Auswahl fehlt", - "lmstudio_invalid_response_missing_content": "Ungültiges Antwortformat: Inhalt in der Nachricht fehlt oder ist kein String", - "lmstudio_invalid_response_missing_text": "Ungültiges Antwortformat: Text in der ersten Auswahl fehlt oder ist kein String", - "lmstudio_no_embeddings_returned": "Keine Einbettungen zurückgegeben", - "extension_warning_load_registry": "Warnung: Erweiterungsregistrierung konnte nicht geladen werden: %v\n", - "extension_name_empty": "Erweiterungsname darf nicht leer sein", - "extension_name_contains_spaces": "Erweiterungsname '%s' enthält Leerzeichen - Namen dürfen keine Leerzeichen enthalten", - "extension_executable_not_found": "Programmdatei nicht gefunden: %w", - "extension_failed_get_absolute_path": "absoluter Pfad konnte nicht ermittelt werden: %w", - "extension_failed_hash_executable": "Programmdatei-Hash konnte nicht berechnet werden: %w", - "extension_invalid_definition": "ungültige Erweiterungsdefinition: %w", - "extension_name_required": "Erweiterungsname ist erforderlich", - "extension_executable_required": "Pfad zur Programmdatei ist erforderlich", - "extension_type_required": "Erweiterungstyp ist erforderlich", - "extension_invalid_timeout_format": "ungültiges Zeitlimit-Format: %w", - "extension_operation_required": "mindestens eine Operation muss definiert sein", - "extension_cmd_template_required": "Befehlsvorlage ist für Operation %s erforderlich", - "extension_not_found": "Erweiterung %s nicht gefunden", - "extension_config_hash_mismatch": "Hash-Abweichung der Konfigurationsdatei für %s", - "extension_failed_verify_executable": "Programmdatei konnte nicht verifiziert werden: %w", - "extension_executable_hash_mismatch": "Hash-Abweichung der Programmdatei für %s", - "extension_failed_marshal_registry": "Erweiterungsregistrierung konnte nicht serialisiert werden: %w", - "extension_failed_read_registry": "Erweiterungsregistrierung konnte nicht gelesen werden: %w", - "extension_failed_parse_registry": "Erweiterungsregistrierung konnte nicht geparst werden: %w", - "extension_failed_get_extension": "Erweiterung konnte nicht abgerufen werden: %w", - "extension_failed_format_command": "Befehl konnte nicht formatiert werden: %w", - "extension_empty_command": "Leerer Befehl nach Formatierung", - "extension_operation_not_found": "Operation %s für Erweiterung %s nicht gefunden", - "extension_executing_command": "Befehl wird ausgeführt: %s\n", - "extension_execution_failed_stderr": "Ausführung fehlgeschlagen: %w\nstderr: %s", - "extension_no_file_config": "Keine Dateikonfiguration gefunden", - "extension_no_output_file": "Keine Ausgabedatei in der Konfiguration angegeben", - "extension_execution_timed_out": "Ausführung nach %v abgelaufen", - "extension_execution_failed_err": "Ausführung fehlgeschlagen: %w\nerr: %s", - "extension_failed_read_output_file": "Ausgabedatei konnte nicht gelesen werden: %w", - "extension_failed_get_output_path": "Ausgabepfad konnte nicht ermittelt werden: %w\nerr: %s", - "spotify_failed_create_token_request": "Token-Anfrage konnte nicht erstellt werden: %w", - "spotify_failed_request_access_token": "Zugriffstoken konnte nicht angefordert werden: %w", - "spotify_failed_get_access_token": "Zugriffstoken konnte nicht abgerufen werden: Status %d, Antwort: %s", - "spotify_failed_decode_token_response": "Token-Antwort konnte nicht dekodiert werden: %w", - "spotify_failed_create_request": "Anfrage konnte nicht erstellt werden: %w", - "spotify_failed_execute_request": "Anfrage konnte nicht ausgeführt werden: %w", - "spotify_failed_read_response_body": "Antwortinhalt konnte nicht gelesen werden: %w", - "spotify_api_request_failed": "API-Anfrage fehlgeschlagen: Status %d, Antwort: %s", - "spotify_failed_parse_show_metadata": "Show-Metadaten konnten nicht analysiert werden: %w", - "spotify_failed_parse_episode_metadata": "Episoden-Metadaten konnten nicht analysiert werden: %w", - "spotify_search_failed": "Suche fehlgeschlagen: %w", - "spotify_failed_parse_search_results": "Suchergebnisse konnten nicht analysiert werden: %w", - "spotify_failed_get_show_episodes": "Show-Episoden konnten nicht abgerufen werden: %w", - "spotify_failed_parse_episodes": "Episoden konnten nicht analysiert werden: %w" -, + "html_readability_error": "verwende ursprüngliche Eingabe, da HTML-Lesbarkeit nicht angewendet werden kann", + "vendor_not_configured": "Anbieter %s ist nicht konfiguriert", + "vendor_no_transcription_support": "Anbieter %s unterstützt keine Audio-Transkription", + "transcription_model_required": "Transkriptionsmodell ist erforderlich (verwende --transcribe-model)", + "youtube_not_configured": "YouTube ist nicht konfiguriert, bitte führen Sie die Einrichtung durch", + "spotify_not_configured": "Spotify ist nicht konfiguriert, bitte führen Sie die Einrichtung durch", + "spotify_label": "Spotify", + "spotify_setup_description": "Spotify - um Podcast-/Show-Metadaten von Spotify abzurufen", + "spotify_invalid_url": "Ungültige Spotify-URL, kann Show- oder Episoden-ID nicht abrufen: '%s'", + "spotify_error_getting_metadata": "Fehler beim Abrufen der Spotify-Metadaten: %v", + "spotify_no_show_found": "Keine Show mit ID gefunden: %s", + "spotify_no_episode_found": "Keine Episode mit ID gefunden: %s", + "spotify_url_help": "Spotify-Podcast- oder Episoden-URL zum Abrufen von Metadaten und Senden an den Chat", + "youtube_api_key_required": "YouTube API-Schlüssel erforderlich für Kommentare und Metadaten. Führen Sie 'fabric --setup' zur Konfiguration aus", + "youtube_ytdlp_not_found": "yt-dlp wurde nicht in PATH gefunden. Bitte installiere yt-dlp, um die YouTube-Transkript-Funktionalität zu nutzen", + "youtube_invalid_url": "ungültige YouTube-URL, kann keine Video- oder Playlist-ID abrufen: '%s'", + "youtube_url_is_playlist_not_video": "URL ist eine Playlist, kein Video", + "youtube_no_video_id_found": "keine Video-ID in URL gefunden", + "youtube_rate_limit_exceeded": "YouTube-Ratenlimit überschritten. Versuche es später erneut oder verwende andere yt-dlp-Argumente wie '--sleep-requests 1', um Anfragen zu verlangsamen.", + "youtube_auth_required_bot_detection": "YouTube erfordert Authentifizierung (Bot-Erkennung). Verwende --yt-dlp-args='--cookies-from-browser BROWSER' wobei BROWSER chrome, firefox, brave usw. sein kann.", + "youtube_ytdlp_stderr_error": "Fehler beim Lesen von yt-dlp stderr", + "youtube_invalid_ytdlp_arguments": "ungültige yt-dlp-Argumente: %v", + "youtube_failed_create_temp_dir": "temporäres Verzeichnis konnte nicht erstellt werden: %v", + "youtube_no_transcript_content": "kein Transkriptinhalt in VTT-Datei gefunden", + "youtube_no_vtt_files_found": "keine VTT-Dateien im Verzeichnis gefunden", + "youtube_failed_walk_directory": "Verzeichnis konnte nicht durchlaufen werden: %v", + "youtube_error_getting_video_details": "Fehler beim Abrufen der Videodetails: %v", + "youtube_invalid_duration_string": "ungültige Dauer-Zeichenfolge: %s", + "youtube_error_getting_metadata": "Fehler beim Abrufen der Video-Metadaten: %v", + "youtube_error_parsing_duration": "Fehler beim Parsen der Videodauer: %v", + "youtube_error_getting_comments": "Fehler beim Abrufen der Kommentare: %v", + "youtube_error_saving_csv": "Fehler beim Speichern der Videos in CSV: %v", + "youtube_no_video_found_with_id": "kein Video mit ID gefunden: %s", + "youtube_invalid_timestamp_format": "ungültiges Zeitstempel-Format: %s", + "youtube_empty_seconds_string": "leere Sekunden-Zeichenfolge", + "youtube_invalid_seconds_format": "ungültiges Sekundenformat %q: %w", + "error_fetching_playlist_videos": "Fehler beim Abrufen der Playlist-Videos: %w", + "openai_api_base_url_not_configured": "API-Basis-URL für Anbieter %s nicht konfiguriert", + "openai_failed_to_create_models_url": "Modell-URL konnte nicht erstellt werden: %w", + "openai_unexpected_status_code_with_body": "unerwarteter Statuscode: %d von Anbieter %s, Antwort: %s", + "openai_unexpected_status_code_read_error_partial": "unerwarteter Statuscode: %d von Anbieter %s (Fehler beim Lesen: %v), teilweise Antwort: %s", + "openai_unexpected_status_code_read_error": "unerwarteter Statuscode: %d von Anbieter %s (Fehler beim Lesen der Antwort: %v)", + "openai_unable_to_parse_models_response": "Modell-Antwort konnte nicht geparst werden; rohe Antwort: %s", + "openai_warning_model_no_image_generation": "Warnung: Modell '%s' unterstützt keine Bildgenerierung. Unterstützte Modelle: %s. Erwägen Sie die Verwendung von -m gpt-5.2 für Bildgenerierung.\n", + "openai_model_no_image_generation": "Modell '%s' unterstützt keine Bildgenerierung. Unterstützte Modelle: %s", + "scraping_not_configured": "Scraping-Funktionalität ist nicht konfiguriert. Bitte richte Jina ein, um Scraping zu aktivieren", + "could_not_determine_home_dir": "konnte Benutzer-Home-Verzeichnis nicht bestimmen: %w", + "could_not_stat_env_file": "konnte .env-Datei nicht überprüfen: %w", + "could_not_create_config_dir": "konnte Konfigurationsverzeichnis nicht erstellen: %w", + "could_not_create_env_file": "konnte .env-Datei nicht erstellen: %w", + "could_not_copy_to_clipboard": "konnte nicht in die Zwischenablage kopieren: %v", + "file_already_exists_not_overwriting": "Datei %s existiert bereits, wird nicht überschrieben. Benenne die vorhandene Datei um oder wähle einen anderen Namen", + "error_creating_file": "Fehler beim Erstellen der Datei: %v", + "error_writing_to_file": "Fehler beim Schreiben in die Datei: %v", + "error_creating_audio_file": "Fehler beim Erstellen der Audio-Datei: %v", + "error_writing_audio_data": "Fehler beim Schreiben von Audio-Daten in die Datei: %v", + "tts_model_requires_audio_output": "TTS-Modell '%s' benötigt Audio-Ausgabe. Bitte gib eine Audio-Ausgabedatei mit dem -o Flag an (z.B., -o output.wav)", + "audio_output_file_specified_but_not_tts_model": "Audio-Ausgabedatei '%s' angegeben, aber Modell '%s' ist kein TTS-Modell. Bitte verwende ein TTS-Modell wie gemini-2.5-flash-preview-tts", + "file_already_exists_choose_different": "Datei %s existiert bereits. Bitte wähle einen anderen Dateinamen oder entferne die vorhandene Datei", + "no_notification_system_available": "kein Benachrichtigungssystem verfügbar", + "cannot_convert_string": "kann String %q nicht zu %v konvertieren", + "unsupported_conversion": "nicht unterstützte Konvertierung von %v zu %v", + "invalid_config_path": "ungültiger Konfigurationspfad: %w", + "config_file_not_found": "Konfigurationsdatei nicht gefunden: %s", + "error_reading_config_file": "Fehler beim Lesen der Konfigurationsdatei: %w", + "error_parsing_config_file": "Fehler beim Parsen der Konfigurationsdatei: %w", + "error_reading_piped_message": "Fehler beim Lesen der weitergeleiteten Nachricht von stdin: %w", + "image_file_already_exists": "Bilddatei existiert bereits: %s", + "invalid_image_file_extension": "ungültige Bilddatei-Erweiterung '%s'. Unterstützte Formate: .png, .jpeg, .jpg, .webp", + "image_parameters_require_image_file": "Bildparameter (--image-size, --image-quality, --image-background, --image-compression) können nur mit --image-file verwendet werden", + "invalid_image_size": "ungültige Bildgröße '%s'. Unterstützte Größen: 1024x1024, 1536x1024, 1024x1536, auto", + "invalid_image_quality": "ungültige Bildqualität '%s'. Unterstützte Qualitäten: low, medium, high, auto", + "invalid_image_background": "ungültiger Bildhintergrund '%s'. Unterstützte Hintergründe: opaque, transparent", + "image_compression_jpeg_webp_only": "Bildkomprimierung kann nur mit JPEG- und WebP-Formaten verwendet werden, nicht %s", + "image_compression_range_error": "Bildkomprimierung muss zwischen 0 und 100 liegen, erhalten: %d", + "transparent_background_png_webp_only": "transparenter Hintergrund kann nur mit PNG- und WebP-Formaten verwendet werden, nicht %s", + "available_transcription_models": "Verfügbare Transkriptionsmodelle:", + "tts_audio_generated_successfully": "TTS-Audio erfolgreich generiert und gespeichert unter: %s\n", + "fabric_command_complete": "Fabric-Befehl abgeschlossen", + "fabric_command_complete_with_pattern": "Fabric: %s abgeschlossen", + "command_completed_successfully": "Befehl erfolgreich abgeschlossen", + "output_truncated": "Ausgabe: %s...", + "output_full": "Ausgabe: %s", + "choose_pattern_from_available": "Wähle ein Muster aus den verfügbaren Mustern", + "pattern_variables_help": "Werte für Mustervariablen, z.B. -v=#role:expert -v=#points:30", + "choose_context_from_available": "Wähle einen Kontext aus den verfügbaren Kontexten", + "choose_session_from_available": "Wähle eine Sitzung aus den verfügbaren Sitzungen", + "attachment_path_or_url_help": "Anhangspfad oder URL (z.B. für OpenAI-Bilderkennungsnachrichten)", + "run_setup_for_reconfigurable_parts": "Setup für alle rekonfigurierbaren Teile von Fabric ausführen", + "set_temperature": "Temperatur festlegen", + "set_top_p": "Top P festlegen", + "stream_help": "Streaming", + "set_presence_penalty": "Präsenzstrafe festlegen", + "use_model_defaults_raw_help": "Verwende die Standardwerte des Modells, ohne Chat-Optionen (temperature, top_p usw.) zu senden. Gilt nur für OpenAI-kompatible Anbieter. Anthropic-Modelle verwenden stets eine intelligente Parameterauswahl, um modell-spezifische Anforderungen einzuhalten.", + "set_frequency_penalty": "Häufigkeitsstrafe festlegen", + "list_all_patterns": "Alle Muster auflisten", + "list_all_available_models": "Alle verfügbaren Modelle auflisten", + "list_all_contexts": "Alle Kontexte auflisten", + "list_all_sessions": "Alle Sitzungen auflisten", + "update_patterns": "Muster aktualisieren", + "messages_to_send_to_chat": "Nachrichten zum Senden an den Chat", + "copy_to_clipboard": "In Zwischenablage kopieren", + "choose_model": "Modell wählen", + "specify_vendor_for_model": "Anbieter für das ausgewählte Modell angeben (z.B., -V \"LM Studio\" -m openai/gpt-oss-20b)", + "model_context_length_ollama": "Modell-Kontextlänge (betrifft nur ollama)", + "output_to_file": "Ausgabe in Datei", + "output_entire_session": "Gesamte Sitzung (auch eine temporäre) in die Ausgabedatei ausgeben", + "number_of_latest_patterns": "Anzahl der neuesten Muster zum Auflisten", + "change_default_model": "Standardmodell ändern", + "youtube_url_help": "YouTube-Video oder Playlist-\"URL\" zum Abrufen von Transkript und Kommentaren und Senden an Chat oder Ausgabe in Konsole und Speichern in Ausgabedatei", + "prefer_playlist_over_video": "Playlist gegenüber Video bevorzugen, wenn beide IDs in der URL vorhanden sind", + "grab_transcript_from_youtube": "Transkript von YouTube-Video abrufen und an Chat senden (wird standardmäßig verwendet).", + "grab_transcript_with_timestamps": "Transkript von YouTube-Video mit Zeitstempeln abrufen und an Chat senden", + "grab_comments_from_youtube": "Kommentare von YouTube-Video abrufen und an Chat senden", + "output_video_metadata": "Video-Metadaten ausgeben", + "additional_yt_dlp_args": "Zusätzliche Argumente für yt-dlp (z.B. '--cookies-from-browser brave')", + "specify_language_code": "Sprachencode für den Chat angeben, z.B. -g=en -g=zh -g=pt-BR -g=pt-PT", + "scrape_website_url": "Website-URL zu Markdown mit Jina AI scrapen", + "search_question_jina": "Suchanfrage mit Jina AI", + "seed_for_lmm_generation": "Seed für LMM-Generierung", + "wipe_context": "Kontext löschen", + "wipe_session": "Sitzung löschen", + "print_context": "Kontext ausgeben", + "print_session": "Sitzung ausgeben", + "convert_html_readability": "HTML-Eingabe in eine saubere, lesbare Ansicht konvertieren", + "apply_variables_to_input": "Variablen auf Benutzereingabe anwenden", + "disable_pattern_variable_replacement": "Mustervariablenersetzung deaktivieren", + "show_dry_run": "Zeige, was an das Modell gesendet würde, ohne es tatsächlich zu senden", + "serve_fabric_rest_api": "Fabric REST API bereitstellen", + "serve_fabric_api_ollama_endpoints": "Fabric REST API mit ollama-Endpunkten bereitstellen", + "address_to_bind_rest_api": "Adresse zum Binden der REST API", + "api_key_secure_server_routes": "API-Schlüssel zum Sichern der Server-Routen", + "path_to_yaml_config": "Pfad zur YAML-Konfigurationsdatei", + "print_current_version": "Aktuelle Version ausgeben", + "list_all_registered_extensions": "Alle registrierten Erweiterungen auflisten", + "register_new_extension": "Neue Erweiterung aus Konfigurationsdateipfad registrieren", + "remove_registered_extension": "Registrierte Erweiterung nach Name entfernen", + "choose_strategy_from_available": "Strategie aus den verfügbaren Strategien wählen", + "list_all_strategies": "Alle Strategien auflisten", + "list_all_vendors": "Alle Anbieter auflisten", + "output_raw_list_shell_completion": "Rohe Liste ohne Kopfzeilen/Formatierung ausgeben (für Shell-Vervollständigung)", + "enable_web_search_tool": "Web-Such-Tool für unterstützte Modelle aktivieren (Anthropic, OpenAI, Gemini)", + "set_location_web_search": "Standort für Web-Suchergebnisse festlegen (z.B., 'America/Los_Angeles')", + "save_generated_image_to_file": "Generiertes Bild in angegebenem Dateipfad speichern (z.B., 'output.png')", + "image_dimensions_help": "Bildabmessungen: 1024x1024, 1536x1024, 1024x1536, auto (Standard: auto)", + "image_quality_help": "Bildqualität: low, medium, high, auto (Standard: auto)", + "compression_level_jpeg_webp": "Komprimierungslevel 0-100 für JPEG/WebP-Formate (Standard: nicht gesetzt)", + "background_type_help": "Hintergrundtyp: opaque, transparent (Standard: opaque, nur für PNG/WebP)", + "suppress_thinking_tags": "In Denk-Tags eingeschlossenen Text unterdrücken", + "start_tag_thinking_sections": "Start-Tag für Denk-Abschnitte", + "end_tag_thinking_sections": "End-Tag für Denk-Abschnitte", + "disable_openai_responses_api": "OpenAI Responses API deaktivieren (Standard: false)", + "audio_video_file_transcribe": "Audio- oder Video-Datei zum Transkribieren", + "model_for_transcription": "Modell für Transkription (getrennt vom Chat-Modell)", + "split_media_files_ffmpeg": "Audio/Video-Dateien größer als 25MB mit ffmpeg aufteilen", + "tts_voice_name": "TTS-Stimmenname für unterstützte Modelle (z.B., Kore, Charon, Puck)", + "list_gemini_tts_voices": "Alle verfügbaren Gemini TTS-Stimmen auflisten", + "list_transcription_models": "Alle verfügbaren Transkriptionsmodelle auflisten", + "send_desktop_notification": "Desktop-Benachrichtigung senden, wenn Befehl abgeschlossen ist", + "custom_notification_command": "Benutzerdefinierter Befehl für Benachrichtigungen (überschreibt eingebaute Benachrichtigungen)", + "set_reasoning_thinking_level": "Reasoning/Thinking-Level festlegen (z.B., off, low, medium, high, oder numerische Token für Anthropic oder Google Gemini)", + "set_debug_level": "Debug-Level festlegen (0=aus, 1=grundlegend, 2=detailliert, 3=Trace)", + "usage_header": "Verwendung:", + "application_options_header": "Anwendungsoptionen:", + "help_options_header": "Hilfe-Optionen:", + "help_message": "Diese Hilfenachricht anzeigen", + "options_placeholder": "[OPTIONEN]", + "available_vendors_header": "Verfügbare Anbieter:", + "available_models_header": "Verfügbare Modelle", + "no_items_found": "Keine %s", + "no_description_available": "Keine Beschreibung verfügbar", + "i18n_download_failed": "Fehler beim Herunterladen der Übersetzung für Sprache '%s': %v", + "i18n_load_failed": "Fehler beim Laden der Übersetzungsdatei: %v", + "setup_welcome_header": "🎉 Willkommen bei Fabric! Lass uns mit der Einrichtung beginnen.", + "setup_step_downloading_patterns": "📥 Schritt 1: Patterns werden heruntergeladen (erforderlich für Fabric)...", + "setup_step_downloading_strategies": "📥 Schritt 2: Strategien werden heruntergeladen (erforderlich für Fabric)...", + "setup_step_configure_ai_provider": "🤖 Schritt 3: KI-Anbieter konfigurieren", + "setup_ai_provider_required": "Fabric benötigt mindestens einen KI-Anbieter.", + "setup_add_more_providers_later": "Sie können später weitere Anbieter mit 'fabric --setup' hinzufügen", + "setup_step_setting_defaults": "⚙️ Schritt 4: Standard-Anbieter und -Modell werden festgelegt...", + "setup_complete_header": "✅ Einrichtung abgeschlossen! Sie können Fabric jetzt verwenden.", + "setup_next_steps": "Nächste Schritte:", + "setup_list_patterns": "• Verfügbare Patterns auflisten: fabric -l", + "setup_try_pattern": "• Ein Pattern ausprobieren: echo 'Ihr Text' | fabric --pattern summarize", + "setup_configure_more": "• Weitere Einstellungen konfigurieren: fabric --setup", + "setup_failed_download_patterns": "Fehler beim Herunterladen der Patterns: %w", + "setup_failed_download_strategies": "Fehler beim Herunterladen der Strategien: %w", + "setup_failed_set_defaults": "Fehler beim Festlegen des Standard-Anbieters und -Modells: %w", + "setup_no_ai_provider_selected": "Kein KI-Anbieter ausgewählt - mindestens einer ist erforderlich", + "setup_invalid_selection": "Ungültige Auswahl: %s", + "setup_available_ai_providers": "Verfügbare KI-Anbieter:", + "setup_enter_ai_provider_number": "KI-Anbieter-Nummer", + "setup_available_plugins": "Verfügbare Plugins:", + "setup_plugin_number": "Plugin-Nummer", + "setup_plugin_prompt": "Geben Sie die Nummer des Plugins ein, das eingerichtet werden soll", + "setup_required_configuration_header": "━━━ ERFORDERLICHE KONFIGURATION ━━━\n\nKI-Anbieter [mindestens einer erforderlich]", + "setup_required_tools": "Erforderliche Werkzeuge", + "setup_optional_configuration_header": "━━━ OPTIONALE KONFIGURATION ━━━\n\nOptionale Werkzeuge", + "setup_validation_header": "Konfigurationsstatus:", + "setup_validation_ai_provider_configured": "✓ KI-Anbieter konfiguriert", + "setup_validation_ai_provider_missing": "✗ KI-Anbieter nicht konfiguriert - Erforderlich für Fabric", + "setup_validation_defaults_configured": "✓ Standard-Anbieter/-Modell festgelegt: %s/%s", + "setup_validation_defaults_missing": "✗ Standard-Anbieter/-Modell nicht festgelegt - Erforderlich für Fabric", + "setup_validation_patterns_configured": "✓ Patterns heruntergeladen", + "setup_validation_patterns_missing": "✗ Patterns nicht gefunden - Erforderlich für Fabric", + "setup_validation_strategies_configured": "✓ Strategien heruntergeladen", + "setup_validation_strategies_missing": "✗ Strategien nicht gefunden - Erforderlich für Fabric", + "setup_validation_incomplete_warning": "⚠️ Einrichtung unvollständig! Erforderliche Komponenten fehlen.", + "setup_validation_incomplete_help": "Führen Sie 'fabric --setup' erneut aus, um fehlende Elemente zu konfigurieren,\noder 'fabric -U', um Patterns und Strategien herunterzuladen.", + "setup_validation_complete": "✓ Alle erforderlichen Komponenten konfiguriert!", + "patterns_not_found_header": "⚠️ Keine Patterns gefunden!", + "patterns_required_to_work": "Patterns sind erforderlich, damit Fabric funktioniert. Um dies zu beheben:", + "patterns_option_run_setup": "Option 1 (Empfohlen): Setup ausführen, um Patterns herunterzuladen", + "patterns_option_run_setup_command": "fabric --setup", + "patterns_option_run_update": "Option 2: Patterns direkt herunterladen/aktualisieren", + "patterns_option_run_update_command": "fabric -U", + "pattern_not_found_no_patterns": "Pattern '%s' nicht gefunden.\n\nKeine Patterns installiert! Um dies zu beheben:\n • Führen Sie 'fabric --setup' aus, um Patterns zu konfigurieren und herunterzuladen\n • Oder führen Sie 'fabric -U' aus, um Patterns direkt herunterzuladen/zu aktualisieren", + "pattern_not_found_list_available": "Pattern '%s' nicht gefunden. Führen Sie 'fabric -l' aus, um verfügbare Patterns anzuzeigen", + "plugin_configured": " ✓", + "plugin_not_configured": " ⚠️ NICHT KONFIGURIERT", + "defaults_setup_description": "Standard-KI-Anbieter und -Modell", + "defaults_model_question": "Geben Sie den Index oder den Namen Ihres Standardmodells ein", + "defaults_model_context_length_question": "Geben Sie die Kontextlänge des Modells ein", + "custom_patterns_label": "Benutzerdefinierte Patterns", + "custom_patterns_setup_description": "Benutzerdefinierte Patterns - Verzeichnis für Ihre benutzerdefinierten Patterns festlegen", + "custom_patterns_directory_question": "Geben Sie den Pfad zu Ihrem benutzerdefinierten Pattern-Verzeichnis ein", + "jina_label": "Jina AI", + "jina_setup_description": "Jina AI Service - zum Erfassen einer Webseite als sauberer, LLM-freundlicher Text", + "youtube_label": "YouTube", + "youtube_setup_description": "YouTube - zum Erfassen von Video-Transkripten (via yt-dlp) und Kommentaren/Metadaten (via YouTube API)", + "language_label": "Sprache", + "language_setup_description": "Sprache - Standard-Ausgabesprache des AI-Anbieters", + "language_output_question": "Geben Sie Ihre Standard-Ausgabesprache ein (zum Beispiel: zh_CN)", + "optional_marker": "(optional)", + "required_marker": "[erforderlich]", + "patterns_loader_label": "Pattern-Loader", + "patterns_setup_description": "Patterns – lädt Patterns herunter", + "patterns_git_repo_url_label": "Git Repo URL", + "patterns_git_repo_url_question": "Geben Sie die Standard-Git-Repository-URL für die Patterns ein", + "patterns_git_repo_folder_label": "Git Repo Patterns Ordner", + "patterns_git_repo_folder_question": "Geben Sie den Standardordner im Git-Repository an, in dem die Patterns gespeichert sind", + "patterns_failed_create_temp_folder": "Fehler beim Erstellen des temporären Pattern-Ordners: %w", + "patterns_downloading": "Lade Patterns herunter und befülle %s...\\n", + "patterns_failed_download_from_git": "Fehler beim Herunterladen der Patterns aus dem Git-Repository: %w", + "patterns_saving_updated_configuration": "💾 Aktualisierte Konfiguration wird gespeichert (Pfad geändert von '%s' zu '%s')...\\n", + "patterns_failed_move_patterns": "Fehler beim Verschieben der Patterns in das Konfigurationsverzeichnis: %w", + "patterns_download_success": "✅ Patterns erfolgreich nach %s heruntergeladen und installiert\\n", + "patterns_failed_unique_file": "Fehler beim Erstellen der Datei mit eindeutigen Patterns: %w", + "patterns_failed_access_directory": "Fehler beim Zugriff auf den Pattern-Ordner '%s': %w", + "patterns_preserve_warning": "Warnung: Benutzerdefiniertes Pattern '%s' konnte nicht erhalten werden: %v\\n", + "patterns_preserved_custom_pattern": "Benutzerdefiniertes Pattern beibehalten: %s\\n", + "patterns_failed_create_temp_dir": "Fehler beim Erstellen des temporären Verzeichnisses: %w", + "patterns_cloning_repository": "Repository %s wird geklont (Pfad: %s)...\\n", + "patterns_failed_download_from_repo": "Fehler beim Herunterladen der Patterns von %s: %w", + "patterns_failed_read_temp_directory": "Fehler beim Lesen des temporären Pattern-Verzeichnisses: %w", + "patterns_no_patterns_migration_failed": "Keine Patterns im Repository unter Pfad %s gefunden und Migration fehlgeschlagen: %w", + "patterns_downloaded_temp": "%d Patterns in temporäres Verzeichnis heruntergeladen\\n", + "patterns_detected_old_path": "🔄 Alter Pattern-Pfad 'patterns' erkannt, versuche Migration zu 'data/patterns'...", + "patterns_warning_remove_test_folder": "Warnung: Der temporäre Testordner '%s' konnte nicht entfernt werden: %v\\n", + "patterns_found_new_path": "✅ %d Patterns im neuen Pfad '%s' gefunden, Konfiguration wird aktualisiert...\\n", + "patterns_failed_move_test_patterns": "Fehler beim Verschieben der Test-Patterns in den temporären Ordner: %w", + "patterns_unable_to_find_or_migrate": "Keine Patterns im aktuellen Pfad '%s' gefunden oder Migration auf neue Struktur fehlgeschlagen", + "patterns_failed_read_directory": "Fehler beim Lesen des Pattern-Verzeichnisses: %w", + "patterns_debug_included_custom_directory": "📂 Auch Patterns aus dem benutzerdefinierten Verzeichnis aufgenommen: %s\\n", + "patterns_warning_custom_directory": "Warnung: Benutzerdefiniertes Pattern-Verzeichnis %s konnte nicht gelesen werden: %v\\n", + "patterns_no_patterns_found_in_directories": "Keine Patterns in den Verzeichnissen %s und %s gefunden", + "patterns_no_patterns_found_in_directory": "Keine Patterns im Verzeichnis %s gefunden", + "patterns_failed_write_unique_file": "Fehler beim Schreiben der Datei mit eindeutigen Patterns: %w", + "patterns_unique_file_created": "📝 Datei mit eindeutigen Patterns mit %d Einträgen erstellt\\n", + "patterns_no_patterns_copied": "Keine Patterns wurden erfolgreich nach %s kopiert", + "patterns_failed_loaded_marker": "Marker-Datei '%s' konnte nicht erstellt werden: %w", + "strategies_label": "Prompt-Strategien", + "strategies_setup_description": "Strategien – lädt Prompt-Strategien herunter (z. B. Chain of Thought)", + "strategies_git_repo_url_label": "Git Repo URL", + "strategies_git_repo_url_question": "Geben Sie die Standard-Git-Repository-URL für die Strategien ein", + "strategies_git_repo_folder_label": "Git Repo Strategien Ordner", + "strategies_git_repo_folder_question": "Geben Sie den Standardordner im Git-Repository an, in dem Strategien gespeichert sind", + "strategies_downloading": "Lade Strategien herunter und befülle %s...\\n", + "strategies_download_success": "✅ Strategien erfolgreich nach %s heruntergeladen und installiert\\n", + "strategies_home_dir_error": "Startverzeichnis konnte nicht ermittelt werden: %v", + "strategies_failed_create_directory": "Strategie-Verzeichnis konnte nicht erstellt werden: %w", + "strategies_cloning_repository": "Repository %s wird geklont (Pfad: %s)...\\n", + "strategies_failed_download": "Fehler beim Herunterladen der Strategien: %w", + "strategies_downloaded_count": "%d Strategien heruntergeladen\\n", + "strategies_home_dir_fallback": "Startverzeichnis konnte nicht ermittelt werden: %v, verwende stattdessen aktuelles Verzeichnis", + "strategy_not_found": "Strategie %s nicht gefunden. Führen Sie 'fabric --liststrategies' aus, um eine Liste zu erhalten", + "strategies_none_found": "Keine Strategien gefunden. Führen Sie 'fabric --setup' aus, um Strategien herunterzuladen", + "strategies_available_header": "Verfügbare Strategien:", + "plugin_enter_value": "Geben Sie Ihren %v %v ein", + "plugin_enable_bool_question": "%v %v aktivieren (true/false)", + "plugin_setup_skipped": "[%v] übersprungen\\n", + "plugin_question_bool": "%v%v (true/false, leer lassen für '%s' oder '%v' eingeben, um den Wert zu entfernen):", + "plugin_question_with_default": "%v%v (leer lassen für '%s' oder '%v' eingeben, um den Wert zu entfernen):", + "plugin_question_optional": "%v%v (leer lassen zum Überspringen):", + "plugin_invalid_boolean_value": "Ungültiger Boolescher Wert: %v", + "plugin_setting_not_valid": "%v=%v ist nicht gültig", + "plugin_invalid_bool": "Ungültiger boolescher Wert: %q", + "ollama_num_ctx_must_be_finite": "num_ctx muss eine endliche Zahl sein", + "ollama_num_ctx_must_be_integer": "num_ctx muss eine Ganzzahl sein, erhielt Float mit Nachkommastellen", + "ollama_num_ctx_value_out_of_range": "num_ctx Wert außerhalb des Bereichs", + "ollama_num_ctx_must_be_positive": "num_ctx muss positiv sein, erhalten: %d", + "ollama_num_ctx_value_too_large": "num_ctx Wert zu groß: %d", + "ollama_num_ctx_must_be_valid_number": "num_ctx muss eine gültige Zahl sein", + "ollama_num_ctx_must_be_valid_number_got": "num_ctx muss eine gültige Zahl sein, erhalten: %s", + "ollama_num_ctx_invalid_type": "num_ctx muss eine Zahl sein, ungültiger Typ erhalten", + "ollama_num_ctx_exceeds_maximum": "num_ctx überschreitet den maximal zulässigen Wert von %d", + "ollama_error_reading_body": "Fehler beim Lesen des Bodys: %v", + "ollama_error_endpoint": "Endpunkt wird getestet", + "ollama_error_unmarshalling_body": "Fehler beim Unmarshalling des Bodys: %v", + "ollama_invalid_num_ctx_in_request": "Ungültiger num_ctx in Anfrage: %v", + "ollama_warning_parse_variables": "Warnung: Fehler beim Parsen von options.variables als JSON: %v", + "ollama_error_marshalling_body": "Fehler beim Marshalling des Bodys: %v", + "ollama_error_building_chat_url": "Fehler beim Erstellen der /chat URL: %v", + "ollama_error_creating_chat_request": "Fehler beim Erstellen der /chat Anfrage: %v", + "ollama_failed_create_request": "Fehler beim Erstellen der Anfrage", + "ollama_error_getting_chat_body": "Fehler beim Abrufen des /chat Bodys: %v", + "ollama_upstream_non_2xx_body_unreadable": "Upstream Fabric Server hat nicht-2xx Status %d zurückgegeben und Body konnte nicht gelesen werden: %v", + "ollama_upstream_non_2xx": "Upstream Fabric Server hat nicht-2xx Status %d zurückgegeben: %s", + "ollama_upstream_returned_status": "Upstream Fabric Server hat Status %d zurückgegeben", + "ollama_error_prefix": "Fehler: %s", + "ollama_error_parse_upstream_response": "Fehler: Upstream-Antwort konnte nicht geparst werden", + "ollama_failed_unmarshal_fabric_response": "Fehler beim Unmarshalling der Fabric Antwort", + "ollama_error_writing_response": "Fehler beim Schreiben der Antwort: %v", + "ollama_error_scanning_body": "Fehler beim Scannen des Bodys: %v", + "ollama_failed_scan_sse_stream": "Fehler beim Scannen des SSE Response Streams: %v", + "ollama_sse_buffer_limit": "SSE Zeile überschreitet 1MB Puffer-Limit - Datenzeile zu groß", + "ollama_warning_no_content": "Warnung: Kein Inhalt vom Upstream Fabric Server erhalten", + "ollama_no_content_from_upstream": "Kein Inhalt vom Upstream Fabric Server erhalten", + "ollama_empty_address": "Leere Adresse", + "ollama_invalid_address": "Ungültige Adresse: %w", + "ollama_invalid_address_missing_host": "Ungültige Adresse: Host fehlt", + "ollama_invalid_address_missing_hostname": "Ungültige Adresse: Hostname fehlt", + "ollama_invalid_address_path_not_allowed": "Ungültige Adresse: Pfadkomponente in bloßer Adresse nicht zulässig", + "extension_registry_not_initialized": "Erweiterungsregistrierung nicht initialisiert", + "extension_name_label": "Erweiterung: %s\n", + "extension_status_disabled": " Status: DEAKTIVIERT - Hash-Überprüfung fehlgeschlagen: %v\n", + "extension_config_path_label": " Konfigurationspfad: %s\n\n", + "extension_status_enabled": " Status: AKTIVIERT\n", + "extension_executable_label": " Programmdatei: %s\n", + "extension_type_label": " Typ: %s\n", + "extension_timeout_label": " Zeitlimit: %s\n", + "extension_description_label": " Beschreibung: %s\n", + "extension_version_label": " Version: %s\n", + "extension_operations_label": " Operationen:\n", + "extension_command_template_label": " Befehlsvorlage: %s\n", + "extension_file_config_label": " Dateikonfiguration:\n", + "extension_invalid_config_path": "ungültiger Konfigurationspfad: %w", + "extension_failed_read_config": "Konfigurationsdatei konnte nicht gelesen werden: %w", + "extension_failed_parse_config": "Konfigurationsdatei konnte nicht geparst werden: %w", + "extension_failed_register": "Erweiterung konnte nicht registriert werden: %w", + "extension_invalid_timeout": "ungültiger Zeitlimit-Wert '%s': muss eine Dauer wie '30s' oder '1m' sein: %w", + "extension_registered_success": "Erweiterung erfolgreich registriert:\n", + "extension_name_detail_label": "Name: %s\n", + "extension_failed_remove": "Erweiterung konnte nicht entfernt werden: %w", + "lmstudio_api_url_question": "Geben Sie Ihre %v URL ein (zur Erinnerung, sie ist normalerweise %v)", + "lmstudio_failed_create_request": "Anfrage konnte nicht erstellt werden: %w", + "lmstudio_failed_send_request": "Anfrage konnte nicht gesendet werden: %w", + "lmstudio_unexpected_status_code": "Unerwarteter Statuscode: %d", + "lmstudio_failed_decode_response": "Antwort konnte nicht dekodiert werden: %w", + "lmstudio_failed_marshal_payload": "Nutzlast konnte nicht serialisiert werden: %w", + "lmstudio_error_reading_response": "Fehler beim Lesen der Antwort: %w", + "lmstudio_invalid_response_missing_choices": "Ungültiges Antwortformat: Auswahlmöglichkeiten fehlen oder sind leer", + "lmstudio_invalid_response_missing_message": "Ungültiges Antwortformat: Nachricht in der ersten Auswahl fehlt", + "lmstudio_invalid_response_missing_content": "Ungültiges Antwortformat: Inhalt in der Nachricht fehlt oder ist kein String", + "lmstudio_invalid_response_missing_text": "Ungültiges Antwortformat: Text in der ersten Auswahl fehlt oder ist kein String", + "lmstudio_no_embeddings_returned": "Keine Einbettungen zurückgegeben", + "extension_warning_load_registry": "Warnung: Erweiterungsregistrierung konnte nicht geladen werden: %v\n", + "extension_name_empty": "Erweiterungsname darf nicht leer sein", + "extension_name_contains_spaces": "Erweiterungsname '%s' enthält Leerzeichen - Namen dürfen keine Leerzeichen enthalten", + "extension_executable_not_found": "Programmdatei nicht gefunden: %w", + "extension_failed_get_absolute_path": "absoluter Pfad konnte nicht ermittelt werden: %w", + "extension_failed_hash_executable": "Programmdatei-Hash konnte nicht berechnet werden: %w", + "extension_invalid_definition": "ungültige Erweiterungsdefinition: %w", + "extension_name_required": "Erweiterungsname ist erforderlich", + "extension_executable_required": "Pfad zur Programmdatei ist erforderlich", + "extension_type_required": "Erweiterungstyp ist erforderlich", + "extension_invalid_timeout_format": "ungültiges Zeitlimit-Format: %w", + "extension_operation_required": "mindestens eine Operation muss definiert sein", + "extension_cmd_template_required": "Befehlsvorlage ist für Operation %s erforderlich", + "extension_not_found": "Erweiterung %s nicht gefunden", + "extension_config_hash_mismatch": "Hash-Abweichung der Konfigurationsdatei für %s", + "extension_failed_verify_executable": "Programmdatei konnte nicht verifiziert werden: %w", + "extension_executable_hash_mismatch": "Hash-Abweichung der Programmdatei für %s", + "extension_failed_marshal_registry": "Erweiterungsregistrierung konnte nicht serialisiert werden: %w", + "extension_failed_read_registry": "Erweiterungsregistrierung konnte nicht gelesen werden: %w", + "extension_failed_parse_registry": "Erweiterungsregistrierung konnte nicht geparst werden: %w", + "extension_failed_get_extension": "Erweiterung konnte nicht abgerufen werden: %w", + "extension_failed_format_command": "Befehl konnte nicht formatiert werden: %w", + "extension_empty_command": "Leerer Befehl nach Formatierung", + "extension_operation_not_found": "Operation %s für Erweiterung %s nicht gefunden", + "extension_executing_command": "Befehl wird ausgeführt: %s\n", + "extension_execution_failed_stderr": "Ausführung fehlgeschlagen: %w\nstderr: %s", + "extension_no_file_config": "Keine Dateikonfiguration gefunden", + "extension_no_output_file": "Keine Ausgabedatei in der Konfiguration angegeben", + "extension_execution_timed_out": "Ausführung nach %v abgelaufen", + "extension_execution_failed_err": "Ausführung fehlgeschlagen: %w\nerr: %s", + "extension_failed_read_output_file": "Ausgabedatei konnte nicht gelesen werden: %w", + "extension_failed_get_output_path": "Ausgabepfad konnte nicht ermittelt werden: %w\nerr: %s", + "spotify_failed_create_token_request": "Token-Anfrage konnte nicht erstellt werden: %w", + "spotify_failed_request_access_token": "Zugriffstoken konnte nicht angefordert werden: %w", + "spotify_failed_get_access_token": "Zugriffstoken konnte nicht abgerufen werden: Status %d, Antwort: %s", + "spotify_failed_decode_token_response": "Token-Antwort konnte nicht dekodiert werden: %w", + "spotify_failed_create_request": "Anfrage konnte nicht erstellt werden: %w", + "spotify_failed_execute_request": "Anfrage konnte nicht ausgeführt werden: %w", + "spotify_failed_read_response_body": "Antwortinhalt konnte nicht gelesen werden: %w", + "spotify_api_request_failed": "API-Anfrage fehlgeschlagen: Status %d, Antwort: %s", + "spotify_failed_parse_show_metadata": "Show-Metadaten konnten nicht analysiert werden: %w", + "spotify_failed_parse_episode_metadata": "Episoden-Metadaten konnten nicht analysiert werden: %w", + "spotify_search_failed": "Suche fehlgeschlagen: %w", + "spotify_failed_parse_search_results": "Suchergebnisse konnten nicht analysiert werden: %w", + "spotify_failed_get_show_episodes": "Show-Episoden konnten nicht abgerufen werden: %w", + "spotify_failed_parse_episodes": "Episoden konnten nicht analysiert werden: %w", "template_file_log_validating_path": "Datei: Pfad %q wird validiert", "template_file_error_path_contains_parent_ref": "datei: pfad darf '..' nicht enthalten", "template_file_error_expand_home_dir": "datei: home-verzeichnis konnte nicht erweitert werden: %v", @@ -491,5 +490,31 @@ "fetch_content_too_large": "fetch: Inhalt zu groß: %d Bytes (max %d Bytes)", "fetch_unsupported_content_type": "fetch: nicht unterstützter Inhaltstyp %q - nur Textinhalt erlaubt", "fetch_error_reading_response": "fetch: Fehler beim Lesen der Antwort: %v", - "fetch_content_exceeds_limit": "fetch: Inhalt zu groß: überschreitet %d Bytes" + "fetch_content_exceeds_limit": "fetch: Inhalt zu groß: überschreitet %d Bytes", + "file_manager_invalid_format_no_json_array": "ungültiges %s-Format: kein JSON-Array gefunden", + "file_manager_invalid_format_unbalanced_brackets": "ungültiges %s-Format: unausgewogene Klammern", + "file_manager_failed_parse_json": "%s JSON konnte nicht geparst werden: %w", + "file_manager_invalid_operation": "ungültige Operation für Dateiänderung %d: %s", + "file_manager_empty_path": "leerer Pfad für Dateiänderung %d", + "file_manager_suspicious_path": "verdächtiger Pfad für Dateiänderung %d: %s", + "file_manager_file_content_too_large": "Dateiinhalt zu groß für Dateiänderung %d: %d Bytes", + "file_manager_failed_create_directory": "Verzeichnis %s konnte nicht für Dateiänderung %d erstellt werden: %w", + "file_manager_failed_write_file": "Datei %s konnte nicht für Dateiänderung %d geschrieben werden: %w", + "file_manager_applied_operation": "Operation %s auf %s angewendet", + "vertexai_error_create_request": "Anfrage konnte nicht erstellt werden: %w", + "vertexai_error_request_failed": "Anfrage fehlgeschlagen: %w", + "vertexai_error_api_status": "API hat Status %d zurückgegeben: %s", + "vertexai_error_read_response": "Antwort konnte nicht gelesen werden: %w", + "vertexai_error_response_too_large": "Antwort zu groß (>%d Bytes)", + "vertexai_error_parse_response": "Antwort konnte nicht analysiert werden: %w", + "copilot_tenant_client_id_required": "Mandanten-ID und Client-ID sind erforderlich", + "copilot_failed_create_conversation": "Konversation konnte nicht erstellt werden: %w", + "copilot_failed_send_message": "Nachricht konnte nicht gesendet werden: %w", + "copilot_failed_stream_message": "Nachricht konnte nicht gestreamt werden: %w", + "copilot_error_create_conversation": "Konversation konnte nicht erstellt werden: %s - %s", + "copilot_error_chat_request": "Chat-Anfrage fehlgeschlagen: %s - %s", + "copilot_error_stream_request": "Stream-Anforderung fehlgeschlagen: %s - %s", + "copilot_debug_created_conversation": "Copilot-Konversation erstellt: %s", + "copilot_debug_failed_parse_sse_event": "SSE-Ereignis konnte nicht geparst werden: %v", + "copilot_error_reading_stream": "Fehler beim Lesen des Streams: %w" } diff --git a/internal/i18n/locales/en.json b/internal/i18n/locales/en.json index 054b8ab8..8310a55c 100644 --- a/internal/i18n/locales/en.json +++ b/internal/i18n/locales/en.json @@ -410,8 +410,7 @@ "spotify_search_failed": "search failed: %w", "spotify_failed_parse_search_results": "failed to parse search results: %w", "spotify_failed_get_show_episodes": "failed to get show episodes: %w", - "spotify_failed_parse_episodes": "failed to parse episodes: %w" -, + "spotify_failed_parse_episodes": "failed to parse episodes: %w", "template_file_log_validating_path": "File: validating path %q", "template_file_error_path_contains_parent_ref": "file: path cannot contain '..'", "template_file_error_expand_home_dir": "file: could not expand home directory: %v", @@ -491,5 +490,31 @@ "fetch_content_too_large": "fetch: content too large: %d bytes (max %d bytes)", "fetch_unsupported_content_type": "fetch: unsupported content type %q - only text content allowed", "fetch_error_reading_response": "fetch: error reading response: %v", - "fetch_content_exceeds_limit": "fetch: content too large: exceeds %d bytes" + "fetch_content_exceeds_limit": "fetch: content too large: exceeds %d bytes", + "file_manager_invalid_format_no_json_array": "invalid %s format: no JSON array found", + "file_manager_invalid_format_unbalanced_brackets": "invalid %s format: unbalanced brackets", + "file_manager_failed_parse_json": "failed to parse %s JSON: %w", + "file_manager_invalid_operation": "invalid operation for file change %d: %s", + "file_manager_empty_path": "empty path for file change %d", + "file_manager_suspicious_path": "suspicious path for file change %d: %s", + "file_manager_file_content_too_large": "file content too large for file change %d: %d bytes", + "file_manager_failed_create_directory": "failed to create directory %s for file change %d: %w", + "file_manager_failed_write_file": "failed to write file %s for file change %d: %w", + "file_manager_applied_operation": "Applied %s operation to %s", + "vertexai_error_create_request": "failed to create request: %w", + "vertexai_error_request_failed": "request failed: %w", + "vertexai_error_api_status": "API returned status %d: %s", + "vertexai_error_read_response": "failed to read response: %w", + "vertexai_error_response_too_large": "response too large (>%d bytes)", + "vertexai_error_parse_response": "failed to parse response: %w", + "copilot_tenant_client_id_required": "tenant ID and client ID are required", + "copilot_failed_create_conversation": "failed to create conversation: %w", + "copilot_failed_send_message": "failed to send message: %w", + "copilot_failed_stream_message": "failed to stream message: %w", + "copilot_error_create_conversation": "failed to create conversation: %s - %s", + "copilot_error_chat_request": "chat request failed: %s - %s", + "copilot_error_stream_request": "stream request failed: %s - %s", + "copilot_debug_created_conversation": "Created Copilot conversation: %s", + "copilot_debug_failed_parse_sse_event": "Failed to parse SSE event: %v", + "copilot_error_reading_stream": "error reading stream: %w" } diff --git a/internal/i18n/locales/es.json b/internal/i18n/locales/es.json index 23df17e9..8450c534 100644 --- a/internal/i18n/locales/es.json +++ b/internal/i18n/locales/es.json @@ -410,8 +410,7 @@ "spotify_search_failed": "la búsqueda falló: %w", "spotify_failed_parse_search_results": "no se pudieron analizar los resultados de búsqueda: %w", "spotify_failed_get_show_episodes": "no se pudieron obtener los episodios del programa: %w", - "spotify_failed_parse_episodes": "no se pudieron analizar los episodios: %w" -, + "spotify_failed_parse_episodes": "no se pudieron analizar los episodios: %w", "template_file_log_validating_path": "Archivo: validando ruta %q", "template_file_error_path_contains_parent_ref": "archivo: la ruta no puede contener '..'", "template_file_error_expand_home_dir": "archivo: no se pudo expandir el directorio home: %v", @@ -491,5 +490,31 @@ "fetch_content_too_large": "fetch: contenido demasiado grande: %d bytes (máx %d bytes)", "fetch_unsupported_content_type": "fetch: tipo de contenido no admitido %q - solo se permite contenido de texto", "fetch_error_reading_response": "fetch: error al leer la respuesta: %v", - "fetch_content_exceeds_limit": "fetch: contenido demasiado grande: supera %d bytes" + "fetch_content_exceeds_limit": "fetch: contenido demasiado grande: supera %d bytes", + "file_manager_invalid_format_no_json_array": "formato %s no válido: no se encontró ningún array JSON", + "file_manager_invalid_format_unbalanced_brackets": "formato %s no válido: corchetes desequilibrados", + "file_manager_failed_parse_json": "error al analizar %s JSON: %w", + "file_manager_invalid_operation": "operación no válida para el cambio de archivo %d: %s", + "file_manager_empty_path": "ruta vacía para el cambio de archivo %d", + "file_manager_suspicious_path": "ruta sospechosa para el cambio de archivo %d: %s", + "file_manager_file_content_too_large": "contenido del archivo demasiado grande para el cambio de archivo %d: %d bytes", + "file_manager_failed_create_directory": "error al crear el directorio %s para el cambio de archivo %d: %w", + "file_manager_failed_write_file": "error al escribir el archivo %s para el cambio de archivo %d: %w", + "file_manager_applied_operation": "Operación %s aplicada a %s", + "vertexai_error_create_request": "error al crear la solicitud: %w", + "vertexai_error_request_failed": "solicitud fallida: %w", + "vertexai_error_api_status": "API devolvió estado %d: %s", + "vertexai_error_read_response": "error al leer la respuesta: %w", + "vertexai_error_response_too_large": "respuesta demasiado grande (>%d bytes)", + "vertexai_error_parse_response": "error al analizar la respuesta: %w", + "copilot_tenant_client_id_required": "se requieren el ID de inquilino y el ID de cliente", + "copilot_failed_create_conversation": "error al crear la conversación: %w", + "copilot_failed_send_message": "error al enviar el mensaje: %w", + "copilot_failed_stream_message": "error al transmitir el mensaje: %w", + "copilot_error_create_conversation": "error al crear la conversación: %s - %s", + "copilot_error_chat_request": "solicitud de chat fallida: %s - %s", + "copilot_error_stream_request": "falló la solicitud de transmisión: %s - %s", + "copilot_debug_created_conversation": "Conversación de Copilot creada: %s", + "copilot_debug_failed_parse_sse_event": "Error al analizar el evento SSE: %v", + "copilot_error_reading_stream": "error al leer la transmisión: %w" } diff --git a/internal/i18n/locales/fa.json b/internal/i18n/locales/fa.json index a9985c48..e38df468 100644 --- a/internal/i18n/locales/fa.json +++ b/internal/i18n/locales/fa.json @@ -402,8 +402,7 @@ "spotify_search_failed": "جستجو ناموفق بود: %w", "spotify_failed_parse_search_results": "تجزیه نتایج جستجو ناموفق بود: %w", "spotify_failed_get_show_episodes": "دریافت قسمت‌های برنامه ناموفق بود: %w", - "spotify_failed_parse_episodes": "تجزیه قسمت‌ها ناموفق بود: %w" -, + "spotify_failed_parse_episodes": "تجزیه قسمت‌ها ناموفق بود: %w", "template_file_log_validating_path": "فایل: در حال اعتبارسنجی مسیر %q", "template_file_error_path_contains_parent_ref": "فایل: مسیر نمی‌تواند '..' داشته باشد", "template_file_error_expand_home_dir": "فایل: گسترش پوشه خانگی ممکن نشد: %v", @@ -483,5 +482,31 @@ "fetch_content_too_large": "fetch: محتوا بسیار بزرگ است: %d بایت (حداکثر %d بایت)", "fetch_unsupported_content_type": "fetch: نوع محتوای پشتیبانی‌نشده %q - فقط محتوای متنی مجاز است", "fetch_error_reading_response": "fetch: خطا در خواندن پاسخ: %v", - "fetch_content_exceeds_limit": "fetch: محتوا بسیار بزرگ است: از %d بایت بیشتر است" + "fetch_content_exceeds_limit": "fetch: محتوا بسیار بزرگ است: از %d بایت بیشتر است", + "file_manager_invalid_format_no_json_array": "فرمت %s نامعتبر: هیچ آرایه JSON یافت نشد", + "file_manager_invalid_format_unbalanced_brackets": "فرمت %s نامعتبر: پرانتزهای نامتعادل", + "file_manager_failed_parse_json": "پارس %s JSON ناموفق بود: %w", + "file_manager_invalid_operation": "عملیات نامعتبر برای تغییر فایل %d: %s", + "file_manager_empty_path": "مسیر خالی برای تغییر فایل %d", + "file_manager_suspicious_path": "مسیر مشکوک برای تغییر فایل %d: %s", + "file_manager_file_content_too_large": "محتوای فایل بیش از حد بزرگ برای تغییر فایل %d: %d بایت", + "file_manager_failed_create_directory": "ایجاد دایرکتوری %s برای تغییر فایل %d ناموفق بود: %w", + "file_manager_failed_write_file": "نوشتن فایل %s برای تغییر فایل %d ناموفق بود: %w", + "file_manager_applied_operation": "عملیات %s روی %s اعمال شد", + "vertexai_error_create_request": "ایجاد درخواست ناموفق بود: %w", + "vertexai_error_request_failed": "درخواست ناموفق بود: %w", + "vertexai_error_api_status": "API وضعیت %d را برگرداند: %s", + "vertexai_error_read_response": "خواندن پاسخ ناموفق بود: %w", + "vertexai_error_response_too_large": "پاسخ خیلی بزرگ است (>%d بایت)", + "vertexai_error_parse_response": "تجزیه پاسخ ناموفق بود: %w", + "copilot_tenant_client_id_required": "شناسه مشتری و شناسه مستاجر الزامی است", + "copilot_failed_create_conversation": "ایجاد مکالمه ناموفق بود: %w", + "copilot_failed_send_message": "ارسال پیام ناموفق بود: %w", + "copilot_failed_stream_message": "پخش جریانی پیام ناموفق بود: %w", + "copilot_error_create_conversation": "ایجاد مکالمه ناموفق بود: %s - %s", + "copilot_error_chat_request": "درخواست چت ناموفق بود: %s - %s", + "copilot_error_stream_request": "درخواست جریان ناموفق بود: %s - %s", + "copilot_debug_created_conversation": "مکالمه Copilot ایجاد شد: %s", + "copilot_debug_failed_parse_sse_event": "تجزیه رویداد SSE ناموفق بود: %v", + "copilot_error_reading_stream": "خطا در خواندن جریان: %w" } diff --git a/internal/i18n/locales/fr.json b/internal/i18n/locales/fr.json index 0666c208..14e03f15 100644 --- a/internal/i18n/locales/fr.json +++ b/internal/i18n/locales/fr.json @@ -410,8 +410,7 @@ "spotify_search_failed": "la recherche a échoué : %w", "spotify_failed_parse_search_results": "impossible d'analyser les résultats de recherche : %w", "spotify_failed_get_show_episodes": "impossible de récupérer les épisodes de l'émission : %w", - "spotify_failed_parse_episodes": "impossible d'analyser les épisodes : %w" -, + "spotify_failed_parse_episodes": "impossible d'analyser les épisodes : %w", "template_file_log_validating_path": "Fichier : validation du chemin %q", "template_file_error_path_contains_parent_ref": "fichier : le chemin ne peut pas contenir '..'", "template_file_error_expand_home_dir": "fichier : impossible d'étendre le répertoire personnel : %v", @@ -491,5 +490,31 @@ "fetch_content_too_large": "fetch: contenu trop volumineux: %d octets (max %d octets)", "fetch_unsupported_content_type": "fetch: type de contenu non pris en charge %q - seul le contenu texte est autorisé", "fetch_error_reading_response": "fetch: erreur lors de la lecture de la réponse: %v", - "fetch_content_exceeds_limit": "fetch: contenu trop volumineux: dépasse %d octets" + "fetch_content_exceeds_limit": "fetch: contenu trop volumineux: dépasse %d octets", + "file_manager_invalid_format_no_json_array": "format %s non valide: aucun tableau JSON trouvé", + "file_manager_invalid_format_unbalanced_brackets": "format %s non valide: crochets déséquilibrés", + "file_manager_failed_parse_json": "échec de l'analyse %s JSON: %w", + "file_manager_invalid_operation": "opération non valide pour la modification de fichier %d: %s", + "file_manager_empty_path": "chemin vide pour la modification de fichier %d", + "file_manager_suspicious_path": "chemin suspect pour la modification de fichier %d: %s", + "file_manager_file_content_too_large": "contenu du fichier trop volumineux pour la modification de fichier %d: %d octets", + "file_manager_failed_create_directory": "échec de la création du répertoire %s pour la modification de fichier %d: %w", + "file_manager_failed_write_file": "échec de l'écriture du fichier %s pour la modification de fichier %d: %w", + "file_manager_applied_operation": "Opération %s appliquée à %s", + "vertexai_error_create_request": "échec de la création de la requête: %w", + "vertexai_error_request_failed": "échec de la requête: %w", + "vertexai_error_api_status": "l'API a retourné le statut %d: %s", + "vertexai_error_read_response": "échec de la lecture de la réponse: %w", + "vertexai_error_response_too_large": "réponse trop volumineuse (>%d octets)", + "vertexai_error_parse_response": "échec de l'analyse de la réponse: %w", + "copilot_tenant_client_id_required": "l'ID de locataire et l'ID client sont requis", + "copilot_failed_create_conversation": "échec de la création de la conversation: %w", + "copilot_failed_send_message": "échec de l'envoi du message: %w", + "copilot_failed_stream_message": "échec du streaming du message: %w", + "copilot_error_create_conversation": "échec de la création de la conversation: %s - %s", + "copilot_error_chat_request": "échec de la requête de chat: %s - %s", + "copilot_error_stream_request": "échec de la demande de flux: %s - %s", + "copilot_debug_created_conversation": "Conversation Copilot créée: %s", + "copilot_debug_failed_parse_sse_event": "Échec de l'analyse de l'événement SSE: %v", + "copilot_error_reading_stream": "erreur lors de la lecture du flux: %w" } diff --git a/internal/i18n/locales/it.json b/internal/i18n/locales/it.json index a93a3616..aa5511ae 100644 --- a/internal/i18n/locales/it.json +++ b/internal/i18n/locales/it.json @@ -410,8 +410,7 @@ "spotify_search_failed": "ricerca fallita: %w", "spotify_failed_parse_search_results": "impossibile analizzare i risultati della ricerca: %w", "spotify_failed_get_show_episodes": "impossibile ottenere gli episodi dello show: %w", - "spotify_failed_parse_episodes": "impossibile analizzare gli episodi: %w" -, + "spotify_failed_parse_episodes": "impossibile analizzare gli episodi: %w", "template_file_log_validating_path": "File: convalida del percorso %q", "template_file_error_path_contains_parent_ref": "file: il percorso non può contenere '..'", "template_file_error_expand_home_dir": "file: impossibile espandere la directory home: %v", @@ -491,5 +490,31 @@ "fetch_content_too_large": "fetch: contenuto troppo grande: %d byte (max %d byte)", "fetch_unsupported_content_type": "fetch: tipo di contenuto non supportato %q - solo contenuto testuale consentito", "fetch_error_reading_response": "fetch: errore durante la lettura della risposta: %v", - "fetch_content_exceeds_limit": "fetch: contenuto troppo grande: supera %d byte" + "fetch_content_exceeds_limit": "fetch: contenuto troppo grande: supera %d byte", + "file_manager_invalid_format_no_json_array": "formato %s non valido: nessun array JSON trovato", + "file_manager_invalid_format_unbalanced_brackets": "formato %s non valido: parentesi non bilanciate", + "file_manager_failed_parse_json": "analisi %s JSON non riuscita: %w", + "file_manager_invalid_operation": "operazione non valida per la modifica del file %d: %s", + "file_manager_empty_path": "percorso vuoto per la modifica del file %d", + "file_manager_suspicious_path": "percorso sospetto per la modifica del file %d: %s", + "file_manager_file_content_too_large": "contenuto del file troppo grande per la modifica del file %d: %d byte", + "file_manager_failed_create_directory": "creazione della directory %s non riuscita per la modifica del file %d: %w", + "file_manager_failed_write_file": "scrittura del file %s non riuscita per la modifica del file %d: %w", + "file_manager_applied_operation": "Operazione %s applicata a %s", + "vertexai_error_create_request": "creazione della richiesta fallita: %w", + "vertexai_error_request_failed": "richiesta fallita: %w", + "vertexai_error_api_status": "l'API ha restituito lo stato %d: %s", + "vertexai_error_read_response": "lettura della risposta fallita: %w", + "vertexai_error_response_too_large": "risposta troppo grande (>%d byte)", + "vertexai_error_parse_response": "analisi della risposta fallita: %w", + "copilot_tenant_client_id_required": "sono richiesti l'ID tenant e l'ID client", + "copilot_failed_create_conversation": "creazione della conversazione fallita: %w", + "copilot_failed_send_message": "invio del messaggio fallito: %w", + "copilot_failed_stream_message": "streaming del messaggio fallito: %w", + "copilot_error_create_conversation": "creazione della conversazione fallita: %s - %s", + "copilot_error_chat_request": "richiesta di chat fallita: %s - %s", + "copilot_error_stream_request": "richiesta di stream fallita: %s - %s", + "copilot_debug_created_conversation": "Conversazione Copilot creata: %s", + "copilot_debug_failed_parse_sse_event": "Impossibile analizzare l'evento SSE: %v", + "copilot_error_reading_stream": "errore nella lettura dello stream: %w" } diff --git a/internal/i18n/locales/ja.json b/internal/i18n/locales/ja.json index b86c189b..bc0944d7 100644 --- a/internal/i18n/locales/ja.json +++ b/internal/i18n/locales/ja.json @@ -410,8 +410,7 @@ "spotify_search_failed": "検索に失敗しました: %w", "spotify_failed_parse_search_results": "検索結果の解析に失敗しました: %w", "spotify_failed_get_show_episodes": "番組エピソードの取得に失敗しました: %w", - "spotify_failed_parse_episodes": "エピソードの解析に失敗しました: %w" -, + "spotify_failed_parse_episodes": "エピソードの解析に失敗しました: %w", "template_file_log_validating_path": "File: パス %q を検証中", "template_file_error_path_contains_parent_ref": "file: パスに '..' を含めることはできません", "template_file_error_expand_home_dir": "file: ホームディレクトリを展開できませんでした: %v", @@ -491,5 +490,31 @@ "fetch_content_too_large": "fetch: コンテンツが大きすぎます: %dバイト(最大%dバイト)", "fetch_unsupported_content_type": "fetch: サポートされていないコンテンツタイプ %q - テキストコンテンツのみ許可されています", "fetch_error_reading_response": "fetch: レスポンス読み取りエラー: %v", - "fetch_content_exceeds_limit": "fetch: コンテンツが大きすぎます: %dバイトを超えています" + "fetch_content_exceeds_limit": "fetch: コンテンツが大きすぎます: %dバイトを超えています", + "file_manager_invalid_format_no_json_array": "無効な%s形式: JSON配列が見つかりません", + "file_manager_invalid_format_unbalanced_brackets": "無効な%s形式: 括弧の対応が取れていません", + "file_manager_failed_parse_json": "%s JSONの解析に失敗しました: %w", + "file_manager_invalid_operation": "ファイル変更%dの無効な操作: %s", + "file_manager_empty_path": "ファイル変更%dの空のパス", + "file_manager_suspicious_path": "ファイル変更%dの不審なパス: %s", + "file_manager_file_content_too_large": "ファイル変更%dのファイルコンテンツが大きすぎます: %dバイト", + "file_manager_failed_create_directory": "ファイル変更%dのディレクトリ%sの作成に失敗しました: %w", + "file_manager_failed_write_file": "ファイル変更%dのファイル%sの書き込みに失敗しました: %w", + "file_manager_applied_operation": "%s操作を%sに適用しました", + "vertexai_error_create_request": "リクエストの作成に失敗しました: %w", + "vertexai_error_request_failed": "リクエストが失敗しました: %w", + "vertexai_error_api_status": "APIはステータス%dを返しました: %s", + "vertexai_error_read_response": "レスポンスの読み取りに失敗しました: %w", + "vertexai_error_response_too_large": "レスポンスが大きすぎます (>%dバイト)", + "vertexai_error_parse_response": "レスポンスの解析に失敗しました: %w", + "copilot_tenant_client_id_required": "テナントIDとクライアントIDが必要です", + "copilot_failed_create_conversation": "会話の作成に失敗しました: %w", + "copilot_failed_send_message": "メッセージの送信に失敗しました: %w", + "copilot_failed_stream_message": "メッセージのストリーミングに失敗しました: %w", + "copilot_error_create_conversation": "会話の作成に失敗しました: %s - %s", + "copilot_error_chat_request": "チャットリクエストが失敗しました: %s - %s", + "copilot_error_stream_request": "ストリームリクエストが失敗しました: %s - %s", + "copilot_debug_created_conversation": "Copilot会話を作成しました: %s", + "copilot_debug_failed_parse_sse_event": "SSEイベントの解析に失敗しました: %v", + "copilot_error_reading_stream": "ストリームの読み取りエラー: %w" } diff --git a/internal/i18n/locales/pt-BR.json b/internal/i18n/locales/pt-BR.json index 510bc543..5b56d09e 100644 --- a/internal/i18n/locales/pt-BR.json +++ b/internal/i18n/locales/pt-BR.json @@ -410,8 +410,7 @@ "spotify_search_failed": "a pesquisa falhou: %w", "spotify_failed_parse_search_results": "falha ao analisar os resultados da pesquisa: %w", "spotify_failed_get_show_episodes": "falha ao obter os episódios do programa: %w", - "spotify_failed_parse_episodes": "falha ao analisar os episódios: %w" -, + "spotify_failed_parse_episodes": "falha ao analisar os episódios: %w", "template_file_log_validating_path": "Arquivo: validando caminho %q", "template_file_error_path_contains_parent_ref": "arquivo: o caminho não pode conter '..'", "template_file_error_expand_home_dir": "arquivo: não foi possível expandir o diretório home: %v", @@ -491,5 +490,31 @@ "fetch_content_too_large": "fetch: conteúdo muito grande: %d bytes (máx %d bytes)", "fetch_unsupported_content_type": "fetch: tipo de conteúdo não suportado %q - apenas conteúdo de texto permitido", "fetch_error_reading_response": "fetch: erro ao ler a resposta: %v", - "fetch_content_exceeds_limit": "fetch: conteúdo muito grande: excede %d bytes" + "fetch_content_exceeds_limit": "fetch: conteúdo muito grande: excede %d bytes", + "file_manager_invalid_format_no_json_array": "formato %s inválido: nenhum array JSON encontrado", + "file_manager_invalid_format_unbalanced_brackets": "formato %s inválido: colchetes desbalanceados", + "file_manager_failed_parse_json": "falha ao analisar %s JSON: %w", + "file_manager_invalid_operation": "operação inválida para alteração de arquivo %d: %s", + "file_manager_empty_path": "caminho vazio para alteração de arquivo %d", + "file_manager_suspicious_path": "caminho suspeito para alteração de arquivo %d: %s", + "file_manager_file_content_too_large": "conteúdo do arquivo muito grande para alteração de arquivo %d: %d bytes", + "file_manager_failed_create_directory": "falha ao criar diretório %s para alteração de arquivo %d: %w", + "file_manager_failed_write_file": "falha ao escrever arquivo %s para alteração de arquivo %d: %w", + "file_manager_applied_operation": "Operação %s aplicada a %s", + "vertexai_error_create_request": "falha ao criar requisição: %w", + "vertexai_error_request_failed": "requisição falhou: %w", + "vertexai_error_api_status": "API retornou status %d: %s", + "vertexai_error_read_response": "falha ao ler resposta: %w", + "vertexai_error_response_too_large": "resposta muito grande (>%d bytes)", + "vertexai_error_parse_response": "falha ao analisar resposta: %w", + "copilot_tenant_client_id_required": "ID do locatário e ID do cliente são obrigatórios", + "copilot_failed_create_conversation": "falha ao criar conversa: %w", + "copilot_failed_send_message": "falha ao enviar mensagem: %w", + "copilot_failed_stream_message": "falha ao transmitir mensagem: %w", + "copilot_error_create_conversation": "falha ao criar conversa: %s - %s", + "copilot_error_chat_request": "solicitação de chat falhou: %s - %s", + "copilot_error_stream_request": "falha na solicitação de stream: %s - %s", + "copilot_debug_created_conversation": "Conversa do Copilot criada: %s", + "copilot_debug_failed_parse_sse_event": "Falha ao analisar evento SSE: %v", + "copilot_error_reading_stream": "erro ao ler stream: %w" } diff --git a/internal/i18n/locales/pt-PT.json b/internal/i18n/locales/pt-PT.json index 7735f796..09bdb33a 100644 --- a/internal/i18n/locales/pt-PT.json +++ b/internal/i18n/locales/pt-PT.json @@ -410,8 +410,7 @@ "spotify_search_failed": "a pesquisa falhou: %w", "spotify_failed_parse_search_results": "falha ao analisar os resultados da pesquisa: %w", "spotify_failed_get_show_episodes": "falha ao obter os episódios do programa: %w", - "spotify_failed_parse_episodes": "falha ao analisar os episódios: %w" -, + "spotify_failed_parse_episodes": "falha ao analisar os episódios: %w", "template_file_log_validating_path": "Ficheiro: a validar caminho %q", "template_file_error_path_contains_parent_ref": "ficheiro: o caminho não pode conter '..'", "template_file_error_expand_home_dir": "ficheiro: não foi possível expandir a diretoria home: %v", @@ -491,5 +490,31 @@ "fetch_content_too_large": "fetch: conteúdo demasiado grande: %d bytes (máx %d bytes)", "fetch_unsupported_content_type": "fetch: tipo de conteúdo não suportado %q - apenas conteúdo de texto permitido", "fetch_error_reading_response": "fetch: erro ao ler a resposta: %v", - "fetch_content_exceeds_limit": "fetch: conteúdo demasiado grande: excede %d bytes" + "fetch_content_exceeds_limit": "fetch: conteúdo demasiado grande: excede %d bytes", + "file_manager_invalid_format_no_json_array": "formato %s inválido: nenhum array JSON encontrado", + "file_manager_invalid_format_unbalanced_brackets": "formato %s inválido: parêntesis desequilibrados", + "file_manager_failed_parse_json": "falha ao analisar %s JSON: %w", + "file_manager_invalid_operation": "operação inválida para alteração de ficheiro %d: %s", + "file_manager_empty_path": "caminho vazio para alteração de ficheiro %d", + "file_manager_suspicious_path": "caminho suspeito para alteração de ficheiro %d: %s", + "file_manager_file_content_too_large": "conteúdo do ficheiro demasiado grande para alteração de ficheiro %d: %d bytes", + "file_manager_failed_create_directory": "falha ao criar diretório %s para alteração de ficheiro %d: %w", + "file_manager_failed_write_file": "falha ao escrever ficheiro %s para alteração de ficheiro %d: %w", + "file_manager_applied_operation": "Operação %s aplicada a %s", + "vertexai_error_create_request": "falha ao criar pedido: %w", + "vertexai_error_request_failed": "pedido falhou: %w", + "vertexai_error_api_status": "API devolveu estado %d: %s", + "vertexai_error_read_response": "falha ao ler resposta: %w", + "vertexai_error_response_too_large": "resposta demasiado grande (>%d bytes)", + "vertexai_error_parse_response": "falha ao analisar resposta: %w", + "copilot_tenant_client_id_required": "ID do locatário e ID do cliente são obrigatórios", + "copilot_failed_create_conversation": "falha ao criar conversa: %w", + "copilot_failed_send_message": "falha ao enviar mensagem: %w", + "copilot_failed_stream_message": "falha ao transmitir mensagem: %w", + "copilot_error_create_conversation": "falha ao criar conversa: %s - %s", + "copilot_error_chat_request": "pedido de chat falhou: %s - %s", + "copilot_error_stream_request": "pedido de transmissão falhou: %s - %s", + "copilot_debug_created_conversation": "Conversa do Copilot criada: %s", + "copilot_debug_failed_parse_sse_event": "Falha ao analisar evento SSE: %v", + "copilot_error_reading_stream": "erro ao ler transmissão: %w" } diff --git a/internal/i18n/locales/zh.json b/internal/i18n/locales/zh.json index 3125d673..208212ff 100644 --- a/internal/i18n/locales/zh.json +++ b/internal/i18n/locales/zh.json @@ -410,8 +410,7 @@ "spotify_search_failed": "搜索失败:%w", "spotify_failed_parse_search_results": "解析搜索结果失败:%w", "spotify_failed_get_show_episodes": "获取节目剧集失败:%w", - "spotify_failed_parse_episodes": "解析剧集失败:%w" -, + "spotify_failed_parse_episodes": "解析剧集失败:%w", "template_file_log_validating_path": "文件:正在验证路径 %q", "template_file_error_path_contains_parent_ref": "file: 路径不能包含 '..'", "template_file_error_expand_home_dir": "file: 无法展开主目录: %v", @@ -491,5 +490,31 @@ "fetch_content_too_large": "fetch:内容过大:%d 字节(最大 %d 字节)", "fetch_unsupported_content_type": "fetch:不支持的内容类型 %q - 仅允许文本内容", "fetch_error_reading_response": "fetch:读取响应时出错:%v", - "fetch_content_exceeds_limit": "fetch:内容过大:超过 %d 字节" + "fetch_content_exceeds_limit": "fetch:内容过大:超过 %d 字节", + "file_manager_invalid_format_no_json_array": "无效的%s格式:未找到JSON数组", + "file_manager_invalid_format_unbalanced_brackets": "无效的%s格式:括号不平衡", + "file_manager_failed_parse_json": "解析%s JSON失败:%w", + "file_manager_invalid_operation": "文件更改%d的无效操作:%s", + "file_manager_empty_path": "文件更改%d的空路径", + "file_manager_suspicious_path": "文件更改%d的可疑路径:%s", + "file_manager_file_content_too_large": "文件更改%d的文件内容太大:%d字节", + "file_manager_failed_create_directory": "为文件更改%d创建目录%s失败:%w", + "file_manager_failed_write_file": "为文件更改%d写入文件%s失败:%w", + "file_manager_applied_operation": "已将%s操作应用于%s", + "vertexai_error_create_request": "创建请求失败: %w", + "vertexai_error_request_failed": "请求失败: %w", + "vertexai_error_api_status": "API返回状态%d: %s", + "vertexai_error_read_response": "读取响应失败: %w", + "vertexai_error_response_too_large": "响应太大 (>%d字节)", + "vertexai_error_parse_response": "解析响应失败: %w", + "copilot_tenant_client_id_required": "需要租户ID和客户端ID", + "copilot_failed_create_conversation": "创建对话失败: %w", + "copilot_failed_send_message": "发送消息失败: %w", + "copilot_failed_stream_message": "流式传输消息失败: %w", + "copilot_error_create_conversation": "创建对话失败: %s - %s", + "copilot_error_chat_request": "聊天请求失败: %s - %s", + "copilot_error_stream_request": "流请求失败: %s - %s", + "copilot_debug_created_conversation": "已创建 Copilot 对话: %s", + "copilot_debug_failed_parse_sse_event": "解析 SSE 事件失败: %v", + "copilot_error_reading_stream": "读取流时出错: %w" } diff --git a/internal/plugins/ai/bedrock/bedrock.go b/internal/plugins/ai/bedrock/bedrock.go index 16af873f..1880ef93 100644 --- a/internal/plugins/ai/bedrock/bedrock.go +++ b/internal/plugins/ai/bedrock/bedrock.go @@ -55,7 +55,7 @@ func NewClient() (ret *BedrockClient) { ret.PluginBase = plugins.NewVendorPluginBase(vendorName, func() error { return fmt.Errorf(i18n.T("bedrock_unable_load_aws_config"), err) }) - ret.bedrockRegion = ret.PluginBase.AddSetupQuestion(i18n.T("bedrock_aws_region_label"), true) + ret.bedrockRegion = ret.PluginBase.AddSetupQuestionWithEnvName("AWS Region", true, i18n.T("bedrock_aws_region_label")) return } @@ -69,7 +69,7 @@ func NewClient() (ret *BedrockClient) { ret.runtimeClient = runtimeClient ret.controlPlaneClient = controlPlaneClient - ret.bedrockRegion = ret.PluginBase.AddSetupQuestion(i18n.T("bedrock_aws_region_label"), true) + ret.bedrockRegion = ret.PluginBase.AddSetupQuestionWithEnvName("AWS Region", true, i18n.T("bedrock_aws_region_label")) if cfg.Region != "" { ret.bedrockRegion.Value = cfg.Region diff --git a/internal/plugins/ai/copilot/copilot.go b/internal/plugins/ai/copilot/copilot.go index a00d4150..b89d67a3 100644 --- a/internal/plugins/ai/copilot/copilot.go +++ b/internal/plugins/ai/copilot/copilot.go @@ -24,6 +24,7 @@ import ( "github.com/danielmiessler/fabric/internal/chat" "github.com/danielmiessler/fabric/internal/domain" + "github.com/danielmiessler/fabric/internal/i18n" debuglog "github.com/danielmiessler/fabric/internal/log" "github.com/danielmiessler/fabric/internal/plugins" "golang.org/x/oauth2" @@ -106,7 +107,7 @@ type Client struct { // configure initializes the client with OAuth2 configuration. func (c *Client) configure() error { if c.TenantID.Value == "" || c.ClientID.Value == "" { - return fmt.Errorf("tenant ID and client ID are required") + return fmt.Errorf("%s", i18n.T("copilot_tenant_client_id_required")) } // Build OAuth2 configuration @@ -168,7 +169,7 @@ func (c *Client) Send(ctx context.Context, msgs []*chat.ChatCompletionMessage, o // Create a conversation conversationID, err := c.createConversation(ctx) if err != nil { - return "", fmt.Errorf("failed to create conversation: %w", err) + return "", fmt.Errorf(i18n.T("copilot_failed_create_conversation"), err) } // Build the message content from chat messages @@ -177,7 +178,7 @@ func (c *Client) Send(ctx context.Context, msgs []*chat.ChatCompletionMessage, o // Send the chat message response, err := c.sendChatMessage(ctx, conversationID, messageText) if err != nil { - return "", fmt.Errorf("failed to send message: %w", err) + return "", fmt.Errorf(i18n.T("copilot_failed_send_message"), err) } return response, nil @@ -192,7 +193,7 @@ func (c *Client) SendStream(msgs []*chat.ChatCompletionMessage, opts *domain.Cha // Create a conversation conversationID, err := c.createConversation(ctx) if err != nil { - return fmt.Errorf("failed to create conversation: %w", err) + return fmt.Errorf(i18n.T("copilot_failed_create_conversation"), err) } // Build the message content from chat messages @@ -200,7 +201,7 @@ func (c *Client) SendStream(msgs []*chat.ChatCompletionMessage, opts *domain.Cha // Send the streaming chat message if err := c.sendChatMessageStream(ctx, conversationID, messageText, channel); err != nil { - return fmt.Errorf("failed to stream message: %w", err) + return fmt.Errorf(i18n.T("copilot_failed_stream_message"), err) } return nil @@ -253,7 +254,7 @@ func (c *Client) createConversation(ctx context.Context) (string, error) { if resp.StatusCode != http.StatusCreated { body, _ := io.ReadAll(resp.Body) - return "", fmt.Errorf("failed to create conversation: %s - %s", resp.Status, string(body)) + return "", fmt.Errorf(i18n.T("copilot_error_create_conversation"), resp.Status, string(body)) } var result conversationResponse @@ -261,7 +262,7 @@ func (c *Client) createConversation(ctx context.Context) (string, error) { return "", err } - debuglog.Debug(debuglog.Detailed, "Created Copilot conversation: %s\n", result.ID) + debuglog.Debug(debuglog.Detailed, i18n.T("copilot_debug_created_conversation")+"\n", result.ID) return result.ID, nil } @@ -299,7 +300,7 @@ func (c *Client) sendChatMessage(ctx context.Context, conversationID, messageTex if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) - return "", fmt.Errorf("chat request failed: %s - %s", resp.Status, string(body)) + return "", fmt.Errorf(i18n.T("copilot_error_chat_request"), resp.Status, string(body)) } var result conversationResponse @@ -346,7 +347,7 @@ func (c *Client) sendChatMessageStream(ctx context.Context, conversationID, mess if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) - return fmt.Errorf("stream request failed: %s - %s", resp.Status, string(body)) + return fmt.Errorf(i18n.T("copilot_error_stream_request"), resp.Status, string(body)) } // Parse SSE stream @@ -373,7 +374,7 @@ func (c *Client) parseSSEStream(reader io.Reader, channel chan domain.StreamUpda var event conversationResponse if err := json.Unmarshal([]byte(jsonData), &event); err != nil { - debuglog.Debug(debuglog.Detailed, "Failed to parse SSE event: %v\n", err) + debuglog.Debug(debuglog.Detailed, i18n.T("copilot_debug_failed_parse_sse_event")+"\n", err) continue } @@ -394,7 +395,7 @@ func (c *Client) parseSSEStream(reader io.Reader, channel chan domain.StreamUpda } if err := scanner.Err(); err != nil { - return fmt.Errorf("error reading stream: %w", err) + return fmt.Errorf(i18n.T("copilot_error_reading_stream"), err) } channel <- domain.StreamUpdate{Type: domain.StreamTypeContent, Content: "\n"} diff --git a/internal/plugins/ai/vertexai/models.go b/internal/plugins/ai/vertexai/models.go index 2e5c3e04..7353f7be 100644 --- a/internal/plugins/ai/vertexai/models.go +++ b/internal/plugins/ai/vertexai/models.go @@ -9,6 +9,7 @@ import ( "sort" "strings" + "github.com/danielmiessler/fabric/internal/i18n" debuglog "github.com/danielmiessler/fabric/internal/log" ) @@ -40,7 +41,7 @@ type publisherModel struct { func fetchModelsPage(ctx context.Context, httpClient *http.Client, url, projectID, publisher string) (*publisherModelsResponse, error) { req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) + return nil, fmt.Errorf(i18n.T("vertexai_error_create_request"), err) } req.Header.Set("Accept", "application/json") @@ -49,28 +50,28 @@ func fetchModelsPage(ctx context.Context, httpClient *http.Client, url, projectI resp, err := httpClient.Do(req) if err != nil { - return nil, fmt.Errorf("request failed: %w", err) + return nil, fmt.Errorf(i18n.T("vertexai_error_request_failed"), err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { bodyBytes, _ := io.ReadAll(io.LimitReader(resp.Body, errorResponseLimit)) debuglog.Debug(debuglog.Basic, "API error for %s: status %d, url: %s, body: %s\n", publisher, resp.StatusCode, url, string(bodyBytes)) - return nil, fmt.Errorf("API returned status %d: %s", resp.StatusCode, string(bodyBytes)) + return nil, fmt.Errorf(i18n.T("vertexai_error_api_status"), resp.StatusCode, string(bodyBytes)) } bodyBytes, err := io.ReadAll(io.LimitReader(resp.Body, maxResponseSize+1)) if err != nil { - return nil, fmt.Errorf("failed to read response: %w", err) + return nil, fmt.Errorf(i18n.T("vertexai_error_read_response"), err) } if len(bodyBytes) > maxResponseSize { - return nil, fmt.Errorf("response too large (>%d bytes)", maxResponseSize) + return nil, fmt.Errorf(i18n.T("vertexai_error_response_too_large"), maxResponseSize) } var response publisherModelsResponse if err := json.Unmarshal(bodyBytes, &response); err != nil { - return nil, fmt.Errorf("failed to parse response: %w", err) + return nil, fmt.Errorf(i18n.T("vertexai_error_parse_response"), err) } return &response, nil From cff5ec2cbee3bc7f9b07349b4f7d5eef0c6e5157 Mon Sep 17 00:00:00 2001 From: Kayvan Sylvan Date: Mon, 16 Feb 2026 13:34:46 -0800 Subject: [PATCH 2/2] chore: incoming 2005 changelog entry --- cmd/generate_changelog/incoming/2005.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 cmd/generate_changelog/incoming/2005.txt diff --git a/cmd/generate_changelog/incoming/2005.txt b/cmd/generate_changelog/incoming/2005.txt new file mode 100644 index 00000000..a695bf2e --- /dev/null +++ b/cmd/generate_changelog/incoming/2005.txt @@ -0,0 +1,7 @@ +### PR [#2005](https://github.com/danielmiessler/Fabric/pull/2005) by [ksylvan](https://github.com/ksylvan): I18N: For file manager, Vertex AI, and Copilot errors + +- Internationalized file manager, Vertex AI, and Copilot error messages via i18n by replacing hardcoded error strings with translation keys +- Added file manager, Vertex AI, and Copilot i18n keys to all 10 locale files +- Fixed JSON trailing comma syntax errors across all locale files +- Normalized German locale JSON indentation from tabs to spaces +- Updated Bedrock AWS region setup to use `AddSetupQuestionWithEnvName`