Hi @DavidLMS 😁,
First of all, thank you for building Aphra. We've been using it in LibreFolio to automatically translate our MkDocs documentation (36 source files × 3 languages = 108 translated files), and the results have been genuinely impressive.
This issue isn't about a bug — it's about sharing what we built on top of Aphra and a suggestion that might benefit other users.
Our setup
We installed Aphra directly via Pipenv from your GitHub repository:
[dev-packages]
"aphra " = {git = "https://github.com/DavidLMS/aphra.git"}
This worked perfectly. You might consider mentioning Pipenv as an alternative installation method alongside pip/Poetry in your README — it's already supported out of the box since you have a proper setup.py/pyproject.toml.
What we customized
We wrapped Aphra's workflow (Analyze → Translate → Critique → Refine) inside an orchestration script (translate_docs.py) that adds:
-
Shared analysis — Step 1 (Analyze) runs once per source file and its result is reused across all 3 target languages. This saves ~25% of LLM calls.
-
Step 2 (Search) paused — We disabled the web search step entirely (APHRA_WEB_SEARCH=false). For technical documentation where terms are well-known, it added cost and latency without benefit.
-
Structural diff (our main addition) — Instead of relying solely on the LLM critic to catch structural issues, we created an objective, deterministic structural diff function (_structural_diff()) that compares the source and translated markdown on 13 dimensions:
- Heading count and level sequence
- Code block count and language tags
- Link URLs (missing/added)
- Image URLs
- MkDocs admonition count (
!!!, ???)
- Horizontal rules, bullet lists, numbered lists
- Table row count
- Bold marker count
- Line count delta
The diff report is injected into the glossary parameter of the Critique step, so the critic LLM receives factual, objective data alongside its own subjective analysis. This dramatically reduced false negatives — issues the critic would have missed on its own.
-
Post-translation validation — A separate script (validate_translations.py) runs offline checks on all translated files (admonition indentation, artifact remnants like [N] glossary markers, truncated words, LaTeX corruption, etc.).
Suggestion: custom diff hook parameter
We think other Aphra users could benefit from a hook/callback parameter in the pipeline — something like:
def my_structural_diff(source: str, translated: str) -> str:
"""Return a factual report to inject into the critique step."""
...
aphra.translate(
source_text,
...,
structural_diff_fn=my_structural_diff, # optional callback
)
This way, users could provide their own domain-specific quality checks (markdown structure for us, XML tags for others, JSON schema for i18n files, etc.) without forking the library.
Results
The Markdown structural diff is working well. We did have to clean up some "Translator's Notes" that the LLM occasionally appended, but overall the quality has been excellent — especially with cloud models (we used stepfun/step-3.5-flash via OpenRouter for the final run, $0 cost on their free tier).
We're also considering building a JSON i18n translation pipeline next (for our svelte-i18n frontend localization files), which would be a different beast but could reuse the same Aphra workflow with a JSON-aware structural diff.
Thank you
We wanted to share this experience not because there were problems, but in the hope that these ideas might help you improve the project. The Analyze → Critique → Refine architecture is really well thought out, and adding an objective diff layer on top of it made it even more powerful for our use case.
All our customization code is public in the LibreFolio repository — feel free to look at it, reuse it, or draw inspiration from it.
Keep up the great work! 🙏
Hi @DavidLMS 😁,
First of all, thank you for building Aphra. We've been using it in LibreFolio to automatically translate our MkDocs documentation (36 source files × 3 languages = 108 translated files), and the results have been genuinely impressive.
This issue isn't about a bug — it's about sharing what we built on top of Aphra and a suggestion that might benefit other users.
Our setup
We installed Aphra directly via Pipenv from your GitHub repository:
This worked perfectly. You might consider mentioning Pipenv as an alternative installation method alongside pip/Poetry in your README — it's already supported out of the box since you have a proper
setup.py/pyproject.toml.What we customized
We wrapped Aphra's workflow (Analyze → Translate → Critique → Refine) inside an orchestration script (
translate_docs.py) that adds:Shared analysis — Step 1 (Analyze) runs once per source file and its result is reused across all 3 target languages. This saves ~25% of LLM calls.
Step 2 (Search) paused — We disabled the web search step entirely (
APHRA_WEB_SEARCH=false). For technical documentation where terms are well-known, it added cost and latency without benefit.Structural diff (our main addition) — Instead of relying solely on the LLM critic to catch structural issues, we created an objective, deterministic structural diff function (
_structural_diff()) that compares the source and translated markdown on 13 dimensions:!!!,???)The diff report is injected into the
glossaryparameter of the Critique step, so the critic LLM receives factual, objective data alongside its own subjective analysis. This dramatically reduced false negatives — issues the critic would have missed on its own.Post-translation validation — A separate script (
validate_translations.py) runs offline checks on all translated files (admonition indentation, artifact remnants like[N]glossary markers, truncated words, LaTeX corruption, etc.).Suggestion: custom diff hook parameter
We think other Aphra users could benefit from a hook/callback parameter in the pipeline — something like:
This way, users could provide their own domain-specific quality checks (markdown structure for us, XML tags for others, JSON schema for i18n files, etc.) without forking the library.
Results
The Markdown structural diff is working well. We did have to clean up some "Translator's Notes" that the LLM occasionally appended, but overall the quality has been excellent — especially with cloud models (we used
stepfun/step-3.5-flashvia OpenRouter for the final run, $0 cost on their free tier).We're also considering building a JSON i18n translation pipeline next (for our
svelte-i18nfrontend localization files), which would be a different beast but could reuse the same Aphra workflow with a JSON-aware structural diff.Thank you
We wanted to share this experience not because there were problems, but in the hope that these ideas might help you improve the project. The Analyze → Critique → Refine architecture is really well thought out, and adding an objective diff layer on top of it made it even more powerful for our use case.
All our customization code is public in the LibreFolio repository — feel free to look at it, reuse it, or draw inspiration from it.
Keep up the great work! 🙏