Pre-publication review draft
日常訳NICHIJOYAKU日本語 ↗

OPEN SOURCE

software/src/output/formatters.py

Read on this site and download the files you need.

Nichijoyaku was created using AI. A complete review by human biblical-language and biblical-studies specialists has not been established. Read alongside established translations and original-language resources.

← Back to the open-source guide

software/src/output/formatters.py228 linesDownload this file ↓

This is the same source included in the download. Each line number is a link you can save or share.

File verification detailsSHA-256 5089824f49dfa528f5e5aced74355ac1471f62f31e0aee53f2fba2374ca46c7f
1"""Output formatters for translations."""23from __future__ import annotations45import json6from pathlib import Path7from typing import TYPE_CHECKING89from src.utils.furigana import parse_furigana, format_furigana_html1011if TYPE_CHECKING:12    from src.data.storage import Storage13    from src.models.verse import BookMetadata141516class OutputFormatter:17    """Formats translations for various output formats."""1819    def __init__(self, storage: Storage) -> None:20        """Initialize the formatter.2122        Args:23            storage: Storage instance for loading translations.24        """25        self.storage = storage2627    def export_chapter_json(28        self, book: str, chapter: int, output_path: Path29    ) -> Path:30        """Export a chapter as JSON.3132        Args:33            book: Book name.34            chapter: Chapter number.35            output_path: Directory to write output.3637        Returns:38            Path to the created file.39        """40        translations = self.storage.load_chapter_translations(book, chapter)4142        output_data = {43            "book": book,44            "chapter": chapter,45            "verses": {},46        }4748        for verse_num, translation in sorted(translations.items()):49            output_data["verses"][str(verse_num)] = {50                "text": translation.text,51                "model": translation.model,52                "timestamp": translation.timestamp.isoformat(),53            }5455        output_path.mkdir(parents=True, exist_ok=True)56        file_path = output_path / f"{book}_chapter_{chapter:02d}.json"5758        with file_path.open("w", encoding="utf-8") as f:59            json.dump(output_data, f, ensure_ascii=False, indent=2)6061        return file_path6263    def export_chapter_text(64        self, book: str, chapter: int, output_path: Path65    ) -> Path:66        """Export a chapter as plain text.6768        Args:69            book: Book name.70            chapter: Chapter number.71            output_path: Directory to write output.7273        Returns:74            Path to the created file.75        """76        translations = self.storage.load_chapter_translations(book, chapter)7778        lines = [f"{book.title()} Chapter {chapter}", "=" * 40, ""]7980        for verse_num, translation in sorted(translations.items()):81            lines.append(f"{verse_num}. {translation.text}")82            lines.append("")8384        output_path.mkdir(parents=True, exist_ok=True)85        file_path = output_path / f"{book}_chapter_{chapter:02d}.txt"8687        with file_path.open("w", encoding="utf-8") as f:88            f.write("\n".join(lines))8990        return file_path9192    def export_chapter_html(93        self,94        book: str,95        chapter: int,96        output_path: Path,97        metadata: BookMetadata | None = None,98    ) -> Path:99        """Export a chapter as HTML.100101        Args:102            book: Book name.103            chapter: Chapter number.104            output_path: Directory to write output.105            metadata: Optional book metadata for title.106107        Returns:108            Path to the created file.109        """110        translations = self.storage.load_chapter_translations(book, chapter)111112        book_name = metadata.name_japanese if metadata else book.title()113        title = f"{book_name} 第{chapter}章"114115        html_parts = [116            "<!DOCTYPE html>",117            '<html lang="ja">',118            "<head>",119            '<meta charset="UTF-8">',120            '<meta name="viewport" content="width=device-width, initial-scale=1.0">',121            f"<title>{title}</title>",122            "<style>",123            "body { font-family: 'Noto Sans JP', sans-serif; max-width: 800px; "124            "margin: 0 auto; padding: 20px; line-height: 1.8; }",125            "h1 { border-bottom: 2px solid #333; padding-bottom: 10px; }",126            ".verse { margin: 1em 0; }",127            ".verse-num { color: #666; font-size: 0.8em; vertical-align: super; "128            "margin-right: 0.3em; }",129            "ruby { ruby-position: over; }",130            "rt { font-size: 0.6em; color: #666; }",131            "</style>",132            "</head>",133            "<body>",134            f"<h1>{title}</h1>",135        ]136137        for verse_num, translation in sorted(translations.items()):138            # Use furigana HTML if available139            if translation.text_with_furigana:140                plain, annotations = parse_furigana(translation.text_with_furigana)141                verse_html = format_furigana_html(plain, annotations)142            else:143                verse_html = translation.text144145            html_parts.append(146                f'<p class="verse"><span class="verse-num">{verse_num}</span>'147                f"{verse_html}</p>"148            )149150        html_parts.extend(["</body>", "</html>"])151152        output_path.mkdir(parents=True, exist_ok=True)153        file_path = output_path / f"{book}_chapter_{chapter:02d}.html"154155        with file_path.open("w", encoding="utf-8") as f:156            f.write("\n".join(html_parts))157158        return file_path159160    def export_book_json(self, book: str, output_path: Path) -> Path:161        """Export an entire book as JSON.162163        Args:164            book: Book name.165            output_path: Directory to write output.166167        Returns:168            Path to the created file.169        """170        all_chapters: dict = {}171172        # Find all chapter files173        book_output_dir = self.storage.output_dir / book174        if book_output_dir.exists():175            for chapter_file in sorted(book_output_dir.glob("chapter_*.json")):176                # Extract chapter number from filename177                chapter_num = int(chapter_file.stem.split("_")[1])178                translations = self.storage.load_chapter_translations(book, chapter_num)179180                all_chapters[str(chapter_num)] = {181                    str(v): {"text": t.text, "model": t.model}182                    for v, t in sorted(translations.items())183                }184185        output_data = {"book": book, "chapters": all_chapters}186187        output_path.mkdir(parents=True, exist_ok=True)188        file_path = output_path / f"{book}_complete.json"189190        with file_path.open("w", encoding="utf-8") as f:191            json.dump(output_data, f, ensure_ascii=False, indent=2)192193        return file_path194195    def export_book_text(self, book: str, output_path: Path) -> Path:196        """Export an entire book as plain text.197198        Args:199            book: Book name.200            output_path: Directory to write output.201202        Returns:203            Path to the created file.204        """205        lines = [f"{book.title()}", "=" * 40, ""]206207        book_output_dir = self.storage.output_dir / book208        if book_output_dir.exists():209            for chapter_file in sorted(book_output_dir.glob("chapter_*.json")):210                chapter_num = int(chapter_file.stem.split("_")[1])211                translations = self.storage.load_chapter_translations(book, chapter_num)212213                lines.append(f"\nChapter {chapter_num}")214                lines.append("-" * 20)215216                for verse_num, translation in sorted(translations.items()):217                    lines.append(f"{verse_num}. {translation.text}")218219                lines.append("")220221        output_path.mkdir(parents=True, exist_ok=True)222        file_path = output_path / f"{book}_complete.txt"223224        with file_path.open("w", encoding="utf-8") as f:225            f.write("\n".join(lines))226227        return file_path228