Skip to content

PaperLocale

tests release PyPI license

Verified, layout-preserving academic PDF translation with pluggable model providers and domain-specific terminology packs.

中文说明

PaperLocale verified workflow

The demo below is generated from PaperLocale's own one-page, double-column PDF fixture. It contains formula text, a vector table, and an embedded image; no copyrighted paper is redistributed.

PaperLocale source, translation, and all-page QA demo

Status

PaperLocale is under active development. The first release focuses on one strict pipeline:

  1. collect translatable segments from a PDF layout engine;
  2. translate them with one explicitly selected provider;
  3. reject translations that lose formulas, style tags, numbers, units, abbreviations, URLs, DOIs, or required terminology;
  4. rebuild the PDF without changing its page geometry;
  5. render every page and produce a reviewable QA report.

The project does not promise bitwise-identical typography. Chinese text naturally changes line breaks. Its promise is narrower and testable: preserve the page structure and protected scientific content, and fail before rendering when that contract is broken.

Implemented providers and gates

  • codex-local: local-only translation through an authenticated Codex CLI session;
  • openai-compatible: BYOK access to OpenAI and compatible endpoints;
  • an auditable manual ChatGPT Web bridge that exports hash-bound prompts and imports strict JSON responses without browser login, scraping, or automation;
  • qwen-mt: BYOK access to Qwen-MT's dedicated translation endpoint, with one-segment checkpoints and domain-pack terminology intervention;
  • built-in atmospheric-science and ecology packs with terminology and evaluation cases;
  • a resumable collect -> translate -> validate -> render -> qa -> accept workflow;
  • page geometry, image-object, vector-drawing, blank-page, placeholder, and all-page visual checks.

PaperLocale never reads or copies Codex authentication files. ChatGPT-managed Codex access is for trusted local use only and is not exposed as a public translation API.

Domain packs

The built-in packs are atmospheric-science and ecology. Each pack contains a manifest, glossary, prompt rules, and evaluation cases. New disciplines can be added without changing the translation pipeline.

python -m paperlocale domain-check atmospheric-science
python -m paperlocale domain-check ecology
python -m paperlocale validate-segments \
  --segments segments.jsonl \
  --translations translations.jsonl \
  --domain atmospheric-science

Evaluate a real Provider on every public domain case and save candidates next to their references:

paperlocale provider-eval \
  --provider codex-local \
  --model gpt-5.6-sol \
  --reasoning-effort high \
  --domain atmospheric-science \
  --output provider-eval.json

The report automatically evaluates only the hard content contract and exact reference matches. It never treats string similarity as semantic accuracy; every candidate remains marked for manual domain review.

Install

Python 3.10–3.13 and Poppler's pdftoppm are required for the complete workflow. Stable PaperLocale releases are published on PyPI through attested Trusted Publishing. The audited maintainer procedure and release evidence are documented in docs/PYPI_PUBLISHING.zh-CN.md. PaperLocale 0.4.2 adds --unattended and the audited repair commands documented below. To run this checkout, use the normal non-editable install path python -m pip install ".[layout]". The v0.4.0 manual ChatGPT Web bridge is documented in docs/CHATGPT_WEB_MANUAL.zh-CN.md for its copy/paste workflow and usage-limit boundary.

Version 0.6.2 checks numbers together with their units for both GPT and Qwen. Registered aliases and equivalent compound notation are allowed; omitted units, changed scales, and swapped associations fail. Qwen preserves complete source quantities during its bounded repair. See release details.

Qwen-MT 0.6.0 protects identifiers by occurrence and uses one bounded source-gap translation pass if normal output loses markers or violates the content contract. Unknown, duplicate, or malformed markers invalidate the whole candidate and use the same bounded recovery; markers returned during recovery still fail. This may increase API calls and affect fluency; visual and semantic review remain required. Requests share a 1.1-second minimum interval per provider instance; an explicit request-rate limit gets at most one retry after a wait of up to 60 seconds. Use --api-key-csv /path/to/key.csv to read a complete, unique sk- CSV field for Qwen-MT without truncating punctuation. This explicit option overrides the key environment variable and never writes credentials to run metadata.

