
Baoyu Translate
- 22.6k installs
- 24.2k repo stars
- Updated July 4, 2026
- jimliu/baoyu-skills
baoyu-translate is an agent skill that >-.
About
>- --- name: baoyu-translate description: >- This skill should be used when the user asks to "translate", "翻译", "精翻", "translate article", "translate to Chinese", "translate to English", "改成中文", "改成英文", "convert to Chinese", "localize", "本地化", "refined translation", "精细翻译", "proofread translation", "快速翻译", "快翻", "这篇文章翻译一下", or provides a URL/file with translation intent. Supports three modes (quick/normal/refined) with custom glossary support. version: 1.59.0 metadata: openclaw: homepage: https://github.com/JimLiu/baoyu-skills#baoyu-translate requires: anyBins: - bun - npx --- # Translator Three-mode translation skill: **quick** for direct translation, **normal** for analysis-informed translation, **refined** for full publication-quality workflow with review and polish. ## User Input Tools When this skill prompts the user, follow this tool-selection rule (priority order): 1. **Prefer built-in user-input tools** exposed by the current agent runtime - e.g., `AskUserQuestion`, `request_user_input`, `clarify`, `ask_user`, or any equivalent. **Fallback**: if no such tool exists, emit a numbered plain-text message and ask the user to reply with the chosen number/answer for each questi.
- **Prefer built-in user-input tools** exposed by the current agent runtime - e.g., `AskUserQuestion`, `request_user_inp
- **Fallback**: if no such tool exists, emit a numbered plain-text message and ask the user to reply with the chosen numbe
- "快翻", "quick", "直接翻译" → quick mode
- "精翻", "refined", "publication quality", "proofread" → refined mode
- Otherwise → default mode (normal)
Baoyu Translate by the numbers
- 22,650 all-time installs (skills.sh)
- +438 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #47 of 4,386 Backend & APIs skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
baoyu-translate capabilities & compatibility
- Capabilities
- **prefer built in user input tools** exposed by · **fallback**: if no such tool exists, emit a num · "快翻", "quick", "直接翻译" → quick mode · "精翻", "refined", "publication quality", "proofre · otherwise → default mode (normal)
- Use cases
- documentation
What baoyu-translate says it does
Supports three modes (quick/normal/refined) with custom glossary support.
## User Input Tools When this skill prompts the user, follow this tool-selection rule (priority order): 1.
**Prefer built-in user-input tools** exposed by the current agent runtime — e.g., `AskUserQuestion`, `request_user_input`, `clarify`, `ask_user`, or any equivalent.
**Fallback**: if no such tool exists, emit a numbered plain-text message and ask the user to reply with the chosen number/answer for each question.
npx skills add https://github.com/jimliu/baoyu-skills --skill baoyu-translateAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 22.6k |
|---|---|
| repo stars | ★ 24.2k |
| Security audit | 2 / 3 scanners passed |
| Last updated | July 4, 2026 |
| Repository | jimliu/baoyu-skills ↗ |
What problem does baoyu-translate solve for developers using this skill?
>-
Who is it for?
Developers who need baoyu-translate patterns described in the cached skill documentation.
Skip if: Skip when docs are empty or the task is outside the skill's documented scope.
When should I use this skill?
>-
What you get
Actionable workflows and conventions from SKILL.md for baoyu-translate.
- translated documentation files
- glossary-consistent localized copy
By the numbers
- Default chunk_threshold of 4000 words triggers chunked translation
- chunk_max_words caps each segment at 5000 words
- Three translation modes: quick, normal, and refined
Files
Translator
Three-mode translation skill: quick for direct translation, normal for analysis-informed translation, refined for full publication-quality workflow with review and polish.
User Input Tools
When this skill prompts the user, follow this tool-selection rule (priority order):
1. Prefer built-in user-input tools exposed by the current agent runtime — e.g., AskUserQuestion, request_user_input, clarify, ask_user, or any equivalent. 2. Fallback: if no such tool exists, emit a numbered plain-text message and ask the user to reply with the chosen number/answer for each question. 3. Batching: if the tool supports multiple questions per call, combine all applicable questions into a single call; if only single-question, ask them one at a time in priority order.
Concrete AskUserQuestion references below are examples — substitute the local equivalent in other runtimes.
Script Directory
Scripts in scripts/ subdirectory. {baseDir} = this SKILL.md's directory path. Resolve ${BUN_X} runtime: if bun installed → bun; if npx available → npx -y bun; else suggest installing bun. Replace {baseDir} and ${BUN_X} with actual values.
| Script | Purpose |
|---|---|
scripts/main.ts | CLI entry point. Default action splits markdown into chunks; also supports explicit chunk subcommand |
scripts/chunk.ts | Markdown chunking implementation used by main.ts and kept compatible for direct invocation |
Preferences (EXTEND.md)
Check EXTEND.md in priority order — the first one found wins:
| Priority | Path | Scope |
|---|---|---|
| 1 | .baoyu-skills/baoyu-translate/EXTEND.md | Project |
| 2 | ${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-translate/EXTEND.md | XDG |
| 3 | $HOME/.baoyu-skills/baoyu-translate/EXTEND.md | User home |
| Result | Action |
|---|---|
| Found | Read, parse, apply. On first use in session, briefly remind: "Using preferences from [path]. You can edit EXTEND.md to customize glossary, audience, etc." |
| Not found | MUST run first-time setup (see below) — do NOT silently use defaults |
EXTEND.md supports: default target language, default mode, target audience, custom glossaries (inline or file path), translation style, chunk settings.
Schema: references/config/extend-schema.md.
First-Time Setup (BLOCKING)
CRITICAL: When EXTEND.md is not found, you MUST run the first-time setup before ANY translation. This is a BLOCKING operation.
Full reference: references/config/first-time-setup.md
Use AskUserQuestion with all questions (target language, mode, audience, style, save location) in ONE call. After user answers, create EXTEND.md at the chosen location, confirm "Preferences saved to [path]", then continue.
Defaults
All configurable values in one place. EXTEND.md overrides these; CLI flags override EXTEND.md.
| Setting | Default | EXTEND.md key | CLI flag | Description |
|---|---|---|---|---|
| Target language | zh-CN | target_language | --to | Translation target language |
| Mode | normal | default_mode | --mode | Translation mode |
| Audience | general | audience | --audience | Target reader profile |
| Style | storytelling | style | --style | Translation style preference |
| Chunk threshold | 4000 | chunk_threshold | — | Word count to trigger chunked translation |
| Chunk max words | 5000 | chunk_max_words | — | Max words per chunk |
Modes
| Mode | Flag | Steps | When to Use |
|---|---|---|---|
| Quick | --mode quick | Translate | Short texts, informal content, quick tasks |
| Normal | --mode normal (default) | Analyze → Translate | Articles, blog posts, general content |
| Refined | --mode refined | Analyze → Translate → Review → Polish | Publication-quality, important documents |
Default mode: Normal (can be overridden in EXTEND.md default_mode setting).
Style presets — control the voice and tone of the translation (independent of audience):
| Value | Description | Effect |
|---|---|---|
storytelling | Engaging narrative flow (default) | Draws readers in, smooth transitions, vivid phrasing |
formal | Professional, structured | Neutral tone, clear organization, no colloquialisms |
technical | Precise, documentation-style | Concise, terminology-heavy, minimal embellishment |
literal | Close to original structure | Minimal restructuring, preserves source sentence patterns |
academic | Scholarly, rigorous | Formal register, complex clauses OK, citation-aware |
business | Concise, results-focused | Action-oriented, executive-friendly, bullet-point mindset |
humorous | Preserves and adapts humor | Witty, playful, recreates comedic effect in target language |
conversational | Casual, spoken-like | Friendly, approachable, as if explaining to a friend |
elegant | Literary, polished prose | Aesthetically refined, rhythmic, carefully crafted word choices |
Custom style descriptions are also accepted, e.g., --style "poetic and lyrical".
Auto-detection:
- "快翻", "quick", "直接翻译" → quick mode
- "精翻", "refined", "publication quality", "proofread" → refined mode
- Otherwise → default mode (normal)
Upgrade prompt: After normal mode completes, display:
Translation saved. To further review and polish, reply "继续润色" or "refine".
If user responds, continue with review → polish steps (same as refined mode Steps 4-6 in refined-workflow.md) on the existing output.
Audience presets:
| Value | Description | Effect |
|---|---|---|
general | General readers (default) | Plain language, more translator's notes for jargon |
technical | Developers / engineers | Less annotation on common tech terms |
academic | Researchers / scholars | Formal register, precise terminology |
business | Business professionals | Business-friendly tone, explain tech concepts |
Custom audience descriptions are also accepted, e.g., --audience "AI感兴趣的普通读者".
Workflow
Step 1: Load Preferences
1.1 Check EXTEND.md (see Preferences section above)
1.2 Load built-in glossary for the language pair if available:
- EN→ZH: references/glossary-en-zh.md
1.3 Merge glossaries: EXTEND.md glossary (inline) + EXTEND.md glossary_files (external files, paths relative to EXTEND.md location) + built-in glossary + --glossary file (CLI overrides all)
Step 2: Materialize Source & Create Output Directory
Materialize source (file as-is, inline text/URL → save to translate/{slug}.md), then create output directory: {source-dir}/{source-basename}-{target-lang}/. Detect source language if --from not specified.
Full details: references/workflow-mechanics.md
Output directory contents (all intermediate and final files go here):
| File | Mode | Description |
|---|---|---|
translation.md | All | Final translation (always this name) |
01-analysis.md | Normal, Refined | Content analysis (domain, tone, terminology) |
02-prompt.md | Normal, Refined | Assembled translation prompt |
03-draft.md | Refined | Initial draft before review |
04-critique.md | Refined | Critical review findings (diagnosis only) |
05-revision.md | Refined | Revised translation based on critique |
chunks/ | Chunked | Source chunks + translated chunks |
Step 3: Assess Content Length
Quick mode does not chunk — translate directly regardless of length. Before translating, estimate word count. If content exceeds chunk threshold (default 4000 words), proactively warn: "This article is ~{N} words. Quick mode translates in one pass without chunking — for long content, --mode normal produces better results with terminology consistency." Then proceed if user doesn't switch.
For normal and refined modes:
| Content | Action |
|---|---|
| < chunk threshold | Translate as single unit |
| >= chunk threshold | Chunk translation (see Step 3.1) |
3.1 Long Content Preparation (normal/refined modes, >= chunk threshold only)
Before translating chunks:
1. Extract terminology: Scan entire document for proper nouns, technical terms, recurring phrases 2. Build session glossary: Merge extracted terms with loaded glossaries, establish consistent translations 3. Split into chunks: Use ${BUN_X} {baseDir}/scripts/main.ts <file> [--max-words <chunk_max_words>] [--output-dir <output-dir>]
- Parses markdown blocks (headings, paragraphs, lists, code blocks, tables, etc.)
- Splits at markdown block boundaries to preserve structure
- If a single block exceeds the threshold, falls back to line splitting, then word splitting
4. Assemble translation prompt:
- Main agent reads
01-analysis.md(if exists) and assembles shared context using Part 1 of references/subagent-prompt-template.md — inlining: target style, content background, merged glossary, and translation challenges - Save as
02-prompt.mdin the output directory (shared context only, no task instructions)
5. Draft translation via subagents (if Agent tool available):
- Spawn one subagent per chunk, all in parallel (Part 2 of the template)
- Each subagent reads
02-prompt.mdfor shared context, receives chunk position info (chunk N of M + brief context of where it sits in the argument), translates its chunk, saves tochunks/chunk-NN-draft.md - Consistency is guaranteed by the shared
02-prompt.md(glossary, figurative language mapping, comprehension challenges, source voice, and translation challenges from analysis) - If no chunks (content under threshold): spawn one subagent for the entire source file
- If Agent tool is unavailable, translate chunks sequentially inline using
02-prompt.md
6. Merge: Once all subagents complete, combine translated chunks in order. If chunks/frontmatter.md exists, prepend it. Save as 03-draft.md (refined) or translation.md (normal) 7. All intermediate files (source chunks + translated chunks) are preserved in chunks/
After chunked draft is merged, return control to main agent for critical review, revision, and polish (Step 4).
Step 4: Translate & Refine
Translation principles (apply to all modes):
- Rewrite, not translate: Rewrite content into natural, engaging target language as if a skilled native writer composed it from scratch. Quality test: "Does this read like it was originally written in the target language?"
- Accuracy first: Facts, data, and logic must match the original exactly
- Natural flow: Use idiomatic target language word order. Break long source sentences into shorter, natural ones. Interpret metaphors and idioms by intended meaning, not word-for-word
- Terminology: Use standard translations consistently. First occurrence of specialized terms: annotate with original in parentheses
- Preserve format: Keep all markdown formatting (headings, bold, italic, images, links, code blocks)
- Proactive interpretation: For jargon or concepts the target audience may lack context for, add concise explanations in bold parentheses
(**解释**). Keep annotations few — only where genuinely needed for comprehension - Frontmatter: If source has YAML frontmatter, rename source-metadata fields with
sourceprefix (camelCase:url→sourceUrl,title→sourceTitle, etc.), add translated values as new top-level fields (skiptitleif body has H1), keep other fields as-is
Quick Mode
Translate directly → save to translation.md. Apply all translation principles above.
Normal Mode
1. Analyze → 01-analysis.md (domain, tone, terminology, translation challenges) 2. Assemble prompt → 02-prompt.md (translation instructions with context, glossary, challenges) 3. Translate (following 02-prompt.md) → translation.md
After completion, prompt user: "Translation saved. To further review and polish, reply 继续润色 or refine."
If user continues, proceed with critical review → revision → polish (same as refined mode Steps 4-6 below), saving 03-draft.md (rename current translation.md), 04-critique.md, 05-revision.md, and updated translation.md.
Refined Mode
Full workflow for publication quality. See references/refined-workflow.md for detailed guidelines per step.
The subagent (if used in Step 3.1) only handles the initial draft. All subsequent steps (critical review, revision, polish) are handled by the main agent, which may delegate to subagents at its discretion.
Steps and saved files (all in output directory): 1. Analyze → 01-analysis.md (domain, tone, terminology, translation challenges) 2. Assemble prompt → 02-prompt.md (translation instructions with inlined context) 3. Draft → 03-draft.md (initial translation with translator's notes; from subagent if chunked) 4. Critical review → 04-critique.md (diagnosis only: accuracy, Europeanized language, strategy execution, expression issues) 5. Revision → 05-revision.md (apply all critique findings to produce revised translation) 6. Polish → translation.md (final publication-quality translation)
Each step reads the previous step's file and builds on it.
Step 5: Output
Final translation is always at translation.md in the output directory.
After the final translation is written, do a lightweight image-language pass:
1. Collect image references from the translated article 2. Identify likely text-heavy images such as covers, screenshots, diagrams, charts, frameworks, and infographics 3. If any image likely contains a main text language that does not match the translated article language, proactively remind the user 4. The reminder must be a list only. Do not automatically localize those images unless the user asks
Reminder format (use whatever image syntax the article already uses — standard markdown or wikilink):
Possible image localization needed:
- : likely still contains source-language text while the article is now in target language
- : likely text-heavy framework graphic, check whether labels need translationDisplay summary:
**Translation complete** ({mode} mode)
Source: {source-path}
Languages: {from} → {to}
Output dir: {output-dir}/
Final: {output-dir}/translation.md
Glossary terms applied: {count}If mismatched image-language candidates were found, append a short note after the summary telling the user that some embedded images may still need image-text localization, followed by the candidate list.
Extension Support
Custom configurations via EXTEND.md. See Preferences section for paths and supported options.
EXTEND.md Schema for baoyu-translate
Format
EXTEND.md uses YAML format:
# Default target language (ISO code or common name)
target_language: zh-CN
# Default translation mode
default_mode: normal # quick | normal | refined
# Target audience (affects annotation depth and register)
audience: general # general | technical | academic | business | or custom string
# Translation style preference
style: storytelling # storytelling | formal | technical | literal | academic | business | humorous | conversational | elegant | or custom string
# Word count threshold to trigger chunked translation
chunk_threshold: 4000
# Max words per chunk
chunk_max_words: 5000
# Custom glossary (merged with built-in glossary)
# CLI --glossary flag overrides these
# Supports inline entries and/or file paths
glossary:
- from: "Reinforcement Learning"
to: "强化学习"
- from: "Transformer"
to: "Transformer"
note: "Keep English"
# Load glossary from external file(s)
# Supports absolute path or relative to EXTEND.md location
# File format: markdown table with | from | to | note | columns,
# or YAML list of {from, to, note} entries
glossary_files:
- ./my-glossary.md
- /path/to/shared-glossary.yaml
# Language-pair specific glossaries
glossaries:
en-zh:
- from: "AI Agent"
to: "AI 智能体"
ja-zh:
- from: "人工知能"
to: "人工智能"Fields
| Field | Type | Default | Description |
|---|---|---|---|
target_language | string | zh-CN | Default target language code |
default_mode | string | normal | Default translation mode (quick / normal / refined) |
audience | string | general | Target reader profile (general / technical / academic / business / custom) |
style | string | storytelling | Translation style (storytelling / formal / technical / literal / academic / business / humorous / conversational / elegant / custom) |
chunk_threshold | number | 4000 | Word count threshold to trigger chunked translation |
chunk_max_words | number | 5000 | Max words per chunk |
glossary | array | [] | Universal glossary entries (inline) |
glossary_files | array | [] | External glossary file paths (absolute or relative to EXTEND.md) |
glossaries | object | {} | Language-pair specific glossary entries |
Glossary Entry
| Field | Required | Description |
|---|---|---|
from | yes | Source term |
to | yes | Target translation |
note | no | Usage note (e.g., "Keep English", "Only in tech context") |
Glossary File Format
External glossary files (glossary_files) support two formats:
Markdown table (.md):
| from | to | note |
|------|----|------|
| Reinforcement Learning | 强化学习 | |
| Transformer | Transformer | Keep English |YAML list (.yaml / .yml):
- from: "Reinforcement Learning"
to: "强化学习"
- from: "Transformer"
to: "Transformer"
note: "Keep English"Paths can be absolute or relative to the EXTEND.md file location.
Priority
1. CLI --glossary file entries 2. EXTEND.md glossaries[pair] entries 3. EXTEND.md glossary entries (inline) 4. EXTEND.md glossary_files entries (in listed order, later files override earlier) 5. Built-in glossary (e.g., references/glossary-en-zh.md)
Later entries override earlier ones for the same source term.
First-Time Setup
Overview
When no EXTEND.md is found, guide user through preference setup.
BLOCKING OPERATION: This setup MUST complete before ANY translation. Do NOT:
- Start translating content
- Ask about files or output paths
- Proceed to any workflow steps
ONLY ask the questions in this setup flow, save EXTEND.md, then continue.
Setup Flow
No EXTEND.md found
|
v
+---------------------+
| AskUserQuestion |
| (all questions) |
+---------------------+
|
v
+---------------------+
| Create EXTEND.md |
+---------------------+
|
v
Continue translationQuestions
Language: Use user's input language or saved language preference.
Use AskUserQuestion with ALL questions in ONE call:
Question 1: Target Language
header: "Target Language"
question: "Default target language?"
options:
- label: "简体中文 zh-CN (Recommended)"
description: "Translate to Simplified Chinese"
- label: "繁體中文 zh-TW"
description: "Translate to Traditional Chinese"
- label: "English en"
description: "Translate to English"
- label: "日本語 ja"
description: "Translate to Japanese"Note: User may type a custom language code.
Question 2: Translation Mode
header: "Mode"
question: "Default translation mode?"
options:
- label: "Normal (Recommended)"
description: "Analyze content first, then translate"
- label: "Quick"
description: "Direct translation, no analysis"
- label: "Refined"
description: "Full workflow: analyze → translate → review → polish"Question 3: Target Audience
header: "Audience"
question: "Default target audience?"
options:
- label: "General readers (Recommended)"
description: "Plain language, more translator's notes for jargon"
- label: "Technical"
description: "Developers/engineers, less annotation on tech terms"
- label: "Academic"
description: "Formal register, precise terminology"
- label: "Business"
description: "Business-friendly tone, explain tech concepts"Note: User may type a custom audience description.
Question 4: Translation Style
header: "Style"
question: "Translation style?"
options:
- label: "Storytelling (Recommended)"
description: "Engaging narrative flow, smooth transitions"
- label: "Formal"
description: "Professional, structured, neutral tone"
- label: "Technical"
description: "Precise, documentation-style, concise"
- label: "Literal"
description: "Close to original structure"
- label: "Academic"
description: "Scholarly, rigorous, formal register"
- label: "Business"
description: "Concise, results-focused, action-oriented"
- label: "Humorous"
description: "Preserves humor, witty, playful"
- label: "Conversational"
description: "Casual, friendly, spoken-like"
- label: "Elegant"
description: "Literary, polished, aesthetically refined"Note: User may type a custom style description.
Question 5: Save Location
header: "Save"
question: "Where to save preferences?"
options:
- label: "User (Recommended)"
description: "$HOME/.baoyu-skills/ (all projects)"
- label: "Project"
description: ".baoyu-skills/ (this project only)"Save Locations
| Choice | Path | Scope |
|---|---|---|
| User | $HOME/.baoyu-skills/baoyu-translate/EXTEND.md | All projects |
| Project | .baoyu-skills/baoyu-translate/EXTEND.md | Current project |
After Setup
1. Create directory if needed 2. Write EXTEND.md with selected values 3. Confirm: "Preferences saved to [path]" 4. Mention: "You can add custom glossary terms to EXTEND.md anytime. See the glossary section in the file for the format." 5. Continue with translation using saved preferences
EXTEND.md Template
target_language: [zh-CN/zh-TW/en/ja/...]
default_mode: [quick/normal/refined]
audience: [general/technical/academic/business/custom]
style: [storytelling/formal/technical/literal/academic/business/humorous/conversational/elegant]
# Custom glossary (optional) — add your own term translations here
# glossary:
# - from: "Term"
# to: "翻译"
# - from: "Another Term"
# to: "另一个翻译"
# note: "Usage context"Modifying Preferences Later
Users can edit EXTEND.md directly or delete it to trigger setup again.
English → Chinese Glossary
Terms where standard translation is non-obvious or easily mistranslated. Common terms with straightforward translations (e.g., Machine Learning → 机器学习) are omitted — the model already knows these.
| English | Chinese | Notes |
|---|---|---|
| AI Agent | AI 智能体 | |
| Vibe Coding | 凭感觉编程 | |
| the Bitter Lesson | 苦涩的教训 | Rich Sutton's essay |
| Context Engineering | 上下文工程 | |
| AI Wrapper | AI 套壳 | |
| RLHF | 基于人类反馈的强化学习 | |
| Hallucination | 幻觉 | AI-specific meaning |
| Alignment | 对齐 | AI safety context |
| Guardrails | 护栏 | AI safety context |
| Agentic | 智能体化的 | |
| Grounding | 基础化/落地 | Context-dependent |
| Embedding | 嵌入/向量化 | Context-dependent |
| Moat | 护城河 | Business context |
| Flywheel | 飞轮效应 | |
| Boilerplate | 样板代码 |
Translation Workflow Details
This file provides detailed guidelines for each workflow step. Steps are shared across modes:
- Quick: Translate only (no steps from this file)
- Normal: Step 1 (Analysis) → Translate
- Refined: Step 1 (Analysis) → Step 2 (Draft) → Step 3 (Review) → Step 4 (Revision) → Step 5 (Polish)
- Normal → Upgrade: After normal mode, user can continue with Step 3 → Step 4 → Step 5
All intermediate results are saved as files in the output directory.
Step 1: Content Analysis
Before translating, analyze the source material. Save analysis to 01-analysis.md in the output directory.
1.1 Content Summary
- What is this content about? What is the core argument?
- Author background, stance, and writing context
- Purpose and intended audience of the original
1.2 Terminology
- List technical terms, proper nouns, brand names, acronyms
- Cross-reference with loaded glossaries
- For terms not in glossary, determine standard translations
- Record in a terminology table
1.3 Tone & Style
- Formal or conversational? Humor, metaphor, cultural references?
- What register is appropriate for the translation given the target audience?
1.4 Translation Challenges
Identify what may cause difficulty in translation:
- Comprehension gaps: Terms or references that target readers may not understand — note what explanation is needed
- Figurative language: Metaphors, idioms, expressions that don't translate literally — note intended meaning and target-language approach (interpret / substitute / retain)
- Structural challenges: Long complex sentences, wordplay, puns, or humor that needs creative adaptation
Save `01-analysis.md` with:
## Content Summary
[Core argument, author, context, purpose]
## Terminology
[term → translation, ...]
## Tone & Style
[assessment]
## Translation Challenges
- [term/passage] → [challenge type] → [suggested approach]
- ...Step 2: Assemble Translation Prompt
Main agent reads 01-analysis.md and assembles a complete translation prompt using references/subagent-prompt-template.md. Inline the following from analysis:
- Target style: Resolved style preset + source voice assessment from §1.3
- Content background: Summary from §1.1
- Glossary: Merged glossary with analysis-extracted terms from §1.2
- Translation challenges: All challenges from §1.4
Save to 02-prompt.md. This prompt is used by the subagent (chunked) or by the main agent itself (non-chunked).
Step 3: Initial Draft
Save to 03-draft.md in the output directory.
For chunked content, the subagent produces this draft (merged from chunk translations). For non-chunked content, the main agent produces it directly.
Translate the full content following 02-prompt.md. Apply all Translation principles from SKILL.md.
Step 4: Critical Review
The main agent critically reviews the draft against the source. Save review findings to 04-critique.md. This step produces diagnosis only — no rewriting yet.
4.1 Accuracy
- Compare each paragraph against the original
- Verify facts, numbers, dates, proper nouns
- Flag content accidentally added, removed, or altered
- Check terminology consistency with glossary
4.2 Native Voice
- Flag sentences that read as "translated" rather than "written" — unnatural word order, calques, stiff phrasing
- For CJK targets: check for unnecessary connectives (因此/然而/此外), passive voice abuse (被/由/受到), noun pile-ups, over-nominalization
- Flag metaphors translated literally that sound unnatural in the target language
- Check emotional connotations are preserved, not flattened
- Note where sentence restructuring would improve readability
4.3 Notes & Adaptation
- Are translator's notes accurate, concise, and genuinely helpful?
- Flag missed comprehension challenges that need notes, and over-annotations on obvious terms
- Were translation strategies from
02-prompt.mdfollowed? - Do cultural references work in the target language?
Save `04-critique.md` with:
## Accuracy
- [issue]: [location] — [description]
## Native Voice
- [issue]: [example] → [suggested fix]
## Notes & Adaptation
- [add/remove/revise]: [term/passage] — [reason]
## Summary
[Overall assessment: X critical issues, Y improvements]Step 5: Revision
Apply all findings from 04-critique.md to produce a revised translation. Save to 05-revision.md.
Read 03-draft.md and 04-critique.md, fix all accuracy issues, rewrite unnatural expressions, adjust notes, and improve flow.
Step 6: Polish
Save final version to translation.md.
Final pass on 05-revision.md for publication quality:
- Read the entire translation as a standalone piece — does it flow as native content?
- Smooth remaining rough transitions
- Ensure consistent narrative voice and style throughout
- Final terminology consistency check
- Verify formatting is preserved correctly
Subagent Responsibility
Each subagent (one per chunk) is responsible only for producing the initial draft of its chunk (Step 3). The main agent assembles the shared prompt (Step 2), spawns all subagents in parallel, then takes over for critical review (Step 4), revision (Step 5), and polish (Step 6).
Chunked Refined Translation
When content exceeds the chunk threshold and uses refined mode:
1. Main agent runs analysis (Step 1) on the entire document first → 01-analysis.md 2. Main agent assembles translation prompt → 02-prompt.md 3. Split into chunks → chunks/ 4. Spawn one subagent per chunk in parallel (each reads 02-prompt.md for shared context) → merge all results into 03-draft.md 5. Main agent critically reviews the merged draft → 04-critique.md 6. Main agent revises based on critique → 05-revision.md 7. Main agent polishes → translation.md 8. Final cross-chunk consistency check: terminology, narrative flow, transitions at chunk boundaries
Subagent Translation Prompt Template
Two parts: 1. `02-prompt.md` — Shared context (saved to output directory). Contains background, glossary, challenges, and principles. No task-specific instructions. 2. Subagent spawn prompt — Task instructions passed when spawning each subagent. One subagent per chunk (or per source file if non-chunked).
The main agent reads 01-analysis.md (if exists), inlines all relevant context into 02-prompt.md, then spawns subagents in parallel with task instructions referencing that file.
Replace {placeholders} with actual values. Omit sections marked "if analysis exists" for quick mode.
---
Part 1: 02-prompt.md (shared context, saved as file)
You are a professional translator. Your task is to translate markdown content from {source_lang} to {target_lang}.
## Target Audience & Style
**Audience**: {audience description}
**Target style**: {style description — e.g., "storytelling: engaging narrative flow, smooth transitions, vivid phrasing" or custom style from user}
**Source voice** (from analysis, if exists): {Brief description of the original author's voice — formal/conversational, humor, register, sentence rhythm.}
## Content Background
{Inlined from 01-analysis.md if analysis exists: content summary, core argument, author background, context.}
## Glossary
Apply these term translations consistently. First occurrence: include original in parentheses.
{Merged glossary — one per line: English → Translation}
## Translation Challenges
{Inlined from 01-analysis.md §1.4 if analysis exists. Comprehension gaps, figurative language, structural challenges with suggested approaches:}
- **{term/passage}**: {challenge type} → {suggested approach}
## Translation Principles
Rewrite the content into natural, engaging {target_lang} — not merely translate it. Every sentence should read as if a skilled native writer composed it from scratch.
- **Accuracy first**: Facts, data, and logic must match the original exactly
- **Natural flow**: Use idiomatic {target_lang} word order. Break long source sentences into shorter, natural ones. Interpret metaphors and idioms by intended meaning, not word-for-word
- **Terminology**: Use glossary translations consistently. Annotate with original in parentheses on first occurrence of specialized terms
- **Preserve format**: Keep all markdown formatting (headings, bold, italic, images, links, code blocks)
- **Proactive interpretation**: For jargon or concepts the target audience may lack context for, add concise explanations in **bold parentheses** `(**解释**)`. Keep annotations few — only where genuinely needed---
Part 2: Subagent spawn prompt (passed as Agent tool prompt)
Chunked mode (one subagent per chunk, all spawned in parallel)
Read the translation instructions from: {output_dir}/02-prompt.md
You are translating chunk {NN} of {total_chunks}.
Context: {brief description of what this chunk covers and where it sits in the overall argument}
Translate this chunk:
1. Read `{output_dir}/chunks/chunk-{NN}.md`
2. Translate following the instructions in 02-prompt.md
3. Save translation to `{output_dir}/chunks/chunk-{NN}-draft.md`Non-chunked mode
Read the translation instructions from: {output_dir}/02-prompt.md
Translate the source file and save the result:
1. Read `{source_file_path}`
2. Save translation to `{output_path}`Workflow Mechanics
Details for source materialization, output directory creation, and conflict resolution.
Materialize Source
| Input Type | Action |
|---|---|
| File | Use as-is (no copy needed) |
| Inline text | Save to translate/{slug}.md |
| URL | Fetch content, save to translate/{slug}.md |
{slug}: 2-4 word kebab-case slug derived from content topic.
Create Output Directory
Create a subdirectory next to the source file: {source-dir}/{source-basename}-{target-lang}/
Examples:
posts/article.md→posts/article-zh/translate/ai-future.md→translate/ai-future-zh/
Conflict Resolution
If the output directory already exists, rename the existing one to {name}.backup-YYYYMMDD-HHMMSS/ before creating the new one. Never overwrite existing results.
{
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "baoyu-translate-chunk",
"dependencies": {
"markdown-it": "14.1.1",
},
},
},
"packages": {
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
"entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"linkify-it": ["linkify-it@5.0.0", "", { "dependencies": { "uc.micro": "^2.0.0" } }, "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ=="],
"markdown-it": ["markdown-it@14.1.1", "", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", "linkify-it": "^5.0.0", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA=="],
"mdurl": ["mdurl@2.0.0", "", {}, "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="],
"punycode.js": ["punycode.js@2.3.1", "", {}, "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="],
"uc.micro": ["uc.micro@2.1.0", "", {}, "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="],
}
}
import { mkdirSync, readFileSync, writeFileSync } from "fs"
import { dirname, join } from "path"
import MarkdownIt from "markdown-it"
type BlockKind =
| "heading"
| "thematicBreak"
| "html"
| "code"
| "flow"
interface Block {
kind: BlockKind
md: string
words: number
}
interface Chunk {
blocks: Block[]
words: number
}
export interface ChunkCliOptions {
file: string
maxWords: number
outputDir: string
}
export interface ChunkResult {
source: string
chunks: number
output_dir: string
frontmatter: boolean
words_per_chunk: number[]
}
const parser = new MarkdownIt({ html: true })
export function formatChunkUsage(command: string): string {
return `Usage: ${command} <file> [--max-words 5000] [--output-dir <dir>]`
}
export function runChunkCli(args: string[], command = "chunk.ts"): number {
const parsed = parseChunkCliArgs(args)
if ("help" in parsed) {
console.log(formatChunkUsage(command))
return 0
}
if ("error" in parsed) {
console.error(parsed.error)
console.error(formatChunkUsage(command))
return 1
}
const result = chunkMarkdownFile(parsed.file, {
maxWords: parsed.maxWords,
outputDir: parsed.outputDir,
})
console.log(JSON.stringify(result))
return 0
}
export function chunkMarkdownFile(
file: string,
options: { maxWords?: number; outputDir?: string } = {}
): ChunkResult {
const maxWords = options.maxWords ?? 5000
const outputDir = options.outputDir ?? ""
const rawContent = normalizeNewlines(readFileSync(file, "utf-8"))
const { frontmatter, body } = extractFrontmatter(rawContent)
const chunks = buildChunks(parseMarkdown(body), maxWords)
const dir = outputDir ? join(outputDir, "chunks") : join(dirname(file), "chunks")
mkdirSync(dir, { recursive: true })
if (frontmatter) {
writeFileSync(join(dir, "frontmatter.md"), frontmatter)
}
chunks.forEach((chunk, index) => {
const num = String(index + 1).padStart(2, "0")
writeFileSync(join(dir, `chunk-${num}.md`), chunk.blocks.map(block => block.md).join("\n\n"))
})
return {
source: file,
chunks: chunks.length,
output_dir: dir,
frontmatter: Boolean(frontmatter),
words_per_chunk: chunks.map(chunk => chunk.words),
}
}
function parseChunkCliArgs(args: string[]):
| ChunkCliOptions
| { help: true }
| { error: string } {
let file = ""
let maxWords = 5000
let outputDir = ""
for (let index = 0; index < args.length; index += 1) {
const arg = args[index]
if (arg === "-h" || arg === "--help") {
return { help: true }
}
if (arg === "--max-words") {
const value = args[index + 1]
if (!value) return { error: "Missing value for --max-words" }
maxWords = parsePositiveInt(value, 0)
if (maxWords <= 0) return { error: `Invalid --max-words value: ${value}` }
index += 1
continue
}
if (arg === "--output-dir") {
const value = args[index + 1]
if (!value) return { error: "Missing value for --output-dir" }
outputDir = value
index += 1
continue
}
if (arg.startsWith("-")) {
return { error: `Unknown option: ${arg}` }
}
if (!file) {
file = arg
continue
}
return { error: `Unexpected positional argument: ${arg}` }
}
if (!file) {
return { error: "Missing input file" }
}
return { file, maxWords, outputDir }
}
function parsePositiveInt(value: string | undefined, fallback: number): number {
if (!value) return fallback
const parsed = Number.parseInt(value, 10)
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback
}
function normalizeNewlines(text: string): string {
return text.replace(/^\uFEFF/, "").replace(/\r\n?/g, "\n")
}
function trimBoundaryBlankLines(text: string): string {
return text.replace(/^\n+/, "").replace(/\n+$/, "")
}
function extractFrontmatter(content: string): { frontmatter: string; body: string } {
const lines = content.split("\n")
if (lines[0] !== "---") {
return { frontmatter: "", body: content }
}
for (let index = 1; index < lines.length; index += 1) {
if (lines[index] === "---" || lines[index] === "...") {
return {
frontmatter: lines.slice(0, index + 1).join("\n"),
body: lines.slice(index + 1).join("\n").replace(/^\n+/, ""),
}
}
}
return { frontmatter: "", body: content }
}
function parseMarkdown(content: string): Block[] {
if (!content.trim()) return []
const lines = content.split("\n")
const tokens = parser.parse(content, {})
const blocks: Block[] = []
for (const token of tokens) {
if (!token.map || token.level !== 0) continue
if (token.nesting !== 1 && token.nesting !== 0) continue
const [startLine, endLine] = token.map
const md = trimBoundaryBlankLines(lines.slice(startLine, endLine).join("\n"))
if (!md) continue
blocks.push(makeBlock(tokenTypeToBlockKind(token.type), md))
}
if (blocks.length === 0) {
const body = trimBoundaryBlankLines(content)
if (body) {
blocks.push(makeBlock("flow", body))
}
}
return blocks
}
function tokenTypeToBlockKind(tokenType: string): BlockKind {
if (tokenType === "heading_open") return "heading"
if (tokenType === "hr") return "thematicBreak"
if (tokenType === "html_block") return "html"
if (tokenType === "fence" || tokenType === "code_block") return "code"
return "flow"
}
function makeBlock(kind: BlockKind, md: string): Block {
return {
kind,
md: trimBoundaryBlankLines(md),
words: countWords(md),
}
}
function buildChunks(blocks: Block[], maxWordsPerChunk: number): Chunk[] {
const sections = splitIntoSections(blocks)
const normalizedBlocks: Block[] = []
for (const section of sections) {
const sectionWords = section.reduce((sum, block) => sum + block.words, 0)
if (sectionWords <= maxWordsPerChunk) {
normalizedBlocks.push(makeBlock("flow", section.map(block => block.md).join("\n\n")))
continue
}
for (const block of section) {
normalizedBlocks.push(...splitOversizedBlock(block, maxWordsPerChunk))
}
}
const chunks: Chunk[] = []
let currentBlocks: Block[] = []
let currentWords = 0
for (const block of normalizedBlocks) {
if (currentWords + block.words > maxWordsPerChunk && currentBlocks.length > 0) {
chunks.push({ blocks: currentBlocks, words: currentWords })
currentBlocks = [block]
currentWords = block.words
continue
}
currentBlocks.push(block)
currentWords += block.words
}
if (currentBlocks.length > 0) {
chunks.push({ blocks: currentBlocks, words: currentWords })
}
return chunks
}
function splitIntoSections(blocks: Block[]): Block[][] {
const sections: Block[][] = []
let current: Block[] = []
for (const block of blocks) {
if (block.kind === "heading" && current.length > 0) {
sections.push(current)
current = [block]
continue
}
current.push(block)
}
if (current.length > 0) {
sections.push(current)
}
return sections
}
function splitOversizedBlock(block: Block, maxWordsPerChunk: number): Block[] {
if (block.words <= maxWordsPerChunk) return [block]
if (
block.kind === "heading"
|| block.kind === "thematicBreak"
|| block.kind === "html"
|| block.kind === "code"
) {
return [block]
}
const lines = block.md.split("\n")
if (lines.length <= 1) {
return [block]
}
const splitBlocks: Block[] = []
let buffer: string[] = []
let bufferWords = 0
for (const line of lines) {
const lineWords = countWords(line)
if (bufferWords + lineWords > maxWordsPerChunk && buffer.length > 0) {
splitBlocks.push(makeBlock(block.kind, buffer.join("\n")))
buffer = [line]
bufferWords = lineWords
continue
}
buffer.push(line)
bufferWords += lineWords
}
if (buffer.length > 0) {
splitBlocks.push(makeBlock(block.kind, buffer.join("\n")))
}
return splitBlocks
}
function countWords(text: string): number {
const cleaned = text.replace(/[#*`\[\]()>|_~-]/g, " ")
const cjk = cleaned.match(/[\u4e00-\u9fff\u3400-\u4dbf\uf900-\ufaff]/g)
const latin = cleaned.match(/[a-zA-Z0-9]+/g)
return (cjk?.length ?? 0) + (latin?.length ?? 0)
}
if (import.meta.main) {
process.exit(runChunkCli(process.argv.slice(2), process.argv[1] ?? "chunk.ts"))
}
#!/usr/bin/env bun
import path from "node:path"
import process from "node:process"
import { runChunkCli } from "./chunk.js"
function formatScriptCommand(fallback: string): string {
const raw = process.argv[1]
const displayPath = raw
? (() => {
const relative = path.relative(process.cwd(), raw)
return relative && !relative.startsWith("..") ? relative : raw
})()
: fallback
const quotedPath = displayPath.includes(" ")
? `"${displayPath.replace(/"/g, '\\"')}"`
: displayPath
return `npx -y bun ${quotedPath}`
}
function printUsage(exitCode: number): never {
const cmd = formatScriptCommand("scripts/main.ts")
console.log(`Baoyu Translate CLI
Usage:
${cmd} <file> [--max-words 5000] [--output-dir <dir>]
${cmd} chunk <file> [--max-words 5000] [--output-dir <dir>]
Commands:
chunk Split markdown into chunks
Options:
--max-words <n> Maximum words per chunk (default: 5000)
--output-dir <dir> Write chunks into <dir>/chunks/
-h, --help Show help
`)
process.exit(exitCode)
}
const args = process.argv.slice(2)
if (args.length === 0) {
printUsage(1)
}
if (args[0] === "-h" || args[0] === "--help") {
printUsage(0)
}
if (args[0] === "chunk") {
process.exit(runChunkCli(args.slice(1), `${formatScriptCommand("scripts/main.ts")} chunk`))
}
process.exit(runChunkCli(args, formatScriptCommand("scripts/main.ts")))
{
"name": "baoyu-translate-chunk",
"private": true,
"dependencies": {
"markdown-it": "14.1.1"
}
}
Related skills
Forks & variants (2)
Baoyu Translate has 2 known copies in the catalog totaling 180 installs. They canonicalize to this original listing.
- skills.volces.com - 144 installs
- guanyang - 36 installs
How it compares
Pick baoyu-translate over generic translation prompts when you need YAML-driven style, audience register, glossaries, and chunked handling for long technical docs.
FAQ
What does baoyu-translate do?
>-
When should I use baoyu-translate?
>-
Is baoyu-translate safe to install?
Review the Security Audits panel on this page before installing in production.