Add separate logs per run and remove retry functionality that was making things more expensive
This commit is contained in:
parent
7bcc1b4e7b
commit
7ef200c13a
5 changed files with 123 additions and 25 deletions
|
|
@ -179,7 +179,6 @@ if errorlevel 1 (
|
|||
|
||||
echo.
|
||||
echo GUI closed successfully.
|
||||
pause
|
||||
|
||||
:: End of main flow - prevent falling through into subroutines below
|
||||
goto :eof
|
||||
|
|
|
|||
|
|
@ -73,7 +73,12 @@ class LogViewer(QWidget):
|
|||
self._tail_timer.timeout.connect(self._poll_tail)
|
||||
self._tail_interval = 300 # ms
|
||||
self._tail_f = None
|
||||
self._tail_path = Path("log/translationHistory.txt")
|
||||
# Default: prefer the most recent file in log/history, else legacy path
|
||||
try:
|
||||
latest = self._latest_history_file()
|
||||
except Exception:
|
||||
latest = None
|
||||
self._tail_path = latest or Path("log/translationHistory.txt")
|
||||
|
||||
def toggle_auto_refresh(self, enabled):
|
||||
"""Toggle auto-refresh functionality."""
|
||||
|
|
@ -124,8 +129,9 @@ class LogViewer(QWidget):
|
|||
def start_tail(self, file_path: str | Path = None, interval_ms: int = None):
|
||||
"""Start tailing the given log file and append new lines as they arrive.
|
||||
|
||||
By default tails `log/translationHistory.txt`. Seeks to the end so
|
||||
only new lines after this call are shown.
|
||||
By default tails the most recent file in `log/history/` (if present),
|
||||
otherwise falls back to `log/translationHistory.txt`.
|
||||
Seeks to the end so only new lines after this call are shown.
|
||||
"""
|
||||
if file_path:
|
||||
self._tail_path = Path(file_path)
|
||||
|
|
@ -213,3 +219,16 @@ class LogViewer(QWidget):
|
|||
"""Handle widget hide event - pause refresh to save resources."""
|
||||
super().hideEvent(event)
|
||||
# No-op for simplified viewer
|
||||
|
||||
def _latest_history_file(self):
|
||||
"""Return the most recent file in log/history or None if not found."""
|
||||
try:
|
||||
hist_dir = Path("log") / "history"
|
||||
# Ensure history directory exists so callers can rely on it
|
||||
hist_dir.mkdir(parents=True, exist_ok=True)
|
||||
files = [p for p in hist_dir.iterdir() if p.is_file()]
|
||||
if not files:
|
||||
return None
|
||||
return max(files, key=lambda p: p.stat().st_mtime)
|
||||
except Exception:
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ Simple file management and translation execution with console log display.
|
|||
"""
|
||||
|
||||
import os
|
||||
import datetime
|
||||
import subprocess
|
||||
import threading
|
||||
import sys
|
||||
|
|
@ -1549,13 +1550,53 @@ class TranslationTab(QWidget):
|
|||
self.translation_worker.progress_signal.connect(self.update_file_progress)
|
||||
self.translation_worker.item_progress_signal.connect(self.update_item_progress)
|
||||
self.translation_worker.finished_signal.connect(self.on_translation_finished)
|
||||
# Clear and start tailing the translation history so only new
|
||||
# lines are shown in the right-hand log panel.
|
||||
# Prepare a per-run log file in log/history and start tailing it so
|
||||
# the right-hand log panel shows only this run's new lines.
|
||||
try:
|
||||
history_dir = self.project_root / 'log' / 'history'
|
||||
history_dir.mkdir(parents=True, exist_ok=True)
|
||||
# Use timestamp (safe filename) for sorting
|
||||
fname = datetime.datetime.now().strftime('translationHistory_%Y%m%d_%H%M%S.txt')
|
||||
run_log_path = history_dir / fname
|
||||
# Create/touch the file so tailer can open and seek to end
|
||||
run_log_path.touch(exist_ok=True)
|
||||
|
||||
# Export env var so subprocess workers inherit the path
|
||||
try:
|
||||
os.environ['TRANSLATION_RUN_LOG'] = str(run_log_path)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Try to create a hard link at legacy location so modules that
|
||||
# still write to log/translationHistory.txt end up in this file.
|
||||
legacy = self.project_root / 'log' / 'translationHistory.txt'
|
||||
try:
|
||||
# Remove any existing legacy file and create hard link
|
||||
if legacy.exists():
|
||||
try:
|
||||
legacy.unlink()
|
||||
except Exception:
|
||||
pass
|
||||
os.link(str(run_log_path), str(legacy))
|
||||
except Exception:
|
||||
# If hard link fails (Windows permissions or cross-device),
|
||||
# fallback to ensuring the legacy file exists but do not fail.
|
||||
try:
|
||||
legacy.parent.mkdir(parents=True, exist_ok=True)
|
||||
legacy.touch(exist_ok=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Clear UI log and start tailing the per-run file
|
||||
self.translation_log_viewer.clear_log()
|
||||
self.translation_log_viewer.start_tail(self.project_root / 'log' / 'translationHistory.txt')
|
||||
self.translation_log_viewer.start_tail(run_log_path)
|
||||
except Exception:
|
||||
pass
|
||||
# Fallback to legacy file if anything goes wrong
|
||||
try:
|
||||
self.translation_log_viewer.clear_log()
|
||||
self.translation_log_viewer.start_tail(self.project_root / 'log' / 'translationHistory.txt')
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Start the worker
|
||||
self.translation_worker.start()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import sys
|
||||
import os
|
||||
import traceback
|
||||
import datetime
|
||||
from pathlib import Path
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
from colorama import Fore
|
||||
from tqdm import tqdm
|
||||
|
|
@ -132,6 +134,37 @@ files to translate are in the /files folder and that you picked the right game e
|
|||
setSpeakerParseMode(True)
|
||||
|
||||
# Open File (Threads) - recursively walk 'files' and preserve directory structure
|
||||
# Prepare per-run log file so CLI runs also write to a run-specific history file
|
||||
try:
|
||||
hist_dir = Path("log") / "history"
|
||||
hist_dir.mkdir(parents=True, exist_ok=True)
|
||||
fname = datetime.datetime.now().strftime("translationHistory_%Y%m%d_%H%M%S.txt")
|
||||
run_log_path = hist_dir / fname
|
||||
run_log_path.touch(exist_ok=True)
|
||||
# Export env var so other modules/util functions pick it up
|
||||
try:
|
||||
os.environ['TRANSLATION_RUN_LOG'] = str(run_log_path)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Try to create a hard link from legacy path to this run file for compatibility
|
||||
legacy = Path("log") / "translationHistory.txt"
|
||||
try:
|
||||
if legacy.exists():
|
||||
try:
|
||||
legacy.unlink()
|
||||
except Exception:
|
||||
pass
|
||||
os.link(str(run_log_path), str(legacy))
|
||||
except Exception:
|
||||
# Fallback: ensure legacy file exists so modules writing to it won't fail
|
||||
try:
|
||||
legacy.parent.mkdir(parents=True, exist_ok=True)
|
||||
legacy.touch(exist_ok=True)
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
with ThreadPoolExecutor(max_workers=THREADS) as executor:
|
||||
futures = []
|
||||
files_root = "files"
|
||||
|
|
|
|||
|
|
@ -611,7 +611,23 @@ def translateAI(text, history, fullPromptFlag, config, filename=None, pbar=None,
|
|||
"""
|
||||
if not text:
|
||||
return [text, [0, 0]]
|
||||
|
||||
|
||||
# If a per-run log file is specified via environment variable, prefer it.
|
||||
run_log = os.getenv("TRANSLATION_RUN_LOG")
|
||||
if run_log:
|
||||
# Make sure parent dir exists
|
||||
try:
|
||||
Path(run_log).parent.mkdir(parents=True, exist_ok=True)
|
||||
except Exception:
|
||||
pass
|
||||
config.logFilePath = run_log
|
||||
|
||||
# Ensure log directory exists for the configured path
|
||||
try:
|
||||
Path(config.logFilePath).parent.mkdir(parents=True, exist_ok=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
with open(config.logFilePath, "a+", encoding="utf-8") as logFile:
|
||||
totalTokens = [0, 0]
|
||||
|
||||
|
|
@ -693,27 +709,17 @@ def translateAI(text, history, fullPromptFlag, config, filename=None, pbar=None,
|
|||
if cleaned_text:
|
||||
if isinstance(tItem, list):
|
||||
extracted = extractTranslation(cleaned_text, True, pbar)
|
||||
|
||||
# Check 1: Mismatch in length
|
||||
|
||||
# Check 1: Mismatch in length -> still a hard failure
|
||||
if extracted is None or len(tItem) != len(extracted):
|
||||
is_valid = False
|
||||
|
||||
# Check 2: Untranslated content
|
||||
else:
|
||||
# Set translations first (line count matches)
|
||||
# Set translations (line count matches)
|
||||
final_translations = extracted
|
||||
|
||||
# Then check for untranslated content as a warning, not a blocker
|
||||
for line in extracted:
|
||||
if re.search(config.langRegex, str(line)):
|
||||
is_valid = False
|
||||
break
|
||||
else:
|
||||
# Check for untranslated content in single string
|
||||
if re.search(config.langRegex, cleaned_text):
|
||||
is_valid = False
|
||||
else:
|
||||
final_translations = cleaned_text.replace("Placeholder Text", "")
|
||||
# Single string: accept output even if it contains characters
|
||||
# matching langRegex (allow names or untranslated tokens).
|
||||
final_translations = cleaned_text.replace("Placeholder Text", "")
|
||||
else:
|
||||
is_valid = False
|
||||
if pbar: pbar.write(f"AI Refused: {tItem}\n")
|
||||
|
|
|
|||
Loading…
Reference in a new issue