For v0.6.3, install the exact public release with:

python -m venv .venv
source .venv/bin/activate
python -m pip install "paperlocale[layout]==0.7.8"
paperlocale --version
paperlocale domain-check atmospheric-science

Quick start (0.7.8)

New runs use paragraph frames (--layout-mode paragraph). The title, abstract, main text and figure/table captions are translated. Natural paragraph boundaries are detected inside PDF text blocks; a paragraph split across pages, columns or figures is translated once and placed into its corresponding frames. Chinese lines flow continuously, without artificial spaces or spreading short lines across the old English lines. Inline citations and supported mathematical glyphs move with the text using the original font programs; their link targets are preserved.

Figure labels, tables, standalone formulas, author details, auxiliary sections and references remain original. Fonts may shrink within each paragraph to 80% of the source size to fit complete content; --min-font-size specifies an explicit floor. Existing preserved and legacy runs retain their original engines and caches.

paperlocale run paper.pdf --run-dir runs/paper

No manual layout-plan review is required. A complete candidate is created only after all body translations, layout, protected content, and text readback pass. Errors save progress and keep the process waiting. After correcting an external problem, run paperlocale resume-waiting --run-dir runs/paper. Transient failures receive at most one automatic retry; saved translations and refinement responses are reused without changing the provider.

New runs default to codex-local, model gpt-6-sol, and reasoning effort medium. Explicit options override these defaults; resumed runs retain their recorded model. After machine QA passes, the candidate is also saved beside the source as paper_translated_by_paperlocale.pdf. An existing unrelated file is never overwritten. The terminal prints the error cause, location, and recovery step immediately, including when a run remains waiting. Human visual review and paperlocale accept are still required.

qa_generated remains a machine-checked candidate requiring visual acceptance. This is not a guarantee for arbitrary PDFs: scanned pages, rotated body text, or layouts that cannot pass safety checks remain waiting. See the detailed scope and recovery guide.

Legacy workflow

The examples below select --layout-mode legacy; existing runs retain their engine.

For a single non-interactive command that produces a complete candidate PDF, use --unattended. The codex-local provider invokes structured codex exec --ephemeral in the background; it does not open or wait for a Codex conversation window:

paperlocale run paper.pdf --layout-mode legacy --run-dir runs/paper \
  --provider codex-local \
  --model gpt-5.6-sol \
  --reasoning-effort high \
  --domain atmospheric-science \
  --unattended

The command automatically adopts only deterministic reference matches and deterministic layout-safety passthroughs, then translates, validates, rebuilds, and generates all-page machine QA. On success it prints the exact candidate PDF path under runs/paper/render_output/. References remain unchanged under the default preserve policy, and unsafe split layout objects remain byte-for-byte unchanged with an audit record. A "complete candidate PDF" therefore means that all pages and collected segments are closed, not that formulas, references, or unsafe fragments are forcibly converted to Chinese.

Unattended mode does not fabricate human visual acceptance: the final state is still qa_generated. Provider, content-contract, or machine-QA failures save progress and keep the process waiting by default. Use --no-wait-on-error for explicit failure exits. PaperLocale never silently switches providers.

The supervised workflow remains available when reference boundaries should be reviewed manually:

0.5.1 makes Codex return a required short-key object instead of copying long segment hashes. Hashes stay local; every response key is validated before the original IDs are restored. Existing validated caches remain reusable. This prevents hash-transcription failures without fuzzy matching or blind retries. Other providers retain their existing interfaces; content and PDF checks remain.

In 0.5.0, run performs one bounded vector restoration by default; use --no-restore-source-vectors to disable it. Recovery verifies both PDF hashes, retains a backup, and reruns full QA. Other failures remain explicit. Matching checks path geometry, style and multiplicity; zero opacity, existing drawings and text positions are protected.

