feat: add internationalization support for chatter and template file operations

- Replace hardcoded strings with i18n keys in chatter.go
- Add translation keys for errors, warnings, and metadata in locale files
- Update file.go to use i18n for operation messages and errors
- Provide translations in German, English, Spanish, Persian, French, Italian, Japanese, Portuguese, and Chinese
- Enable localized output for stream updates and file plugin operations
- Ensure consistent error handling across supported languages
- Maintain backward compatibility with existing functionality
This commit is contained in:
Kayvan Sylvan
2026-02-16 04:21:56 -08:00
parent 4626fd6c44
commit a71a006f74
12 changed files with 442 additions and 41 deletions

View File

@@ -10,6 +10,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/ai"
"github.com/danielmiessler/fabric/internal/plugins/db/fsdb"
"github.com/danielmiessler/fabric/internal/plugins/strategy"
@@ -49,7 +50,7 @@ func (o *Chatter) Send(request *domain.ChatRequest, opts *domain.ChatOptions) (s
return
}
}
err = fmt.Errorf("no messages provided")
err = fmt.Errorf("%s", i18n.T("chatter_error_no_messages_provided"))
return
}
@@ -89,12 +90,20 @@ func (o *Chatter) Send(request *domain.ChatRequest, opts *domain.ChatOptions) (s
}
case domain.StreamTypeUsage:
if opts.ShowMetadata && update.Usage != nil && !opts.Quiet {
fmt.Fprintf(os.Stderr, "\n[Metadata] Input: %d | Output: %d | Total: %d\n",
update.Usage.InputTokens, update.Usage.OutputTokens, update.Usage.TotalTokens)
fmt.Fprintf(
os.Stderr,
"\n%s\n",
fmt.Sprintf(
i18n.T("chatter_log_stream_usage_metadata"),
update.Usage.InputTokens,
update.Usage.OutputTokens,
update.Usage.TotalTokens,
),
)
}
case domain.StreamTypeError:
if !opts.Quiet {
fmt.Fprintf(os.Stderr, "Error: %s\n", update.Content)
fmt.Fprintf(os.Stderr, "%s\n", fmt.Sprintf(i18n.T("chatter_error_stream_update"), update.Content))
}
errChan <- errors.New(update.Content)
}
@@ -129,7 +138,7 @@ func (o *Chatter) Send(request *domain.ChatRequest, opts *domain.ChatOptions) (s
if message == "" {
session = nil
err = fmt.Errorf("empty response")
err = fmt.Errorf("%s", i18n.T("chatter_error_empty_response"))
return
}
@@ -137,17 +146,17 @@ func (o *Chatter) Send(request *domain.ChatRequest, opts *domain.ChatOptions) (s
if request.PatternName == "create_coding_feature" {
summary, fileChanges, parseErr := domain.ParseFileChanges(message)
if parseErr != nil {
fmt.Printf("Warning: Failed to parse file changes: %v\n", parseErr)
fmt.Printf("%s\n", fmt.Sprintf(i18n.T("chatter_warning_parse_file_changes_failed"), parseErr))
} else if len(fileChanges) > 0 {
projectRoot, err := os.Getwd()
if err != nil {
fmt.Printf("Warning: Failed to get current directory: %v\n", err)
fmt.Printf("%s\n", fmt.Sprintf(i18n.T("chatter_warning_get_current_directory_failed"), err))
} else {
if applyErr := domain.ApplyFileChanges(projectRoot, fileChanges); applyErr != nil {
fmt.Printf("Warning: Failed to apply file changes: %v\n", applyErr)
fmt.Printf("%s\n", fmt.Sprintf(i18n.T("chatter_warning_apply_file_changes_failed"), applyErr))
} else {
fmt.Println("Successfully applied file changes.")
fmt.Printf("You can review the changes with 'git diff' if you're using git.\n\n")
fmt.Println(i18n.T("chatter_info_file_changes_applied_successfully"))
fmt.Printf("%s\n\n", i18n.T("chatter_help_review_changes_with_git_diff"))
}
}
}
@@ -166,7 +175,7 @@ func (o *Chatter) BuildSession(request *domain.ChatRequest, raw bool) (session *
if request.SessionName != "" {
var sess *fsdb.Session
if sess, err = o.db.Sessions.Get(request.SessionName); err != nil {
err = fmt.Errorf("could not find session %s: %v", request.SessionName, err)
err = fmt.Errorf(i18n.T("chatter_error_find_session"), request.SessionName, err)
return
}
session = sess
@@ -183,7 +192,7 @@ func (o *Chatter) BuildSession(request *domain.ChatRequest, raw bool) (session *
if request.ContextName != "" {
var ctx *fsdb.Context
if ctx, err = o.db.Contexts.Get(request.ContextName); err != nil {
err = fmt.Errorf("could not find context %s: %v", request.ContextName, err)
err = fmt.Errorf(i18n.T("chatter_error_find_context"), request.ContextName, err)
return
}
contextContent = ctx.Content
@@ -218,7 +227,7 @@ func (o *Chatter) BuildSession(request *domain.ChatRequest, raw bool) (session *
}
if err != nil {
return nil, fmt.Errorf("could not get pattern %s: %v", request.PatternName, err)
return nil, fmt.Errorf(i18n.T("chatter_error_get_pattern"), request.PatternName, err)
}
patternContent = pattern.Pattern
inputUsed = true
@@ -229,7 +238,7 @@ func (o *Chatter) BuildSession(request *domain.ChatRequest, raw bool) (session *
if request.StrategyName != "" {
strategy, err := strategy.LoadStrategy(request.StrategyName)
if err != nil {
return nil, fmt.Errorf("could not load strategy %s: %v", request.StrategyName, err)
return nil, fmt.Errorf(i18n.T("chatter_error_load_strategy"), request.StrategyName, err)
}
if strategy != nil && strategy.Prompt != "" {
// prepend the strategy prompt to the system message
@@ -240,7 +249,7 @@ func (o *Chatter) BuildSession(request *domain.ChatRequest, raw bool) (session *
// Apply refined language instruction if specified
if request.Language != "" && request.Language != "en" {
// Refined instruction: Execute pattern using user input, then translate the entire response.
systemMessage = fmt.Sprintf("%s\n\nIMPORTANT: First, execute the instructions provided in this prompt using the user's input. Second, ensure your entire final response, including any section headers or titles generated as part of executing the instructions, is written ONLY in the %s language.", systemMessage, request.Language)
systemMessage = fmt.Sprintf(i18n.T("chatter_prompt_enforce_response_language"), systemMessage, request.Language)
}
if raw {
@@ -295,7 +304,7 @@ func (o *Chatter) BuildSession(request *domain.ChatRequest, raw bool) (session *
if session.IsEmpty() {
session = nil
err = errors.New(NoSessionPatternUserMessages)
err = errors.New(i18n.T("chatter_error_no_session_pattern_user_messages"))
}
return
}

View File

@@ -411,4 +411,43 @@
"spotify_failed_parse_search_results": "Suchergebnisse konnten nicht analysiert werden: %w",
"spotify_failed_get_show_episodes": "Show-Episoden konnten nicht abgerufen werden: %w",
"spotify_failed_parse_episodes": "Episoden konnten nicht analysiert werden: %w"
,
"template_file_log_validating_path": "Datei: Pfad %q wird validiert",
"template_file_error_path_contains_parent_ref": "datei: pfad darf '..' nicht enthalten",
"template_file_error_expand_home_dir": "datei: home-verzeichnis konnte nicht erweitert werden: %v",
"template_file_log_cleaned_path": "Datei: bereinigter Pfad %q",
"template_file_log_operation_value": "Datei: operation=%q wert=%q",
"template_file_error_tail_requires_path_lines": "datei: tail erfordert das format pfad|zeilen",
"template_file_error_invalid_line_count": "datei: ungültige zeilenanzahl %q",
"template_file_error_line_count_positive": "datei: zeilenanzahl muss positiv sein",
"template_file_log_tail_returning_lines": "Datei: tail gibt %d Zeilen zurück",
"template_file_error_stat_file": "datei: dateistatus konnte nicht gelesen werden: %v",
"template_file_error_size_exceeds_limit": "datei: größe %d überschreitet das limit von %d bytes",
"template_file_error_read_file": "datei: konnte nicht gelesen werden: %v",
"template_file_log_read_bytes": "Datei: %d Bytes gelesen",
"template_file_log_exists_for_path": "Datei: exists=%v für Pfad %q",
"template_file_log_size_for_path": "Datei: größe=%d für Pfad %q",
"template_file_log_modified_for_path": "Datei: geändert=%q für Pfad %q",
"template_file_error_unknown_operation": "datei: unbekannte operation %q (unterstützt: read, tail, exists, size, modified)",
"template_file_log_reading_last_lines": "Datei: lese die letzten %d Zeilen aus %q",
"template_file_error_open_file": "datei: konnte nicht geöffnet werden: %v",
"template_file_error_stat_open_file": "datei: status konnte nicht gelesen werden: %v",
"template_file_error_scanner_read": "datei: fehler beim lesen: %v",
"template_file_log_read_total_return_last": "Datei: insgesamt %d Zeilen gelesen, letzte %d werden zurückgegeben",
"chatter_error_no_session_pattern_user_messages": "keine Sitzung, kein Pattern oder keine Benutzernachrichten angegeben",
"chatter_error_no_messages_provided": "keine Nachrichten angegeben",
"chatter_log_stream_usage_metadata": "[Metadaten] Eingabe: %d | Ausgabe: %d | Gesamt: %d",
"chatter_error_stream_update": "Fehler: %s",
"chatter_error_empty_response": "leere Antwort",
"chatter_warning_parse_file_changes_failed": "Warnung: Dateiaenderungen konnten nicht geparst werden: %v",
"chatter_warning_get_current_directory_failed": "Warnung: Aktuelles Verzeichnis konnte nicht ermittelt werden: %v",
"chatter_warning_apply_file_changes_failed": "Warnung: Dateiaenderungen konnten nicht angewendet werden: %v",
"chatter_info_file_changes_applied_successfully": "Dateiaenderungen wurden erfolgreich angewendet.",
"chatter_help_review_changes_with_git_diff": "Sie koennen die Aenderungen mit 'git diff' pruefen, wenn Sie git verwenden.",
"chatter_error_find_session": "Sitzung %s konnte nicht gefunden werden: %v",
"chatter_error_find_context": "Kontext %s konnte nicht gefunden werden: %v",
"chatter_error_get_pattern": "Pattern %s konnte nicht geladen werden: %v",
"chatter_error_load_strategy": "Strategie %s konnte nicht geladen werden: %v",
"chatter_prompt_enforce_response_language": "%s\n\nWICHTIG: Fuehren Sie zuerst die in diesem Prompt bereitgestellten Anweisungen mit der Eingabe des Benutzers aus. Stellen Sie zweitens sicher, dass Ihre gesamte endgueltige Antwort, einschliesslich aller Abschnittsueberschriften oder Titel, die bei der Ausfuehrung der Anweisungen erzeugt werden, AUSSCHLIESSLICH in der Sprache %s verfasst ist."
}

View File

@@ -411,4 +411,43 @@
"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"
,
"template_file_log_validating_path": "File: validating path %q",
"template_file_error_path_contains_parent_ref": "file: path cannot contain '..'",
"template_file_error_expand_home_dir": "file: could not expand home directory: %v",
"template_file_log_cleaned_path": "File: cleaned path %q",
"template_file_log_operation_value": "File: operation=%q value=%q",
"template_file_error_tail_requires_path_lines": "file: tail requires format path|lines",
"template_file_error_invalid_line_count": "file: invalid line count %q",
"template_file_error_line_count_positive": "file: line count must be positive",
"template_file_log_tail_returning_lines": "File: tail returning %d lines",
"template_file_error_stat_file": "file: could not stat file: %v",
"template_file_error_size_exceeds_limit": "file: size %d exceeds limit of %d bytes",
"template_file_error_read_file": "file: could not read: %v",
"template_file_log_read_bytes": "File: read %d bytes",
"template_file_log_exists_for_path": "File: exists=%v for path %q",
"template_file_log_size_for_path": "File: size=%d for path %q",
"template_file_log_modified_for_path": "File: modified=%q for path %q",
"template_file_error_unknown_operation": "file: unknown operation %q (supported: read, tail, exists, size, modified)",
"template_file_log_reading_last_lines": "File: reading last %d lines from %q",
"template_file_error_open_file": "file: could not open: %v",
"template_file_error_stat_open_file": "file: could not stat: %v",
"template_file_error_scanner_read": "file: error reading: %v",
"template_file_log_read_total_return_last": "File: read %d lines total, returning last %d",
"chatter_error_no_session_pattern_user_messages": "no session, pattern or user messages provided",
"chatter_error_no_messages_provided": "no messages provided",
"chatter_log_stream_usage_metadata": "[Metadata] Input: %d | Output: %d | Total: %d",
"chatter_error_stream_update": "Error: %s",
"chatter_error_empty_response": "empty response",
"chatter_warning_parse_file_changes_failed": "Warning: Failed to parse file changes: %v",
"chatter_warning_get_current_directory_failed": "Warning: Failed to get current directory: %v",
"chatter_warning_apply_file_changes_failed": "Warning: Failed to apply file changes: %v",
"chatter_info_file_changes_applied_successfully": "Successfully applied file changes.",
"chatter_help_review_changes_with_git_diff": "You can review the changes with 'git diff' if you're using git.",
"chatter_error_find_session": "could not find session %s: %v",
"chatter_error_find_context": "could not find context %s: %v",
"chatter_error_get_pattern": "could not get pattern %s: %v",
"chatter_error_load_strategy": "could not load strategy %s: %v",
"chatter_prompt_enforce_response_language": "%s\n\nIMPORTANT: First, execute the instructions provided in this prompt using the user's input. Second, ensure your entire final response, including any section headers or titles generated as part of executing the instructions, is written ONLY in the %s language."
}

View File

@@ -411,4 +411,43 @@
"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"
,
"template_file_log_validating_path": "Archivo: validando ruta %q",
"template_file_error_path_contains_parent_ref": "archivo: la ruta no puede contener '..'",
"template_file_error_expand_home_dir": "archivo: no se pudo expandir el directorio home: %v",
"template_file_log_cleaned_path": "Archivo: ruta limpiada %q",
"template_file_log_operation_value": "Archivo: operación=%q valor=%q",
"template_file_error_tail_requires_path_lines": "archivo: tail requiere el formato ruta|líneas",
"template_file_error_invalid_line_count": "archivo: número de líneas no válido %q",
"template_file_error_line_count_positive": "archivo: el número de líneas debe ser positivo",
"template_file_log_tail_returning_lines": "Archivo: tail devuelve %d líneas",
"template_file_error_stat_file": "archivo: no se pudo obtener el estado del archivo: %v",
"template_file_error_size_exceeds_limit": "archivo: el tamaño %d supera el límite de %d bytes",
"template_file_error_read_file": "archivo: no se pudo leer: %v",
"template_file_log_read_bytes": "Archivo: %d bytes leídos",
"template_file_log_exists_for_path": "Archivo: exists=%v para la ruta %q",
"template_file_log_size_for_path": "Archivo: tamaño=%d para la ruta %q",
"template_file_log_modified_for_path": "Archivo: modified=%q para la ruta %q",
"template_file_error_unknown_operation": "archivo: operación desconocida %q (admitidas: read, tail, exists, size, modified)",
"template_file_log_reading_last_lines": "Archivo: leyendo las últimas %d líneas de %q",
"template_file_error_open_file": "archivo: no se pudo abrir: %v",
"template_file_error_stat_open_file": "archivo: no se pudo obtener el estado: %v",
"template_file_error_scanner_read": "archivo: error al leer: %v",
"template_file_log_read_total_return_last": "Archivo: se leyeron %d líneas en total, devolviendo las últimas %d",
"chatter_error_no_session_pattern_user_messages": "no se proporcionó ninguna sesión, patrón ni mensajes de usuario",
"chatter_error_no_messages_provided": "no se proporcionaron mensajes",
"chatter_log_stream_usage_metadata": "[Metadatos] Entrada: %d | Salida: %d | Total: %d",
"chatter_error_stream_update": "Error: %s",
"chatter_error_empty_response": "respuesta vacía",
"chatter_warning_parse_file_changes_failed": "Advertencia: No se pudieron analizar los cambios de archivo: %v",
"chatter_warning_get_current_directory_failed": "Advertencia: No se pudo obtener el directorio actual: %v",
"chatter_warning_apply_file_changes_failed": "Advertencia: No se pudieron aplicar los cambios de archivo: %v",
"chatter_info_file_changes_applied_successfully": "Los cambios de archivo se aplicaron correctamente.",
"chatter_help_review_changes_with_git_diff": "Puede revisar los cambios con 'git diff' si esta usando git.",
"chatter_error_find_session": "no se pudo encontrar la sesion %s: %v",
"chatter_error_find_context": "no se pudo encontrar el contexto %s: %v",
"chatter_error_get_pattern": "no se pudo obtener el patron %s: %v",
"chatter_error_load_strategy": "no se pudo cargar la estrategia %s: %v",
"chatter_prompt_enforce_response_language": "%s\n\nIMPORTANTE: Primero, ejecute las instrucciones proporcionadas en este prompt usando la entrada del usuario. Segundo, asegurese de que toda su respuesta final, incluidos los encabezados de seccion o titulos generados como parte de la ejecucion de las instrucciones, este escrita SOLO en el idioma %s."
}

View File

@@ -403,4 +403,43 @@
"spotify_failed_parse_search_results": "تجزیه نتایج جستجو ناموفق بود: %w",
"spotify_failed_get_show_episodes": "دریافت قسمت‌های برنامه ناموفق بود: %w",
"spotify_failed_parse_episodes": "تجزیه قسمت‌ها ناموفق بود: %w"
,
"template_file_log_validating_path": "فایل: در حال اعتبارسنجی مسیر %q",
"template_file_error_path_contains_parent_ref": "فایل: مسیر نمی‌تواند '..' داشته باشد",
"template_file_error_expand_home_dir": "فایل: گسترش پوشه خانگی ممکن نشد: %v",
"template_file_log_cleaned_path": "فایل: مسیر پاک‌سازی‌شده %q",
"template_file_log_operation_value": "فایل: operation=%q value=%q",
"template_file_error_tail_requires_path_lines": "فایل: tail به قالب path|lines نیاز دارد",
"template_file_error_invalid_line_count": "فایل: تعداد خط نامعتبر %q",
"template_file_error_line_count_positive": "فایل: تعداد خط باید مثبت باشد",
"template_file_log_tail_returning_lines": "فایل: tail در حال بازگرداندن %d خط است",
"template_file_error_stat_file": "فایل: دریافت وضعیت فایل ممکن نشد: %v",
"template_file_error_size_exceeds_limit": "فایل: اندازه %d از محدودیت %d بایت بیشتر است",
"template_file_error_read_file": "فایل: خواندن ممکن نشد: %v",
"template_file_log_read_bytes": "فایل: %d بایت خوانده شد",
"template_file_log_exists_for_path": "فایل: exists=%v برای مسیر %q",
"template_file_log_size_for_path": "فایل: size=%d برای مسیر %q",
"template_file_log_modified_for_path": "فایل: modified=%q برای مسیر %q",
"template_file_error_unknown_operation": "فایل: عملیات ناشناخته %q (پشتیبانی‌شده: read, tail, exists, size, modified)",
"template_file_log_reading_last_lines": "فایل: در حال خواندن %d خط آخر از %q",
"template_file_error_open_file": "فایل: باز کردن ممکن نشد: %v",
"template_file_error_stat_open_file": "فایل: دریافت وضعیت ممکن نشد: %v",
"template_file_error_scanner_read": "فایل: خطا در خواندن: %v",
"template_file_log_read_total_return_last": "فایل: در مجموع %d خط خوانده شد، %d خط آخر بازگردانده می‌شود",
"chatter_error_no_session_pattern_user_messages": "هیچ نشست، الگو یا پیام کاربری ارائه نشده است",
"chatter_error_no_messages_provided": "هیچ پیامی ارائه نشده است",
"chatter_log_stream_usage_metadata": "[فراداده] ورودی: %d | خروجی: %d | مجموع: %d",
"chatter_error_stream_update": "خطا: %s",
"chatter_error_empty_response": "پاسخ خالی",
"chatter_warning_parse_file_changes_failed": "هشدار: تجزیه تغییرات فایل ناموفق بود: %v",
"chatter_warning_get_current_directory_failed": "هشدار: دریافت پوشه جاری ناموفق بود: %v",
"chatter_warning_apply_file_changes_failed": "هشدار: اعمال تغییرات فایل ناموفق بود: %v",
"chatter_info_file_changes_applied_successfully": "تغییرات فایل با موفقیت اعمال شد.",
"chatter_help_review_changes_with_git_diff": "اگر از git استفاده مي‌کنيد، مي‌توانيد تغييرات را با 'git diff' بررسي کنيد.",
"chatter_error_find_session": "نشست %s پيدا نشد: %v",
"chatter_error_find_context": "زمينه %s پيدا نشد: %v",
"chatter_error_get_pattern": "دريافت الگو %s ممکن نشد: %v",
"chatter_error_load_strategy": "بارگذاري راهبرد %s ممکن نشد: %v",
"chatter_prompt_enforce_response_language": "%s\n\nمهم: ابتدا دستورالعمل‌هاي ارائه‌شده در اين پرامپت را با استفاده از ورودي کاربر اجرا کنيد. سپس اطمينان حاصل کنيد که کل پاسخ نهايي شما، از جمله هر عنوان يا سربخشي که در جريان اجراي دستورالعمل‌ها توليد مي‌شود، فقط به زبان %s نوشته شده باشد."
}

View File

@@ -411,4 +411,43 @@
"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"
,
"template_file_log_validating_path": "Fichier : validation du chemin %q",
"template_file_error_path_contains_parent_ref": "fichier : le chemin ne peut pas contenir '..'",
"template_file_error_expand_home_dir": "fichier : impossible d'étendre le répertoire personnel : %v",
"template_file_log_cleaned_path": "Fichier : chemin nettoyé %q",
"template_file_log_operation_value": "Fichier : opération=%q valeur=%q",
"template_file_error_tail_requires_path_lines": "fichier : tail nécessite le format chemin|lignes",
"template_file_error_invalid_line_count": "fichier : nombre de lignes invalide %q",
"template_file_error_line_count_positive": "fichier : le nombre de lignes doit être positif",
"template_file_log_tail_returning_lines": "Fichier : tail renvoie %d lignes",
"template_file_error_stat_file": "fichier : impossible d'obtenir l'état du fichier : %v",
"template_file_error_size_exceeds_limit": "fichier : la taille %d dépasse la limite de %d octets",
"template_file_error_read_file": "fichier : lecture impossible : %v",
"template_file_log_read_bytes": "Fichier : %d octets lus",
"template_file_log_exists_for_path": "Fichier : exists=%v pour le chemin %q",
"template_file_log_size_for_path": "Fichier : taille=%d pour le chemin %q",
"template_file_log_modified_for_path": "Fichier : modifié=%q pour le chemin %q",
"template_file_error_unknown_operation": "fichier : opération inconnue %q (prises en charge : read, tail, exists, size, modified)",
"template_file_log_reading_last_lines": "Fichier : lecture des %d dernières lignes depuis %q",
"template_file_error_open_file": "fichier : ouverture impossible : %v",
"template_file_error_stat_open_file": "fichier : impossible d'obtenir l'état : %v",
"template_file_error_scanner_read": "fichier : erreur de lecture : %v",
"template_file_log_read_total_return_last": "Fichier : %d lignes lues au total, retour des %d dernières",
"chatter_error_no_session_pattern_user_messages": "aucune session, aucun modèle ni message utilisateur fourni",
"chatter_error_no_messages_provided": "aucun message fourni",
"chatter_log_stream_usage_metadata": "[Métadonnées] Entrée : %d | Sortie : %d | Total : %d",
"chatter_error_stream_update": "Erreur : %s",
"chatter_error_empty_response": "réponse vide",
"chatter_warning_parse_file_changes_failed": "Avertissement : echec de l'analyse des modifications de fichiers : %v",
"chatter_warning_get_current_directory_failed": "Avertissement : echec de l'obtention du repertoire courant : %v",
"chatter_warning_apply_file_changes_failed": "Avertissement : echec de l'application des modifications de fichiers : %v",
"chatter_info_file_changes_applied_successfully": "Les modifications de fichiers ont ete appliquees avec succes.",
"chatter_help_review_changes_with_git_diff": "Vous pouvez verifier les modifications avec 'git diff' si vous utilisez git.",
"chatter_error_find_session": "impossible de trouver la session %s : %v",
"chatter_error_find_context": "impossible de trouver le contexte %s : %v",
"chatter_error_get_pattern": "impossible d'obtenir le modele %s : %v",
"chatter_error_load_strategy": "impossible de charger la strategie %s : %v",
"chatter_prompt_enforce_response_language": "%s\n\nIMPORTANT : D'abord, executez les instructions fournies dans ce prompt en utilisant l'entree de l'utilisateur. Ensuite, assurez-vous que l'integralite de votre reponse finale, y compris tous les en-tetes de section ou titres generes lors de l'execution des instructions, soit redigee UNIQUEMENT en langue %s."
}

View File

@@ -411,4 +411,43 @@
"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"
,
"template_file_log_validating_path": "File: convalida del percorso %q",
"template_file_error_path_contains_parent_ref": "file: il percorso non può contenere '..'",
"template_file_error_expand_home_dir": "file: impossibile espandere la directory home: %v",
"template_file_log_cleaned_path": "File: percorso pulito %q",
"template_file_log_operation_value": "File: operazione=%q valore=%q",
"template_file_error_tail_requires_path_lines": "file: tail richiede il formato percorso|righe",
"template_file_error_invalid_line_count": "file: numero di righe non valido %q",
"template_file_error_line_count_positive": "file: il numero di righe deve essere positivo",
"template_file_log_tail_returning_lines": "File: tail restituisce %d righe",
"template_file_error_stat_file": "file: impossibile ottenere lo stato del file: %v",
"template_file_error_size_exceeds_limit": "file: la dimensione %d supera il limite di %d byte",
"template_file_error_read_file": "file: impossibile leggere: %v",
"template_file_log_read_bytes": "File: letti %d byte",
"template_file_log_exists_for_path": "File: exists=%v per il percorso %q",
"template_file_log_size_for_path": "File: dimensione=%d per il percorso %q",
"template_file_log_modified_for_path": "File: modificato=%q per il percorso %q",
"template_file_error_unknown_operation": "file: operazione sconosciuta %q (supportate: read, tail, exists, size, modified)",
"template_file_log_reading_last_lines": "File: lettura delle ultime %d righe da %q",
"template_file_error_open_file": "file: impossibile aprire: %v",
"template_file_error_stat_open_file": "file: impossibile ottenere lo stato: %v",
"template_file_error_scanner_read": "file: errore durante la lettura: %v",
"template_file_log_read_total_return_last": "File: lette %d righe totali, restituzione delle ultime %d",
"chatter_error_no_session_pattern_user_messages": "nessuna sessione, pattern o messaggio utente fornito",
"chatter_error_no_messages_provided": "nessun messaggio fornito",
"chatter_log_stream_usage_metadata": "[Metadati] Input: %d | Output: %d | Totale: %d",
"chatter_error_stream_update": "Errore: %s",
"chatter_error_empty_response": "risposta vuota",
"chatter_warning_parse_file_changes_failed": "Avviso: analisi delle modifiche ai file non riuscita: %v",
"chatter_warning_get_current_directory_failed": "Avviso: impossibile ottenere la directory corrente: %v",
"chatter_warning_apply_file_changes_failed": "Avviso: impossibile applicare le modifiche ai file: %v",
"chatter_info_file_changes_applied_successfully": "Modifiche ai file applicate con successo.",
"chatter_help_review_changes_with_git_diff": "Puoi rivedere le modifiche con 'git diff' se stai usando git.",
"chatter_error_find_session": "impossibile trovare la sessione %s: %v",
"chatter_error_find_context": "impossibile trovare il contesto %s: %v",
"chatter_error_get_pattern": "impossibile ottenere il pattern %s: %v",
"chatter_error_load_strategy": "impossibile caricare la strategia %s: %v",
"chatter_prompt_enforce_response_language": "%s\n\nIMPORTANTE: Per prima cosa, esegui le istruzioni fornite in questo prompt usando l'input dell'utente. In secondo luogo, assicurati che l'intera risposta finale, inclusi eventuali titoli o intestazioni di sezione generati durante l'esecuzione delle istruzioni, sia scritta SOLO nella lingua %s."
}

View File

@@ -411,4 +411,43 @@
"spotify_failed_parse_search_results": "検索結果の解析に失敗しました: %w",
"spotify_failed_get_show_episodes": "番組エピソードの取得に失敗しました: %w",
"spotify_failed_parse_episodes": "エピソードの解析に失敗しました: %w"
,
"template_file_log_validating_path": "File: パス %q を検証中",
"template_file_error_path_contains_parent_ref": "file: パスに '..' を含めることはできません",
"template_file_error_expand_home_dir": "file: ホームディレクトリを展開できませんでした: %v",
"template_file_log_cleaned_path": "File: 正規化後のパス %q",
"template_file_log_operation_value": "File: operation=%q value=%q",
"template_file_error_tail_requires_path_lines": "file: tail には path|lines 形式が必要です",
"template_file_error_invalid_line_count": "file: 無効な行数 %q",
"template_file_error_line_count_positive": "file: 行数は正の値である必要があります",
"template_file_log_tail_returning_lines": "File: tail は %d 行を返します",
"template_file_error_stat_file": "file: ファイルの状態を取得できませんでした: %v",
"template_file_error_size_exceeds_limit": "file: サイズ %d は上限 %d バイトを超えています",
"template_file_error_read_file": "file: 読み取れませんでした: %v",
"template_file_log_read_bytes": "File: %d バイトを読み取りました",
"template_file_log_exists_for_path": "File: パス %q の exists=%v",
"template_file_log_size_for_path": "File: パス %q の size=%d",
"template_file_log_modified_for_path": "File: パス %q の modified=%q",
"template_file_error_unknown_operation": "file: 不明な操作 %q対応: read, tail, exists, size, modified",
"template_file_log_reading_last_lines": "File: %q から最後の %d 行を読み取り中",
"template_file_error_open_file": "file: 開けませんでした: %v",
"template_file_error_stat_open_file": "file: 状態を取得できませんでした: %v",
"template_file_error_scanner_read": "file: 読み取りエラー: %v",
"template_file_log_read_total_return_last": "File: 合計 %d 行を読み取り、最後の %d 行を返します",
"chatter_error_no_session_pattern_user_messages": "セッション、パターン、またはユーザーメッセージが指定されていません",
"chatter_error_no_messages_provided": "メッセージが指定されていません",
"chatter_log_stream_usage_metadata": "[メタデータ] 入力: %d | 出力: %d | 合計: %d",
"chatter_error_stream_update": "エラー: %s",
"chatter_error_empty_response": "空の応答",
"chatter_warning_parse_file_changes_failed": "警告: ファイル変更の解析に失敗しました: %v",
"chatter_warning_get_current_directory_failed": "警告: 現在のディレクトリの取得に失敗しました: %v",
"chatter_warning_apply_file_changes_failed": "警告: ファイル変更の適用に失敗しました: %v",
"chatter_info_file_changes_applied_successfully": "ファイル変更を正常に適用しました。",
"chatter_help_review_changes_with_git_diff": "git を使用している場合は、'git diff' で変更を確認できます。",
"chatter_error_find_session": "セッション %s が見つかりませんでした: %v",
"chatter_error_find_context": "コンテキスト %s が見つかりませんでした: %v",
"chatter_error_get_pattern": "パターン %s を取得できませんでした: %v",
"chatter_error_load_strategy": "戦略 %s を読み込めませんでした: %v",
"chatter_prompt_enforce_response_language": "%s\n\n重要: まず、このプロンプトで提供された指示をユーザー入力を使って実行してください。次に、指示の実行中に生成されるセクション見出しやタイトルを含む最終回答全体を、必ず %s 言語のみで記述してください。"
}

View File

@@ -411,4 +411,43 @@
"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"
,
"template_file_log_validating_path": "Arquivo: validando caminho %q",
"template_file_error_path_contains_parent_ref": "arquivo: o caminho não pode conter '..'",
"template_file_error_expand_home_dir": "arquivo: não foi possível expandir o diretório home: %v",
"template_file_log_cleaned_path": "Arquivo: caminho limpo %q",
"template_file_log_operation_value": "Arquivo: operação=%q valor=%q",
"template_file_error_tail_requires_path_lines": "arquivo: tail requer o formato caminho|linhas",
"template_file_error_invalid_line_count": "arquivo: contagem de linhas inválida %q",
"template_file_error_line_count_positive": "arquivo: a contagem de linhas deve ser positiva",
"template_file_log_tail_returning_lines": "Arquivo: tail retornando %d linhas",
"template_file_error_stat_file": "arquivo: não foi possível obter o estado do arquivo: %v",
"template_file_error_size_exceeds_limit": "arquivo: tamanho %d excede o limite de %d bytes",
"template_file_error_read_file": "arquivo: não foi possível ler: %v",
"template_file_log_read_bytes": "Arquivo: %d bytes lidos",
"template_file_log_exists_for_path": "Arquivo: exists=%v para o caminho %q",
"template_file_log_size_for_path": "Arquivo: tamanho=%d para o caminho %q",
"template_file_log_modified_for_path": "Arquivo: modified=%q para o caminho %q",
"template_file_error_unknown_operation": "arquivo: operação desconhecida %q (suportadas: read, tail, exists, size, modified)",
"template_file_log_reading_last_lines": "Arquivo: lendo as últimas %d linhas de %q",
"template_file_error_open_file": "arquivo: não foi possível abrir: %v",
"template_file_error_stat_open_file": "arquivo: não foi possível obter o estado: %v",
"template_file_error_scanner_read": "arquivo: erro ao ler: %v",
"template_file_log_read_total_return_last": "Arquivo: %d linhas lidas no total, retornando as últimas %d",
"chatter_error_no_session_pattern_user_messages": "nenhuma sessão, padrão ou mensagem do usuário fornecida",
"chatter_error_no_messages_provided": "nenhuma mensagem fornecida",
"chatter_log_stream_usage_metadata": "[Metadados] Entrada: %d | Saída: %d | Total: %d",
"chatter_error_stream_update": "Erro: %s",
"chatter_error_empty_response": "resposta vazia",
"chatter_warning_parse_file_changes_failed": "Aviso: Falha ao analisar alteracoes de arquivo: %v",
"chatter_warning_get_current_directory_failed": "Aviso: Falha ao obter o diretorio atual: %v",
"chatter_warning_apply_file_changes_failed": "Aviso: Falha ao aplicar alteracoes de arquivo: %v",
"chatter_info_file_changes_applied_successfully": "Alteracoes de arquivo aplicadas com sucesso.",
"chatter_help_review_changes_with_git_diff": "Voce pode revisar as alteracoes com 'git diff' se estiver usando git.",
"chatter_error_find_session": "nao foi possivel encontrar a sessao %s: %v",
"chatter_error_find_context": "nao foi possivel encontrar o contexto %s: %v",
"chatter_error_get_pattern": "nao foi possivel obter o padrao %s: %v",
"chatter_error_load_strategy": "nao foi possivel carregar a estrategia %s: %v",
"chatter_prompt_enforce_response_language": "%s\n\nIMPORTANTE: Primeiro, execute as instrucoes fornecidas neste prompt usando a entrada do usuario. Em seguida, garanta que toda a sua resposta final, incluindo quaisquer cabecalhos de secao ou titulos gerados como parte da execucao das instrucoes, seja escrita SOMENTE no idioma %s."
}

View File

@@ -411,4 +411,43 @@
"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"
,
"template_file_log_validating_path": "Ficheiro: a validar caminho %q",
"template_file_error_path_contains_parent_ref": "ficheiro: o caminho não pode conter '..'",
"template_file_error_expand_home_dir": "ficheiro: não foi possível expandir a diretoria home: %v",
"template_file_log_cleaned_path": "Ficheiro: caminho limpo %q",
"template_file_log_operation_value": "Ficheiro: operação=%q valor=%q",
"template_file_error_tail_requires_path_lines": "ficheiro: tail requer o formato caminho|linhas",
"template_file_error_invalid_line_count": "ficheiro: contagem de linhas inválida %q",
"template_file_error_line_count_positive": "ficheiro: a contagem de linhas tem de ser positiva",
"template_file_log_tail_returning_lines": "Ficheiro: tail a devolver %d linhas",
"template_file_error_stat_file": "ficheiro: não foi possível obter o estado do ficheiro: %v",
"template_file_error_size_exceeds_limit": "ficheiro: o tamanho %d excede o limite de %d bytes",
"template_file_error_read_file": "ficheiro: não foi possível ler: %v",
"template_file_log_read_bytes": "Ficheiro: %d bytes lidos",
"template_file_log_exists_for_path": "Ficheiro: exists=%v para o caminho %q",
"template_file_log_size_for_path": "Ficheiro: tamanho=%d para o caminho %q",
"template_file_log_modified_for_path": "Ficheiro: modified=%q para o caminho %q",
"template_file_error_unknown_operation": "ficheiro: operação desconhecida %q (suportadas: read, tail, exists, size, modified)",
"template_file_log_reading_last_lines": "Ficheiro: a ler as últimas %d linhas de %q",
"template_file_error_open_file": "ficheiro: não foi possível abrir: %v",
"template_file_error_stat_open_file": "ficheiro: não foi possível obter o estado: %v",
"template_file_error_scanner_read": "ficheiro: erro ao ler: %v",
"template_file_log_read_total_return_last": "Ficheiro: %d linhas lidas no total, a devolver as últimas %d",
"chatter_error_no_session_pattern_user_messages": "não foi fornecida nenhuma sessão, padrão ou mensagem do utilizador",
"chatter_error_no_messages_provided": "não foram fornecidas mensagens",
"chatter_log_stream_usage_metadata": "[Metadados] Entrada: %d | Saída: %d | Total: %d",
"chatter_error_stream_update": "Erro: %s",
"chatter_error_empty_response": "resposta vazia",
"chatter_warning_parse_file_changes_failed": "Aviso: Falha ao analisar alteracoes de ficheiro: %v",
"chatter_warning_get_current_directory_failed": "Aviso: Falha ao obter a diretoria atual: %v",
"chatter_warning_apply_file_changes_failed": "Aviso: Falha ao aplicar alteracoes de ficheiro: %v",
"chatter_info_file_changes_applied_successfully": "Alteracoes de ficheiro aplicadas com sucesso.",
"chatter_help_review_changes_with_git_diff": "Pode rever as alteracoes com 'git diff' se estiver a usar git.",
"chatter_error_find_session": "nao foi possivel encontrar a sessao %s: %v",
"chatter_error_find_context": "nao foi possivel encontrar o contexto %s: %v",
"chatter_error_get_pattern": "nao foi possivel obter o padrao %s: %v",
"chatter_error_load_strategy": "nao foi possivel carregar a estrategia %s: %v",
"chatter_prompt_enforce_response_language": "%s\n\nIMPORTANTE: Primeiro, execute as instrucoes fornecidas neste prompt usando a entrada do utilizador. Em seguida, garanta que toda a sua resposta final, incluindo quaisquer cabecalhos de secao ou titulos gerados como parte da execucao das instrucoes, seja escrita APENAS no idioma %s."
}

View File

@@ -411,4 +411,43 @@
"spotify_failed_parse_search_results": "解析搜索结果失败:%w",
"spotify_failed_get_show_episodes": "获取节目剧集失败:%w",
"spotify_failed_parse_episodes": "解析剧集失败:%w"
,
"template_file_log_validating_path": "文件:正在验证路径 %q",
"template_file_error_path_contains_parent_ref": "file: 路径不能包含 '..'",
"template_file_error_expand_home_dir": "file: 无法展开主目录: %v",
"template_file_log_cleaned_path": "文件:清理后的路径 %q",
"template_file_log_operation_value": "文件operation=%q value=%q",
"template_file_error_tail_requires_path_lines": "file: tail 需要 path|lines 格式",
"template_file_error_invalid_line_count": "file: 无效的行数 %q",
"template_file_error_line_count_positive": "file: 行数必须为正数",
"template_file_log_tail_returning_lines": "文件tail 返回 %d 行",
"template_file_error_stat_file": "file: 无法获取文件状态: %v",
"template_file_error_size_exceeds_limit": "file: 大小 %d 超过 %d 字节限制",
"template_file_error_read_file": "file: 无法读取: %v",
"template_file_log_read_bytes": "文件:已读取 %d 字节",
"template_file_log_exists_for_path": "文件:路径 %q 的 exists=%v",
"template_file_log_size_for_path": "文件:路径 %q 的 size=%d",
"template_file_log_modified_for_path": "文件:路径 %q 的 modified=%q",
"template_file_error_unknown_operation": "file: 未知操作 %q支持: read, tail, exists, size, modified",
"template_file_log_reading_last_lines": "文件:正在从 %q 读取最后 %d 行",
"template_file_error_open_file": "file: 无法打开: %v",
"template_file_error_stat_open_file": "file: 无法获取状态: %v",
"template_file_error_scanner_read": "file: 读取时出错: %v",
"template_file_log_read_total_return_last": "文件:共读取 %d 行,返回最后 %d 行",
"chatter_error_no_session_pattern_user_messages": "未提供会话、模式或用户消息",
"chatter_error_no_messages_provided": "未提供消息",
"chatter_log_stream_usage_metadata": "[元数据] 输入: %d | 输出: %d | 总计: %d",
"chatter_error_stream_update": "错误:%s",
"chatter_error_empty_response": "空响应",
"chatter_warning_parse_file_changes_failed": "警告:解析文件更改失败:%v",
"chatter_warning_get_current_directory_failed": "警告:获取当前目录失败:%v",
"chatter_warning_apply_file_changes_failed": "警告:应用文件更改失败:%v",
"chatter_info_file_changes_applied_successfully": "文件更改已成功应用。",
"chatter_help_review_changes_with_git_diff": "如果你正在使用 git可以用 'git diff' 查看这些更改。",
"chatter_error_find_session": "找不到会话 %s%v",
"chatter_error_find_context": "找不到上下文 %s%v",
"chatter_error_get_pattern": "无法获取模式 %s%v",
"chatter_error_load_strategy": "无法加载策略 %s%v",
"chatter_prompt_enforce_response_language": "%s\n\n重要首先请使用用户输入执行此提示中提供的指令。其次请确保你的整个最终回复包括执行指令时生成的任何章节标题或标题仅使用 %s 语言撰写。"
}

View File

@@ -11,6 +11,8 @@ import (
"strconv"
"strings"
"time"
"github.com/danielmiessler/fabric/internal/i18n"
)
// MaxFileSize defines the maximum file size that can be read (1MB)
@@ -24,25 +26,25 @@ type FilePlugin struct{}
// safePath validates and normalizes file paths
func (p *FilePlugin) safePath(path string) (string, error) {
debugf("File: validating path %q", path)
debugf(i18n.T("template_file_log_validating_path"), path)
// Basic security check - no path traversal
if strings.Contains(path, "..") {
return "", fmt.Errorf("file: path cannot contain '..'")
return "", fmt.Errorf("%s", i18n.T("template_file_error_path_contains_parent_ref"))
}
// Expand home directory if needed
if strings.HasPrefix(path, "~/") {
home, err := os.UserHomeDir()
if err != nil {
return "", fmt.Errorf("file: could not expand home directory: %v", err)
return "", fmt.Errorf(i18n.T("template_file_error_expand_home_dir"), err)
}
path = filepath.Join(home, path[2:])
}
// Clean the path
cleaned := filepath.Clean(path)
debugf("File: cleaned path %q", cleaned)
debugf(i18n.T("template_file_log_cleaned_path"), cleaned)
return cleaned, nil
}
@@ -53,13 +55,13 @@ func (p *FilePlugin) safePath(path string) (string, error) {
// - size:PATH - Get file size in bytes
// - modified:PATH - Get last modified time
func (p *FilePlugin) Apply(operation string, value string) (string, error) {
debugf("File: operation=%q value=%q", operation, value)
debugf(i18n.T("template_file_log_operation_value"), operation, value)
switch operation {
case "tail":
parts := strings.Split(value, "|")
if len(parts) != 2 {
return "", fmt.Errorf("file: tail requires format path|lines")
return "", fmt.Errorf("%s", i18n.T("template_file_error_tail_requires_path_lines"))
}
path, err := p.safePath(parts[0])
@@ -69,11 +71,11 @@ func (p *FilePlugin) Apply(operation string, value string) (string, error) {
n, err := strconv.Atoi(parts[1])
if err != nil {
return "", fmt.Errorf("file: invalid line count %q", parts[1])
return "", fmt.Errorf(i18n.T("template_file_error_invalid_line_count"), parts[1])
}
if n < 1 {
return "", fmt.Errorf("file: line count must be positive")
return "", fmt.Errorf("%s", i18n.T("template_file_error_line_count_positive"))
}
lines, err := p.lastNLines(path, n)
@@ -82,7 +84,7 @@ func (p *FilePlugin) Apply(operation string, value string) (string, error) {
}
result := strings.Join(lines, "\n")
debugf("File: tail returning %d lines", len(lines))
debugf(i18n.T("template_file_log_tail_returning_lines"), len(lines))
return result, nil
case "read":
@@ -93,20 +95,20 @@ func (p *FilePlugin) Apply(operation string, value string) (string, error) {
info, err := os.Stat(path)
if err != nil {
return "", fmt.Errorf("file: could not stat file: %v", err)
return "", fmt.Errorf(i18n.T("template_file_error_stat_file"), err)
}
if info.Size() > MaxFileSize {
return "", fmt.Errorf("file: size %d exceeds limit of %d bytes",
return "", fmt.Errorf(i18n.T("template_file_error_size_exceeds_limit"),
info.Size(), MaxFileSize)
}
content, err := os.ReadFile(path)
if err != nil {
return "", fmt.Errorf("file: could not read: %v", err)
return "", fmt.Errorf(i18n.T("template_file_error_read_file"), err)
}
debugf("File: read %d bytes", len(content))
debugf(i18n.T("template_file_log_read_bytes"), len(content))
return string(content), nil
case "exists":
@@ -117,7 +119,7 @@ func (p *FilePlugin) Apply(operation string, value string) (string, error) {
_, err = os.Stat(path)
exists := err == nil
debugf("File: exists=%v for path %q", exists, path)
debugf(i18n.T("template_file_log_exists_for_path"), exists, path)
return fmt.Sprintf("%t", exists), nil
case "size":
@@ -128,11 +130,11 @@ func (p *FilePlugin) Apply(operation string, value string) (string, error) {
info, err := os.Stat(path)
if err != nil {
return "", fmt.Errorf("file: could not stat file: %v", err)
return "", fmt.Errorf(i18n.T("template_file_error_stat_file"), err)
}
size := info.Size()
debugf("File: size=%d for path %q", size, path)
debugf(i18n.T("template_file_log_size_for_path"), size, path)
return fmt.Sprintf("%d", size), nil
case "modified":
@@ -143,36 +145,36 @@ func (p *FilePlugin) Apply(operation string, value string) (string, error) {
info, err := os.Stat(path)
if err != nil {
return "", fmt.Errorf("file: could not stat file: %v", err)
return "", fmt.Errorf(i18n.T("template_file_error_stat_file"), err)
}
mtime := info.ModTime().Format(time.RFC3339)
debugf("File: modified=%q for path %q", mtime, path)
debugf(i18n.T("template_file_log_modified_for_path"), mtime, path)
return mtime, nil
default:
return "", fmt.Errorf("file: unknown operation %q (supported: read, tail, exists, size, modified)",
return "", fmt.Errorf(i18n.T("template_file_error_unknown_operation"),
operation)
}
}
// lastNLines returns the last n lines from a file
func (p *FilePlugin) lastNLines(path string, n int) ([]string, error) {
debugf("File: reading last %d lines from %q", n, path)
debugf(i18n.T("template_file_log_reading_last_lines"), n, path)
file, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("file: could not open: %v", err)
return nil, fmt.Errorf(i18n.T("template_file_error_open_file"), err)
}
defer file.Close()
info, err := file.Stat()
if err != nil {
return nil, fmt.Errorf("file: could not stat: %v", err)
return nil, fmt.Errorf(i18n.T("template_file_error_stat_open_file"), err)
}
if info.Size() > MaxFileSize {
return nil, fmt.Errorf("file: size %d exceeds limit of %d bytes",
return nil, fmt.Errorf(i18n.T("template_file_error_size_exceeds_limit"),
info.Size(), MaxFileSize)
}
@@ -189,9 +191,9 @@ func (p *FilePlugin) lastNLines(path string, n int) ([]string, error) {
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("file: error reading: %v", err)
return nil, fmt.Errorf(i18n.T("template_file_error_scanner_read"), err)
}
debugf("File: read %d lines total, returning last %d", lineCount, len(lines))
debugf(i18n.T("template_file_log_read_total_return_last"), lineCount, len(lines))
return lines, nil
}