skills/do.translate-markdown/SKILL.md
Translate Markdown documents to a target language with guaranteed completeness. Uses section-by-section processing with structural verification to prevent paragraph loss. Triggers: "translate markdown", "translate this md", "translate note", "translate to Chinese/English/Japanese"
npx skillsauth add dull-bird/deeporbit do.translate-markdownInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Translate Markdown documents while ensuring zero paragraph loss, perfect structure preservation, and consistent terminology. Uses the same checklist-driven approach as do.pdf-to-markdown.
deeporbit.json from the workspace root and use its language field.<filename> to <language>. Proceed?"Before translating anything, you MUST read the entire document to build a glossary and structural map.
Read the FULL source Markdown end-to-end. This is NOT optional. You must understand the full context, writing style, and key terminology before translating a single word.
Extract a Terminology Glossary — identify ALL key terms, proper nouns, and recurring phrases. Decide their correct translation NOW so every section uses the same terms later:
## Terminology Glossary
| Source Term | Translation | Notes |
|-------------|-------------|-------|
| Knowledge Base | 知识库 | Not "知识基地" |
| Agent | Agent | Keep English |
| Vault | 知识库 | Obsidian context |
| Wikilink | 双链 | |
| Completeness Verification | 完整性验证 | |
| ... | ... | Add 15-30 key terms |
[!IMPORTANT] The glossary is the single source of truth for terminology. Every Ralph iteration MUST re-read the glossary before translating its section. This is how consistency is maintained across fresh context windows.
## Translation Manifest: <filename>
- Source: <filename>.md (<word count> words, <line count> lines)
- Target language: <language>
- Sections discovered:
- [ ] Frontmatter/YAML (preserve as-is or translate values only)
- [ ] # Section 1: Title (lines 1-25)
- [ ] ## Section 1.1: Subtitle (lines 26-50)
- [ ] ## Section 1.2: ... (lines 51-80)
- [ ] ...
- [ ] # Section N: References (lines X-Y)
- Code blocks: C (preserve untranslated)
- Tables: T (translate content, preserve structure)
- Math blocks: M (preserve untranslated)
- Wikilinks: W (preserve untranslated)
- Estimated output: ~<word count> words
<filename>_translation_manifest.md alongside the source file. Do not proceed to Phase 2 until this file is written.CRITICAL: Each section is translated in a separate Ralph iteration. Do NOT attempt to translate multiple sections in one agent turn.
Step 1: After Phase 0 + Phase 1 are done (language confirmed, manifest + glossary written), launch the Ralph loop:
/ralph:loop "You are running do.translate-markdown Phase 2. The manifest is at '<filename>_translation_manifest.md'. Target language: <language>. Your job in THIS iteration: 1) Read the manifest and glossary at the top. 2) Find the FIRST section still marked '- [ ]'. 3) Read that section from the source file. 4) Translate following preservation rules (DO NOT translate code blocks, math, wikilink targets, URLs). Use glossary for terminology. 5) APPEND to '<output_filename>.md'. 6) Update manifest: '- [ ]' to '- [x]'. 7) If ALL sections are now [x], run Phase 3 verification and output '<promise>TRANSLATION_COMPLETE</promise>'. Otherwise, just finish this turn." --completion-promise "TRANSLATION_COMPLETE" --max-iterations 30
Step 2: Each Ralph iteration does the following for ONE section:
[ ] section.# level)title, description, summary values...) — keep all code untouched` ... `) — keep untouched$...$ and $$...$$)[[...]]) — keep link targets, may translate display text [[target|显示文本]][显示文本](url)- [ ] → - [x].flowchart TD
A["Phase 1 done: manifest + glossary"] --> B["/ralph:loop"]
B --> C["Iteration N: Read glossary + manifest"]
C --> D{"Find next [ ] section"}
D -->|Found| E["Read source section"]
E --> F["Translate using glossary"]
F --> G["Append to output + check off [x]"]
G --> H["Turn ends"]
H --> C
D -->|All [x]| I["Phase 3: Verification"]
I --> J["TRANSLATION_COMPLETE"]
[!IMPORTANT] Set
--max-iterationsto roughly 2× the number of sections. If Ralph stops mid-way, just re-run — it picks up from the first unchecked[ ].
Only after all sections are [x] does the loop proceed to Phase 3.
After all sections are translated:
Manifest check: Every [ ] must be [x]. If any remain, go back and translate them.
Line count comparison:
Heading structure check: Extract all headings from source and output. They must be 1:1 matching (same count, same hierarchy).
Code block preservation check: Count code blocks in source vs output — must be identical.
Link preservation check: Count wikilinks [[...]] and URLs in source vs output — must be identical.
Report results:
## Translation Report
- Source: <filename>.md (<S> lines, <W> words)
- Output: <filename>_<LANG>.md (<O> lines, <W'> words)
- Target language: <language>
- Sections: <M>/<M> translated ✅
- Headings: <H>/<H> matched ✅
- Code blocks: <C>/<C> preserved ✅
- Wikilinks: <L>/<L> preserved ✅
- Terminology consistency: verified ✅
Output file naming: <filename>_<LANG>.md
README_CN.md, research_EN.md, notes_JA.mdCN (Chinese), EN (English), JA (Japanese), KO (Korean), FR (French), DE (German), ES (Spanish)Frontmatter: Update the output file's frontmatter:
---
title: "<Translated Title>"
source: "[[<original filename>]]"
language: "<target language code>"
translated: YYYY-MM-DD
tags: [translation]
---
Translate cell content but preserve the table structure exactly:
| Source | Target | → | 源文本 | 目标语言 |
|--------|--------| |--------|----------|
| Hello | World | → | 你好 | 世界 |
A["Start"] → A["开始"]TD, LR), or syntax keywordsTranslate the content, preserve the type:
> [!NOTE] → > [!NOTE]
> This is important. → > 这很重要。
# Source # Translated
related: "[[Some Note]]" → related: "[[Some Note]]" # keep link target
title: "My Research" → title: "我的研究" # translate value
If the source already contains mixed languages (e.g., English terms in a Chinese doc), preserve the untranslated terms unless user specifies otherwise. Technical terms, brand names, and proper nouns often stay in their original language.
| Criterion | Requirement | |-----------|-------------| | Completeness | Every paragraph in source must appear in output | | Structure | Heading hierarchy must be identical | | Terminology | Consistent glossary terms throughout | | Code integrity | All code blocks byte-identical to source | | Link integrity | All wikilinks and URLs preserved | | Natural language | Translation reads naturally, not machine-translated | | No hallucination | Output contains ONLY content from the source |
| Ralph Feature | How Translate-Markdown Uses It |
|---|---|
| Persistent state via files | Manifest + glossary track progress and terminology across turns |
| Fresh context each turn | Each section gets full context window — no translation drift |
| Completion promise | TRANSLATION_COMPLETE triggers when all [ ] become [x] |
| Max iterations safety | Prevents infinite loops if a section fails repeatedly |
| Self-correction | Each turn re-reads glossary — terminology stays consistent |
deeporbit.json from the workspace root to determine the interaction language. Use this language for all your responses and generated note contents (e.g. zh-CN). The Obsidian folder paths themselves will ALWAYS remain in English.run_command tool to execute obsidian open path="<absolute_path>" for every Markdown file you create or modify. See the do.obsidian-open skill for details.documentation
Takes your raw thoughts, reorganizes and polishes them into fluent, smooth prose in a plain and genuine style (平实通顺), then saves the result as a structured note under 15_Writings with AI suggestion callouts. Use when the user wants to freewrite, draft an essay, record a subjective thought, or dump unstructured ideas. Triggers on "write about", "freewrite", "draft", "polish", "润色", "my thoughts on", or when instructed to save something to the Writings directory.
documentation
Translate documents smartly. Accepts a URL or a PDF file as input. Detects if it is an arXiv URL or paper. If yes, runs do.arxiv-translator. If it is a standard PDF, runs do.pdf-to-markdown followed by do.translate-markdown.
tools
Exact string or regex matching search for Obsidian Vault files
research
Deep research workflow for technologies, concepts, or complex topics