With preserve, deterministic reference regions are copied with their original glyphs and layout instead of being typeset again. This prevents overlapping or partially translated bibliographies. Ambiguous or missing reference headings are not guessed. Existing maps are never silently rewritten; repair a candidate with restore-reference-layout --run-dir runs/paper, then rerun QA and review. Cross-column publisher continuations are no longer treated as bibliography. This release does not guarantee lossless output for every unknown layout: OCR/scans, uncollected source text, formula placement and caption formatting still require review. Successful machine QA remains qa_generated, not accept.

Use the same resumable command to initialize the run, collect layout segments, translate, validate, rebuild, and generate all-page QA:

# Uses the authenticated Codex CLI session on this trusted local machine.
paperlocale run paper.pdf --layout-mode legacy --run-dir runs/paper \
  --provider codex-local \
  --model gpt-5.6-sol \
  --reasoning-effort high \
  --domain atmospheric-science

# The first invocation stops after collection for reference review.
paperlocale confirm-references --run-dir runs/paper \
  --segment-id manually-confirmed-reference-segment-id \
  --confirmed-by "Your name"

# Rerun the original paperlocale run command after confirmation.
paperlocale run paper.pdf --layout-mode legacy --run-dir runs/paper \
  --provider codex-local \
  --model gpt-5.6-sol \
  --reasoning-effort high \
  --domain atmospheric-science

# Inspect every image under runs/paper/qa/comparisons/ before acceptance.
paperlocale accept --run-dir runs/paper --reviewed-by "Your name"

If a stage fails, rerun the same paperlocale run command. The manifest resumes from the last completed stage and every accepted segment is reused, including valid rows from a batch that also produced rejected candidates. Those candidates and their contract errors are stored in rejected_translations.jsonl. The command deliberately stops at qa_generated; it never records human acceptance. Once translation is complete, a resume command does not need --provider or API credentials.

If a rejected segment is genuinely non-translatable, such as a pure formula or an author-name list, confirm it explicitly instead of adding artificial Chinese text or weakening the global CJK gate:

paperlocale confirm-passthrough --run-dir runs/paper \
  --segment-id confirmed-nontranslatable-segment-id \
  --reason "Pure formula with no translatable prose" \
  --confirmed-by "Your name"

The audited map binds the source PDF and segments.jsonl hashes. Confirmed segments must remain byte-for-byte equal to their source, never reach the Provider, and can safely resolve a rejected partial batch without repeating already accepted model calls.

Before any Provider call, PaperLocale also compares collected segments with the source PDF's exact visible page text. A segment that starts or ends inside the same ASCII word (for example Figu + re ... perio + d), or a short ASCII segment absent from visible page text, is written to segment_safety_review.jsonl and blocks translation. Inspect that local file, then confirm every listed ID with confirm-passthrough. v0.3.2 deliberately keeps these objects unchanged; full translation requires upstream adjacent- object context or merge support.

The default reference policy is preserve. PaperLocale writes every segment to reference_review.jsonl, automatically selects only long segments that match the source PDF's exact REFERENCES region, and requires explicit confirmation before any model call. Automatically matched IDs do not need to be repeated; omit --segment-id when no manual additions are needed. If page columns or post-reference sections cause a reviewed false positive, repeat --exclude-segment-id ID on confirm-references; only IDs from the current automatic set can be excluded, and every exclusion is recorded in the bound map. The confirmed map is bound to the source PDF and segments.jsonl hashes. Use --reference-policy translate-titles to translate work titles only; reference rows do not use body-domain glossary gates.

The current released BabelDOC may still re-typeset an unchanged reference paragraph. The object-level fix is proposed upstream in BabelDOC #610 and PR #611; PaperLocale does not carry a local PDF overlay workaround while that review is pending.

The schema 4 run manifest binds the domain-pack content hash, provider, model, reasoning effort, Codex CLI version history, collect/render layout-engine versions, and any human-confirmed passthrough map. A Codex run therefore requires an explicit --model.

