Files
epub_bilingual_translator/archive/v0.13/src/translation/manifest_manager.py
T

75 lines
2.8 KiB
Python

from pathlib import Path
from typing import List, Dict, Optional
import json
from src.common.data_model import ManifestEntry
from src.common.utils import setup_logger
logger = setup_logger("manifest_manager")
class ManifestManager:
"""
Manages the translation manifest (Source of Truth).
Handles persistence and state updates.
"""
def __init__(self, manifest_path: Path):
self.manifest_path = manifest_path
self.entries: List[ManifestEntry] = []
self._entries_map: Dict[str, ManifestEntry] = {}
def load(self):
"""Loads manifest from disk if it exists."""
if not self.manifest_path.exists():
logger.info(f"Manifest not found at {self.manifest_path}, starting empty.")
return
try:
with open(self.manifest_path, 'r', encoding='utf-8') as f:
data = json.load(f)
self.entries = [ManifestEntry.model_validate(item) for item in data]
self._rebuild_map()
logger.info(f"Loaded {len(self.entries)} entries from manifest.")
except Exception as e:
logger.error(f"Failed to load manifest: {e}")
raise
def save(self):
"""Saves current state to disk."""
try:
# Pydantic v2: model_dump(mode='json') or just list dump
data = [entry.model_dump(mode='json') for entry in self.entries]
with open(self.manifest_path, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
logger.info(f"Saved {len(self.entries)} entries to manifest.")
except Exception as e:
logger.error(f"Failed to save manifest: {e}")
raise
def add_entries(self, new_entries: List[ManifestEntry]):
"""
Adds new entries to the manifest.
If an entry with the same ID exists, it keeps the EXISTING one (to preserve translations).
"""
count = 0
for entry in new_entries:
if entry.entry_id not in self._entries_map:
self.entries.append(entry)
self._entries_map[entry.entry_id] = entry
count += 1
if count > 0:
logger.info(f"Added {count} new entries to manifest.")
def update_translation(self, entry_id: str, translation: str):
"""Updates translation for a specific entry."""
if entry_id in self._entries_map:
self._entries_map[entry_id].translated_text = translation
else:
logger.warning(f"Attempted to update translation for unknown ID: {entry_id}")
def get_entry(self, entry_id: str) -> Optional[ManifestEntry]:
return self._entries_map.get(entry_id)
def _rebuild_map(self):
self._entries_map = {e.entry_id: e for e in self.entries}