deusyu/translate-book는 PDF·DOCX·EPUB 한 권을 하나의 긴 컨텍스트로 번역하지 않고, Markdown 청크 단위의 독립 서브에이전트를 병렬 실행한 뒤 검증·병합·전자책/문서 변환까지 수행하는 Agent Skill이다.

개요

이 저장소는 Codex, Claude Code, OpenClaw에서 사용할 수 있는 translate-book 스킬을 제공한다. Calibre와 Pandoc을 변환 계층으로 사용하고, Python 스크립트가 변환·분할·manifest·용어집·실행 상태·병합·출력 생성을 담당한다. README는 claude_translater에서 영감을 받았다고 밝히지만, 구조와 구현이 크게 달라 독립 프로젝트이며 fork는 아니라고 설명한다.

핵심 문제의식은 책 전체를 한 번에 모델 컨텍스트에 넣을 때 생기는 컨텍스트 누적과 출력 truncation이다. 각 청크에 새 컨텍스트의 서브에이전트를 배정하면 병렬화와 재시작이 가능하고, manifest·용어집·이웃 청크 문맥으로 완전성과 용어 일관성을 보강할 수 있다.

한눈에 보는 파이프라인

PDF / DOCX / EPUB
  ↓ Calibre ebook-convert
HTMLZ → HTML → Markdown
  ↓ 구조를 보존하며 약 6,000자 청크 분할
chunk0001.md … + manifest.json + source_fingerprint.json
  ↓ 기본 8개 동시 서브에이전트 배치
output_chunk0001.md … + output_chunkNNNN.meta.json
  ↓ manifest·해시·빈 출력·이미지 참조 검증
output.md 병합
  ↓ Pandoc HTML + 목차 + Calibre
HTML / DOCX / EPUB / PDF

각 번역 청크는 독립적인 fresh context에서 처리되며, 배치가 끝날 때 다음 배치에 영향을 줄 용어집 피드백을 보수적으로 반영한다.

설치와 시작

요구사항

  • Codex, Claude Code 또는 OpenClaw 런타임
  • Calibre의 ebook-convert 명령
  • Pandoc
  • Python 3
  • pypandoc 필수, beautifulsoup4 선택 사항(더 나은 TOC 생성)

스킬 설치

# Codex
npx skills add deusyu/translate-book -a codex -g
 
# Claude Code
npx skills add deusyu/translate-book -a claude-code -g
 
# OpenClaw
openclaw skills install @deusyu/translate-book

수동 설치도 가능하다. Codex는 ~/.agents/skills/translate-book, Claude Code는 ~/.claude/skills/translate-book에 저장소를 clone하는 방식이다.

호출 예시

Codex에서는 다음처럼 명시적으로 호출한다.

$translate-book Translate /path/to/book.pdf into Chinese.

Claude Code와 OpenClaw에서는 다음처럼 자연어로 요청할 수 있다.

translate /path/to/book.pdf to Chinese

Claude Code에서는 /translate-book translate /path/to/book.pdf to Japanese 형태의 slash command도 사용할 수 있다. 기본 출력 언어는 zh이고, README가 안내하는 언어 표면은 zh, en, ja, ko, fr, de, es다.

단계별 구현

1. 변환과 구조 보존 분할

scripts/convert.py가 PDF·DOCX·EPUB를 Calibre HTMLZ로 변환하고, HTML을 Markdown으로 정리한 뒤 구조 단위로 분할한다.

  • 기본 청크 목표 크기는 약 6,000자이며 --chunk-size로 조정할 수 있다.
  • 제목·단락·인용·표·목록·이미지·코드 블록의 경계를 우선해 자른다.
  • 12,000자를 넘는 구조 블록은 단락 또는 줄 단위로 강제 분할하며 fenced code block은 각 결과에 fence를 다시 씌운다.
  • 작업 디렉터리는 기본적으로 {book_name}_temp/이며 --temp-root로 부모 위치만 바꿀 수 있다.
  • config.txt에는 입력 파일, 입력/출력 언어, 변환 방식과 책 메타데이터가 기록된다.
  • manifest.json은 원본 전체와 각 chunkNNNN.md의 SHA-256을 기록한다.
  • source_fingerprint.json은 source path·size·SHA-256을 기록해 다른 책의 캐시를 실수로 재사용하는 것을 중단시킨다.
  • --strip-page-numbers는 standalone 숫자 줄을 공격적으로 제거하는 선택 기능이며, 기존 input.md나 chunk 캐시가 있으면 효과가 무효화될 수 있어 스크립트가 중단한다.

2. 용어집과 용어 선택

각 청크를 새 컨텍스트에서 번역하면 인명·지명·전문 용어가 청크마다 흔들릴 수 있다. 이를 위해 메인 에이전트가 먼저 일부 청크(첫 청크·마지막 청크·간격을 둔 중간 청크 3개)를 샘플링해 hand-editable glossary.json을 만든다.

v2 용어 항목은 source, target, category, aliases, gender, confidence, frequency, evidence_refs, notes를 가진다. 이후 다음 흐름으로 사용한다.

  1. count-frequencies가 모든 원본 청크에서 용어 빈도를 계산한다.
  2. print-terms-for-chunk가 해당 청크에 실제로 등장하는 용어와 책 전체 빈도 상위 용어를 골라낸다.
  3. 선택 결과를 원문 | 별칭 | 번역 3열 Markdown 표로 각 서브에이전트 프롬프트에 주입한다.
  4. 사용자가 glossary의 번역·별칭·범주를 수정하면 이후 실행에서 영향받는 청크만 재번역한다.

v2는 하나의 surface form이 서로 다른 두 용어에 매핑되는 것을 금지한다. v1 파일은 자동 업그레이드되지만 다의적 중복 source가 있으면 임의로 결정하지 않고 수동 구분을 요구한다.

3. 선택적 재번역 상태

scripts/run_state.pyrun_state.json에 청크별 다음 상태를 기록한다.

  • source/output hash
  • 사용한 glossary hash
  • 선택된 용어 ID와 각 용어 hash
  • 갱신 시각

plan은 누락·빈 출력, manifest source hash 변경, state가 없는 기존 출력, 기록 이후 source 변경, 용어 선택/용어 hash 변경을 구분한다. 따라서 기존 결과가 유효하면 그대로 두고, 출력만 바뀌었으면 상태만 기록하며, glossary 영향이 있는 청크만 다시 번역할 수 있다. 오래된 temp 디렉터리의 추적되지 않은 출력까지 강제로 다시 번역하려면 --retranslate-untracked를 사용한다.

4. 병렬 서브에이전트와 이웃 문맥

기본 동시성은 배치당 8개다. 각 서브에이전트는 정확히 하나의 source chunk를 읽고 output_chunkNNNN.md를 작성하며, 번역 관찰을 output_chunkNNNN.meta.json에 남긴다.

scripts/chunk_context.py는 이전 청크의 끝 약 300자와 다음 청크의 시작 약 300자를 read-only 문맥으로 제공한다. 이 문맥은 대명사·성별·인명 지시 대상을 판단하기 위한 것이며, 이웃 문장을 번역하거나 결과에 복사하는 용도가 아니다.

서브에이전트 meta에는 새 entity, alias 가설, 속성/성별 가설, 사용한 용어, 충돌 관찰과 근거 인용을 담을 수 있다. 확신이 없으면 빈 배열을 허용하고, 존재하지 않는 entity를 만들어 생산성을 가장하지 않도록 설계되어 있다.

5. 메타 병합과 결정 경계