When vector objects disappear, QA records their page, bounding box, and area, and draws red boxes at the expected locations in both comparison panels. When the original source paths should remain at those locations, replay only the exactly missing paths through PaperLocale's controlled command:

paperlocale restore-source-vectors --run-dir runs/paper \
  --description "Restore source vectors confirmed missing by machine QA"

The command requires a current QA report whose source and translated hashes match the manifest. It only inspects pages where QA records source_vector_drawings > translated_vector_drawings, matches missing paths at 0.01 PDF-point precision, rejects text, page-geometry, or image changes, backs up the candidate, and records repair_history. Other independently repaired candidates can still use the audited import path:

paperlocale apply-vector-repair --run-dir runs/paper \
  --repaired-pdf repaired-paper.pdf \
  --description "Restore page 1 link vector icons"

The command rejects candidates that alter text, page geometry, or image counts, backs up the previous PDF, appends repair_history, and requires QA and human acceptance to run again.

If visual review finds a broken caption that cannot be repaired at segment level, replace only an explicitly reviewed page rectangle:

paperlocale apply-text-repair --run-dir runs/paper \
  --page 27 \
  --rect 40 120 500 160 \
  --replacement "Figure 5 corrected caption" \
  --font-file /path/to/NotoSansCJKsc-Regular.otf \
  --font-size 9.5 \
  --single-line \
  --description "Repair a split-token figure caption"

The command verifies that the font contains every replacement glyph, removes text only inside the rectangle while preserving page geometry, images, links, existing vectors, and outside text, and rejects overflow. It subsets the repair font before embedding it without rewriting existing PDF font programs, and records the font and subset hashes, byte reduction, before/after text, geometry, PDF hashes, and backup in repair_history. QA and human acceptance must then run again. Use a locally licensed font and do not commit it to the repository; a TTF/OTF usually produces cleaner extraction metadata than a font collection, but every result still goes through the same QA warnings and visual review. --single-line measures the subset font's actual width, ascender, and descender and rejects a shallow rectangle before modification if the line does not fit; omit it when normal textbox wrapping is intended.

For a reviewed fragment that must only be removed, pass an explicit empty replacement and omit the font options:

paperlocale apply-text-repair --run-dir runs/paper \
  --page 2 --rect 120 29 144 39 --replacement '' \
  --description "Remove a reviewed split-token fragment"

Removal mode embeds no font, records text-removal in repair_history, and still enforces the same rectangle, outside-text, page, image, link, vector, backup, QA, and human-acceptance gates. Whitespace-only replacements are rejected.

Every recorded PDF repair can be reversed from the current chain tail only:

paperlocale rollback-last-repair --run-dir runs/paper \
  --reason "Remove the last audited repair before rebuilding QA"

The command requires the current PDF to match the tail after_sha256 and its backup to match before_sha256. It restores that exact backup, moves the entry from repair_history to repair_rollback_history, returns the run to rendered, and invalidates the old QA and visual-acceptance binding. It cannot skip newer repairs; run machine QA and full visual review again after rollback.

For a BYOK OpenAI-compatible endpoint:

export PAPERLOCALE_API_KEY="your-key"
paperlocale run paper.pdf --layout-mode legacy --run-dir runs/paper \
  --provider openai-compatible \
  --base-url https://api.example.com/v1 \
  --model your-model \
  --domain atmospheric-science

Remote compatible endpoints must use HTTPS. Plain HTTP is accepted only for loopback services on localhost, 127.0.0.1, or ::1.

For Alibaba Cloud Bailian's dedicated Qwen-MT endpoint, keep the API key in an environment variable and select the explicit provider. The base URL is the API version prefix and must not include /chat/completions:

export PAPERLOCALE_API_KEY="your-DashScope-key"
paperlocale run paper.pdf --layout-mode legacy --run-dir runs/paper \
  --provider qwen-mt \
  --base-url https://dashscope.aliyuncs.com/compatible-mode/v1 \
  --model qwen-mt-plus \
  --domain atmospheric-science

Qwen-MT receives only one source segment per request. PaperLocale derives its language codes, domain instruction, and glossary terms from the selected domain pack, validates every returned segment, and saves each accepted result before starting the next request. API keys are sent only in the Authorization header and are never written to the run manifest.

For explicit stage-by-stage control, the same production path remains available as init-run -> collect -> reference-review/confirm-references -> optional confirm-passthrough -> translate -> validate -> render -> qa -> accept.

See the detailed Chinese guide, ROADMAP, ARCHITECTURE, domain-pack guide, Codex for Open Source readiness, and PROVENANCE.

Citation and community

Research and teaching users can cite the software through CITATION.cff; GitHub exposes the same metadata through its “Cite this repository” control. Participation in issues, pull requests, and reviews follows the PaperLocale Code of Conduct.

Development

Unit tests do not call a model or require the layout engine:

python -m pip install -e ".[test]"
python -m unittest discover -s tests -v

After layout-engine upgrades, run the deterministic full-path smoke test:

python -m pip install -e ".[layout,test]"
python scripts/layout_smoke.py \
  --output tmp/layout-smoke-001 \
  --demo-gif tmp/layout-smoke-001.gif

The script intentionally stops before visual acceptance and prints the comparison image to inspect. The scheduled compatibility workflow repeats this real CLI check weekly against the newest pdf2zh-next release allowed by the declared dependency range.

Contributing

Start with the scoped good first issues, or read CONTRIBUTING.md. Current entry points cover an ecology domain pack, Ubuntu installation verification, and independent review of the atmospheric-science Provider evaluation.

License

GNU Affero General Public License v3.0 only. This choice is aligned with the AGPL-licensed PDF layout engines the project is designed to integrate.

0.6.3 fixes scaled-area and URL-only validation without changing either provider implementation. Release notes.

Controlled repair and fail-fast runs (0.6.4)

Use --no-contract-repair --no-restore-source-vectors with run to stop before optional model or vector repair. Successful segments and rejection evidence remain resumable; this does not override retries inside an external provider/CLI. Author names are not prose: inspect the source PDF before using confirm-passthrough with the full segment ID.

apply-text-repair now preflights Chinese wrapping using the embedded font. --font-size 8.2 --min-font-size 7.5 explicitly permits shrinking in 0.1 pt steps to the requested floor; without the floor, size stays fixed. The rectangle never grows automatically. Overflow changes no PDF. Re-run qa, inspect every page, then accept after any repair. Split headings and residual English can still need source-backed local repair even when structural QA passes.

0.7.4: explicit cache handoff and local OCR

Use a new run directory with --import-cache-from OLD_RUN to reuse validated paragraph translations while explicitly selecting a new provider/model. Source and anchor identity are checked; imported provenance and rejected rows are recorded. Old runs are not edited. Unresolved extraction codes generate local OCR crops and suggestions (installed Tesseract, or macOS Vision via Swift); OCR never silently rewrites source scientific text. See validation and limitations.

0.7.5: headings, scientific symbols and numbered paragraphs

See changes, validation and limits. Existing runs use a new directory with explicit cache import.

0.7.7 and the macOS frontend

Fixes split inline subscripts, a reviewed C0-encoded minus, duplicate confidence-band drawing, and caption detection edges. Adds explicit --no-qa without claiming acceptance. See the release notes.

The experimental macOS native frontend selects PDFs, models and reasoning effort. It requires an installed CLI and layout dependencies. Universal 2, macOS 13+; ad-hoc signed, not Apple notarized.

0.7.8

Soft-hyphen, font-subset and event-unit repairs; macOS provider selection and custom PDF save paths. See release notes.

About

Verified, layout-preserving academic PDF translation with Codex/API providers and extensible scientific terminology packs.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

23 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages