mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-02-19 10:14:21 -05:00
feat: add i18n translations for ollama, extensions, lmstudio, and spotify modules
- Add i18n translation keys for Ollama `num_ctx` validation error messages - Add i18n strings for Ollama server chat endpoint and SSE streaming errors - Add i18n strings for extension registry, executor, and manager operations - Add i18n strings for LM Studio client error messages and response handling - Add i18n strings for Spotify API client error messages - Add OpenAI image generation model compatibility warning translations - Replace hardcoded English strings with `i18n.T()` calls across all modules - Add translations for all new keys in de, en, es, fa, fr, it, ja, pt-BR, pt-PT, and zh locales
This commit is contained in:
@@ -42,6 +42,8 @@
|
||||
"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",
|
||||
@@ -293,5 +295,120 @@
|
||||
"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"
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
"openai_unexpected_status_code_read_error_partial": "unexpected status code: %d from provider %s (error reading body: %v), partial response: %s",
|
||||
"openai_unexpected_status_code_read_error": "unexpected status code: %d from provider %s (failed to read response body: %v)",
|
||||
"openai_unable_to_parse_models_response": "unable to parse models response; raw response: %s",
|
||||
"openai_warning_model_no_image_generation": "Warning: Model '%s' does not support image generation. Supported models: %s. Consider using -m gpt-5.2 for image generation.\n",
|
||||
"openai_model_no_image_generation": "model '%s' does not support image generation. Supported models: %s",
|
||||
"scraping_not_configured": "scraping functionality is not configured. Please set up Jina to enable scraping",
|
||||
"could_not_determine_home_dir": "could not determine user home directory: %w",
|
||||
"could_not_stat_env_file": "could not stat .env file: %w",
|
||||
@@ -293,5 +295,120 @@
|
||||
"plugin_question_optional": "%v%v (leave empty to skip):",
|
||||
"plugin_invalid_boolean_value": "invalid boolean value: %v",
|
||||
"plugin_setting_not_valid": "%v=%v, is not valid",
|
||||
"plugin_invalid_bool": "invalid bool: %q"
|
||||
"plugin_invalid_bool": "invalid bool: %q",
|
||||
"ollama_num_ctx_must_be_finite": "num_ctx must be a finite number",
|
||||
"ollama_num_ctx_must_be_integer": "num_ctx must be an integer, got float with fractional part",
|
||||
"ollama_num_ctx_value_out_of_range": "num_ctx value out of range",
|
||||
"ollama_num_ctx_must_be_positive": "num_ctx must be positive, got: %d",
|
||||
"ollama_num_ctx_value_too_large": "num_ctx value too large: %d",
|
||||
"ollama_num_ctx_must_be_valid_number": "num_ctx must be a valid number",
|
||||
"ollama_num_ctx_must_be_valid_number_got": "num_ctx must be a valid number, got: %s",
|
||||
"ollama_num_ctx_invalid_type": "num_ctx must be a number, got invalid type",
|
||||
"ollama_num_ctx_exceeds_maximum": "num_ctx exceeds maximum allowed value of %d",
|
||||
"ollama_error_reading_body": "Error reading body: %v",
|
||||
"ollama_error_endpoint": "testing endpoint",
|
||||
"ollama_error_unmarshalling_body": "Error unmarshalling body: %v",
|
||||
"ollama_invalid_num_ctx_in_request": "Invalid num_ctx in request: %v",
|
||||
"ollama_warning_parse_variables": "Warning: failed to parse options.variables as JSON: %v",
|
||||
"ollama_error_marshalling_body": "Error marshalling body: %v",
|
||||
"ollama_error_building_chat_url": "Error building /chat URL: %v",
|
||||
"ollama_error_creating_chat_request": "Error creating /chat request: %v",
|
||||
"ollama_failed_create_request": "failed to create request",
|
||||
"ollama_error_getting_chat_body": "Error getting /chat body: %v",
|
||||
"ollama_upstream_non_2xx_body_unreadable": "Upstream Fabric server returned non-2xx status %d and body could not be read: %v",
|
||||
"ollama_upstream_non_2xx": "Upstream Fabric server returned non-2xx status %d: %s",
|
||||
"ollama_upstream_returned_status": "upstream Fabric server returned status %d",
|
||||
"ollama_error_prefix": "Error: %s",
|
||||
"ollama_error_parse_upstream_response": "Error: failed to parse upstream response",
|
||||
"ollama_failed_unmarshal_fabric_response": "failed to unmarshal Fabric response",
|
||||
"ollama_error_writing_response": "Error writing response: %v",
|
||||
"ollama_error_scanning_body": "Error scanning body: %v",
|
||||
"ollama_failed_scan_sse_stream": "failed to scan SSE response stream: %v",
|
||||
"ollama_sse_buffer_limit": "SSE line exceeds 1MB buffer limit - data line too large",
|
||||
"ollama_warning_no_content": "Warning: no content received from upstream Fabric server",
|
||||
"ollama_no_content_from_upstream": "no content received from upstream Fabric server",
|
||||
"ollama_empty_address": "empty address",
|
||||
"ollama_invalid_address": "invalid address: %w",
|
||||
"ollama_invalid_address_missing_host": "invalid address: missing host",
|
||||
"ollama_invalid_address_missing_hostname": "invalid address: missing hostname",
|
||||
"ollama_invalid_address_path_not_allowed": "invalid address: path component not allowed in bare address",
|
||||
"extension_registry_not_initialized": "extension registry not initialized",
|
||||
"extension_name_label": "Extension: %s\n",
|
||||
"extension_status_disabled": " Status: DISABLED - Hash verification failed: %v\n",
|
||||
"extension_config_path_label": " Config Path: %s\n\n",
|
||||
"extension_status_enabled": " Status: ENABLED\n",
|
||||
"extension_executable_label": " Executable: %s\n",
|
||||
"extension_type_label": " Type: %s\n",
|
||||
"extension_timeout_label": " Timeout: %s\n",
|
||||
"extension_description_label": " Description: %s\n",
|
||||
"extension_version_label": " Version: %s\n",
|
||||
"extension_operations_label": " Operations:\n",
|
||||
"extension_command_template_label": " Command Template: %s\n",
|
||||
"extension_file_config_label": " File Configuration:\n",
|
||||
"extension_invalid_config_path": "invalid config path: %w",
|
||||
"extension_failed_read_config": "failed to read config file: %w",
|
||||
"extension_failed_parse_config": "failed to parse config file: %w",
|
||||
"extension_failed_register": "failed to register extension: %w",
|
||||
"extension_invalid_timeout": "invalid timeout value '%s': must be a duration like '30s' or '1m': %w",
|
||||
"extension_registered_success": "Successfully registered extension:\n",
|
||||
"extension_name_detail_label": "Name: %s\n",
|
||||
"extension_failed_remove": "failed to remove extension: %w",
|
||||
"lmstudio_api_url_question": "Enter your %v URL (as a reminder, it is usually %v)",
|
||||
"lmstudio_failed_create_request": "failed to create request: %w",
|
||||
"lmstudio_failed_send_request": "failed to send request: %w",
|
||||
"lmstudio_unexpected_status_code": "unexpected status code: %d",
|
||||
"lmstudio_failed_decode_response": "failed to decode response: %w",
|
||||
"lmstudio_failed_marshal_payload": "failed to marshal payload: %w",
|
||||
"lmstudio_error_reading_response": "error reading response: %w",
|
||||
"lmstudio_invalid_response_missing_choices": "invalid response format: missing or empty choices",
|
||||
"lmstudio_invalid_response_missing_message": "invalid response format: missing message in first choice",
|
||||
"lmstudio_invalid_response_missing_content": "invalid response format: missing or non-string content in message",
|
||||
"lmstudio_invalid_response_missing_text": "invalid response format: missing or non-string text in first choice",
|
||||
"lmstudio_no_embeddings_returned": "no embeddings returned",
|
||||
"extension_warning_load_registry": "Warning: could not load extension registry: %v\n",
|
||||
"extension_name_empty": "extension name cannot be empty",
|
||||
"extension_name_contains_spaces": "extension name '%s' contains spaces - names must not contain spaces",
|
||||
"extension_executable_not_found": "executable not found: %w",
|
||||
"extension_failed_get_absolute_path": "failed to get absolute path: %w",
|
||||
"extension_failed_hash_executable": "failed to hash executable: %w",
|
||||
"extension_invalid_definition": "invalid extension definition: %w",
|
||||
"extension_name_required": "extension name is required",
|
||||
"extension_executable_required": "executable path is required",
|
||||
"extension_type_required": "extension type is required",
|
||||
"extension_invalid_timeout_format": "invalid timeout format: %w",
|
||||
"extension_operation_required": "at least one operation must be defined",
|
||||
"extension_cmd_template_required": "command template is required for operation %s",
|
||||
"extension_not_found": "extension %s not found",
|
||||
"extension_config_hash_mismatch": "config file hash mismatch for %s",
|
||||
"extension_failed_verify_executable": "failed to verify executable: %w",
|
||||
"extension_executable_hash_mismatch": "executable hash mismatch for %s",
|
||||
"extension_failed_marshal_registry": "failed to marshal extension registry: %w",
|
||||
"extension_failed_read_registry": "failed to read extension registry: %w",
|
||||
"extension_failed_parse_registry": "failed to parse extension registry: %w",
|
||||
"extension_failed_get_extension": "failed to get extension: %w",
|
||||
"extension_failed_format_command": "failed to format command: %w",
|
||||
"extension_empty_command": "empty command after formatting",
|
||||
"extension_operation_not_found": "operation %s not found for extension %s",
|
||||
"extension_executing_command": "Executing command: %s\n",
|
||||
"extension_execution_failed_stderr": "execution failed: %w\nstderr: %s",
|
||||
"extension_no_file_config": "no file configuration found",
|
||||
"extension_no_output_file": "no output file specified in configuration",
|
||||
"extension_execution_timed_out": "execution timed out after %v",
|
||||
"extension_execution_failed_err": "execution failed: %w\nerr: %s",
|
||||
"extension_failed_read_output_file": "failed to read output file: %w",
|
||||
"extension_failed_get_output_path": "failed to get output path: %w\nerr: %s",
|
||||
"spotify_failed_create_token_request": "failed to create token request: %w",
|
||||
"spotify_failed_request_access_token": "failed to request access token: %w",
|
||||
"spotify_failed_get_access_token": "failed to get access token: status %d, body: %s",
|
||||
"spotify_failed_decode_token_response": "failed to decode token response: %w",
|
||||
"spotify_failed_create_request": "failed to create request: %w",
|
||||
"spotify_failed_execute_request": "failed to execute request: %w",
|
||||
"spotify_failed_read_response_body": "failed to read response body: %w",
|
||||
"spotify_api_request_failed": "API request failed: status %d, body: %s",
|
||||
"spotify_failed_parse_show_metadata": "failed to parse show metadata: %w",
|
||||
"spotify_failed_parse_episode_metadata": "failed to parse episode metadata: %w",
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
"openai_unexpected_status_code_read_error_partial": "código de estado inesperado: %d del proveedor %s (error al leer cuerpo: %v), respuesta parcial: %s",
|
||||
"openai_unexpected_status_code_read_error": "código de estado inesperado: %d del proveedor %s (error al leer cuerpo de respuesta: %v)",
|
||||
"openai_unable_to_parse_models_response": "no se pudo analizar la respuesta de modelos; respuesta cruda: %s",
|
||||
"openai_warning_model_no_image_generation": "Advertencia: El modelo '%s' no soporta generación de imágenes. Modelos soportados: %s. Considere usar -m gpt-5.2 para generación de imágenes.\n",
|
||||
"openai_model_no_image_generation": "el modelo '%s' no soporta generación de imágenes. Modelos soportados: %s",
|
||||
"scraping_not_configured": "la funcionalidad de extracción no está configurada. Por favor configura Jina para habilitar la extracción",
|
||||
"could_not_determine_home_dir": "no se pudo determinar el directorio home del usuario: %w",
|
||||
"could_not_stat_env_file": "no se pudo verificar el archivo .env: %w",
|
||||
@@ -293,5 +295,120 @@
|
||||
"plugin_question_optional": "%v%v (deja vacío para omitir):",
|
||||
"plugin_invalid_boolean_value": "valor booleano no válido: %v",
|
||||
"plugin_setting_not_valid": "%v=%v no es válido",
|
||||
"plugin_invalid_bool": "bool no válido: %q"
|
||||
"plugin_invalid_bool": "bool no válido: %q",
|
||||
"ollama_num_ctx_must_be_finite": "num_ctx debe ser un número finito",
|
||||
"ollama_num_ctx_must_be_integer": "num_ctx debe ser un entero, se obtuvo float con parte fraccionaria",
|
||||
"ollama_num_ctx_value_out_of_range": "valor num_ctx fuera de rango",
|
||||
"ollama_num_ctx_must_be_positive": "num_ctx debe ser positivo, se obtuvo: %d",
|
||||
"ollama_num_ctx_value_too_large": "valor num_ctx demasiado grande: %d",
|
||||
"ollama_num_ctx_must_be_valid_number": "num_ctx debe ser un número válido",
|
||||
"ollama_num_ctx_must_be_valid_number_got": "num_ctx debe ser un número válido, se obtuvo: %s",
|
||||
"ollama_num_ctx_invalid_type": "num_ctx debe ser un número, se obtuvo tipo inválido",
|
||||
"ollama_num_ctx_exceeds_maximum": "num_ctx excede el valor máximo permitido de %d",
|
||||
"ollama_error_reading_body": "Error al leer el cuerpo: %v",
|
||||
"ollama_error_endpoint": "probando endpoint",
|
||||
"ollama_error_unmarshalling_body": "Error al deserializar el cuerpo: %v",
|
||||
"ollama_invalid_num_ctx_in_request": "num_ctx inválido en la solicitud: %v",
|
||||
"ollama_warning_parse_variables": "Advertencia: error al analizar options.variables como JSON: %v",
|
||||
"ollama_error_marshalling_body": "Error al serializar el cuerpo: %v",
|
||||
"ollama_error_building_chat_url": "Error al construir la URL /chat: %v",
|
||||
"ollama_error_creating_chat_request": "Error al crear la solicitud /chat: %v",
|
||||
"ollama_failed_create_request": "error al crear la solicitud",
|
||||
"ollama_error_getting_chat_body": "Error al obtener el cuerpo /chat: %v",
|
||||
"ollama_upstream_non_2xx_body_unreadable": "El servidor Fabric upstream devolvió estado no-2xx %d y el cuerpo no se pudo leer: %v",
|
||||
"ollama_upstream_non_2xx": "El servidor Fabric upstream devolvió estado no-2xx %d: %s",
|
||||
"ollama_upstream_returned_status": "el servidor Fabric upstream devolvió estado %d",
|
||||
"ollama_error_prefix": "Error: %s",
|
||||
"ollama_error_parse_upstream_response": "Error: no se pudo analizar la respuesta upstream",
|
||||
"ollama_failed_unmarshal_fabric_response": "error al deserializar la respuesta Fabric",
|
||||
"ollama_error_writing_response": "Error al escribir la respuesta: %v",
|
||||
"ollama_error_scanning_body": "Error al escanear el cuerpo: %v",
|
||||
"ollama_failed_scan_sse_stream": "error al escanear el flujo de respuesta SSE: %v",
|
||||
"ollama_sse_buffer_limit": "Línea SSE excede el límite de búfer de 1MB - línea de datos demasiado grande",
|
||||
"ollama_warning_no_content": "Advertencia: no se recibió contenido del servidor Fabric upstream",
|
||||
"ollama_no_content_from_upstream": "no se recibió contenido del servidor Fabric upstream",
|
||||
"ollama_empty_address": "dirección vacía",
|
||||
"ollama_invalid_address": "dirección inválida: %w",
|
||||
"ollama_invalid_address_missing_host": "dirección inválida: falta el host",
|
||||
"ollama_invalid_address_missing_hostname": "dirección inválida: falta el nombre de host",
|
||||
"ollama_invalid_address_path_not_allowed": "dirección inválida: componente de ruta no permitido en dirección simple",
|
||||
"extension_registry_not_initialized": "registro de extensiones no inicializado",
|
||||
"extension_name_label": "Extensión: %s\n",
|
||||
"extension_status_disabled": " Estado: DESHABILITADA - Verificación de hash fallida: %v\n",
|
||||
"extension_config_path_label": " Ruta de configuración: %s\n\n",
|
||||
"extension_status_enabled": " Estado: HABILITADA\n",
|
||||
"extension_executable_label": " Ejecutable: %s\n",
|
||||
"extension_type_label": " Tipo: %s\n",
|
||||
"extension_timeout_label": " Tiempo límite: %s\n",
|
||||
"extension_description_label": " Descripción: %s\n",
|
||||
"extension_version_label": " Versión: %s\n",
|
||||
"extension_operations_label": " Operaciones:\n",
|
||||
"extension_command_template_label": " Plantilla de comando: %s\n",
|
||||
"extension_file_config_label": " Configuración de archivo:\n",
|
||||
"extension_invalid_config_path": "ruta de configuración inválida: %w",
|
||||
"extension_failed_read_config": "error al leer el archivo de configuración: %w",
|
||||
"extension_failed_parse_config": "error al analizar el archivo de configuración: %w",
|
||||
"extension_failed_register": "error al registrar la extensión: %w",
|
||||
"extension_invalid_timeout": "valor de tiempo límite inválido '%s': debe ser una duración como '30s' o '1m': %w",
|
||||
"extension_registered_success": "Extensión registrada exitosamente:\n",
|
||||
"extension_name_detail_label": "Nombre: %s\n",
|
||||
"extension_failed_remove": "error al eliminar la extensión: %w",
|
||||
"lmstudio_api_url_question": "Introduzca su URL de %v (como recordatorio, generalmente es %v)",
|
||||
"lmstudio_failed_create_request": "error al crear la solicitud: %w",
|
||||
"lmstudio_failed_send_request": "error al enviar la solicitud: %w",
|
||||
"lmstudio_unexpected_status_code": "código de estado inesperado: %d",
|
||||
"lmstudio_failed_decode_response": "error al decodificar la respuesta: %w",
|
||||
"lmstudio_failed_marshal_payload": "error al serializar la carga útil: %w",
|
||||
"lmstudio_error_reading_response": "error al leer la respuesta: %w",
|
||||
"lmstudio_invalid_response_missing_choices": "formato de respuesta inválido: opciones ausentes o vacías",
|
||||
"lmstudio_invalid_response_missing_message": "formato de respuesta inválido: mensaje ausente en la primera opción",
|
||||
"lmstudio_invalid_response_missing_content": "formato de respuesta inválido: contenido ausente o no es una cadena en el mensaje",
|
||||
"lmstudio_invalid_response_missing_text": "formato de respuesta inválido: texto ausente o no es una cadena en la primera opción",
|
||||
"lmstudio_no_embeddings_returned": "no se devolvieron incrustaciones",
|
||||
"extension_warning_load_registry": "Advertencia: no se pudo cargar el registro de extensiones: %v\n",
|
||||
"extension_name_empty": "el nombre de la extensión no puede estar vacío",
|
||||
"extension_name_contains_spaces": "el nombre de la extensión '%s' contiene espacios - los nombres no deben contener espacios",
|
||||
"extension_executable_not_found": "ejecutable no encontrado: %w",
|
||||
"extension_failed_get_absolute_path": "no se pudo obtener la ruta absoluta: %w",
|
||||
"extension_failed_hash_executable": "no se pudo calcular el hash del ejecutable: %w",
|
||||
"extension_invalid_definition": "definición de extensión inválida: %w",
|
||||
"extension_name_required": "el nombre de la extensión es obligatorio",
|
||||
"extension_executable_required": "la ruta del ejecutable es obligatoria",
|
||||
"extension_type_required": "el tipo de extensión es obligatorio",
|
||||
"extension_invalid_timeout_format": "formato de tiempo límite inválido: %w",
|
||||
"extension_operation_required": "se debe definir al menos una operación",
|
||||
"extension_cmd_template_required": "la plantilla de comando es obligatoria para la operación %s",
|
||||
"extension_not_found": "extensión %s no encontrada",
|
||||
"extension_config_hash_mismatch": "discrepancia de hash del archivo de configuración para %s",
|
||||
"extension_failed_verify_executable": "no se pudo verificar el ejecutable: %w",
|
||||
"extension_executable_hash_mismatch": "discrepancia de hash del ejecutable para %s",
|
||||
"extension_failed_marshal_registry": "no se pudo serializar el registro de extensiones: %w",
|
||||
"extension_failed_read_registry": "no se pudo leer el registro de extensiones: %w",
|
||||
"extension_failed_parse_registry": "no se pudo analizar el registro de extensiones: %w",
|
||||
"extension_failed_get_extension": "no se pudo obtener la extensión: %w",
|
||||
"extension_failed_format_command": "no se pudo formatear el comando: %w",
|
||||
"extension_empty_command": "comando vacío después del formateo",
|
||||
"extension_operation_not_found": "operación %s no encontrada para la extensión %s",
|
||||
"extension_executing_command": "Ejecutando comando: %s\n",
|
||||
"extension_execution_failed_stderr": "la ejecución falló: %w\nstderr: %s",
|
||||
"extension_no_file_config": "no se encontró configuración de archivo",
|
||||
"extension_no_output_file": "no se especificó archivo de salida en la configuración",
|
||||
"extension_execution_timed_out": "la ejecución expiró después de %v",
|
||||
"extension_execution_failed_err": "la ejecución falló: %w\nerr: %s",
|
||||
"extension_failed_read_output_file": "no se pudo leer el archivo de salida: %w",
|
||||
"extension_failed_get_output_path": "no se pudo obtener la ruta de salida: %w\nerr: %s",
|
||||
"spotify_failed_create_token_request": "no se pudo crear la solicitud de token: %w",
|
||||
"spotify_failed_request_access_token": "no se pudo solicitar el token de acceso: %w",
|
||||
"spotify_failed_get_access_token": "no se pudo obtener el token de acceso: estado %d, respuesta: %s",
|
||||
"spotify_failed_decode_token_response": "no se pudo decodificar la respuesta del token: %w",
|
||||
"spotify_failed_create_request": "no se pudo crear la solicitud: %w",
|
||||
"spotify_failed_execute_request": "no se pudo ejecutar la solicitud: %w",
|
||||
"spotify_failed_read_response_body": "no se pudo leer el cuerpo de la respuesta: %w",
|
||||
"spotify_api_request_failed": "la solicitud a la API falló: estado %d, respuesta: %s",
|
||||
"spotify_failed_parse_show_metadata": "no se pudieron analizar los metadatos del programa: %w",
|
||||
"spotify_failed_parse_episode_metadata": "no se pudieron analizar los metadatos del episodio: %w",
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
"openai_unexpected_status_code_read_error_partial": "کد وضعیت غیرمنتظره: %d از ارائهدهنده %s (خطا در خواندن: %v)، پاسخ جزئی: %s",
|
||||
"openai_unexpected_status_code_read_error": "کد وضعیت غیرمنتظره: %d از ارائهدهنده %s (خطا در خواندن پاسخ: %v)",
|
||||
"openai_unable_to_parse_models_response": "تجزیه پاسخ مدلها ناموفق بود; پاسخ خام: %s",
|
||||
"openai_warning_model_no_image_generation": "هشدار: مدل '%s' از تولید تصویر پشتیبانی نمیکند. مدلهای پشتیبانی شده: %s. استفاده از -m gpt-5.2 برای تولید تصویر را در نظر بگیرید.\n",
|
||||
"openai_model_no_image_generation": "مدل '%s' از تولید تصویر پشتیبانی نمیکند. مدلهای پشتیبانی شده: %s",
|
||||
"scraping_not_configured": "قابلیت استخراج داده پیکربندی نشده است. لطفاً Jina را برای فعالسازی استخراج تنظیم کنید",
|
||||
"could_not_determine_home_dir": "نتوانست دایرکتوری خانه کاربر را تعیین کند: %w",
|
||||
"could_not_stat_env_file": "نتوانست وضعیت فایل .env را بررسی کند: %w",
|
||||
@@ -285,5 +287,120 @@
|
||||
"plugin_question_optional": "%v%v (برای رد کردن خالی بگذارید):",
|
||||
"plugin_invalid_boolean_value": "مقدار بولی نامعتبر: %v",
|
||||
"plugin_setting_not_valid": "%v=%v معتبر نیست",
|
||||
"plugin_invalid_bool": "مقدار bool نامعتبر: %q"
|
||||
"plugin_invalid_bool": "مقدار bool نامعتبر: %q",
|
||||
"ollama_num_ctx_must_be_finite": "num_ctx باید یک عدد محدود باشد",
|
||||
"ollama_num_ctx_must_be_integer": "num_ctx باید یک عدد صحیح باشد، عدد اعشاری با قسمت کسری دریافت شد",
|
||||
"ollama_num_ctx_value_out_of_range": "مقدار num_ctx خارج از محدوده است",
|
||||
"ollama_num_ctx_must_be_positive": "num_ctx باید مثبت باشد، دریافت شده: %d",
|
||||
"ollama_num_ctx_value_too_large": "مقدار num_ctx بیش از حد بزرگ است: %d",
|
||||
"ollama_num_ctx_must_be_valid_number": "num_ctx باید یک عدد معتبر باشد",
|
||||
"ollama_num_ctx_must_be_valid_number_got": "num_ctx باید یک عدد معتبر باشد، دریافت شده: %s",
|
||||
"ollama_num_ctx_invalid_type": "num_ctx باید یک عدد باشد، نوع نامعتبر دریافت شد",
|
||||
"ollama_num_ctx_exceeds_maximum": "num_ctx از حداکثر مقدار مجاز %d فراتر رفته است",
|
||||
"ollama_error_reading_body": "خطا در خواندن بدنه: %v",
|
||||
"ollama_error_endpoint": "در حال آزمایش نقطه پایانی",
|
||||
"ollama_error_unmarshalling_body": "خطا در تجزیه بدنه: %v",
|
||||
"ollama_invalid_num_ctx_in_request": "num_ctx نامعتبر در درخواست: %v",
|
||||
"ollama_warning_parse_variables": "هشدار: شکست در تجزیه options.variables به عنوان JSON: %v",
|
||||
"ollama_error_marshalling_body": "خطا در سریالسازی بدنه: %v",
|
||||
"ollama_error_building_chat_url": "خطا در ساخت URL چت /: %v",
|
||||
"ollama_error_creating_chat_request": "خطا در ایجاد درخواست /chat: %v",
|
||||
"ollama_failed_create_request": "ایجاد درخواست ناموفق بود",
|
||||
"ollama_error_getting_chat_body": "خطا در دریافت بدنه /chat: %v",
|
||||
"ollama_upstream_non_2xx_body_unreadable": "سرور Fabric بالادستی وضعیت غیر-2xx %d را برگرداند و بدنه قابل خواندن نبود: %v",
|
||||
"ollama_upstream_non_2xx": "سرور Fabric بالادستی وضعیت غیر-2xx %d را برگرداند: %s",
|
||||
"ollama_upstream_returned_status": "سرور Fabric بالادستی وضعیت %d را برگرداند",
|
||||
"ollama_error_prefix": "خطا: %s",
|
||||
"ollama_error_parse_upstream_response": "خطا: شکست در تجزیه پاسخ بالادستی",
|
||||
"ollama_failed_unmarshal_fabric_response": "شکست در تجزیه پاسخ Fabric",
|
||||
"ollama_error_writing_response": "خطا در نوشتن پاسخ: %v",
|
||||
"ollama_error_scanning_body": "خطا در اسکن بدنه: %v",
|
||||
"ollama_failed_scan_sse_stream": "شکست در اسکن جریان پاسخ SSE: %v",
|
||||
"ollama_sse_buffer_limit": "خط SSE از حد بافر 1MB فراتر رفت - خط داده بیش از حد بزرگ است",
|
||||
"ollama_warning_no_content": "هشدار: هیچ محتوایی از سرور Fabric بالادستی دریافت نشد",
|
||||
"ollama_no_content_from_upstream": "هیچ محتوایی از سرور Fabric بالادستی دریافت نشد",
|
||||
"ollama_empty_address": "آدرس خالی",
|
||||
"ollama_invalid_address": "آدرس نامعتبر: %w",
|
||||
"ollama_invalid_address_missing_host": "آدرس نامعتبر: میزبان وجود ندارد",
|
||||
"ollama_invalid_address_missing_hostname": "آدرس نامعتبر: نام میزبان وجود ندارد",
|
||||
"ollama_invalid_address_path_not_allowed": "آدرس نامعتبر: مؤلفه مسیر در آدرس ساده مجاز نیست",
|
||||
"extension_registry_not_initialized": "رجیستری افزونهها مقداردهی نشده است",
|
||||
"extension_name_label": "افزونه: %s\n",
|
||||
"extension_status_disabled": " وضعیت: غیرفعال - تأیید هش ناموفق: %v\n",
|
||||
"extension_config_path_label": " مسیر پیکربندی: %s\n\n",
|
||||
"extension_status_enabled": " وضعیت: فعال\n",
|
||||
"extension_executable_label": " فایل اجرایی: %s\n",
|
||||
"extension_type_label": " نوع: %s\n",
|
||||
"extension_timeout_label": " مهلت زمانی: %s\n",
|
||||
"extension_description_label": " توضیحات: %s\n",
|
||||
"extension_version_label": " نسخه: %s\n",
|
||||
"extension_operations_label": " عملیاتها:\n",
|
||||
"extension_command_template_label": " الگوی دستور: %s\n",
|
||||
"extension_file_config_label": " پیکربندی فایل:\n",
|
||||
"extension_invalid_config_path": "مسیر پیکربندی نامعتبر: %w",
|
||||
"extension_failed_read_config": "خواندن فایل پیکربندی ناموفق بود: %w",
|
||||
"extension_failed_parse_config": "تجزیه فایل پیکربندی ناموفق بود: %w",
|
||||
"extension_failed_register": "ثبت افزونه ناموفق بود: %w",
|
||||
"extension_invalid_timeout": "مقدار مهلت زمانی نامعتبر '%s': باید مدتزمانی مانند '30s' یا '1m' باشد: %w",
|
||||
"extension_registered_success": "افزونه با موفقیت ثبت شد:\n",
|
||||
"extension_name_detail_label": "نام: %s\n",
|
||||
"extension_failed_remove": "حذف افزونه ناموفق بود: %w",
|
||||
"lmstudio_api_url_question": "آدرس URL %v خود را وارد کنید (به عنوان یادآوری، معمولاً %v است)",
|
||||
"lmstudio_failed_create_request": "ایجاد درخواست ناموفق بود: %w",
|
||||
"lmstudio_failed_send_request": "ارسال درخواست ناموفق بود: %w",
|
||||
"lmstudio_unexpected_status_code": "کد وضعیت غیرمنتظره: %d",
|
||||
"lmstudio_failed_decode_response": "رمزگشایی پاسخ ناموفق بود: %w",
|
||||
"lmstudio_failed_marshal_payload": "سریالسازی بار داده ناموفق بود: %w",
|
||||
"lmstudio_error_reading_response": "خطا در خواندن پاسخ: %w",
|
||||
"lmstudio_invalid_response_missing_choices": "فرمت پاسخ نامعتبر: گزینهها وجود ندارند یا خالی هستند",
|
||||
"lmstudio_invalid_response_missing_message": "فرمت پاسخ نامعتبر: پیام در اولین گزینه وجود ندارد",
|
||||
"lmstudio_invalid_response_missing_content": "فرمت پاسخ نامعتبر: محتوا در پیام وجود ندارد یا رشته نیست",
|
||||
"lmstudio_invalid_response_missing_text": "فرمت پاسخ نامعتبر: متن در اولین گزینه وجود ندارد یا رشته نیست",
|
||||
"lmstudio_no_embeddings_returned": "هیچ بردار جاسازی بازگردانده نشد",
|
||||
"extension_warning_load_registry": "هشدار: بارگذاری رجیستری افزونهها ممکن نبود: %v\n",
|
||||
"extension_name_empty": "نام افزونه نمیتواند خالی باشد",
|
||||
"extension_name_contains_spaces": "نام افزونه '%s' حاوی فاصله است - نامها نباید فاصله داشته باشند",
|
||||
"extension_executable_not_found": "فایل اجرایی یافت نشد: %w",
|
||||
"extension_failed_get_absolute_path": "دریافت مسیر مطلق ناموفق بود: %w",
|
||||
"extension_failed_hash_executable": "محاسبه هش فایل اجرایی ناموفق بود: %w",
|
||||
"extension_invalid_definition": "تعریف افزونه نامعتبر: %w",
|
||||
"extension_name_required": "نام افزونه الزامی است",
|
||||
"extension_executable_required": "مسیر فایل اجرایی الزامی است",
|
||||
"extension_type_required": "نوع افزونه الزامی است",
|
||||
"extension_invalid_timeout_format": "فرمت مهلت زمانی نامعتبر: %w",
|
||||
"extension_operation_required": "حداقل یک عملیات باید تعریف شود",
|
||||
"extension_cmd_template_required": "الگوی دستور برای عملیات %s الزامی است",
|
||||
"extension_not_found": "افزونه %s یافت نشد",
|
||||
"extension_config_hash_mismatch": "عدم تطابق هش فایل پیکربندی برای %s",
|
||||
"extension_failed_verify_executable": "تأیید فایل اجرایی ناموفق بود: %w",
|
||||
"extension_executable_hash_mismatch": "عدم تطابق هش فایل اجرایی برای %s",
|
||||
"extension_failed_marshal_registry": "سریالسازی رجیستری افزونهها ناموفق بود: %w",
|
||||
"extension_failed_read_registry": "خواندن رجیستری افزونهها ناموفق بود: %w",
|
||||
"extension_failed_parse_registry": "تجزیه رجیستری افزونهها ناموفق بود: %w",
|
||||
"extension_failed_get_extension": "دریافت افزونه ناموفق بود: %w",
|
||||
"extension_failed_format_command": "قالببندی دستور ناموفق بود: %w",
|
||||
"extension_empty_command": "دستور خالی پس از قالببندی",
|
||||
"extension_operation_not_found": "عملیات %s برای افزونه %s یافت نشد",
|
||||
"extension_executing_command": "در حال اجرای دستور: %s\n",
|
||||
"extension_execution_failed_stderr": "اجرا ناموفق بود: %w\nstderr: %s",
|
||||
"extension_no_file_config": "پیکربندی فایل یافت نشد",
|
||||
"extension_no_output_file": "فایل خروجی در پیکربندی مشخص نشده است",
|
||||
"extension_execution_timed_out": "اجرا پس از %v منقضی شد",
|
||||
"extension_execution_failed_err": "اجرا ناموفق بود: %w\nerr: %s",
|
||||
"extension_failed_read_output_file": "خواندن فایل خروجی ناموفق بود: %w",
|
||||
"extension_failed_get_output_path": "دریافت مسیر خروجی ناموفق بود: %w\nerr: %s",
|
||||
"spotify_failed_create_token_request": "ایجاد درخواست توکن ناموفق بود: %w",
|
||||
"spotify_failed_request_access_token": "درخواست توکن دسترسی ناموفق بود: %w",
|
||||
"spotify_failed_get_access_token": "دریافت توکن دسترسی ناموفق بود: وضعیت %d، پاسخ: %s",
|
||||
"spotify_failed_decode_token_response": "رمزگشایی پاسخ توکن ناموفق بود: %w",
|
||||
"spotify_failed_create_request": "ایجاد درخواست ناموفق بود: %w",
|
||||
"spotify_failed_execute_request": "اجرای درخواست ناموفق بود: %w",
|
||||
"spotify_failed_read_response_body": "خواندن متن پاسخ ناموفق بود: %w",
|
||||
"spotify_api_request_failed": "درخواست API ناموفق بود: وضعیت %d، پاسخ: %s",
|
||||
"spotify_failed_parse_show_metadata": "تجزیه فراداده برنامه ناموفق بود: %w",
|
||||
"spotify_failed_parse_episode_metadata": "تجزیه فراداده قسمت ناموفق بود: %w",
|
||||
"spotify_search_failed": "جستجو ناموفق بود: %w",
|
||||
"spotify_failed_parse_search_results": "تجزیه نتایج جستجو ناموفق بود: %w",
|
||||
"spotify_failed_get_show_episodes": "دریافت قسمتهای برنامه ناموفق بود: %w",
|
||||
"spotify_failed_parse_episodes": "تجزیه قسمتها ناموفق بود: %w"
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
"openai_unexpected_status_code_read_error_partial": "code d'état inattendu : %d du fournisseur %s (erreur de lecture : %v), réponse partielle : %s",
|
||||
"openai_unexpected_status_code_read_error": "code d'état inattendu : %d du fournisseur %s (échec de lecture du corps de réponse : %v)",
|
||||
"openai_unable_to_parse_models_response": "impossible d'analyser la réponse des modèles ; réponse brute : %s",
|
||||
"openai_warning_model_no_image_generation": "Avertissement : Le modèle '%s' ne prend pas en charge la génération d'images. Modèles pris en charge : %s. Envisagez d'utiliser -m gpt-5.2 pour la génération d'images.\n",
|
||||
"openai_model_no_image_generation": "le modèle '%s' ne prend pas en charge la génération d'images. Modèles pris en charge : %s",
|
||||
"scraping_not_configured": "la fonctionnalité de scraping n'est pas configurée. Veuillez configurer Jina pour activer le scraping",
|
||||
"could_not_determine_home_dir": "impossible de déterminer le répertoire home de l'utilisateur : %w",
|
||||
"could_not_stat_env_file": "impossible de vérifier le fichier .env : %w",
|
||||
@@ -293,5 +295,120 @@
|
||||
"plugin_question_optional": "%v%v (laissez vide pour passer) :",
|
||||
"plugin_invalid_boolean_value": "valeur booléenne invalide : %v",
|
||||
"plugin_setting_not_valid": "%v=%v n'est pas valide",
|
||||
"plugin_invalid_bool": "booléen invalide : %q"
|
||||
"plugin_invalid_bool": "booléen invalide : %q",
|
||||
"ollama_num_ctx_must_be_finite": "num_ctx doit être un nombre fini",
|
||||
"ollama_num_ctx_must_be_integer": "num_ctx doit être un entier, float avec partie fractionnaire reçu",
|
||||
"ollama_num_ctx_value_out_of_range": "valeur num_ctx hors limites",
|
||||
"ollama_num_ctx_must_be_positive": "num_ctx doit être positif, reçu : %d",
|
||||
"ollama_num_ctx_value_too_large": "valeur num_ctx trop grande : %d",
|
||||
"ollama_num_ctx_must_be_valid_number": "num_ctx doit être un nombre valide",
|
||||
"ollama_num_ctx_must_be_valid_number_got": "num_ctx doit être un nombre valide, reçu : %s",
|
||||
"ollama_num_ctx_invalid_type": "num_ctx doit être un nombre, type invalide reçu",
|
||||
"ollama_num_ctx_exceeds_maximum": "num_ctx dépasse la valeur maximale autorisée de %d",
|
||||
"ollama_error_reading_body": "Erreur lors de la lecture du corps : %v",
|
||||
"ollama_error_endpoint": "test du point de terminaison",
|
||||
"ollama_error_unmarshalling_body": "Erreur lors du décodage du corps : %v",
|
||||
"ollama_invalid_num_ctx_in_request": "num_ctx invalide dans la requête : %v",
|
||||
"ollama_warning_parse_variables": "Attention : échec de l'analyse de options.variables en JSON : %v",
|
||||
"ollama_error_marshalling_body": "Erreur lors de l'encodage du corps : %v",
|
||||
"ollama_error_building_chat_url": "Erreur lors de la construction de l'URL /chat : %v",
|
||||
"ollama_error_creating_chat_request": "Erreur lors de la création de la requête /chat : %v",
|
||||
"ollama_failed_create_request": "échec de création de la requête",
|
||||
"ollama_error_getting_chat_body": "Erreur lors de l'obtention du corps /chat : %v",
|
||||
"ollama_upstream_non_2xx_body_unreadable": "Le serveur Fabric en amont a renvoyé un statut non-2xx %d et le corps n'a pas pu être lu : %v",
|
||||
"ollama_upstream_non_2xx": "Le serveur Fabric en amont a renvoyé un statut non-2xx %d : %s",
|
||||
"ollama_upstream_returned_status": "le serveur Fabric en amont a renvoyé le statut %d",
|
||||
"ollama_error_prefix": "Erreur : %s",
|
||||
"ollama_error_parse_upstream_response": "Erreur : échec de l'analyse de la réponse en amont",
|
||||
"ollama_failed_unmarshal_fabric_response": "échec du décodage de la réponse Fabric",
|
||||
"ollama_error_writing_response": "Erreur lors de l'écriture de la réponse : %v",
|
||||
"ollama_error_scanning_body": "Erreur lors de l'analyse du corps : %v",
|
||||
"ollama_failed_scan_sse_stream": "échec de l'analyse du flux de réponse SSE : %v",
|
||||
"ollama_sse_buffer_limit": "La ligne SSE dépasse la limite de tampon de 1 Mo - ligne de données trop grande",
|
||||
"ollama_warning_no_content": "Attention : aucun contenu reçu du serveur Fabric en amont",
|
||||
"ollama_no_content_from_upstream": "aucun contenu reçu du serveur Fabric en amont",
|
||||
"ollama_empty_address": "adresse vide",
|
||||
"ollama_invalid_address": "adresse invalide : %w",
|
||||
"ollama_invalid_address_missing_host": "adresse invalide : hôte manquant",
|
||||
"ollama_invalid_address_missing_hostname": "adresse invalide : nom d'hôte manquant",
|
||||
"ollama_invalid_address_path_not_allowed": "adresse invalide : composant de chemin non autorisé dans l'adresse simple",
|
||||
"extension_registry_not_initialized": "registre d'extensions non initialisé",
|
||||
"extension_name_label": "Extension : %s\n",
|
||||
"extension_status_disabled": " Statut : DÉSACTIVÉE - Vérification du hash échouée : %v\n",
|
||||
"extension_config_path_label": " Chemin de configuration : %s\n\n",
|
||||
"extension_status_enabled": " Statut : ACTIVÉE\n",
|
||||
"extension_executable_label": " Exécutable : %s\n",
|
||||
"extension_type_label": " Type : %s\n",
|
||||
"extension_timeout_label": " Délai d'expiration : %s\n",
|
||||
"extension_description_label": " Description : %s\n",
|
||||
"extension_version_label": " Version : %s\n",
|
||||
"extension_operations_label": " Opérations :\n",
|
||||
"extension_command_template_label": " Modèle de commande : %s\n",
|
||||
"extension_file_config_label": " Configuration de fichier :\n",
|
||||
"extension_invalid_config_path": "chemin de configuration invalide : %w",
|
||||
"extension_failed_read_config": "échec de lecture du fichier de configuration : %w",
|
||||
"extension_failed_parse_config": "échec de l'analyse du fichier de configuration : %w",
|
||||
"extension_failed_register": "échec de l'enregistrement de l'extension : %w",
|
||||
"extension_invalid_timeout": "valeur de délai invalide '%s' : doit être une durée comme '30s' ou '1m' : %w",
|
||||
"extension_registered_success": "Extension enregistrée avec succès :\n",
|
||||
"extension_name_detail_label": "Nom : %s\n",
|
||||
"extension_failed_remove": "échec de la suppression de l'extension : %w",
|
||||
"lmstudio_api_url_question": "Entrez votre URL %v (pour rappel, elle est généralement %v)",
|
||||
"lmstudio_failed_create_request": "échec de la création de la requête : %w",
|
||||
"lmstudio_failed_send_request": "échec de l'envoi de la requête : %w",
|
||||
"lmstudio_unexpected_status_code": "code de statut inattendu : %d",
|
||||
"lmstudio_failed_decode_response": "échec du décodage de la réponse : %w",
|
||||
"lmstudio_failed_marshal_payload": "échec de la sérialisation des données : %w",
|
||||
"lmstudio_error_reading_response": "erreur lors de la lecture de la réponse : %w",
|
||||
"lmstudio_invalid_response_missing_choices": "format de réponse invalide : choix manquants ou vides",
|
||||
"lmstudio_invalid_response_missing_message": "format de réponse invalide : message manquant dans le premier choix",
|
||||
"lmstudio_invalid_response_missing_content": "format de réponse invalide : contenu manquant ou non-chaîne dans le message",
|
||||
"lmstudio_invalid_response_missing_text": "format de réponse invalide : texte manquant ou non-chaîne dans le premier choix",
|
||||
"lmstudio_no_embeddings_returned": "aucun embedding retourné",
|
||||
"extension_warning_load_registry": "Attention : impossible de charger le registre d'extensions : %v\n",
|
||||
"extension_name_empty": "le nom de l'extension ne peut pas être vide",
|
||||
"extension_name_contains_spaces": "le nom de l'extension '%s' contient des espaces - les noms ne doivent pas contenir d'espaces",
|
||||
"extension_executable_not_found": "exécutable introuvable : %w",
|
||||
"extension_failed_get_absolute_path": "impossible d'obtenir le chemin absolu : %w",
|
||||
"extension_failed_hash_executable": "impossible de calculer le hash de l'exécutable : %w",
|
||||
"extension_invalid_definition": "définition d'extension invalide : %w",
|
||||
"extension_name_required": "le nom de l'extension est requis",
|
||||
"extension_executable_required": "le chemin de l'exécutable est requis",
|
||||
"extension_type_required": "le type d'extension est requis",
|
||||
"extension_invalid_timeout_format": "format de délai invalide : %w",
|
||||
"extension_operation_required": "au moins une opération doit être définie",
|
||||
"extension_cmd_template_required": "le modèle de commande est requis pour l'opération %s",
|
||||
"extension_not_found": "extension %s introuvable",
|
||||
"extension_config_hash_mismatch": "discordance de hash du fichier de configuration pour %s",
|
||||
"extension_failed_verify_executable": "impossible de vérifier l'exécutable : %w",
|
||||
"extension_executable_hash_mismatch": "discordance de hash de l'exécutable pour %s",
|
||||
"extension_failed_marshal_registry": "impossible de sérialiser le registre d'extensions : %w",
|
||||
"extension_failed_read_registry": "impossible de lire le registre d'extensions : %w",
|
||||
"extension_failed_parse_registry": "impossible d'analyser le registre d'extensions : %w",
|
||||
"extension_failed_get_extension": "impossible d'obtenir l'extension : %w",
|
||||
"extension_failed_format_command": "impossible de formater la commande : %w",
|
||||
"extension_empty_command": "commande vide après le formatage",
|
||||
"extension_operation_not_found": "opération %s introuvable pour l'extension %s",
|
||||
"extension_executing_command": "Exécution de la commande : %s\n",
|
||||
"extension_execution_failed_stderr": "l'exécution a échoué : %w\nstderr : %s",
|
||||
"extension_no_file_config": "aucune configuration de fichier trouvée",
|
||||
"extension_no_output_file": "aucun fichier de sortie spécifié dans la configuration",
|
||||
"extension_execution_timed_out": "l'exécution a expiré après %v",
|
||||
"extension_execution_failed_err": "l'exécution a échoué : %w\nerr : %s",
|
||||
"extension_failed_read_output_file": "impossible de lire le fichier de sortie : %w",
|
||||
"extension_failed_get_output_path": "impossible d'obtenir le chemin de sortie : %w\nerr : %s",
|
||||
"spotify_failed_create_token_request": "impossible de créer la requête de token : %w",
|
||||
"spotify_failed_request_access_token": "impossible de demander le jeton d'accès : %w",
|
||||
"spotify_failed_get_access_token": "impossible d'obtenir le jeton d'accès : statut %d, réponse : %s",
|
||||
"spotify_failed_decode_token_response": "impossible de décoder la réponse du token : %w",
|
||||
"spotify_failed_create_request": "impossible de créer la requête : %w",
|
||||
"spotify_failed_execute_request": "impossible d'exécuter la requête : %w",
|
||||
"spotify_failed_read_response_body": "impossible de lire le corps de la réponse : %w",
|
||||
"spotify_api_request_failed": "la requête API a échoué : statut %d, réponse : %s",
|
||||
"spotify_failed_parse_show_metadata": "impossible d'analyser les métadonnées de l'émission : %w",
|
||||
"spotify_failed_parse_episode_metadata": "impossible d'analyser les métadonnées de l'épisode : %w",
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
"openai_unexpected_status_code_read_error_partial": "codice di stato imprevisto: %d dal provider %s (errore lettura corpo: %v), risposta parziale: %s",
|
||||
"openai_unexpected_status_code_read_error": "codice di stato imprevisto: %d dal provider %s (errore lettura corpo risposta: %v)",
|
||||
"openai_unable_to_parse_models_response": "impossibile analizzare risposta modelli; risposta grezza: %s",
|
||||
"openai_warning_model_no_image_generation": "Avviso: Il modello '%s' non supporta la generazione di immagini. Modelli supportati: %s. Considera di usare -m gpt-5.2 per la generazione di immagini.\n",
|
||||
"openai_model_no_image_generation": "il modello '%s' non supporta la generazione di immagini. Modelli supportati: %s",
|
||||
"scraping_not_configured": "la funzionalità di scraping non è configurata. Per favore configura Jina per abilitare lo scraping",
|
||||
"could_not_determine_home_dir": "impossibile determinare la directory home dell'utente: %w",
|
||||
"could_not_stat_env_file": "impossibile verificare il file .env: %w",
|
||||
@@ -293,5 +295,120 @@
|
||||
"plugin_question_optional": "%v%v (lascia vuoto per saltare):",
|
||||
"plugin_invalid_boolean_value": "valore booleano non valido: %v",
|
||||
"plugin_setting_not_valid": "%v=%v non è valido",
|
||||
"plugin_invalid_bool": "bool non valido: %q"
|
||||
"plugin_invalid_bool": "bool non valido: %q",
|
||||
"ollama_num_ctx_must_be_finite": "num_ctx deve essere un numero finito",
|
||||
"ollama_num_ctx_must_be_integer": "num_ctx deve essere un intero, ricevuto float con parte frazionaria",
|
||||
"ollama_num_ctx_value_out_of_range": "valore num_ctx fuori intervallo",
|
||||
"ollama_num_ctx_must_be_positive": "num_ctx deve essere positivo, ricevuto: %d",
|
||||
"ollama_num_ctx_value_too_large": "valore num_ctx troppo grande: %d",
|
||||
"ollama_num_ctx_must_be_valid_number": "num_ctx deve essere un numero valido",
|
||||
"ollama_num_ctx_must_be_valid_number_got": "num_ctx deve essere un numero valido, ricevuto: %s",
|
||||
"ollama_num_ctx_invalid_type": "num_ctx deve essere un numero, ricevuto tipo non valido",
|
||||
"ollama_num_ctx_exceeds_maximum": "num_ctx supera il valore massimo consentito di %d",
|
||||
"ollama_error_reading_body": "Errore nella lettura del corpo: %v",
|
||||
"ollama_error_endpoint": "test dell'endpoint",
|
||||
"ollama_error_unmarshalling_body": "Errore nella deserializzazione del corpo: %v",
|
||||
"ollama_invalid_num_ctx_in_request": "num_ctx non valido nella richiesta: %v",
|
||||
"ollama_warning_parse_variables": "Avviso: impossibile analizzare options.variables come JSON: %v",
|
||||
"ollama_error_marshalling_body": "Errore nella serializzazione del corpo: %v",
|
||||
"ollama_error_building_chat_url": "Errore nella costruzione dell'URL /chat: %v",
|
||||
"ollama_error_creating_chat_request": "Errore nella creazione della richiesta /chat: %v",
|
||||
"ollama_failed_create_request": "impossibile creare la richiesta",
|
||||
"ollama_error_getting_chat_body": "Errore nell'ottenere il corpo /chat: %v",
|
||||
"ollama_upstream_non_2xx_body_unreadable": "Il server Fabric upstream ha restituito stato non-2xx %d e il corpo non è stato leggibile: %v",
|
||||
"ollama_upstream_non_2xx": "Il server Fabric upstream ha restituito stato non-2xx %d: %s",
|
||||
"ollama_upstream_returned_status": "il server Fabric upstream ha restituito stato %d",
|
||||
"ollama_error_prefix": "Errore: %s",
|
||||
"ollama_error_parse_upstream_response": "Errore: impossibile analizzare la risposta upstream",
|
||||
"ollama_failed_unmarshal_fabric_response": "impossibile deserializzare la risposta Fabric",
|
||||
"ollama_error_writing_response": "Errore nella scrittura della risposta: %v",
|
||||
"ollama_error_scanning_body": "Errore nella scansione del corpo: %v",
|
||||
"ollama_failed_scan_sse_stream": "impossibile scansionare il flusso di risposta SSE: %v",
|
||||
"ollama_sse_buffer_limit": "La riga SSE supera il limite del buffer di 1MB - riga di dati troppo grande",
|
||||
"ollama_warning_no_content": "Avviso: nessun contenuto ricevuto dal server Fabric upstream",
|
||||
"ollama_no_content_from_upstream": "nessun contenuto ricevuto dal server Fabric upstream",
|
||||
"ollama_empty_address": "indirizzo vuoto",
|
||||
"ollama_invalid_address": "indirizzo non valido: %w",
|
||||
"ollama_invalid_address_missing_host": "indirizzo non valido: host mancante",
|
||||
"ollama_invalid_address_missing_hostname": "indirizzo non valido: nome host mancante",
|
||||
"ollama_invalid_address_path_not_allowed": "indirizzo non valido: componente percorso non consentito nell'indirizzo semplice",
|
||||
"extension_registry_not_initialized": "registro estensioni non inizializzato",
|
||||
"extension_name_label": "Estensione: %s\n",
|
||||
"extension_status_disabled": " Stato: DISABILITATA - Verifica hash fallita: %v\n",
|
||||
"extension_config_path_label": " Percorso configurazione: %s\n\n",
|
||||
"extension_status_enabled": " Stato: ABILITATA\n",
|
||||
"extension_executable_label": " Eseguibile: %s\n",
|
||||
"extension_type_label": " Tipo: %s\n",
|
||||
"extension_timeout_label": " Timeout: %s\n",
|
||||
"extension_description_label": " Descrizione: %s\n",
|
||||
"extension_version_label": " Versione: %s\n",
|
||||
"extension_operations_label": " Operazioni:\n",
|
||||
"extension_command_template_label": " Modello di comando: %s\n",
|
||||
"extension_file_config_label": " Configurazione file:\n",
|
||||
"extension_invalid_config_path": "percorso di configurazione non valido: %w",
|
||||
"extension_failed_read_config": "impossibile leggere il file di configurazione: %w",
|
||||
"extension_failed_parse_config": "impossibile analizzare il file di configurazione: %w",
|
||||
"extension_failed_register": "impossibile registrare l'estensione: %w",
|
||||
"extension_invalid_timeout": "valore di timeout non valido '%s': deve essere una durata come '30s' o '1m': %w",
|
||||
"extension_registered_success": "Estensione registrata con successo:\n",
|
||||
"extension_name_detail_label": "Nome: %s\n",
|
||||
"extension_failed_remove": "impossibile rimuovere l'estensione: %w",
|
||||
"lmstudio_api_url_question": "Inserisci il tuo URL %v (come promemoria, di solito è %v)",
|
||||
"lmstudio_failed_create_request": "impossibile creare la richiesta: %w",
|
||||
"lmstudio_failed_send_request": "impossibile inviare la richiesta: %w",
|
||||
"lmstudio_unexpected_status_code": "codice di stato imprevisto: %d",
|
||||
"lmstudio_failed_decode_response": "impossibile decodificare la risposta: %w",
|
||||
"lmstudio_failed_marshal_payload": "impossibile serializzare il payload: %w",
|
||||
"lmstudio_error_reading_response": "errore durante la lettura della risposta: %w",
|
||||
"lmstudio_invalid_response_missing_choices": "formato di risposta non valido: scelte mancanti o vuote",
|
||||
"lmstudio_invalid_response_missing_message": "formato di risposta non valido: messaggio mancante nella prima scelta",
|
||||
"lmstudio_invalid_response_missing_content": "formato di risposta non valido: contenuto mancante o non stringa nel messaggio",
|
||||
"lmstudio_invalid_response_missing_text": "formato di risposta non valido: testo mancante o non stringa nella prima scelta",
|
||||
"lmstudio_no_embeddings_returned": "nessun embedding restituito",
|
||||
"extension_warning_load_registry": "Attenzione: impossibile caricare il registro estensioni: %v\n",
|
||||
"extension_name_empty": "il nome dell'estensione non può essere vuoto",
|
||||
"extension_name_contains_spaces": "il nome dell'estensione '%s' contiene spazi - i nomi non devono contenere spazi",
|
||||
"extension_executable_not_found": "eseguibile non trovato: %w",
|
||||
"extension_failed_get_absolute_path": "impossibile ottenere il percorso assoluto: %w",
|
||||
"extension_failed_hash_executable": "impossibile calcolare l'hash dell'eseguibile: %w",
|
||||
"extension_invalid_definition": "definizione estensione non valida: %w",
|
||||
"extension_name_required": "il nome dell'estensione è obbligatorio",
|
||||
"extension_executable_required": "il percorso dell'eseguibile è obbligatorio",
|
||||
"extension_type_required": "il tipo di estensione è obbligatorio",
|
||||
"extension_invalid_timeout_format": "formato timeout non valido: %w",
|
||||
"extension_operation_required": "deve essere definita almeno un'operazione",
|
||||
"extension_cmd_template_required": "il modello di comando è obbligatorio per l'operazione %s",
|
||||
"extension_not_found": "estensione %s non trovata",
|
||||
"extension_config_hash_mismatch": "discrepanza hash del file di configurazione per %s",
|
||||
"extension_failed_verify_executable": "impossibile verificare l'eseguibile: %w",
|
||||
"extension_executable_hash_mismatch": "discrepanza hash dell'eseguibile per %s",
|
||||
"extension_failed_marshal_registry": "impossibile serializzare il registro estensioni: %w",
|
||||
"extension_failed_read_registry": "impossibile leggere il registro estensioni: %w",
|
||||
"extension_failed_parse_registry": "impossibile analizzare il registro estensioni: %w",
|
||||
"extension_failed_get_extension": "impossibile ottenere l'estensione: %w",
|
||||
"extension_failed_format_command": "impossibile formattare il comando: %w",
|
||||
"extension_empty_command": "comando vuoto dopo la formattazione",
|
||||
"extension_operation_not_found": "operazione %s non trovata per l'estensione %s",
|
||||
"extension_executing_command": "Esecuzione comando: %s\n",
|
||||
"extension_execution_failed_stderr": "esecuzione fallita: %w\nstderr: %s",
|
||||
"extension_no_file_config": "nessuna configurazione file trovata",
|
||||
"extension_no_output_file": "nessun file di output specificato nella configurazione",
|
||||
"extension_execution_timed_out": "esecuzione scaduta dopo %v",
|
||||
"extension_execution_failed_err": "esecuzione fallita: %w\nerr: %s",
|
||||
"extension_failed_read_output_file": "impossibile leggere il file di output: %w",
|
||||
"extension_failed_get_output_path": "impossibile ottenere il percorso di output: %w\nerr: %s",
|
||||
"spotify_failed_create_token_request": "impossibile creare la richiesta del token: %w",
|
||||
"spotify_failed_request_access_token": "impossibile richiedere il token di accesso: %w",
|
||||
"spotify_failed_get_access_token": "impossibile ottenere il token di accesso: stato %d, risposta: %s",
|
||||
"spotify_failed_decode_token_response": "impossibile decodificare la risposta del token: %w",
|
||||
"spotify_failed_create_request": "impossibile creare la richiesta: %w",
|
||||
"spotify_failed_execute_request": "impossibile eseguire la richiesta: %w",
|
||||
"spotify_failed_read_response_body": "impossibile leggere il corpo della risposta: %w",
|
||||
"spotify_api_request_failed": "richiesta API fallita: stato %d, risposta: %s",
|
||||
"spotify_failed_parse_show_metadata": "impossibile analizzare i metadati dello show: %w",
|
||||
"spotify_failed_parse_episode_metadata": "impossibile analizzare i metadati dell'episodio: %w",
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
"openai_unexpected_status_code_read_error_partial": "予期しないステータスコード: プロバイダー %s から %d (本文読み取りエラー: %v)、部分的なレスポンス: %s",
|
||||
"openai_unexpected_status_code_read_error": "予期しないステータスコード: プロバイダー %s から %d (レスポンス本文の読み取りに失敗: %v)",
|
||||
"openai_unable_to_parse_models_response": "モデルレスポンスの解析に失敗しました; 生のレスポンス: %s",
|
||||
"openai_warning_model_no_image_generation": "警告: モデル '%s' は画像生成をサポートしていません。サポートされているモデル: %s。画像生成には -m gpt-5.2 の使用を検討してください。\n",
|
||||
"openai_model_no_image_generation": "モデル '%s' は画像生成をサポートしていません。サポートされているモデル: %s",
|
||||
"scraping_not_configured": "スクレイピング機能が設定されていません。スクレイピングを有効にするためにJinaを設定してください",
|
||||
"could_not_determine_home_dir": "ユーザーのホームディレクトリを特定できませんでした: %w",
|
||||
"could_not_stat_env_file": ".envファイルの状態を確認できませんでした: %w",
|
||||
@@ -293,5 +295,120 @@
|
||||
"plugin_question_optional": "%v%v (スキップするには空欄のまま):",
|
||||
"plugin_invalid_boolean_value": "無効なブール値です: %v",
|
||||
"plugin_setting_not_valid": "%v=%v は無効です",
|
||||
"plugin_invalid_bool": "無効な bool です: %q"
|
||||
"plugin_invalid_bool": "無効な bool です: %q",
|
||||
"ollama_num_ctx_must_be_finite": "num_ctx は有限数である必要があります",
|
||||
"ollama_num_ctx_must_be_integer": "num_ctx は整数である必要があります。小数部分を持つ浮動小数点数を受け取りました",
|
||||
"ollama_num_ctx_value_out_of_range": "num_ctx の値が範囲外です",
|
||||
"ollama_num_ctx_must_be_positive": "num_ctx は正の値である必要があります。受け取った値: %d",
|
||||
"ollama_num_ctx_value_too_large": "num_ctx の値が大きすぎます: %d",
|
||||
"ollama_num_ctx_must_be_valid_number": "num_ctx は有効な数値である必要があります",
|
||||
"ollama_num_ctx_must_be_valid_number_got": "num_ctx は有効な数値である必要があります。受け取った値: %s",
|
||||
"ollama_num_ctx_invalid_type": "num_ctx は数値である必要があります。無効な型を受け取りました",
|
||||
"ollama_num_ctx_exceeds_maximum": "num_ctx が許可される最大値 %d を超えています",
|
||||
"ollama_error_reading_body": "ボディの読み取りエラー: %v",
|
||||
"ollama_error_endpoint": "エンドポイントをテスト中",
|
||||
"ollama_error_unmarshalling_body": "ボディのアンマーシャリングエラー: %v",
|
||||
"ollama_invalid_num_ctx_in_request": "リクエストに無効な num_ctx があります: %v",
|
||||
"ollama_warning_parse_variables": "警告: options.variables を JSON として解析できませんでした: %v",
|
||||
"ollama_error_marshalling_body": "ボディのマーシャリングエラー: %v",
|
||||
"ollama_error_building_chat_url": "/chat URL の構築エラー: %v",
|
||||
"ollama_error_creating_chat_request": "/chat リクエストの作成エラー: %v",
|
||||
"ollama_failed_create_request": "リクエストの作成に失敗しました",
|
||||
"ollama_error_getting_chat_body": "/chat ボディの取得エラー: %v",
|
||||
"ollama_upstream_non_2xx_body_unreadable": "アップストリームの Fabric サーバーが非 2xx ステータス %d を返し、ボディを読み取れませんでした: %v",
|
||||
"ollama_upstream_non_2xx": "アップストリームの Fabric サーバーが非 2xx ステータス %d を返しました: %s",
|
||||
"ollama_upstream_returned_status": "アップストリームの Fabric サーバーがステータス %d を返しました",
|
||||
"ollama_error_prefix": "エラー: %s",
|
||||
"ollama_error_parse_upstream_response": "エラー: アップストリームのレスポンスを解析できませんでした",
|
||||
"ollama_failed_unmarshal_fabric_response": "Fabric レスポンスのアンマーシャルに失敗しました",
|
||||
"ollama_error_writing_response": "レスポンスの書き込みエラー: %v",
|
||||
"ollama_error_scanning_body": "ボディのスキャンエラー: %v",
|
||||
"ollama_failed_scan_sse_stream": "SSE レスポンスストリームのスキャンに失敗しました: %v",
|
||||
"ollama_sse_buffer_limit": "SSE 行が 1MB バッファー制限を超えています - データ行が大きすぎます",
|
||||
"ollama_warning_no_content": "警告: アップストリームの Fabric サーバーからコンテンツを受信しませんでした",
|
||||
"ollama_no_content_from_upstream": "アップストリームの Fabric サーバーからコンテンツを受信しませんでした",
|
||||
"ollama_empty_address": "空のアドレス",
|
||||
"ollama_invalid_address": "無効なアドレス: %w",
|
||||
"ollama_invalid_address_missing_host": "無効なアドレス: ホストが不足しています",
|
||||
"ollama_invalid_address_missing_hostname": "無効なアドレス: ホスト名が不足しています",
|
||||
"ollama_invalid_address_path_not_allowed": "無効なアドレス: 単純なアドレスにパスコンポーネントは許可されていません",
|
||||
"extension_registry_not_initialized": "拡張機能レジストリが初期化されていません",
|
||||
"extension_name_label": "拡張機能: %s\n",
|
||||
"extension_status_disabled": " ステータス: 無効 - ハッシュ検証失敗: %v\n",
|
||||
"extension_config_path_label": " 設定パス: %s\n\n",
|
||||
"extension_status_enabled": " ステータス: 有効\n",
|
||||
"extension_executable_label": " 実行ファイル: %s\n",
|
||||
"extension_type_label": " タイプ: %s\n",
|
||||
"extension_timeout_label": " タイムアウト: %s\n",
|
||||
"extension_description_label": " 説明: %s\n",
|
||||
"extension_version_label": " バージョン: %s\n",
|
||||
"extension_operations_label": " 操作:\n",
|
||||
"extension_command_template_label": " コマンドテンプレート: %s\n",
|
||||
"extension_file_config_label": " ファイル設定:\n",
|
||||
"extension_invalid_config_path": "無効な設定パス: %w",
|
||||
"extension_failed_read_config": "設定ファイルの読み込みに失敗しました: %w",
|
||||
"extension_failed_parse_config": "設定ファイルの解析に失敗しました: %w",
|
||||
"extension_failed_register": "拡張機能の登録に失敗しました: %w",
|
||||
"extension_invalid_timeout": "無効なタイムアウト値 '%s': '30s' や '1m' のような期間である必要があります: %w",
|
||||
"extension_registered_success": "拡張機能が正常に登録されました:\n",
|
||||
"extension_name_detail_label": "名前: %s\n",
|
||||
"extension_failed_remove": "拡張機能の削除に失敗しました: %w",
|
||||
"lmstudio_api_url_question": "%v の URL を入力してください(通常は %v です)",
|
||||
"lmstudio_failed_create_request": "リクエストの作成に失敗しました: %w",
|
||||
"lmstudio_failed_send_request": "リクエストの送信に失敗しました: %w",
|
||||
"lmstudio_unexpected_status_code": "予期しないステータスコード: %d",
|
||||
"lmstudio_failed_decode_response": "レスポンスのデコードに失敗しました: %w",
|
||||
"lmstudio_failed_marshal_payload": "ペイロードのシリアル化に失敗しました: %w",
|
||||
"lmstudio_error_reading_response": "レスポンスの読み取りエラー: %w",
|
||||
"lmstudio_invalid_response_missing_choices": "無効なレスポンス形式: 選択肢がないか空です",
|
||||
"lmstudio_invalid_response_missing_message": "無効なレスポンス形式: 最初の選択肢にメッセージがありません",
|
||||
"lmstudio_invalid_response_missing_content": "無効なレスポンス形式: メッセージにコンテンツがないか文字列ではありません",
|
||||
"lmstudio_invalid_response_missing_text": "無効なレスポンス形式: 最初の選択肢にテキストがないか文字列ではありません",
|
||||
"lmstudio_no_embeddings_returned": "埋め込みが返されませんでした",
|
||||
"extension_warning_load_registry": "警告: 拡張機能レジストリを読み込めませんでした: %v\n",
|
||||
"extension_name_empty": "拡張機能名は空にできません",
|
||||
"extension_name_contains_spaces": "拡張機能名 '%s' にスペースが含まれています - 名前にスペースは使用できません",
|
||||
"extension_executable_not_found": "実行ファイルが見つかりません: %w",
|
||||
"extension_failed_get_absolute_path": "絶対パスの取得に失敗しました: %w",
|
||||
"extension_failed_hash_executable": "実行ファイルのハッシュ計算に失敗しました: %w",
|
||||
"extension_invalid_definition": "無効な拡張機能定義: %w",
|
||||
"extension_name_required": "拡張機能名は必須です",
|
||||
"extension_executable_required": "実行ファイルパスは必須です",
|
||||
"extension_type_required": "拡張機能タイプは必須です",
|
||||
"extension_invalid_timeout_format": "無効なタイムアウト形式: %w",
|
||||
"extension_operation_required": "少なくとも1つの操作を定義する必要があります",
|
||||
"extension_cmd_template_required": "操作 %s にはコマンドテンプレートが必要です",
|
||||
"extension_not_found": "拡張機能 %s が見つかりません",
|
||||
"extension_config_hash_mismatch": "%s の設定ファイルのハッシュが一致しません",
|
||||
"extension_failed_verify_executable": "実行ファイルの検証に失敗しました: %w",
|
||||
"extension_executable_hash_mismatch": "%s の実行ファイルのハッシュが一致しません",
|
||||
"extension_failed_marshal_registry": "拡張機能レジストリのシリアル化に失敗しました: %w",
|
||||
"extension_failed_read_registry": "拡張機能レジストリの読み込みに失敗しました: %w",
|
||||
"extension_failed_parse_registry": "拡張機能レジストリの解析に失敗しました: %w",
|
||||
"extension_failed_get_extension": "拡張機能の取得に失敗しました: %w",
|
||||
"extension_failed_format_command": "コマンドのフォーマットに失敗しました: %w",
|
||||
"extension_empty_command": "フォーマット後のコマンドが空です",
|
||||
"extension_operation_not_found": "拡張機能 %s にオペレーション %s が見つかりません",
|
||||
"extension_executing_command": "コマンドを実行中: %s\n",
|
||||
"extension_execution_failed_stderr": "実行に失敗しました: %w\nstderr: %s",
|
||||
"extension_no_file_config": "ファイル設定が見つかりません",
|
||||
"extension_no_output_file": "設定に出力ファイルが指定されていません",
|
||||
"extension_execution_timed_out": "%v 後に実行がタイムアウトしました",
|
||||
"extension_execution_failed_err": "実行に失敗しました: %w\nerr: %s",
|
||||
"extension_failed_read_output_file": "出力ファイルの読み取りに失敗しました: %w",
|
||||
"extension_failed_get_output_path": "出力パスの取得に失敗しました: %w\nerr: %s",
|
||||
"spotify_failed_create_token_request": "トークンリクエストの作成に失敗しました: %w",
|
||||
"spotify_failed_request_access_token": "アクセストークンのリクエストに失敗しました: %w",
|
||||
"spotify_failed_get_access_token": "アクセストークンの取得に失敗しました: ステータス %d、レスポンス: %s",
|
||||
"spotify_failed_decode_token_response": "トークンレスポンスのデコードに失敗しました: %w",
|
||||
"spotify_failed_create_request": "リクエストの作成に失敗しました: %w",
|
||||
"spotify_failed_execute_request": "リクエストの実行に失敗しました: %w",
|
||||
"spotify_failed_read_response_body": "レスポンスボディの読み取りに失敗しました: %w",
|
||||
"spotify_api_request_failed": "APIリクエストが失敗しました: ステータス %d、レスポンス: %s",
|
||||
"spotify_failed_parse_show_metadata": "番組メタデータの解析に失敗しました: %w",
|
||||
"spotify_failed_parse_episode_metadata": "エピソードメタデータの解析に失敗しました: %w",
|
||||
"spotify_search_failed": "検索に失敗しました: %w",
|
||||
"spotify_failed_parse_search_results": "検索結果の解析に失敗しました: %w",
|
||||
"spotify_failed_get_show_episodes": "番組エピソードの取得に失敗しました: %w",
|
||||
"spotify_failed_parse_episodes": "エピソードの解析に失敗しました: %w"
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
"openai_unexpected_status_code_read_error_partial": "código de status inesperado: %d do provedor %s (erro ao ler corpo: %v), resposta parcial: %s",
|
||||
"openai_unexpected_status_code_read_error": "código de status inesperado: %d do provedor %s (falha ao ler corpo da resposta: %v)",
|
||||
"openai_unable_to_parse_models_response": "não foi possível analisar a resposta de modelos; resposta bruta: %s",
|
||||
"openai_warning_model_no_image_generation": "Aviso: O modelo '%s' não suporta geração de imagens. Modelos suportados: %s. Considere usar -m gpt-5.2 para geração de imagens.\n",
|
||||
"openai_model_no_image_generation": "o modelo '%s' não suporta geração de imagens. Modelos suportados: %s",
|
||||
"scraping_not_configured": "funcionalidade de scraping não está configurada. Por favor configure o Jina para ativar o scraping",
|
||||
"could_not_determine_home_dir": "não foi possível determinar o diretório home do usuário: %w",
|
||||
"could_not_stat_env_file": "não foi possível verificar o arquivo .env: %w",
|
||||
@@ -293,5 +295,120 @@
|
||||
"plugin_question_optional": "%v%v (deixe em branco para pular):",
|
||||
"plugin_invalid_boolean_value": "valor booleano inválido: %v",
|
||||
"plugin_setting_not_valid": "%v=%v não é válido",
|
||||
"plugin_invalid_bool": "bool inválido: %q"
|
||||
"plugin_invalid_bool": "bool inválido: %q",
|
||||
"ollama_num_ctx_must_be_finite": "num_ctx deve ser um número finito",
|
||||
"ollama_num_ctx_must_be_integer": "num_ctx deve ser um inteiro, recebeu float com parte fracionária",
|
||||
"ollama_num_ctx_value_out_of_range": "valor num_ctx fora do intervalo",
|
||||
"ollama_num_ctx_must_be_positive": "num_ctx deve ser positivo, recebeu: %d",
|
||||
"ollama_num_ctx_value_too_large": "valor num_ctx muito grande: %d",
|
||||
"ollama_num_ctx_must_be_valid_number": "num_ctx deve ser um número válido",
|
||||
"ollama_num_ctx_must_be_valid_number_got": "num_ctx deve ser um número válido, recebeu: %s",
|
||||
"ollama_num_ctx_invalid_type": "num_ctx deve ser um número, recebeu tipo inválido",
|
||||
"ollama_num_ctx_exceeds_maximum": "num_ctx excede o valor máximo permitido de %d",
|
||||
"ollama_error_reading_body": "Erro ao ler o corpo: %v",
|
||||
"ollama_error_endpoint": "testando endpoint",
|
||||
"ollama_error_unmarshalling_body": "Erro ao desserializar o corpo: %v",
|
||||
"ollama_invalid_num_ctx_in_request": "num_ctx inválido na requisição: %v",
|
||||
"ollama_warning_parse_variables": "Aviso: falha ao analisar options.variables como JSON: %v",
|
||||
"ollama_error_marshalling_body": "Erro ao serializar o corpo: %v",
|
||||
"ollama_error_building_chat_url": "Erro ao construir a URL /chat: %v",
|
||||
"ollama_error_creating_chat_request": "Erro ao criar a requisição /chat: %v",
|
||||
"ollama_failed_create_request": "falha ao criar a requisição",
|
||||
"ollama_error_getting_chat_body": "Erro ao obter o corpo /chat: %v",
|
||||
"ollama_upstream_non_2xx_body_unreadable": "Servidor Fabric upstream retornou status não-2xx %d e o corpo não pôde ser lido: %v",
|
||||
"ollama_upstream_non_2xx": "Servidor Fabric upstream retornou status não-2xx %d: %s",
|
||||
"ollama_upstream_returned_status": "servidor Fabric upstream retornou status %d",
|
||||
"ollama_error_prefix": "Erro: %s",
|
||||
"ollama_error_parse_upstream_response": "Erro: falha ao analisar resposta upstream",
|
||||
"ollama_failed_unmarshal_fabric_response": "falha ao desserializar resposta Fabric",
|
||||
"ollama_error_writing_response": "Erro ao escrever resposta: %v",
|
||||
"ollama_error_scanning_body": "Erro ao escanear o corpo: %v",
|
||||
"ollama_failed_scan_sse_stream": "falha ao escanear fluxo de resposta SSE: %v",
|
||||
"ollama_sse_buffer_limit": "Linha SSE excede limite de buffer de 1MB - linha de dados muito grande",
|
||||
"ollama_warning_no_content": "Aviso: nenhum conteúdo recebido do servidor Fabric upstream",
|
||||
"ollama_no_content_from_upstream": "nenhum conteúdo recebido do servidor Fabric upstream",
|
||||
"ollama_empty_address": "endereço vazio",
|
||||
"ollama_invalid_address": "endereço inválido: %w",
|
||||
"ollama_invalid_address_missing_host": "endereço inválido: host ausente",
|
||||
"ollama_invalid_address_missing_hostname": "endereço inválido: nome do host ausente",
|
||||
"ollama_invalid_address_path_not_allowed": "endereço inválido: componente de caminho não permitido em endereço simples",
|
||||
"extension_registry_not_initialized": "registro de extensões não inicializado",
|
||||
"extension_name_label": "Extensão: %s\n",
|
||||
"extension_status_disabled": " Status: DESABILITADA - Verificação de hash falhou: %v\n",
|
||||
"extension_config_path_label": " Caminho de configuração: %s\n\n",
|
||||
"extension_status_enabled": " Status: HABILITADA\n",
|
||||
"extension_executable_label": " Executável: %s\n",
|
||||
"extension_type_label": " Tipo: %s\n",
|
||||
"extension_timeout_label": " Tempo limite: %s\n",
|
||||
"extension_description_label": " Descrição: %s\n",
|
||||
"extension_version_label": " Versão: %s\n",
|
||||
"extension_operations_label": " Operações:\n",
|
||||
"extension_command_template_label": " Modelo de comando: %s\n",
|
||||
"extension_file_config_label": " Configuração de arquivo:\n",
|
||||
"extension_invalid_config_path": "caminho de configuração inválido: %w",
|
||||
"extension_failed_read_config": "falha ao ler o arquivo de configuração: %w",
|
||||
"extension_failed_parse_config": "falha ao analisar o arquivo de configuração: %w",
|
||||
"extension_failed_register": "falha ao registrar a extensão: %w",
|
||||
"extension_invalid_timeout": "valor de tempo limite inválido '%s': deve ser uma duração como '30s' ou '1m': %w",
|
||||
"extension_registered_success": "Extensão registrada com sucesso:\n",
|
||||
"extension_name_detail_label": "Nome: %s\n",
|
||||
"extension_failed_remove": "falha ao remover a extensão: %w",
|
||||
"lmstudio_api_url_question": "Digite sua URL %v (como lembrete, geralmente é %v)",
|
||||
"lmstudio_failed_create_request": "falha ao criar a requisição: %w",
|
||||
"lmstudio_failed_send_request": "falha ao enviar a requisição: %w",
|
||||
"lmstudio_unexpected_status_code": "código de status inesperado: %d",
|
||||
"lmstudio_failed_decode_response": "falha ao decodificar a resposta: %w",
|
||||
"lmstudio_failed_marshal_payload": "falha ao serializar o payload: %w",
|
||||
"lmstudio_error_reading_response": "erro ao ler a resposta: %w",
|
||||
"lmstudio_invalid_response_missing_choices": "formato de resposta inválido: escolhas ausentes ou vazias",
|
||||
"lmstudio_invalid_response_missing_message": "formato de resposta inválido: mensagem ausente na primeira escolha",
|
||||
"lmstudio_invalid_response_missing_content": "formato de resposta inválido: conteúdo ausente ou não é uma string na mensagem",
|
||||
"lmstudio_invalid_response_missing_text": "formato de resposta inválido: texto ausente ou não é uma string na primeira escolha",
|
||||
"lmstudio_no_embeddings_returned": "nenhum embedding retornado",
|
||||
"extension_warning_load_registry": "Aviso: não foi possível carregar o registro de extensões: %v\n",
|
||||
"extension_name_empty": "o nome da extensão não pode estar vazio",
|
||||
"extension_name_contains_spaces": "o nome da extensão '%s' contém espaços - nomes não devem conter espaços",
|
||||
"extension_executable_not_found": "executável não encontrado: %w",
|
||||
"extension_failed_get_absolute_path": "falha ao obter o caminho absoluto: %w",
|
||||
"extension_failed_hash_executable": "falha ao calcular o hash do executável: %w",
|
||||
"extension_invalid_definition": "definição de extensão inválida: %w",
|
||||
"extension_name_required": "o nome da extensão é obrigatório",
|
||||
"extension_executable_required": "o caminho do executável é obrigatório",
|
||||
"extension_type_required": "o tipo da extensão é obrigatório",
|
||||
"extension_invalid_timeout_format": "formato de tempo limite inválido: %w",
|
||||
"extension_operation_required": "pelo menos uma operação deve ser definida",
|
||||
"extension_cmd_template_required": "o modelo de comando é obrigatório para a operação %s",
|
||||
"extension_not_found": "extensão %s não encontrada",
|
||||
"extension_config_hash_mismatch": "discrepância de hash do arquivo de configuração para %s",
|
||||
"extension_failed_verify_executable": "falha ao verificar o executável: %w",
|
||||
"extension_executable_hash_mismatch": "discrepância de hash do executável para %s",
|
||||
"extension_failed_marshal_registry": "falha ao serializar o registro de extensões: %w",
|
||||
"extension_failed_read_registry": "falha ao ler o registro de extensões: %w",
|
||||
"extension_failed_parse_registry": "falha ao analisar o registro de extensões: %w",
|
||||
"extension_failed_get_extension": "falha ao obter a extensão: %w",
|
||||
"extension_failed_format_command": "falha ao formatar o comando: %w",
|
||||
"extension_empty_command": "comando vazio após a formatação",
|
||||
"extension_operation_not_found": "operação %s não encontrada para a extensão %s",
|
||||
"extension_executing_command": "Executando comando: %s\n",
|
||||
"extension_execution_failed_stderr": "execução falhou: %w\nstderr: %s",
|
||||
"extension_no_file_config": "nenhuma configuração de arquivo encontrada",
|
||||
"extension_no_output_file": "nenhum arquivo de saída especificado na configuração",
|
||||
"extension_execution_timed_out": "execução expirou após %v",
|
||||
"extension_execution_failed_err": "execução falhou: %w\nerr: %s",
|
||||
"extension_failed_read_output_file": "falha ao ler o arquivo de saída: %w",
|
||||
"extension_failed_get_output_path": "falha ao obter o caminho de saída: %w\nerr: %s",
|
||||
"spotify_failed_create_token_request": "falha ao criar a solicitação de token: %w",
|
||||
"spotify_failed_request_access_token": "falha ao solicitar o token de acesso: %w",
|
||||
"spotify_failed_get_access_token": "falha ao obter o token de acesso: status %d, resposta: %s",
|
||||
"spotify_failed_decode_token_response": "falha ao decodificar a resposta do token: %w",
|
||||
"spotify_failed_create_request": "falha ao criar a solicitação: %w",
|
||||
"spotify_failed_execute_request": "falha ao executar a solicitação: %w",
|
||||
"spotify_failed_read_response_body": "falha ao ler o corpo da resposta: %w",
|
||||
"spotify_api_request_failed": "a solicitação da API falhou: status %d, resposta: %s",
|
||||
"spotify_failed_parse_show_metadata": "falha ao analisar os metadados do programa: %w",
|
||||
"spotify_failed_parse_episode_metadata": "falha ao analisar os metadados do episódio: %w",
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
"openai_unexpected_status_code_read_error_partial": "código de estado inesperado: %d do fornecedor %s (erro ao ler corpo: %v), resposta parcial: %s",
|
||||
"openai_unexpected_status_code_read_error": "código de estado inesperado: %d do fornecedor %s (falha ao ler corpo da resposta: %v)",
|
||||
"openai_unable_to_parse_models_response": "não foi possível analisar a resposta de modelos; resposta bruta: %s",
|
||||
"openai_warning_model_no_image_generation": "Aviso: O modelo '%s' não suporta geração de imagens. Modelos suportados: %s. Considere usar -m gpt-5.2 para geração de imagens.\n",
|
||||
"openai_model_no_image_generation": "o modelo '%s' não suporta geração de imagens. Modelos suportados: %s",
|
||||
"scraping_not_configured": "funcionalidade de scraping não está configurada. Por favor configure o Jina para ativar o scraping",
|
||||
"could_not_determine_home_dir": "não foi possível determinar o diretório home do utilizador: %w",
|
||||
"could_not_stat_env_file": "não foi possível verificar o ficheiro .env: %w",
|
||||
@@ -293,5 +295,120 @@
|
||||
"plugin_question_optional": "%v%v (deixe em branco para ignorar):",
|
||||
"plugin_invalid_boolean_value": "valor booleano inválido: %v",
|
||||
"plugin_setting_not_valid": "%v=%v não é válido",
|
||||
"plugin_invalid_bool": "bool inválido: %q"
|
||||
"plugin_invalid_bool": "bool inválido: %q",
|
||||
"ollama_num_ctx_must_be_finite": "num_ctx deve ser um número finito",
|
||||
"ollama_num_ctx_must_be_integer": "num_ctx deve ser um inteiro, recebeu float com parte fracionária",
|
||||
"ollama_num_ctx_value_out_of_range": "valor num_ctx fora do intervalo",
|
||||
"ollama_num_ctx_must_be_positive": "num_ctx deve ser positivo, recebeu: %d",
|
||||
"ollama_num_ctx_value_too_large": "valor num_ctx demasiado grande: %d",
|
||||
"ollama_num_ctx_must_be_valid_number": "num_ctx deve ser um número válido",
|
||||
"ollama_num_ctx_must_be_valid_number_got": "num_ctx deve ser um número válido, recebeu: %s",
|
||||
"ollama_num_ctx_invalid_type": "num_ctx deve ser um número, recebeu tipo inválido",
|
||||
"ollama_num_ctx_exceeds_maximum": "num_ctx excede o valor máximo permitido de %d",
|
||||
"ollama_error_reading_body": "Erro ao ler o corpo: %v",
|
||||
"ollama_error_endpoint": "a testar endpoint",
|
||||
"ollama_error_unmarshalling_body": "Erro ao desserializar o corpo: %v",
|
||||
"ollama_invalid_num_ctx_in_request": "num_ctx inválido no pedido: %v",
|
||||
"ollama_warning_parse_variables": "Aviso: falha ao analisar options.variables como JSON: %v",
|
||||
"ollama_error_marshalling_body": "Erro ao serializar o corpo: %v",
|
||||
"ollama_error_building_chat_url": "Erro ao construir a URL /chat: %v",
|
||||
"ollama_error_creating_chat_request": "Erro ao criar o pedido /chat: %v",
|
||||
"ollama_failed_create_request": "falha ao criar o pedido",
|
||||
"ollama_error_getting_chat_body": "Erro ao obter o corpo /chat: %v",
|
||||
"ollama_upstream_non_2xx_body_unreadable": "Servidor Fabric upstream retornou estado não-2xx %d e o corpo não pôde ser lido: %v",
|
||||
"ollama_upstream_non_2xx": "Servidor Fabric upstream retornou estado não-2xx %d: %s",
|
||||
"ollama_upstream_returned_status": "servidor Fabric upstream retornou estado %d",
|
||||
"ollama_error_prefix": "Erro: %s",
|
||||
"ollama_error_parse_upstream_response": "Erro: falha ao analisar resposta upstream",
|
||||
"ollama_failed_unmarshal_fabric_response": "falha ao desserializar resposta Fabric",
|
||||
"ollama_error_writing_response": "Erro ao escrever resposta: %v",
|
||||
"ollama_error_scanning_body": "Erro ao analisar o corpo: %v",
|
||||
"ollama_failed_scan_sse_stream": "falha ao analisar fluxo de resposta SSE: %v",
|
||||
"ollama_sse_buffer_limit": "Linha SSE excede limite de buffer de 1MB - linha de dados demasiado grande",
|
||||
"ollama_warning_no_content": "Aviso: nenhum conteúdo recebido do servidor Fabric upstream",
|
||||
"ollama_no_content_from_upstream": "nenhum conteúdo recebido do servidor Fabric upstream",
|
||||
"ollama_empty_address": "endereço vazio",
|
||||
"ollama_invalid_address": "endereço inválido: %w",
|
||||
"ollama_invalid_address_missing_host": "endereço inválido: host ausente",
|
||||
"ollama_invalid_address_missing_hostname": "endereço inválido: nome do host ausente",
|
||||
"ollama_invalid_address_path_not_allowed": "endereço inválido: componente de caminho não permitido em endereço simples",
|
||||
"extension_registry_not_initialized": "registo de extensões não inicializado",
|
||||
"extension_name_label": "Extensão: %s\n",
|
||||
"extension_status_disabled": " Estado: DESATIVADA - Verificação de hash falhou: %v\n",
|
||||
"extension_config_path_label": " Caminho de configuração: %s\n\n",
|
||||
"extension_status_enabled": " Estado: ATIVADA\n",
|
||||
"extension_executable_label": " Executável: %s\n",
|
||||
"extension_type_label": " Tipo: %s\n",
|
||||
"extension_timeout_label": " Tempo limite: %s\n",
|
||||
"extension_description_label": " Descrição: %s\n",
|
||||
"extension_version_label": " Versão: %s\n",
|
||||
"extension_operations_label": " Operações:\n",
|
||||
"extension_command_template_label": " Modelo de comando: %s\n",
|
||||
"extension_file_config_label": " Configuração de ficheiro:\n",
|
||||
"extension_invalid_config_path": "caminho de configuração inválido: %w",
|
||||
"extension_failed_read_config": "falha ao ler o ficheiro de configuração: %w",
|
||||
"extension_failed_parse_config": "falha ao analisar o ficheiro de configuração: %w",
|
||||
"extension_failed_register": "falha ao registar a extensão: %w",
|
||||
"extension_invalid_timeout": "valor de tempo limite inválido '%s': deve ser uma duração como '30s' ou '1m': %w",
|
||||
"extension_registered_success": "Extensão registada com sucesso:\n",
|
||||
"extension_name_detail_label": "Nome: %s\n",
|
||||
"extension_failed_remove": "falha ao remover a extensão: %w",
|
||||
"lmstudio_api_url_question": "Introduza o seu URL %v (como lembrete, geralmente é %v)",
|
||||
"lmstudio_failed_create_request": "falha ao criar o pedido: %w",
|
||||
"lmstudio_failed_send_request": "falha ao enviar o pedido: %w",
|
||||
"lmstudio_unexpected_status_code": "código de estado inesperado: %d",
|
||||
"lmstudio_failed_decode_response": "falha ao descodificar a resposta: %w",
|
||||
"lmstudio_failed_marshal_payload": "falha ao serializar os dados: %w",
|
||||
"lmstudio_error_reading_response": "erro ao ler a resposta: %w",
|
||||
"lmstudio_invalid_response_missing_choices": "formato de resposta inválido: escolhas ausentes ou vazias",
|
||||
"lmstudio_invalid_response_missing_message": "formato de resposta inválido: mensagem ausente na primeira escolha",
|
||||
"lmstudio_invalid_response_missing_content": "formato de resposta inválido: conteúdo ausente ou não é uma string na mensagem",
|
||||
"lmstudio_invalid_response_missing_text": "formato de resposta inválido: texto ausente ou não é uma string na primeira escolha",
|
||||
"lmstudio_no_embeddings_returned": "nenhum embedding retornado",
|
||||
"extension_warning_load_registry": "Aviso: não foi possível carregar o registo de extensões: %v\n",
|
||||
"extension_name_empty": "o nome da extensão não pode estar vazio",
|
||||
"extension_name_contains_spaces": "o nome da extensão '%s' contém espaços - os nomes não devem conter espaços",
|
||||
"extension_executable_not_found": "executável não encontrado: %w",
|
||||
"extension_failed_get_absolute_path": "falha ao obter o caminho absoluto: %w",
|
||||
"extension_failed_hash_executable": "falha ao calcular o hash do executável: %w",
|
||||
"extension_invalid_definition": "definição de extensão inválida: %w",
|
||||
"extension_name_required": "o nome da extensão é obrigatório",
|
||||
"extension_executable_required": "o caminho do executável é obrigatório",
|
||||
"extension_type_required": "o tipo da extensão é obrigatório",
|
||||
"extension_invalid_timeout_format": "formato de tempo limite inválido: %w",
|
||||
"extension_operation_required": "deve ser definida pelo menos uma operação",
|
||||
"extension_cmd_template_required": "o modelo de comando é obrigatório para a operação %s",
|
||||
"extension_not_found": "extensão %s não encontrada",
|
||||
"extension_config_hash_mismatch": "discrepância de hash do ficheiro de configuração para %s",
|
||||
"extension_failed_verify_executable": "falha ao verificar o executável: %w",
|
||||
"extension_executable_hash_mismatch": "discrepância de hash do executável para %s",
|
||||
"extension_failed_marshal_registry": "falha ao serializar o registo de extensões: %w",
|
||||
"extension_failed_read_registry": "falha ao ler o registo de extensões: %w",
|
||||
"extension_failed_parse_registry": "falha ao analisar o registo de extensões: %w",
|
||||
"extension_failed_get_extension": "falha ao obter a extensão: %w",
|
||||
"extension_failed_format_command": "falha ao formatar o comando: %w",
|
||||
"extension_empty_command": "comando vazio após a formatação",
|
||||
"extension_operation_not_found": "operação %s não encontrada para a extensão %s",
|
||||
"extension_executing_command": "A executar comando: %s\n",
|
||||
"extension_execution_failed_stderr": "execução falhou: %w\nstderr: %s",
|
||||
"extension_no_file_config": "nenhuma configuração de ficheiro encontrada",
|
||||
"extension_no_output_file": "nenhum ficheiro de saída especificado na configuração",
|
||||
"extension_execution_timed_out": "execução expirou após %v",
|
||||
"extension_execution_failed_err": "execução falhou: %w\nerr: %s",
|
||||
"extension_failed_read_output_file": "falha ao ler o ficheiro de saída: %w",
|
||||
"extension_failed_get_output_path": "falha ao obter o caminho de saída: %w\nerr: %s",
|
||||
"spotify_failed_create_token_request": "falha ao criar o pedido de token: %w",
|
||||
"spotify_failed_request_access_token": "falha ao solicitar o token de acesso: %w",
|
||||
"spotify_failed_get_access_token": "falha ao obter o token de acesso: estado %d, resposta: %s",
|
||||
"spotify_failed_decode_token_response": "falha ao descodificar a resposta do token: %w",
|
||||
"spotify_failed_create_request": "falha ao criar o pedido: %w",
|
||||
"spotify_failed_execute_request": "falha ao executar o pedido: %w",
|
||||
"spotify_failed_read_response_body": "falha ao ler o corpo da resposta: %w",
|
||||
"spotify_api_request_failed": "o pedido à API falhou: estado %d, resposta: %s",
|
||||
"spotify_failed_parse_show_metadata": "falha ao analisar os metadados do programa: %w",
|
||||
"spotify_failed_parse_episode_metadata": "falha ao analisar os metadados do episódio: %w",
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
"openai_unexpected_status_code_read_error_partial": "意外的状态码:来自提供商 %s 的 %d(读取主体错误:%v),部分响应:%s",
|
||||
"openai_unexpected_status_code_read_error": "意外的状态码:来自提供商 %s 的 %d(读取响应主体失败:%v)",
|
||||
"openai_unable_to_parse_models_response": "无法解析模型响应;原始响应:%s",
|
||||
"openai_warning_model_no_image_generation": "警告:模型 '%s' 不支持图像生成。支持的模型:%s。请考虑使用 -m gpt-5.2 进行图像生成。\n",
|
||||
"openai_model_no_image_generation": "模型 '%s' 不支持图像生成。支持的模型:%s",
|
||||
"scraping_not_configured": "抓取功能未配置。请设置 Jina 以启用抓取功能",
|
||||
"could_not_determine_home_dir": "无法确定用户主目录: %w",
|
||||
"could_not_stat_env_file": "无法获取 .env 文件状态: %w",
|
||||
@@ -293,5 +295,120 @@
|
||||
"plugin_question_optional": "%v%v(留空以跳过):",
|
||||
"plugin_invalid_boolean_value": "无效的布尔值:%v",
|
||||
"plugin_setting_not_valid": "%v=%v 无效",
|
||||
"plugin_invalid_bool": "无效的 bool:%q"
|
||||
"plugin_invalid_bool": "无效的 bool:%q",
|
||||
"ollama_num_ctx_must_be_finite": "num_ctx 必须是有限数",
|
||||
"ollama_num_ctx_must_be_integer": "num_ctx 必须是整数,收到带小数部分的浮点数",
|
||||
"ollama_num_ctx_value_out_of_range": "num_ctx 值超出范围",
|
||||
"ollama_num_ctx_must_be_positive": "num_ctx 必须为正数,收到:%d",
|
||||
"ollama_num_ctx_value_too_large": "num_ctx 值过大:%d",
|
||||
"ollama_num_ctx_must_be_valid_number": "num_ctx 必须是有效的数字",
|
||||
"ollama_num_ctx_must_be_valid_number_got": "num_ctx 必须是有效的数字,收到:%s",
|
||||
"ollama_num_ctx_invalid_type": "num_ctx 必须是数字,收到无效类型",
|
||||
"ollama_num_ctx_exceeds_maximum": "num_ctx 超过允许的最大值 %d",
|
||||
"ollama_error_reading_body": "读取正文时出错:%v",
|
||||
"ollama_error_endpoint": "正在测试端点",
|
||||
"ollama_error_unmarshalling_body": "解析正文时出错:%v",
|
||||
"ollama_invalid_num_ctx_in_request": "请求中的 num_ctx 无效:%v",
|
||||
"ollama_warning_parse_variables": "警告:无法将 options.variables 解析为 JSON:%v",
|
||||
"ollama_error_marshalling_body": "序列化正文时出错:%v",
|
||||
"ollama_error_building_chat_url": "构建 /chat URL 时出错:%v",
|
||||
"ollama_error_creating_chat_request": "创建 /chat 请求时出错:%v",
|
||||
"ollama_failed_create_request": "创建请求失败",
|
||||
"ollama_error_getting_chat_body": "获取 /chat 正文时出错:%v",
|
||||
"ollama_upstream_non_2xx_body_unreadable": "上游 Fabric 服务器返回非 2xx 状态 %d 且无法读取正文:%v",
|
||||
"ollama_upstream_non_2xx": "上游 Fabric 服务器返回非 2xx 状态 %d:%s",
|
||||
"ollama_upstream_returned_status": "上游 Fabric 服务器返回状态 %d",
|
||||
"ollama_error_prefix": "错误:%s",
|
||||
"ollama_error_parse_upstream_response": "错误:无法解析上游响应",
|
||||
"ollama_failed_unmarshal_fabric_response": "解析 Fabric 响应失败",
|
||||
"ollama_error_writing_response": "写入响应时出错:%v",
|
||||
"ollama_error_scanning_body": "扫描正文时出错:%v",
|
||||
"ollama_failed_scan_sse_stream": "扫描 SSE 响应流失败:%v",
|
||||
"ollama_sse_buffer_limit": "SSE 行超过 1MB 缓冲区限制 - 数据行过大",
|
||||
"ollama_warning_no_content": "警告:未从上游 Fabric 服务器收到内容",
|
||||
"ollama_no_content_from_upstream": "未从上游 Fabric 服务器收到内容",
|
||||
"ollama_empty_address": "地址为空",
|
||||
"ollama_invalid_address": "无效地址:%w",
|
||||
"ollama_invalid_address_missing_host": "无效地址:缺少主机",
|
||||
"ollama_invalid_address_missing_hostname": "无效地址:缺少主机名",
|
||||
"ollama_invalid_address_path_not_allowed": "无效地址:简单地址中不允许路径组件",
|
||||
"extension_registry_not_initialized": "扩展注册表未初始化",
|
||||
"extension_name_label": "扩展:%s\n",
|
||||
"extension_status_disabled": " 状态:已禁用 - 哈希验证失败:%v\n",
|
||||
"extension_config_path_label": " 配置路径:%s\n\n",
|
||||
"extension_status_enabled": " 状态:已启用\n",
|
||||
"extension_executable_label": " 可执行文件:%s\n",
|
||||
"extension_type_label": " 类型:%s\n",
|
||||
"extension_timeout_label": " 超时:%s\n",
|
||||
"extension_description_label": " 描述:%s\n",
|
||||
"extension_version_label": " 版本:%s\n",
|
||||
"extension_operations_label": " 操作:\n",
|
||||
"extension_command_template_label": " 命令模板:%s\n",
|
||||
"extension_file_config_label": " 文件配置:\n",
|
||||
"extension_invalid_config_path": "无效的配置路径:%w",
|
||||
"extension_failed_read_config": "读取配置文件失败:%w",
|
||||
"extension_failed_parse_config": "解析配置文件失败:%w",
|
||||
"extension_failed_register": "注册扩展失败:%w",
|
||||
"extension_invalid_timeout": "无效的超时值 '%s':必须是 '30s' 或 '1m' 等时间格式:%w",
|
||||
"extension_registered_success": "扩展注册成功:\n",
|
||||
"extension_name_detail_label": "名称:%s\n",
|
||||
"extension_failed_remove": "删除扩展失败:%w",
|
||||
"lmstudio_api_url_question": "请输入您的 %v URL(提醒一下,通常是 %v)",
|
||||
"lmstudio_failed_create_request": "创建请求失败:%w",
|
||||
"lmstudio_failed_send_request": "发送请求失败:%w",
|
||||
"lmstudio_unexpected_status_code": "意外的状态码:%d",
|
||||
"lmstudio_failed_decode_response": "解码响应失败:%w",
|
||||
"lmstudio_failed_marshal_payload": "序列化负载失败:%w",
|
||||
"lmstudio_error_reading_response": "读取响应时出错:%w",
|
||||
"lmstudio_invalid_response_missing_choices": "无效的响应格式:选项缺失或为空",
|
||||
"lmstudio_invalid_response_missing_message": "无效的响应格式:第一个选项中缺少消息",
|
||||
"lmstudio_invalid_response_missing_content": "无效的响应格式:消息中的内容缺失或不是字符串",
|
||||
"lmstudio_invalid_response_missing_text": "无效的响应格式:第一个选项中的文本缺失或不是字符串",
|
||||
"lmstudio_no_embeddings_returned": "未返回嵌入向量",
|
||||
"extension_warning_load_registry": "警告:无法加载扩展注册表:%v\n",
|
||||
"extension_name_empty": "扩展名称不能为空",
|
||||
"extension_name_contains_spaces": "扩展名称 '%s' 包含空格 - 名称不能包含空格",
|
||||
"extension_executable_not_found": "未找到可执行文件:%w",
|
||||
"extension_failed_get_absolute_path": "获取绝对路径失败:%w",
|
||||
"extension_failed_hash_executable": "计算可执行文件哈希失败:%w",
|
||||
"extension_invalid_definition": "无效的扩展定义:%w",
|
||||
"extension_name_required": "扩展名称为必填项",
|
||||
"extension_executable_required": "可执行文件路径为必填项",
|
||||
"extension_type_required": "扩展类型为必填项",
|
||||
"extension_invalid_timeout_format": "无效的超时格式:%w",
|
||||
"extension_operation_required": "必须定义至少一个操作",
|
||||
"extension_cmd_template_required": "操作 %s 需要命令模板",
|
||||
"extension_not_found": "未找到扩展 %s",
|
||||
"extension_config_hash_mismatch": "%s 的配置文件哈希不匹配",
|
||||
"extension_failed_verify_executable": "验证可执行文件失败:%w",
|
||||
"extension_executable_hash_mismatch": "%s 的可执行文件哈希不匹配",
|
||||
"extension_failed_marshal_registry": "序列化扩展注册表失败:%w",
|
||||
"extension_failed_read_registry": "读取扩展注册表失败:%w",
|
||||
"extension_failed_parse_registry": "解析扩展注册表失败:%w",
|
||||
"extension_failed_get_extension": "获取扩展失败:%w",
|
||||
"extension_failed_format_command": "格式化命令失败:%w",
|
||||
"extension_empty_command": "格式化后命令为空",
|
||||
"extension_operation_not_found": "扩展 %s 中未找到操作 %s",
|
||||
"extension_executing_command": "正在执行命令:%s\n",
|
||||
"extension_execution_failed_stderr": "执行失败:%w\nstderr:%s",
|
||||
"extension_no_file_config": "未找到文件配置",
|
||||
"extension_no_output_file": "配置中未指定输出文件",
|
||||
"extension_execution_timed_out": "执行在 %v 后超时",
|
||||
"extension_execution_failed_err": "执行失败:%w\nerr:%s",
|
||||
"extension_failed_read_output_file": "读取输出文件失败:%w",
|
||||
"extension_failed_get_output_path": "获取输出路径失败:%w\nerr:%s",
|
||||
"spotify_failed_create_token_request": "创建令牌请求失败:%w",
|
||||
"spotify_failed_request_access_token": "请求访问令牌失败:%w",
|
||||
"spotify_failed_get_access_token": "获取访问令牌失败:状态 %d,响应:%s",
|
||||
"spotify_failed_decode_token_response": "解码令牌响应失败:%w",
|
||||
"spotify_failed_create_request": "创建请求失败:%w",
|
||||
"spotify_failed_execute_request": "执行请求失败:%w",
|
||||
"spotify_failed_read_response_body": "读取响应正文失败:%w",
|
||||
"spotify_api_request_failed": "API 请求失败:状态 %d,响应:%s",
|
||||
"spotify_failed_parse_show_metadata": "解析节目元数据失败:%w",
|
||||
"spotify_failed_parse_episode_metadata": "解析剧集元数据失败:%w",
|
||||
"spotify_search_failed": "搜索失败:%w",
|
||||
"spotify_failed_parse_search_results": "解析搜索结果失败:%w",
|
||||
"spotify_failed_get_show_episodes": "获取节目剧集失败:%w",
|
||||
"spotify_failed_parse_episodes": "解析剧集失败:%w"
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/danielmiessler/fabric/internal/chat"
|
||||
|
||||
"github.com/danielmiessler/fabric/internal/domain"
|
||||
"github.com/danielmiessler/fabric/internal/i18n"
|
||||
"github.com/danielmiessler/fabric/internal/plugins"
|
||||
)
|
||||
|
||||
@@ -29,7 +30,7 @@ func NewClientCompatible(vendorName string, defaultBaseUrl string, configureCust
|
||||
}
|
||||
ret.PluginBase = plugins.NewVendorPluginBase(vendorName, configureCustom)
|
||||
ret.ApiUrl = ret.AddSetupQuestionCustom("API URL", true,
|
||||
fmt.Sprintf("Enter your %v URL (as a reminder, it is usually %v')", vendorName, defaultBaseUrl))
|
||||
fmt.Sprintf(i18n.T("lmstudio_api_url_question"), vendorName, defaultBaseUrl))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -52,17 +53,17 @@ func (c *Client) ListModels() ([]string, error) {
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||
return nil, fmt.Errorf(i18n.T("lmstudio_failed_create_request"), err)
|
||||
}
|
||||
|
||||
resp, err := c.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to send request: %w", err)
|
||||
return nil, fmt.Errorf(i18n.T("lmstudio_failed_send_request"), err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||
return nil, fmt.Errorf(i18n.T("lmstudio_unexpected_status_code"), resp.StatusCode)
|
||||
}
|
||||
|
||||
var result struct {
|
||||
@@ -72,7 +73,7 @@ func (c *Client) ListModels() ([]string, error) {
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode response: %w", err)
|
||||
return nil, fmt.Errorf(i18n.T("lmstudio_failed_decode_response"), err)
|
||||
}
|
||||
|
||||
models := make([]string, len(result.Data))
|
||||
@@ -97,13 +98,13 @@ func (c *Client) SendStream(msgs []*chat.ChatCompletionMessage, opts *domain.Cha
|
||||
|
||||
var jsonPayload []byte
|
||||
if jsonPayload, err = json.Marshal(payload); err != nil {
|
||||
err = fmt.Errorf("failed to marshal payload: %w", err)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_failed_marshal_payload"), err)
|
||||
return
|
||||
}
|
||||
|
||||
var req *http.Request
|
||||
if req, err = http.NewRequest("POST", url, bytes.NewBuffer(jsonPayload)); err != nil {
|
||||
err = fmt.Errorf("failed to create request: %w", err)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_failed_create_request"), err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -111,13 +112,13 @@ func (c *Client) SendStream(msgs []*chat.ChatCompletionMessage, opts *domain.Cha
|
||||
|
||||
var resp *http.Response
|
||||
if resp, err = c.HttpClient.Do(req); err != nil {
|
||||
err = fmt.Errorf("failed to send request: %w", err)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_failed_send_request"), err)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
err = fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_unexpected_status_code"), resp.StatusCode)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -131,7 +132,7 @@ func (c *Client) SendStream(msgs []*chat.ChatCompletionMessage, opts *domain.Cha
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
err = fmt.Errorf("error reading response: %w", err)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_error_reading_response"), err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -204,13 +205,13 @@ func (c *Client) Send(ctx context.Context, msgs []*chat.ChatCompletionMessage, o
|
||||
|
||||
var jsonPayload []byte
|
||||
if jsonPayload, err = json.Marshal(payload); err != nil {
|
||||
err = fmt.Errorf("failed to marshal payload: %w", err)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_failed_marshal_payload"), err)
|
||||
return
|
||||
}
|
||||
|
||||
var req *http.Request
|
||||
if req, err = http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(jsonPayload)); err != nil {
|
||||
err = fmt.Errorf("failed to create request: %w", err)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_failed_create_request"), err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -218,37 +219,37 @@ func (c *Client) Send(ctx context.Context, msgs []*chat.ChatCompletionMessage, o
|
||||
|
||||
var resp *http.Response
|
||||
if resp, err = c.HttpClient.Do(req); err != nil {
|
||||
err = fmt.Errorf("failed to send request: %w", err)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_failed_send_request"), err)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
err = fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_unexpected_status_code"), resp.StatusCode)
|
||||
return
|
||||
}
|
||||
|
||||
var result map[string]any
|
||||
if err = json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||||
err = fmt.Errorf("failed to decode response: %w", err)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_failed_decode_response"), err)
|
||||
return
|
||||
}
|
||||
|
||||
var choices []any
|
||||
var ok bool
|
||||
if choices, ok = result["choices"].([]any); !ok || len(choices) == 0 {
|
||||
err = fmt.Errorf("invalid response format: missing or empty choices")
|
||||
err = fmt.Errorf("%s", i18n.T("lmstudio_invalid_response_missing_choices"))
|
||||
return
|
||||
}
|
||||
|
||||
var message map[string]any
|
||||
if message, ok = choices[0].(map[string]any)["message"].(map[string]any); !ok {
|
||||
err = fmt.Errorf("invalid response format: missing message in first choice")
|
||||
err = fmt.Errorf("%s", i18n.T("lmstudio_invalid_response_missing_message"))
|
||||
return
|
||||
}
|
||||
|
||||
if content, ok = message["content"].(string); !ok {
|
||||
err = fmt.Errorf("invalid response format: missing or non-string content in message")
|
||||
err = fmt.Errorf("%s", i18n.T("lmstudio_invalid_response_missing_content"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -266,13 +267,13 @@ func (c *Client) Complete(ctx context.Context, prompt string, opts *domain.ChatO
|
||||
|
||||
var jsonPayload []byte
|
||||
if jsonPayload, err = json.Marshal(payload); err != nil {
|
||||
err = fmt.Errorf("failed to marshal payload: %w", err)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_failed_marshal_payload"), err)
|
||||
return
|
||||
}
|
||||
|
||||
var req *http.Request
|
||||
if req, err = http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(jsonPayload)); err != nil {
|
||||
err = fmt.Errorf("failed to create request: %w", err)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_failed_create_request"), err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -280,31 +281,31 @@ func (c *Client) Complete(ctx context.Context, prompt string, opts *domain.ChatO
|
||||
|
||||
var resp *http.Response
|
||||
if resp, err = c.HttpClient.Do(req); err != nil {
|
||||
err = fmt.Errorf("failed to send request: %w", err)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_failed_send_request"), err)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
err = fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_unexpected_status_code"), resp.StatusCode)
|
||||
return
|
||||
}
|
||||
|
||||
var result map[string]any
|
||||
if err = json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||||
err = fmt.Errorf("failed to decode response: %w", err)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_failed_decode_response"), err)
|
||||
return
|
||||
}
|
||||
|
||||
var choices []any
|
||||
var ok bool
|
||||
if choices, ok = result["choices"].([]any); !ok || len(choices) == 0 {
|
||||
err = fmt.Errorf("invalid response format: missing or empty choices")
|
||||
err = fmt.Errorf("%s", i18n.T("lmstudio_invalid_response_missing_choices"))
|
||||
return
|
||||
}
|
||||
|
||||
if text, ok = choices[0].(map[string]any)["text"].(string); !ok {
|
||||
err = fmt.Errorf("invalid response format: missing or non-string text in first choice")
|
||||
err = fmt.Errorf("%s", i18n.T("lmstudio_invalid_response_missing_text"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -322,13 +323,13 @@ func (c *Client) GetEmbeddings(ctx context.Context, input string, opts *domain.C
|
||||
|
||||
var jsonPayload []byte
|
||||
if jsonPayload, err = json.Marshal(payload); err != nil {
|
||||
err = fmt.Errorf("failed to marshal payload: %w", err)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_failed_marshal_payload"), err)
|
||||
return
|
||||
}
|
||||
|
||||
var req *http.Request
|
||||
if req, err = http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(jsonPayload)); err != nil {
|
||||
err = fmt.Errorf("failed to create request: %w", err)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_failed_create_request"), err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -336,13 +337,13 @@ func (c *Client) GetEmbeddings(ctx context.Context, input string, opts *domain.C
|
||||
|
||||
var resp *http.Response
|
||||
if resp, err = c.HttpClient.Do(req); err != nil {
|
||||
err = fmt.Errorf("failed to send request: %w", err)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_failed_send_request"), err)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
err = fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_unexpected_status_code"), resp.StatusCode)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -353,12 +354,12 @@ func (c *Client) GetEmbeddings(ctx context.Context, input string, opts *domain.C
|
||||
}
|
||||
|
||||
if err = json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||||
err = fmt.Errorf("failed to decode response: %w", err)
|
||||
err = fmt.Errorf(i18n.T("lmstudio_failed_decode_response"), err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(result.Data) == 0 {
|
||||
err = fmt.Errorf("no embeddings returned")
|
||||
err = fmt.Errorf("%s", i18n.T("lmstudio_no_embeddings_returned"))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,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"
|
||||
openai "github.com/openai/openai-go"
|
||||
@@ -75,8 +76,8 @@ func (o *Client) SetResponsesAPIEnabled(enabled bool) {
|
||||
// checkImageGenerationCompatibility warns if the model doesn't support image generation
|
||||
func checkImageGenerationCompatibility(model string) {
|
||||
if !supportsImageGeneration(model) {
|
||||
fmt.Fprintf(os.Stderr, "Warning: Model '%s' does not support image generation. Supported models: %s. Consider using -m gpt-5.2 for image generation.\n",
|
||||
model, strings.Join(ImageGenerationSupportedModels, ", "))
|
||||
fmt.Fprintf(os.Stderr, "%s", fmt.Sprintf(i18n.T("openai_warning_model_no_image_generation"),
|
||||
model, strings.Join(ImageGenerationSupportedModels, ", ")))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +171,7 @@ func (o *Client) sendResponses(ctx context.Context, msgs []*chat.ChatCompletionM
|
||||
|
||||
// Validate model supports image generation if image file is specified
|
||||
if opts.ImageFile != "" && !supportsImageGeneration(opts.Model) {
|
||||
return "", fmt.Errorf("model '%s' does not support image generation. Supported models: %s", opts.Model, strings.Join(ImageGenerationSupportedModels, ", "))
|
||||
return "", fmt.Errorf("%s", fmt.Sprintf(i18n.T("openai_model_no_image_generation"), opts.Model, strings.Join(ImageGenerationSupportedModels, ", ")))
|
||||
}
|
||||
|
||||
req := o.buildResponseParams(msgs, opts)
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/danielmiessler/fabric/internal/i18n"
|
||||
)
|
||||
|
||||
// ExtensionExecutor handles the secure execution of extensions
|
||||
@@ -34,19 +36,19 @@ func (e *ExtensionExecutor) Execute(name, operation, value string) (string, erro
|
||||
// Get and verify extension from registry
|
||||
ext, err := e.registry.GetExtension(name)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get extension: %w", err)
|
||||
return "", fmt.Errorf(i18n.T("extension_failed_get_extension"), err)
|
||||
}
|
||||
|
||||
// Format the command using our template system
|
||||
cmdStr, err := e.formatCommand(ext, operation, value)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to format command: %w", err)
|
||||
return "", fmt.Errorf(i18n.T("extension_failed_format_command"), err)
|
||||
}
|
||||
|
||||
// Split the command string into command and arguments
|
||||
cmdParts := strings.Fields(cmdStr)
|
||||
if len(cmdParts) < 1 {
|
||||
return "", fmt.Errorf("empty command after formatting")
|
||||
return "", fmt.Errorf("%s", i18n.T("extension_empty_command"))
|
||||
}
|
||||
|
||||
// Create command with the Executable and formatted arguments
|
||||
@@ -72,7 +74,7 @@ func (e *ExtensionExecutor) formatCommand(ext *ExtensionDefinition, operation st
|
||||
// Get operation config
|
||||
opConfig, exists := ext.Operations[operation]
|
||||
if !exists {
|
||||
return "", fmt.Errorf("operation %s not found for extension %s", operation, ext.Name)
|
||||
return "", fmt.Errorf("%s", fmt.Sprintf(i18n.T("extension_operation_not_found"), operation, ext.Name))
|
||||
}
|
||||
|
||||
vars := make(map[string]string)
|
||||
@@ -97,10 +99,10 @@ func (e *ExtensionExecutor) executeStdout(cmd *exec.Cmd, ext *ExtensionDefinitio
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
//debug output
|
||||
fmt.Printf("Executing command: %s\n", cmd.String())
|
||||
fmt.Printf(i18n.T("extension_executing_command"), cmd.String())
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return "", fmt.Errorf("execution failed: %w\nstderr: %s", err, stderr.String())
|
||||
return "", fmt.Errorf(i18n.T("extension_execution_failed_stderr"), err, stderr.String())
|
||||
}
|
||||
|
||||
return stdout.String(), nil
|
||||
@@ -111,7 +113,7 @@ func (e *ExtensionExecutor) executeWithFile(cmd *exec.Cmd, ext *ExtensionDefinit
|
||||
// Parse timeout - this is now a first-class field
|
||||
timeout, err := time.ParseDuration(ext.Timeout)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid timeout format: %w", err)
|
||||
return "", fmt.Errorf(i18n.T("extension_invalid_timeout_format"), err)
|
||||
}
|
||||
|
||||
// Create context with timeout
|
||||
@@ -126,7 +128,7 @@ func (e *ExtensionExecutor) executeWithFile(cmd *exec.Cmd, ext *ExtensionDefinit
|
||||
|
||||
fileConfig := ext.GetFileConfig()
|
||||
if fileConfig == nil {
|
||||
return "", fmt.Errorf("no file configuration found")
|
||||
return "", fmt.Errorf("%s", i18n.T("extension_no_file_config"))
|
||||
}
|
||||
|
||||
// Handle path from stdout case
|
||||
@@ -139,7 +141,7 @@ func (e *ExtensionExecutor) executeWithFile(cmd *exec.Cmd, ext *ExtensionDefinit
|
||||
outputFile, _ := fileConfig["output_file"].(string)
|
||||
|
||||
if outputFile == "" {
|
||||
return "", fmt.Errorf("no output file specified in configuration")
|
||||
return "", fmt.Errorf("%s", i18n.T("extension_no_output_file"))
|
||||
}
|
||||
|
||||
// Set working directory if specified
|
||||
@@ -152,9 +154,9 @@ func (e *ExtensionExecutor) executeWithFile(cmd *exec.Cmd, ext *ExtensionDefinit
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
return "", fmt.Errorf("execution timed out after %v", timeout)
|
||||
return "", fmt.Errorf("%s", fmt.Sprintf(i18n.T("extension_execution_timed_out"), timeout))
|
||||
}
|
||||
return "", fmt.Errorf("execution failed: %w\nerr: %s", err, stderr.String())
|
||||
return "", fmt.Errorf(i18n.T("extension_execution_failed_err"), err, stderr.String())
|
||||
}
|
||||
|
||||
// Construct full file path
|
||||
@@ -165,7 +167,7 @@ func (e *ExtensionExecutor) executeWithFile(cmd *exec.Cmd, ext *ExtensionDefinit
|
||||
|
||||
content, err := os.ReadFile(outputPath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read output file: %w", err)
|
||||
return "", fmt.Errorf(i18n.T("extension_failed_read_output_file"), err)
|
||||
}
|
||||
|
||||
// Handle cleanup if enabled
|
||||
@@ -183,13 +185,13 @@ func (e *ExtensionExecutor) handlePathFromStdout(cmd *exec.Cmd, ext *ExtensionDe
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return "", fmt.Errorf("failed to get output path: %w\nerr: %s", err, stderr.String())
|
||||
return "", fmt.Errorf(i18n.T("extension_failed_get_output_path"), err, stderr.String())
|
||||
}
|
||||
|
||||
outputPath := strings.TrimSpace(stdout.String())
|
||||
content, err := os.ReadFile(outputPath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read output file: %w", err)
|
||||
return "", fmt.Errorf(i18n.T("extension_failed_read_output_file"), err)
|
||||
}
|
||||
|
||||
if ext.IsCleanupEnabled() {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/danielmiessler/fabric/internal/i18n"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -29,36 +30,36 @@ func NewExtensionManager(configDir string) *ExtensionManager {
|
||||
// ListExtensions handles the listextensions flag action
|
||||
func (em *ExtensionManager) ListExtensions() error {
|
||||
if em.registry == nil || em.registry.registry.Extensions == nil {
|
||||
return fmt.Errorf("extension registry not initialized")
|
||||
return fmt.Errorf("%s", i18n.T("extension_registry_not_initialized"))
|
||||
}
|
||||
|
||||
for name, entry := range em.registry.registry.Extensions {
|
||||
fmt.Printf("Extension: %s\n", name)
|
||||
fmt.Printf(i18n.T("extension_name_label"), name)
|
||||
|
||||
// Try to load extension details
|
||||
ext, err := em.registry.GetExtension(name)
|
||||
if err != nil {
|
||||
fmt.Printf(" Status: DISABLED - Hash verification failed: %v\n", err)
|
||||
fmt.Printf(" Config Path: %s\n\n", entry.ConfigPath)
|
||||
fmt.Printf(i18n.T("extension_status_disabled"), err)
|
||||
fmt.Printf(i18n.T("extension_config_path_label"), entry.ConfigPath)
|
||||
continue
|
||||
}
|
||||
|
||||
// Print extension details if verification succeeded
|
||||
fmt.Printf(" Status: ENABLED\n")
|
||||
fmt.Printf(" Executable: %s\n", ext.Executable)
|
||||
fmt.Printf(" Type: %s\n", ext.Type)
|
||||
fmt.Printf(" Timeout: %s\n", ext.Timeout)
|
||||
fmt.Printf(" Description: %s\n", ext.Description)
|
||||
fmt.Printf(" Version: %s\n", ext.Version)
|
||||
fmt.Printf("%s", i18n.T("extension_status_enabled"))
|
||||
fmt.Printf(i18n.T("extension_executable_label"), ext.Executable)
|
||||
fmt.Printf(i18n.T("extension_type_label"), ext.Type)
|
||||
fmt.Printf(i18n.T("extension_timeout_label"), ext.Timeout)
|
||||
fmt.Printf(i18n.T("extension_description_label"), ext.Description)
|
||||
fmt.Printf(i18n.T("extension_version_label"), ext.Version)
|
||||
|
||||
fmt.Printf(" Operations:\n")
|
||||
fmt.Printf("%s", i18n.T("extension_operations_label"))
|
||||
for opName, opConfig := range ext.Operations {
|
||||
fmt.Printf(" %s:\n", opName)
|
||||
fmt.Printf(" Command Template: %s\n", opConfig.CmdTemplate)
|
||||
fmt.Printf(i18n.T("extension_command_template_label"), opConfig.CmdTemplate)
|
||||
}
|
||||
|
||||
if fileConfig := ext.GetFileConfig(); fileConfig != nil {
|
||||
fmt.Printf(" File Configuration:\n")
|
||||
fmt.Printf("%s", i18n.T("extension_file_config_label"))
|
||||
for k, v := range fileConfig {
|
||||
fmt.Printf(" %s: %v\n", k, v)
|
||||
}
|
||||
@@ -73,45 +74,45 @@ func (em *ExtensionManager) ListExtensions() error {
|
||||
func (em *ExtensionManager) RegisterExtension(configPath string) error {
|
||||
absPath, err := filepath.Abs(configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid config path: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_invalid_config_path"), err)
|
||||
}
|
||||
|
||||
// Get extension name before registration for status message
|
||||
data, err := os.ReadFile(absPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read config file: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_failed_read_config"), err)
|
||||
}
|
||||
|
||||
var ext ExtensionDefinition
|
||||
if err := yaml.Unmarshal(data, &ext); err != nil {
|
||||
return fmt.Errorf("failed to parse config file: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_failed_parse_config"), err)
|
||||
}
|
||||
|
||||
if err := em.registry.Register(absPath); err != nil {
|
||||
return fmt.Errorf("failed to register extension: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_failed_register"), err)
|
||||
}
|
||||
|
||||
if _, err := time.ParseDuration(ext.Timeout); err != nil {
|
||||
return fmt.Errorf("invalid timeout value '%s': must be a duration like '30s' or '1m': %w", ext.Timeout, err)
|
||||
return fmt.Errorf(i18n.T("extension_invalid_timeout"), ext.Timeout, err)
|
||||
}
|
||||
|
||||
// Print success message with extension details
|
||||
fmt.Printf("Successfully registered extension:\n")
|
||||
fmt.Printf("Name: %s\n", ext.Name)
|
||||
fmt.Printf(" Executable: %s\n", ext.Executable)
|
||||
fmt.Printf(" Type: %s\n", ext.Type)
|
||||
fmt.Printf(" Timeout: %s\n", ext.Timeout)
|
||||
fmt.Printf(" Description: %s\n", ext.Description)
|
||||
fmt.Printf(" Version: %s\n", ext.Version)
|
||||
fmt.Printf("%s", i18n.T("extension_registered_success"))
|
||||
fmt.Printf(i18n.T("extension_name_detail_label"), ext.Name)
|
||||
fmt.Printf(i18n.T("extension_executable_label"), ext.Executable)
|
||||
fmt.Printf(i18n.T("extension_type_label"), ext.Type)
|
||||
fmt.Printf(i18n.T("extension_timeout_label"), ext.Timeout)
|
||||
fmt.Printf(i18n.T("extension_description_label"), ext.Description)
|
||||
fmt.Printf(i18n.T("extension_version_label"), ext.Version)
|
||||
|
||||
fmt.Printf(" Operations:\n")
|
||||
fmt.Printf("%s", i18n.T("extension_operations_label"))
|
||||
for opName, opConfig := range ext.Operations {
|
||||
fmt.Printf(" %s:\n", opName)
|
||||
fmt.Printf(" Command Template: %s\n", opConfig.CmdTemplate)
|
||||
fmt.Printf(i18n.T("extension_command_template_label"), opConfig.CmdTemplate)
|
||||
}
|
||||
|
||||
if fileConfig := ext.GetFileConfig(); fileConfig != nil {
|
||||
fmt.Printf(" File Configuration:\n")
|
||||
fmt.Printf("%s", i18n.T("extension_file_config_label"))
|
||||
for k, v := range fileConfig {
|
||||
fmt.Printf(" %s: %v\n", k, v)
|
||||
}
|
||||
@@ -123,7 +124,7 @@ func (em *ExtensionManager) RegisterExtension(configPath string) error {
|
||||
// RemoveExtension handles the rmextension flag action
|
||||
func (em *ExtensionManager) RemoveExtension(name string) error {
|
||||
if err := em.registry.Remove(name); err != nil {
|
||||
return fmt.Errorf("failed to remove extension: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_failed_remove"), err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/danielmiessler/fabric/internal/i18n"
|
||||
debuglog "github.com/danielmiessler/fabric/internal/log"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
@@ -88,7 +89,7 @@ func NewExtensionRegistry(configDir string) *ExtensionRegistry {
|
||||
r.ensureConfigDir()
|
||||
|
||||
if err := r.loadRegistry(); err != nil {
|
||||
debuglog.Log("Warning: could not load extension registry: %v\n", err)
|
||||
debuglog.Log(i18n.T("extension_warning_load_registry"), err)
|
||||
}
|
||||
|
||||
return r
|
||||
@@ -105,44 +106,44 @@ func (r *ExtensionRegistry) Register(configPath string) error {
|
||||
// Read and parse the extension definition to verify it
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read config file: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_failed_read_config"), err)
|
||||
}
|
||||
|
||||
var ext ExtensionDefinition
|
||||
if err := yaml.Unmarshal(data, &ext); err != nil {
|
||||
return fmt.Errorf("failed to parse config file: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_failed_parse_config"), err)
|
||||
}
|
||||
|
||||
// Validate extension name
|
||||
if ext.Name == "" {
|
||||
return fmt.Errorf("extension name cannot be empty")
|
||||
return fmt.Errorf("%s", i18n.T("extension_name_empty"))
|
||||
}
|
||||
|
||||
if strings.Contains(ext.Name, " ") {
|
||||
return fmt.Errorf("extension name '%s' contains spaces - names must not contain spaces", ext.Name)
|
||||
return fmt.Errorf("%s", fmt.Sprintf(i18n.T("extension_name_contains_spaces"), ext.Name))
|
||||
}
|
||||
|
||||
// Verify executable exists
|
||||
if _, err := os.Stat(ext.Executable); err != nil {
|
||||
return fmt.Errorf("executable not found: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_executable_not_found"), err)
|
||||
}
|
||||
|
||||
// Get absolute path to config
|
||||
absPath, err := filepath.Abs(configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get absolute path: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_failed_get_absolute_path"), err)
|
||||
}
|
||||
|
||||
// Calculate hashes
|
||||
configHash := ComputeStringHash(string(data))
|
||||
executableHash, err := ComputeHash(ext.Executable)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to hash executable: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_failed_hash_executable"), err)
|
||||
}
|
||||
|
||||
// Validate full extension definition (ensures operations and cmd_template present)
|
||||
if err := r.validateExtensionDefinition(&ext); err != nil {
|
||||
return fmt.Errorf("invalid extension definition: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_invalid_definition"), err)
|
||||
}
|
||||
|
||||
// Store entry
|
||||
@@ -158,29 +159,29 @@ func (r *ExtensionRegistry) Register(configPath string) error {
|
||||
func (r *ExtensionRegistry) validateExtensionDefinition(ext *ExtensionDefinition) error {
|
||||
// Validate required fields
|
||||
if ext.Name == "" {
|
||||
return fmt.Errorf("extension name is required")
|
||||
return fmt.Errorf("%s", i18n.T("extension_name_required"))
|
||||
}
|
||||
if ext.Executable == "" {
|
||||
return fmt.Errorf("executable path is required")
|
||||
return fmt.Errorf("%s", i18n.T("extension_executable_required"))
|
||||
}
|
||||
if ext.Type == "" {
|
||||
return fmt.Errorf("extension type is required")
|
||||
return fmt.Errorf("%s", i18n.T("extension_type_required"))
|
||||
}
|
||||
|
||||
// Validate timeout format
|
||||
if ext.Timeout != "" {
|
||||
if _, err := time.ParseDuration(ext.Timeout); err != nil {
|
||||
return fmt.Errorf("invalid timeout format: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_invalid_timeout_format"), err)
|
||||
}
|
||||
}
|
||||
|
||||
// Validate operations
|
||||
if len(ext.Operations) == 0 {
|
||||
return fmt.Errorf("at least one operation must be defined")
|
||||
return fmt.Errorf("%s", i18n.T("extension_operation_required"))
|
||||
}
|
||||
for name, op := range ext.Operations {
|
||||
if op.CmdTemplate == "" {
|
||||
return fmt.Errorf("command template is required for operation %s", name)
|
||||
return fmt.Errorf("%s", fmt.Sprintf(i18n.T("extension_cmd_template_required"), name))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +190,7 @@ func (r *ExtensionRegistry) validateExtensionDefinition(ext *ExtensionDefinition
|
||||
|
||||
func (r *ExtensionRegistry) Remove(name string) error {
|
||||
if _, exists := r.registry.Extensions[name]; !exists {
|
||||
return fmt.Errorf("extension %s not found", name)
|
||||
return fmt.Errorf("%s", fmt.Sprintf(i18n.T("extension_not_found"), name))
|
||||
}
|
||||
|
||||
delete(r.registry.Extensions, name)
|
||||
@@ -201,35 +202,35 @@ func (r *ExtensionRegistry) Verify(name string) error {
|
||||
// Get the registry entry
|
||||
entry, exists := r.registry.Extensions[name]
|
||||
if !exists {
|
||||
return fmt.Errorf("extension %s not found", name)
|
||||
return fmt.Errorf("%s", fmt.Sprintf(i18n.T("extension_not_found"), name))
|
||||
}
|
||||
|
||||
// Load and parse the config file
|
||||
data, err := os.ReadFile(entry.ConfigPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read config file: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_failed_read_config"), err)
|
||||
}
|
||||
|
||||
// Verify config hash
|
||||
currentConfigHash := ComputeStringHash(string(data))
|
||||
if currentConfigHash != entry.ConfigHash {
|
||||
return fmt.Errorf("config file hash mismatch for %s", name)
|
||||
return fmt.Errorf("%s", fmt.Sprintf(i18n.T("extension_config_hash_mismatch"), name))
|
||||
}
|
||||
|
||||
// Parse to get executable path
|
||||
var ext ExtensionDefinition
|
||||
if err := yaml.Unmarshal(data, &ext); err != nil {
|
||||
return fmt.Errorf("failed to parse config file: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_failed_parse_config"), err)
|
||||
}
|
||||
|
||||
// Verify executable hash
|
||||
currentExecutableHash, err := ComputeHash(ext.Executable)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to verify executable: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_failed_verify_executable"), err)
|
||||
}
|
||||
|
||||
if currentExecutableHash != entry.ExecutableHash {
|
||||
return fmt.Errorf("executable hash mismatch for %s", name)
|
||||
return fmt.Errorf("%s", fmt.Sprintf(i18n.T("extension_executable_hash_mismatch"), name))
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -238,35 +239,35 @@ func (r *ExtensionRegistry) Verify(name string) error {
|
||||
func (r *ExtensionRegistry) GetExtension(name string) (*ExtensionDefinition, error) {
|
||||
entry, exists := r.registry.Extensions[name]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("extension %s not found", name)
|
||||
return nil, fmt.Errorf("%s", fmt.Sprintf(i18n.T("extension_not_found"), name))
|
||||
}
|
||||
|
||||
// Read current config file
|
||||
data, err := os.ReadFile(entry.ConfigPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read config file: %w", err)
|
||||
return nil, fmt.Errorf(i18n.T("extension_failed_read_config"), err)
|
||||
}
|
||||
|
||||
// Verify config hash
|
||||
currentHash := ComputeStringHash(string(data))
|
||||
if currentHash != entry.ConfigHash {
|
||||
return nil, fmt.Errorf("config file hash mismatch for %s", name)
|
||||
return nil, fmt.Errorf("%s", fmt.Sprintf(i18n.T("extension_config_hash_mismatch"), name))
|
||||
}
|
||||
|
||||
// Parse config
|
||||
var ext ExtensionDefinition
|
||||
if err := yaml.Unmarshal(data, &ext); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse config file: %w", err)
|
||||
return nil, fmt.Errorf(i18n.T("extension_failed_parse_config"), err)
|
||||
}
|
||||
|
||||
// Verify executable hash
|
||||
currentExecHash, err := ComputeHash(ext.Executable)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to verify executable: %w", err)
|
||||
return nil, fmt.Errorf(i18n.T("extension_failed_verify_executable"), err)
|
||||
}
|
||||
|
||||
if currentExecHash != entry.ExecutableHash {
|
||||
return nil, fmt.Errorf("executable hash mismatch for %s", name)
|
||||
return nil, fmt.Errorf("%s", fmt.Sprintf(i18n.T("extension_executable_hash_mismatch"), name))
|
||||
}
|
||||
|
||||
return &ext, nil
|
||||
@@ -307,7 +308,7 @@ func (r *ExtensionRegistry) calculateFileHash(path string) (string, error) {
|
||||
func (r *ExtensionRegistry) saveRegistry() error {
|
||||
data, err := yaml.Marshal(r.registry)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal extension registry: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_failed_marshal_registry"), err)
|
||||
}
|
||||
|
||||
registryPath := filepath.Join(r.configDir, "extensions", "extensions.yaml")
|
||||
@@ -321,12 +322,12 @@ func (r *ExtensionRegistry) loadRegistry() error {
|
||||
if os.IsNotExist(err) {
|
||||
return nil // New registry
|
||||
}
|
||||
return fmt.Errorf("failed to read extension registry: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_failed_read_registry"), err)
|
||||
}
|
||||
|
||||
// Need to unmarshal the data into our registry
|
||||
if err := yaml.Unmarshal(data, &r.registry); err != nil {
|
||||
return fmt.Errorf("failed to parse extension registry: %w", err)
|
||||
return fmt.Errorf(i18n.T("extension_failed_parse_registry"), err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/danielmiessler/fabric/internal/core"
|
||||
"github.com/danielmiessler/fabric/internal/i18n"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -108,28 +109,28 @@ func parseOllamaNumCtx(options map[string]any) (int, error) {
|
||||
switch v := val.(type) {
|
||||
case float64:
|
||||
if math.IsNaN(v) || math.IsInf(v, 0) {
|
||||
return 0, fmt.Errorf("num_ctx must be a finite number")
|
||||
return 0, fmt.Errorf("%s", i18n.T("ollama_num_ctx_must_be_finite"))
|
||||
}
|
||||
if math.Trunc(v) != v {
|
||||
return 0, fmt.Errorf("num_ctx must be an integer, got float with fractional part")
|
||||
return 0, fmt.Errorf("%s", i18n.T("ollama_num_ctx_must_be_integer"))
|
||||
}
|
||||
// Check for overflow on 32-bit systems (negative values handled by validation at line 166)
|
||||
if v > float64(maxInt) {
|
||||
return 0, fmt.Errorf("num_ctx value out of range")
|
||||
return 0, fmt.Errorf("%s", i18n.T("ollama_num_ctx_value_out_of_range"))
|
||||
}
|
||||
contextLength = int(v)
|
||||
|
||||
case float32:
|
||||
f64 := float64(v)
|
||||
if math.IsNaN(f64) || math.IsInf(f64, 0) {
|
||||
return 0, fmt.Errorf("num_ctx must be a finite number")
|
||||
return 0, fmt.Errorf("%s", i18n.T("ollama_num_ctx_must_be_finite"))
|
||||
}
|
||||
if math.Trunc(f64) != f64 {
|
||||
return 0, fmt.Errorf("num_ctx must be an integer, got float with fractional part")
|
||||
return 0, fmt.Errorf("%s", i18n.T("ollama_num_ctx_must_be_integer"))
|
||||
}
|
||||
// Check for overflow on 32-bit systems (negative values handled by validation at line 177)
|
||||
if f64 > float64(maxInt) {
|
||||
return 0, fmt.Errorf("num_ctx value out of range")
|
||||
return 0, fmt.Errorf("%s", i18n.T("ollama_num_ctx_value_out_of_range"))
|
||||
}
|
||||
contextLength = int(v)
|
||||
|
||||
@@ -138,23 +139,23 @@ func parseOllamaNumCtx(options map[string]any) (int, error) {
|
||||
|
||||
case int64:
|
||||
if v < 0 {
|
||||
return 0, fmt.Errorf("num_ctx must be positive, got: %d", v)
|
||||
return 0, fmt.Errorf(i18n.T("ollama_num_ctx_must_be_positive"), v)
|
||||
}
|
||||
if v > maxInt {
|
||||
return 0, fmt.Errorf("num_ctx value too large: %d", v)
|
||||
return 0, fmt.Errorf(i18n.T("ollama_num_ctx_value_too_large"), v)
|
||||
}
|
||||
contextLength = int(v)
|
||||
|
||||
case json.Number:
|
||||
i64, err := v.Int64()
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("num_ctx must be a valid number")
|
||||
return 0, fmt.Errorf("%s", i18n.T("ollama_num_ctx_must_be_valid_number"))
|
||||
}
|
||||
if i64 < 0 {
|
||||
return 0, fmt.Errorf("num_ctx must be positive, got: %d", i64)
|
||||
return 0, fmt.Errorf(i18n.T("ollama_num_ctx_must_be_positive"), i64)
|
||||
}
|
||||
if i64 > maxInt {
|
||||
return 0, fmt.Errorf("num_ctx value too large: %d", i64)
|
||||
return 0, fmt.Errorf(i18n.T("ollama_num_ctx_value_too_large"), i64)
|
||||
}
|
||||
contextLength = int(i64)
|
||||
|
||||
@@ -166,21 +167,21 @@ func parseOllamaNumCtx(options map[string]any) (int, error) {
|
||||
if len(v) > 50 {
|
||||
errVal = v[:50] + "..."
|
||||
}
|
||||
return 0, fmt.Errorf("num_ctx must be a valid number, got: %s", errVal)
|
||||
return 0, fmt.Errorf(i18n.T("ollama_num_ctx_must_be_valid_number_got"), errVal)
|
||||
}
|
||||
contextLength = parsed
|
||||
|
||||
default:
|
||||
return 0, fmt.Errorf("num_ctx must be a number, got invalid type")
|
||||
return 0, fmt.Errorf("%s", i18n.T("ollama_num_ctx_invalid_type"))
|
||||
}
|
||||
|
||||
if contextLength <= 0 {
|
||||
return 0, fmt.Errorf("num_ctx must be positive, got: %d", contextLength)
|
||||
return 0, fmt.Errorf(i18n.T("ollama_num_ctx_must_be_positive"), contextLength)
|
||||
}
|
||||
|
||||
const maxContextLength = 1000000
|
||||
if contextLength > maxContextLength {
|
||||
return 0, fmt.Errorf("num_ctx exceeds maximum allowed value of %d", maxContextLength)
|
||||
return 0, fmt.Errorf(i18n.T("ollama_num_ctx_exceeds_maximum"), maxContextLength)
|
||||
}
|
||||
|
||||
return contextLength, nil
|
||||
@@ -257,22 +258,22 @@ func (f APIConvert) ollamaTags(c *gin.Context) {
|
||||
func (f APIConvert) ollamaChat(c *gin.Context) {
|
||||
body, err := io.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
log.Printf("Error reading body: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "testing endpoint"})
|
||||
log.Printf(i18n.T("ollama_error_reading_body"), err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": i18n.T("ollama_error_endpoint")})
|
||||
return
|
||||
}
|
||||
var prompt OllamaRequestBody
|
||||
err = json.Unmarshal(body, &prompt)
|
||||
if err != nil {
|
||||
log.Printf("Error unmarshalling body: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "testing endpoint"})
|
||||
log.Printf(i18n.T("ollama_error_unmarshalling_body"), err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": i18n.T("ollama_error_endpoint")})
|
||||
return
|
||||
}
|
||||
|
||||
// Extract and validate num_ctx from options
|
||||
numCtx, err := parseOllamaNumCtx(prompt.Options)
|
||||
if err != nil {
|
||||
log.Printf("Invalid num_ctx in request: %v", err)
|
||||
log.Printf(i18n.T("ollama_invalid_num_ctx_in_request"), err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
@@ -289,7 +290,7 @@ func (f APIConvert) ollamaChat(c *gin.Context) {
|
||||
case string:
|
||||
// Parse JSON string into map
|
||||
if err := json.Unmarshal([]byte(v), &variables); err != nil {
|
||||
log.Printf("Warning: failed to parse options.variables as JSON: %v", err)
|
||||
log.Printf(i18n.T("ollama_warning_parse_variables"), err)
|
||||
}
|
||||
case map[string]any:
|
||||
// Convert map[string]any to map[string]string
|
||||
@@ -332,21 +333,21 @@ func (f APIConvert) ollamaChat(c *gin.Context) {
|
||||
|
||||
fabricChatReq, err := json.Marshal(chat)
|
||||
if err != nil {
|
||||
log.Printf("Error marshalling body: %v", err)
|
||||
log.Printf(i18n.T("ollama_error_marshalling_body"), err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
var req *http.Request
|
||||
baseURL, err := buildFabricChatURL(*f.addr)
|
||||
if err != nil {
|
||||
log.Printf("Error building /chat URL: %v", err)
|
||||
log.Printf(i18n.T("ollama_error_building_chat_url"), err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
req, err = http.NewRequest("POST", fmt.Sprintf("%s/chat", baseURL), bytes.NewBuffer(fabricChatReq))
|
||||
if err != nil {
|
||||
log.Printf("Error creating /chat request: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create request"})
|
||||
log.Printf(i18n.T("ollama_error_creating_chat_request"), err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": i18n.T("ollama_failed_create_request")})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -354,7 +355,7 @@ func (f APIConvert) ollamaChat(c *gin.Context) {
|
||||
|
||||
fabricRes, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
log.Printf("Error getting /chat body: %v", err)
|
||||
log.Printf(i18n.T("ollama_error_getting_chat_body"), err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
@@ -363,14 +364,14 @@ func (f APIConvert) ollamaChat(c *gin.Context) {
|
||||
if fabricRes.StatusCode < http.StatusOK || fabricRes.StatusCode >= http.StatusMultipleChoices {
|
||||
bodyBytes, readErr := io.ReadAll(fabricRes.Body)
|
||||
if readErr != nil {
|
||||
log.Printf("Upstream Fabric server returned non-2xx status %d and body could not be read: %v", fabricRes.StatusCode, readErr)
|
||||
log.Printf(i18n.T("ollama_upstream_non_2xx_body_unreadable"), fabricRes.StatusCode, readErr)
|
||||
} else {
|
||||
log.Printf("Upstream Fabric server returned non-2xx status %d: %s", fabricRes.StatusCode, string(bodyBytes))
|
||||
log.Printf(i18n.T("ollama_upstream_non_2xx"), fabricRes.StatusCode, string(bodyBytes))
|
||||
}
|
||||
|
||||
errorMessage := fmt.Sprintf("upstream Fabric server returned status %d", fabricRes.StatusCode)
|
||||
errorMessage := fmt.Sprintf(i18n.T("ollama_upstream_returned_status"), fabricRes.StatusCode)
|
||||
if prompt.Stream {
|
||||
_ = writeOllamaResponse(c, prompt.Model, fmt.Sprintf("Error: %s", errorMessage), true)
|
||||
_ = writeOllamaResponse(c, prompt.Model, fmt.Sprintf(i18n.T("ollama_error_prefix"), errorMessage), true)
|
||||
} else {
|
||||
c.JSON(fabricRes.StatusCode, gin.H{"error": errorMessage})
|
||||
}
|
||||
@@ -392,19 +393,19 @@ func (f APIConvert) ollamaChat(c *gin.Context) {
|
||||
payload := strings.TrimPrefix(line, "data: ")
|
||||
var fabricResponse FabricResponseFormat
|
||||
if err := json.Unmarshal([]byte(payload), &fabricResponse); err != nil {
|
||||
log.Printf("Error unmarshalling body: %v", err)
|
||||
log.Printf(i18n.T("ollama_error_unmarshalling_body"), err)
|
||||
if prompt.Stream {
|
||||
// In streaming mode, send the error in the same streaming format
|
||||
_ = writeOllamaResponse(c, prompt.Model, "Error: failed to parse upstream response", true)
|
||||
_ = writeOllamaResponse(c, prompt.Model, i18n.T("ollama_error_parse_upstream_response"), true)
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to unmarshal Fabric response"})
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": i18n.T("ollama_failed_unmarshal_fabric_response")})
|
||||
}
|
||||
return
|
||||
}
|
||||
if fabricResponse.Type == "error" {
|
||||
if prompt.Stream {
|
||||
// In streaming mode, propagate the upstream error via a final streaming chunk
|
||||
_ = writeOllamaResponse(c, prompt.Model, fmt.Sprintf("Error: %s", fabricResponse.Content), true)
|
||||
_ = writeOllamaResponse(c, prompt.Model, fmt.Sprintf(i18n.T("ollama_error_prefix"), fabricResponse.Content), true)
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fabricResponse.Content})
|
||||
}
|
||||
@@ -416,21 +417,21 @@ func (f APIConvert) ollamaChat(c *gin.Context) {
|
||||
contentBuilder.WriteString(fabricResponse.Content)
|
||||
if prompt.Stream {
|
||||
if err := writeOllamaResponse(c, prompt.Model, fabricResponse.Content, false); err != nil {
|
||||
log.Printf("Error writing response: %v", err)
|
||||
log.Printf(i18n.T("ollama_error_writing_response"), err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
log.Printf("Error scanning body: %v", err)
|
||||
errorMsg := fmt.Sprintf("failed to scan SSE response stream: %v", err)
|
||||
log.Printf(i18n.T("ollama_error_scanning_body"), err)
|
||||
errorMsg := fmt.Sprintf(i18n.T("ollama_failed_scan_sse_stream"), err)
|
||||
// Check for buffer size exceeded error
|
||||
if strings.Contains(err.Error(), "token too long") {
|
||||
errorMsg = "SSE line exceeds 1MB buffer limit - data line too large"
|
||||
errorMsg = i18n.T("ollama_sse_buffer_limit")
|
||||
}
|
||||
if prompt.Stream {
|
||||
// In streaming mode, send the error in the same streaming format
|
||||
_ = writeOllamaResponse(c, prompt.Model, fmt.Sprintf("Error: %s", errorMsg), true)
|
||||
_ = writeOllamaResponse(c, prompt.Model, fmt.Sprintf(i18n.T("ollama_error_prefix"), errorMsg), true)
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": errorMsg})
|
||||
}
|
||||
@@ -442,10 +443,10 @@ func (f APIConvert) ollamaChat(c *gin.Context) {
|
||||
|
||||
// Check if we received any content from upstream
|
||||
if contentBuilder.Len() == 0 {
|
||||
log.Printf("Warning: no content received from upstream Fabric server")
|
||||
log.Printf("%s", i18n.T("ollama_warning_no_content"))
|
||||
// In non-streaming mode, treat absence of content as an error
|
||||
if !prompt.Stream {
|
||||
c.JSON(http.StatusBadGateway, gin.H{"error": "no content received from upstream Fabric server"})
|
||||
c.JSON(http.StatusBadGateway, gin.H{"error": i18n.T("ollama_no_content_from_upstream")})
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -458,7 +459,7 @@ func (f APIConvert) ollamaChat(c *gin.Context) {
|
||||
|
||||
finalResponse := buildFinalOllamaResponse(prompt.Model, "", duration)
|
||||
if err := writeOllamaResponseStruct(c, finalResponse); err != nil {
|
||||
log.Printf("Error writing response: %v", err)
|
||||
log.Printf(i18n.T("ollama_error_writing_response"), err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,18 +493,18 @@ func buildFinalOllamaResponse(model string, content string, duration int64) Olla
|
||||
// contains a path component.
|
||||
func buildFabricChatURL(addr string) (string, error) {
|
||||
if addr == "" {
|
||||
return "", fmt.Errorf("empty address")
|
||||
return "", fmt.Errorf("%s", i18n.T("ollama_empty_address"))
|
||||
}
|
||||
if strings.HasPrefix(addr, "http://") || strings.HasPrefix(addr, "https://") {
|
||||
parsed, err := url.Parse(addr)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid address: %w", err)
|
||||
return "", fmt.Errorf(i18n.T("ollama_invalid_address"), err)
|
||||
}
|
||||
if parsed.Host == "" {
|
||||
return "", fmt.Errorf("invalid address: missing host")
|
||||
return "", fmt.Errorf("%s", i18n.T("ollama_invalid_address_missing_host"))
|
||||
}
|
||||
if strings.HasPrefix(parsed.Host, ":") {
|
||||
return "", fmt.Errorf("invalid address: missing hostname")
|
||||
return "", fmt.Errorf("%s", i18n.T("ollama_invalid_address_missing_hostname"))
|
||||
}
|
||||
return strings.TrimRight(parsed.String(), "/"), nil
|
||||
}
|
||||
@@ -513,17 +514,17 @@ func buildFabricChatURL(addr string) (string, error) {
|
||||
// Validate bare addresses (without http/https prefix)
|
||||
parsed, err := url.Parse("http://" + addr)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid address: %w", err)
|
||||
return "", fmt.Errorf(i18n.T("ollama_invalid_address"), err)
|
||||
}
|
||||
if parsed.Host == "" {
|
||||
return "", fmt.Errorf("invalid address: missing host")
|
||||
return "", fmt.Errorf("%s", i18n.T("ollama_invalid_address_missing_host"))
|
||||
}
|
||||
if strings.HasPrefix(parsed.Host, ":") {
|
||||
return "", fmt.Errorf("invalid address: missing hostname")
|
||||
return "", fmt.Errorf("%s", i18n.T("ollama_invalid_address_missing_hostname"))
|
||||
}
|
||||
// Bare addresses should be host[:port] only - reject path components
|
||||
if parsed.Path != "" && parsed.Path != "/" {
|
||||
return "", fmt.Errorf("invalid address: path component not allowed in bare address")
|
||||
return "", fmt.Errorf("%s", i18n.T("ollama_invalid_address_path_not_allowed"))
|
||||
}
|
||||
return strings.TrimRight(parsed.String(), "/"), nil
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ func (s *Spotify) refreshAccessToken() error {
|
||||
|
||||
req, err := http.NewRequest("POST", tokenURL, strings.NewReader(data.Encode()))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create token request: %w", err)
|
||||
return fmt.Errorf(i18n.T("spotify_failed_create_token_request"), err)
|
||||
}
|
||||
|
||||
// Set Basic Auth header with Client ID and Secret
|
||||
@@ -108,13 +108,13 @@ func (s *Spotify) refreshAccessToken() error {
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to request access token: %w", err)
|
||||
return fmt.Errorf(i18n.T("spotify_failed_request_access_token"), err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
return fmt.Errorf("failed to get access token: status %d, body: %s", resp.StatusCode, string(body))
|
||||
return fmt.Errorf(i18n.T("spotify_failed_get_access_token"), resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
var tokenResp struct {
|
||||
@@ -124,7 +124,7 @@ func (s *Spotify) refreshAccessToken() error {
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil {
|
||||
return fmt.Errorf("failed to decode token response: %w", err)
|
||||
return fmt.Errorf(i18n.T("spotify_failed_decode_token_response"), err)
|
||||
}
|
||||
|
||||
s.tokenMutex.Lock()
|
||||
@@ -145,7 +145,7 @@ func (s *Spotify) doRequest(method, endpoint string) ([]byte, error) {
|
||||
reqURL := apiBaseURL + endpoint
|
||||
req, err := http.NewRequest(method, reqURL, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||
return nil, fmt.Errorf(i18n.T("spotify_failed_create_request"), err)
|
||||
}
|
||||
|
||||
s.tokenMutex.RLock()
|
||||
@@ -154,17 +154,17 @@ func (s *Spotify) doRequest(method, endpoint string) ([]byte, error) {
|
||||
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute request: %w", err)
|
||||
return nil, fmt.Errorf(i18n.T("spotify_failed_execute_request"), err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response body: %w", err)
|
||||
return nil, fmt.Errorf(i18n.T("spotify_failed_read_response_body"), err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("API request failed: status %d, body: %s", resp.StatusCode, string(body))
|
||||
return nil, fmt.Errorf(i18n.T("spotify_api_request_failed"), resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
return body, nil
|
||||
@@ -249,7 +249,7 @@ func (s *Spotify) GetShowMetadata(showId string) (*ShowMetadata, error) {
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(body, &resp); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse show metadata: %w", err)
|
||||
return nil, fmt.Errorf(i18n.T("spotify_failed_parse_show_metadata"), err)
|
||||
}
|
||||
|
||||
if resp.Id == "" {
|
||||
@@ -303,7 +303,7 @@ func (s *Spotify) GetEpisodeMetadata(episodeId string) (*EpisodeMetadata, error)
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(body, &resp); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse episode metadata: %w", err)
|
||||
return nil, fmt.Errorf(i18n.T("spotify_failed_parse_episode_metadata"), err)
|
||||
}
|
||||
|
||||
if resp.Id == "" {
|
||||
@@ -341,7 +341,7 @@ func (s *Spotify) SearchShows(query string, limit int) (*SearchResult, error) {
|
||||
endpoint := fmt.Sprintf("/search?q=%s&type=show&limit=%d", url.QueryEscape(query), limit)
|
||||
body, err := s.doRequest("GET", endpoint)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("search failed: %w", err)
|
||||
return nil, fmt.Errorf(i18n.T("spotify_search_failed"), err)
|
||||
}
|
||||
|
||||
var resp struct {
|
||||
@@ -365,7 +365,7 @@ func (s *Spotify) SearchShows(query string, limit int) (*SearchResult, error) {
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(body, &resp); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse search results: %w", err)
|
||||
return nil, fmt.Errorf(i18n.T("spotify_failed_parse_search_results"), err)
|
||||
}
|
||||
|
||||
result := &SearchResult{
|
||||
@@ -401,7 +401,7 @@ func (s *Spotify) GetShowEpisodes(showId string, limit int) ([]EpisodeMetadata,
|
||||
endpoint := fmt.Sprintf("/shows/%s/episodes?limit=%d", showId, limit)
|
||||
body, err := s.doRequest("GET", endpoint)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get show episodes: %w", err)
|
||||
return nil, fmt.Errorf(i18n.T("spotify_failed_get_show_episodes"), err)
|
||||
}
|
||||
|
||||
var resp struct {
|
||||
@@ -424,7 +424,7 @@ func (s *Spotify) GetShowEpisodes(showId string, limit int) ([]EpisodeMetadata,
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(body, &resp); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse episodes: %w", err)
|
||||
return nil, fmt.Errorf(i18n.T("spotify_failed_parse_episodes"), err)
|
||||
}
|
||||
|
||||
episodes := make([]EpisodeMetadata, 0, len(resp.Items))
|
||||
|
||||
Reference in New Issue
Block a user