scripts/merge_meta.py는 LLM을 호출하지 않는다. 각 meta 파일의 형식 검증·content hash·그룹화·제안 생성·원자적 반영만 담당한다.

  • prepare-merge: 새 meta를 읽어 자동 반영 후보와 판단이 필요한 alias/conflict를 JSON으로 만든다.
  • 메인 에이전트는 실제 근거 인용을 읽고 alias 여부·충돌 해결·새 entity 선택을 결정한다.
  • apply-merge: 결정 JSON을 검증한 뒤 glossary를 원자적으로 갱신하고 소비한 meta hash를 기록한다.
  • malformed meta는 quarantine하고 경고·개수로 보고하며, 한 청크의 잘못된 meta가 전체 번역을 중단시키지 않도록 한다.
  • 근거 chunk는 최대 5개까지 보존하고, 근거 수에 따라 confidence를 보수적으로 승격한다.

즉 파일 IO·해시·스키마·dedup은 결정론적 Python이 맡고, entity의 의미적 동일성·alias·충돌 해결은 메인 에이전트가 맡는 분업이다.

6. 완전성 검증과 출력 생성

scripts/manifest.pyscripts/merge_and_build.py는 병합 전에 다음을 검사한다.

  • 모든 source chunk에 대응하는 output chunk가 있는지
  • source hash가 split 당시 manifest와 같은지
  • 출력이 비어 있거나 whitespace-only가 아닌지
  • UTF-8로 읽히는지
  • 이미지 Markdown/HTML 참조가 원본과 1:1로 보존되는지
  • 번역 결과가 비정상적으로 짧은 경우 경고하는지

검증을 통과하면 다음 순서로 빌드한다.

python3 scripts/merge_and_build.py \
  --temp-dir book_temp \
  --title "번역된 책 제목"

표준 산출물은 다음과 같다.

파일설명
output.md병합된 번역 Markdown
book.htmlfloating TOC가 포함된 웹 버전
book_doc.html전자책 변환용 HTML
book.docxWord 문서
book.epub전자책
book.pdfPDF

--cover로 EPUB 표지를 지정하고, --export-name으로 사용자용 파일명 별칭을 만들며, 성공적으로 모든 형식을 만든 뒤 --cleanup으로 중간 청크를 삭제할 수 있다. 실패한 형식이 있으면 진단을 위해 중간 파일을 유지한다.

설계상 강점

  • 컨텍스트 격리·재시작: 청크별 fresh context로 누적 오염과 truncation을 줄이고, source fingerprint·manifest로 완료 청크 재사용과 잘못된 캐시 병합 방지를 함께 처리한다.
  • 문맥·용어 일관성: glossary·alias·빈도·term table과 인접 청크의 짧은 read-only 문맥으로 고유명사 drift와 청크 경계의 지시 대상을 보완한다.
  • 안전한 다중 포맷 출력: 빈 출력·stale source·손상된 이미지 참조를 차단한 뒤 HTML, DOCX, EPUB, PDF를 생성하고 cover/export alias를 선택적으로 제어한다.
  • 멀티 런타임: Codex·Claude Code·OpenClaw에 같은 스킬 구조를 배포한다.

한계와 검증 경계

  • Calibre의 ebook-convert, Pandoc, Python 패키지가 모두 준비되어야 한다. 변환 도구나 폰트가 빠지면 최종 포맷 생성이 실패할 수 있다.
  • 이 저장소를 고정 커밋 기준으로 정적 조사했을 뿐, 실제 책의 변환·번역·병합·PDF/EPUB 생성은 실행하지 않았다.
  • API rate limit, 서브에이전트 런타임별 동시성, 모델별 번역 품질, 용어집이 실제 장편 도서에서 drift를 얼마나 줄이는지는 독립 benchmark로 확인하지 않았다.
  • tests/에는 고정 커밋 기준 9개의 test_*.py 파일과 baseline EPUB/Markdown이 있지만, 이번 위키 저장 과정에서 전체 테스트를 실행하지 않았다.
  • glossary.json의 의미 판단은 자동화하지 않고 메인 에이전트에 남겨 두므로, 충돌이 많은 책에서는 사람 또는 에이전트의 검토 품질이 결과를 좌우한다.
  • 입력 책의 저작권·개인정보·외부 provider 전송 경계는 사용 중인 에이전트 런타임과 모델 설정에서 별도로 확인해야 한다.

메타데이터와 출처

관련 노트