integrate the skills

split the review skills into self- and other-
the self- variant makes informational comments
the other- variant makes nice comments

Google docs is a failure
This commit is contained in:
iacore
2026-06-21 12:44:07 +08:00
parent 1964a7c2e2
commit 90b965a867
16 changed files with 871 additions and 116 deletions
+248
View File
@@ -0,0 +1,248 @@
---
name: self-review
description: Review your own CN→EN translations — three-pass review (terminology → mechanical → flow). Edit commented.dj with patch. For reviewing someone else's work, load other-review.
---
{% Serves AGENTS.md Workflow B1 (Self-Review) %}
# Self-Review(自审)
Review YOUR OWN translations. You created the English — you can edit freely.
For reviewing someone else's work, load `other-review` instead.
Two input formats: CSV/XLSX batch, or `.dj` comparison file.
`bilingual.dj` is script-generated ground truth — **never edit it.**
Copy to `commented.dj` for all review work. Always use `patch` (mode='replace')
for edits — not regex-based string replacement in `execute_code`.
## Workflow A: CSV/XLSX batch review
Use when input is a CSV/XLSX with `Chinese`/`English` columns. Produces an `edit-suggestions.dj` file.
### 1. Get the data into CSV
If XLSX, export to CSV (or use `openpyxl`). CSV is faster.
### 2. Read the full file
Use `read_file` with offsets for complete coverage. Don't sample.
### 3. Write a systematic analysis script
Write to `/tmp/script.py`, run with `python3 /tmp/script.py`. No heredocs or `-c`.
The script should:
- Parse CSV with `csv.DictReader`
- Apply detection rules per category
- Collect issues: row number, CN text, EN text, problem, suggested fix
- Group/deduplicate identical issues
Common detection categories:
- **Buddhist terminology**: 正念→mindfulness (not "righteous thoughts"), 布施→generosity (not "alms")
- **Identity terms**: 学士/修士/胜士/智士 are practice stages, not titles
- **Literal machine translations**: "hard drive" for 硬盘 (endurance)
- **四摄法 terms**: 同事→"acting in harmony", 爱语→"kind speech"
- **Grammar**: subject-verb agreement, unbalanced quotes
- **Typos/formatting**: Chinese punctuation in English, "IOS"→"iOS"
- **Inconsistency**: same CN term translated differently across rows
### 4. Write edit-suggestions.dj
Format:
```
# 1
original: <Chinese text or key term>
translated: <current English>
<Explanation and suggested fix.>
# 2
...
```
One entry per problem category, not per row. Mention affected row numbers.
## Workflow B: .dj file review (self-review)
Use when you translated the text and want to review your own work.
### File rules
1. `bilingual.dj` — extracted from script. **Never edit.**
2. `cp bilingual.dj commented.dj` — all edits go here
3. `{% ... %}` comments document non-obvious translation choices
### 1. Read the full file
Use `read_file` with `offset` and `limit` for full coverage of large files
(this session had 322 lines, 93KB). For files >200 lines, paginate
explicitly rather than reading the whole thing at once.
If you have already read part of the file with `read_file` earlier in the
session, use `terminal: cat` (or `sed -n 'A,Bp'`) to get an un-deduped view
of the rest. `read_file` deduplicates within a session.
### 2. Scan for problems — three passes, in order
The review is best done in three distinct passes, each catching a different
category of error. Don't try to catch everything in one scan.
**Pass 1 — terminology + consistency + line count** (fast, mechanical):
- **Line count**: source and target must match exactly. Mismatch means paragraphs were dropped, merged, or split.
- Same CN term translated differently across the file (e.g. 人生佛教/人间佛教 conflation, 恨→resentment, 修行/修学)
- Buddhist terminology against the MPI terms DB (see terms-db-alignment below)
- Mistranslation of key terms, wrong proper names, garbled text
- Mid-paragraph truncation: CN covers 35 clauses but EN stops after 12 sentences. Signal: CN has quoted speech, poems, or a rhetorical climax absent from EN. Flag as "Missing Content" not "Incomplete."
- Use `references/common-issues-taxonomy.md` as a structured checklist for accuracy issues
**Pass 2 — mechanical/formatting** (also mechanical, but easy to skip):
- TOC format: AGENTS.md says TOC must be plain bullet list, no link targets. Strip `[I. Heading](#...)` markdown links if present.
- Double words, double punctuation, capitalisation typos, processing artifacts, stray spacing in Chinese text
- Numbering mismatches between CN and EN headings
- Redundant English calques: when the target mirrors a Chinese grammar pattern literally, it can read as a typo (e.g. "mind of death-mindfulness" for 念死之心 — should be "mindfulness of death"). Clunky idioms: 一念之差 → "a single thought of difference" is unidiomatic. Standard renderings exist (e.g. "a single errant thought," "a moment's carelessness," or rephrase as "a single thought can make all the difference").
**Pass 3 — flow/tonal/calques** (read the whole English as prose):
- Re-read the full English target. Does it hang together as prose, or does it read as "translationese"?
- Dramatic verbs that are calques of Chinese: "draw forth," "into full play," "shoulder," "look to with hope." See `references/translation-pitfalls.md` for the full calque checklist.
- Subject-shift calques: English substitutes a concrete agent (practitioners, people) for an abstract system noun (Buddhism, religion) — see pitfalls.
- Factual inconsistencies across paired descriptions of the same person/place/thing.
- Tonal coherence inside parallel lists: verb choice should be identical across First/Second/Third items.
- Intensifier drift: same intensifier ("profoundly important") used 3+ times in one section reads as over-translation.
- The user may explicitly request this pass ("are the words together nicely?", "does it read well?"). Treat such prompts as a signal to do the full re-read, not just spot-check.
**Terms database drift** (cross-cutting — apply during Pass 1):
- Cross-reference glossary terms against the MPI terms database
- CLI preferred: `python3 $MPI_PROJECT_ROOT/terms-search/search.py <query>`. For a review, batch many queries in one `execute_code` script (subprocess loop) — one terminal call per term is slow and noisy.
- Source priority: DoT定稿 > 内部特色词 > 佛教术语 > 经论名
- Fix both glossary comments AND body text
- See `references/terms-db-alignment.md` for batch-lookup patterns
### 3. Dump findings
Write to `translation-findings.dj` for issues that don't fit as inline fixes:
```
Finding N — Title (line numbers)
Chinese: ...
English: ...
Issue: description
```
### 4. Apply fixes with `patch`
Surgical string replacement in `commented.dj` with `patch` (mode='replace').
Never use regex-based string replacement in `execute_code` for .dj edits.
`patch` is safer, surfaces conflicts, and produces a reviewable diff.
Verify with `cat` — never rely on `read_file` (session dedup).
### 5. Add inline edit suggestions
Copy `bilingual.dj``commented.dj`, then apply inline corrections + `{% %}` comments.
### 6. Final sweep
Run `python3 scripts/sweep.py <source.dj> <target.dj> [--stale term1,term2] [--new term1,term2]`. This runs all mechanical checks in one call: line parity, heading parity, Unicode em/en-dashes, Markdown bold, Chinese punctuation, TOC link artifacts, unbalanced quotes, and stale/new term assertions. Run even when no content patches were needed — it serves as final validation.
## Buddhist terminology reference
See `references/buddhist-terminology.md` for Chinese-English term mappings and common pitfalls.
## Workflow C: Typeset proofread (DOCX manuscript vs PDF layout)
Use when the user gives a manuscript DOCX and a typeset PDF and asks to proofread.
Goal: catch typesetting errors (missing text, typos, wrong special characters, bad line
breaks), not translation quality.
### 0. Clarify scope FIRST
Before any extraction: ask what they want checked. "Proofread" can mean:
- Text accuracy (missing/doubled words, typos introduced by typesetter)
- Special characters (quotes, dashes, ellipses)
- Formatting (page numbers, headers, TOC layout)
- All of the above
Do not run extraction pipelines until scope is clear.
### 1. Extract text
- DOCX → plain: `pandoc file.docx -f docx -t plain --wrap=none`
- PDF → plain: `pdftotext -layout file.pdf` (preserves positional info)
### 2. Clean PDF artifacts
- Strip InDesign slug lines, page headers, page numbers
- Join hyphenated line breaks (line ending `-` + next line starting lowercase)
- Fix drop-cap artifacts (e.g. `L iving``Living`)
### 3. Compare
- Extract English paragraphs from DOCX (skip Chinese lines, match blank-line pattern)
- Check each DOCX paragraph exists as substring in PDF body text
- Flag paragraphs not found; investigate each (may be heading renumbering, not missing)
### Pitfalls specific to this workflow
- **PDF paragraph joining is lossy** — page breaks split paragraphs. Don't expect
perfect paragraph matching; check content coverage, not paragraph identity.
- **Heading numbering differs** — DOCX has `1.`, `(1)`; PDF has `I`, `1)`. Ignore
heading-only differences.
- **InDesign PDFs insert extra spaces** around drop caps and special characters.
Normalize multi-space to single space before comparison.
### Pitfalls
- **Never edit `bilingual.dj`** — it's script-generated ground truth. Copy to `commented.dj` first.
- **Use `patch`, not regex** — for all `.dj` edits. `patch` surfaces conflicts and produces diffs.
- **`commented.dj` comments must not split paragraphs** — always place `{% %}` after the FULL EN paragraph, not mid-sentence. Scan for merged comments after insertions and split them. Collapse triple+ blank lines created by comment insertions.
- **Clarify scope before diving into extraction pipelines** — if the user says
"proofread this" or "校对这篇文章", ask what specifically they want checked
before running pandoc/pdftotext. Getting interrupted mid-pipeline wastes
context.
- **Don't use heredocs or `-c`** — write to `/tmp/script.py` first
- **Deduplicate aggressively** — group by problem type, not per-row
- **Buddhist terminology is technical** — don't guess. When uncertain, flag for review
- **Never delete .dj comparison files** — intentional work artifacts
- **Verify patches with `cat`** — `read_file` dedup makes it unreliable
- **Re-read before fixing** — user may have made interim edits
- **Batch terminology lookups** — when checking many terms against the terms DB, run them in one `execute_code` script that loops over a query list and calls `search.py` via `subprocess.run`. One terminal call per term floods the context with repetitive output.
## Human Review Protocol (审议)
When giving feedback to human translators — whether in a review team or as an AI
assistant flagging issues — follow the Oriental Translation Workshop protocol.
See `references/deliberation-protocol.md` for full guidance.
Key points:
- **Rejoice first** (随喜): affirm what works before flagging issues
- **Three-tier issues**: Level 1 (spelling/grammar/format) — fix directly. Level 2
(omission/mistranslation/wordiness) — suggest or fix with tracked changes. Level 3
(citation versions / marginal wording) — discuss with translator
- **Tone**: questions, not commands; collaborative inquiry, not correction
- **Address translator as 菩萨** (Bodhisattva) — respectful peer
## Common Issues Taxonomy
Use `references/common-issues-taxonomy.md` as a structured checklist when reviewing.
Categories:
- **Accuracy**: omission, mistranslation (over-free, over-literal, misunderstanding,
wrong word choice), overtranslation, terminology errors
- **Readability**: redundancy (long sentences, passive voice, nominalization),
poor structure (top-heavy sentences), wrong register, weak transitions
## References
- `references/buddhist-terminology.md` — Chinese-English Buddhist term mappings and pitfalls
- `references/terms-db-alignment.md` — Batch-aligning glossary terms against the MPI terms database
- `references/translation-pitfalls.md` — Recurring CN→EN mistranslation patterns (关爱→compassion, 生生增上, etc.)
- `references/proofreading-patterns.md` — DOCX/PDF extraction techniques, block-based pairing, common manuscript issues
- `references/docx-md-extraction.md` — Extracting `.docx.md` (pandoc markdown) to bilingual, TOC guards, CN/EN boundary regex
- `references/edit-suggestions-in-bilingual.md` — Inline edit suggestions + `{% %}` comments, two-file comparison (commented.dj / bilingual.dj)
- `references/deliberation-protocol.md` — Oriental Translation Workshop review protocol: tiers, rejoicing, tone
- `references/common-issues-taxonomy.md` — Structured taxonomy of accuracy and readability issues with examples
## Scripts
- `scripts/sweep.py` — Mechanical validation sweep for completed reviews
- `scripts/review_csv.py` — Batch CSV/XLSX translation review
@@ -0,0 +1,47 @@
# Buddhist Text Translation — Terminology
Terms encountered in Chinese-English translation of Dharma study materials. These may vary by translator/context; document actual usage per-project.
## Section headers (common triad)
| Chinese | English options seen | Notes |
|---------|---------------------|-------|
| 法义 | Understanding, Dharma Teachings | |
| 思考 | Contemplation, Reflection | Consistency within a document matters more than which word |
| 练习 | Practice, Application, Exercises | "Application" seen as section header; "Practice"/"Exercise" in running text |
## Key Buddhist terms
| Chinese | English | Pitfalls |
|---------|---------|----------|
| 慈经 | Metta Sutta (Karaniya Metta Sutta) | NOT "Mettavihari Sutta" |
| 回向 | Dedication (of merit) | |
| 因缘之网 | Web of Causes and Conditions | Also "Network of Causes and Conditions" |
| 感恩 | Gratitude | |
| 众生 | sentient beings | Consistent throughout |
| 使人内心调柔 | makes one's heart gentle | 使人 = makes ONE(self), never "makes others" |
| 利益思维 | benefit-oriented thinking | NOT "mindset of benefiting others" — it's about considering benefits TO oneself |
| 恩田 | field of gratitude / gratitude as a field of merit | |
| 观照 | attend to the mind / mindful observation | Contemplative practice, not intellectual study. NOT "observe" (passive) or "study" (analytical). |
| 闻思修 | hearing, contemplating, cultivating | 修 = broad cultivation/practice, not specifically 禅 (meditation). Distinct from 禅修 (meditative cultivation). |
| 八步三禅 | Eight Steps and Three Meditations | Community-specific structured contemplative method |
| 传帮带 | transmit, help, guide (three-part mentoring) | Core community methodology |
| 分灯 | lamp-dividing (decentralization) | Deliberate decentralization of authority across nodes |
| 自觉 | self-awareness, voluntary commitment | First of the "Three Spirits" |
| 法治 | rule-based governance | Second of the "Three Spirits" |
| 无我利他 | selfless service to others | Third of the "Three Spirits" |
| 凡夫心 | ordinary mind | Mind governed by afflictions, contrasted with awakened mind |
| 贪嗔痴 | greed, anger, ignorance (三毒) | The three root poisons: rāga, dveṣa, moha |
| 愿心 | mind of vows, bodhicitta aspiration | Plural "vows" in English |
| 重要感、优越感、主宰欲 | sense of importance, superiority, desire to control | Three ego-driven motivations |
## Structural patterns
- Section numbering: Chinese uses 一、二、三... English should pick one style (Part One/Two, First/Second, I/II) and stick with it.
- Poetry/prayer blocks: Chinese uses parallel structures (感恩... 感恩...; 愿... 愿...). English must match the parallelism.
- 愿 (yuàn) at sentence start = optative "May..." — not "we hope that", not "we should".
## Formatting artifacts
- Stray spaces between Chinese characters (eg. `感 恩 研 究`) are justified-text paste artifacts from the source document — remove them.
- `<!-- === Progress : Below are unprocessed === -->` is a processing marker — remove from final file.
@@ -0,0 +1,174 @@
# Common Translation Issues Taxonomy
From 译文常见问题与案例示范 (Common Issues in Translation, 2026-03-30).
Categorized by accuracy and readability.
## Accuracy Issues
Standard: convey meaning at the content level, not word-by-word correspondence.
"Translation is not simply word conversion."
"You must understand what thought it is actually trying to express."
### 1. Omission (漏翻)
Content present in source but absent from target.
Example:
> 随着黑白牌的运用,象征这部分已能为大家提供系统的学习和训练资料。
>
> With the help of the Black-and-White Cards, this approach now offers a structured
> system of study.
>
> *Missing:* 学习和训练 (learning and training) — "study" only covers half.
> Also: 象征这部分 (symbolizing this aspect) is dropped.
### 2. Mistranslation (错翻)
#### a. Over-free translation, weakening the original
> "道德"一词,人们耳熟能详。即使在道德日渐边缘化的今天,人们依然会用"这人
> 很有道德""这么做太缺德了"来评价周遭人事。
>
> "Morality" is a familiar term, and even in today's world, where it has become
> increasingly marginalized, expressions like "immorality" are still commonly used
> to describe certain behaviors and individuals.
>
> *Issue:* The source gives two concrete colloquial expressions ("这人很有道德" /
> "这么做太缺德了") — the target collapses them into a single abstract "expressions
> like 'immorality'." The vividness and specificity are lost.
#### b. Over-literal translation, harming comprehension
> 作为素菜馆,应该尽量提供绿色食品。
>
> A vegetarian restaurant should strive to offer green food.
>
> *Issue:* 绿色食品 = "safe and healthy food" (Chinese idiom), not
> "green food" (color of food in English). → `safe and healthy options`
#### c. Misunderstanding the source
> 政府现在倡导文化自信,习主席提出的"讲仁爱,重民本,守诚信,崇正义,尚和合,求大同"。
>
> President Xi Jinping has called for a confident embrace of Chinese culture,
> highlighting virtues such as...
>
> *Issue:* Two different subjects: the government advocates cultural confidence;
> Xi proposed the six virtues. The target merges both into Xi alone.
#### d. Wrong word choice causing misunderstanding
> 提供一些通俗易懂的法宝
>
> with easy Buddhist materials
>
> *Issue:* 通俗易懂 means "accessible to a general audience," not "easy/simple."
> The Dharma can be accessible but is never "simple." → `accessible`
### 3. Overtranslation (多翻)
Adding parentheticals or expansions not in the source.
> 出家人不仅要对三宝、师长、道友建立没有染污的情感
>
> Monastics should cultivate pure and untainted emotions not only toward the Three
> Jewels (the Buddha, the Dharma, the Sangha), their teachers (The Head Monk and
> Abbot), and fellow practitioners...
>
> *Issue:* Parenthetical expansions like "(the Buddha, the Dharma, the Sangha)"
> and "(The Head Monk and Abbot)" are not in the source and should be removed.
### 4. Terminology Errors
- 身心 → `body and heart mind` → should be `body and mind`
- 甘露别院 → `Ganlu Bieyuan The Amrita Retreat Center` → official: `Amrita Retreat Center`
- "六字" → `six characters` → should be `six words`
### 5. Detail-Level Issues
- Tone appropriateness
- Citation source authority
- CN→EN conversion rules: numerals, units, date formats
- Proper noun handling: transliteration vs. translation
## Readability Issues
Standard: fluent sentences, graceful expression, matching target reader habits.
"Conform to what foreign readers find readable."
"Concise, clear, accurate, not draggy, meaning clear."
### 1. Redundancy & Wordiness
#### a. Long / nested sentences
Sentences with too many clauses that can't be read in one breath. Split them.
#### b. Passive voice overuse
> 如果对肉食消费得少,乃至完全不消费,那么从业者自然随之减少,很多动物就可以摆脱被屠宰、割截的厄运。
>
> If meat consumption were reduced, or even eliminated entirely, then the number of
> businesses involved would naturally be lessened. This way, many animals could be
> spared from the adversity of being slaughtered and butchered.
>
> *Issue:* Three passives in two sentences. Active rewrite is more concise:
> *If people consume less meat — or none at all — fewer will work in the industry,
> and many animals will be spared the fate of slaughter and dismemberment.*
#### c. Nominalization (动词名词化)
> 我们前期倡导的正念禅修,比较重视培养觉知。
>
> In the early stages of mindfulness practice, we placed greater emphasis on
> cultivating awareness.
>
> *Issue:* "placed greater emphasis on" is nominalized. → `we emphasized`
### 2. Poor Structure (结构不当)
Top-heavy sentences — the main clause arrives too late.
> 没有如法的生活,不能严格要求自己,在今天这个红尘滚滚的时代,我们简直是没希望的。
>
> Weathering today's deluge of worldly temptation, without a Dharma-aligned lifestyle
> and strict self-discipline, we have no hope.
>
> *Issue:* The condition clauses pile up before the main point. Restructure:
> *Without a Dharma-aligned lifestyle and strict self-discipline, we have no hope
> of weathering today's deluge of worldly temptations.*
### 3. Wrong Word Choice (用词不当)
> 当一个人开始关心生命的大问题时,对小问题自然云淡风轻。
>
> when we begin to contemplate the profound questions of existence, the banal
> iterations of daily life lose their significance.
>
> *Issue:* "banal iterations" is obscure. Simplify.
### 4. Weak Flow & Transitions (流畅性 & 连接词)
> 修行的核心就是止恶行善。为什么某种行为能成为生命的主导?就是因为不断重复。
>
> The essence of cultivation lies in ceasing unwholesome actions and promoting
> wholesome ones. But why do certain behaviors dominate our lives? Because of
> constant repetition.
>
> *Issue:* Adding transition words improves flow. The "But" here creates a false
> contrast — the second sentence is explanation, not counterpoint.
## Detection Checklist
When reviewing, run through:
- [ ] Any missing content? (compare paragraph-by-paragraph)
- [ ] Any added content? (parentheticals, expansions not in source)
- [ ] Any over-literal renderings that don't work in English? (idioms, set phrases)
- [ ] Any over-free renderings that lose specificity? (concrete examples → abstract)
- [ ] Subject confusion? (two actors merged into one)
- [ ] Buddhist terminology checked against terms DB?
- [ ] Sentences too long to read in one breath? (split at natural breaks)
- [ ] Passive voice clustering? (3+ in a paragraph)
- [ ] Nominalized verbs? ("placed emphasis on" → "emphasized")
- [ ] Top-heavy sentence structure? (main clause buried after long preamble)
- [ ] Obscure word choices? (would a general reader understand?)
- [ ] Missing or misleading transition words?
@@ -0,0 +1,90 @@
# Deliberation Protocol (审议规程)
From 东方译场审议手册 (Oriental Translation Review Manual, 2026-03-25).
Guidance from Ven. Jiqun on translation review culture and process.
## Core Standards
1. **Accuracy (准确性)** — primary. Convey content-level meaning, not word-by-word
correspondence. Deepen accuracy iteratively; grasp the "inner spirit" rather than
fixating on literal vs free translation.
2. **Readability (可读性)** — secondary. Fluent sentences, graceful expression. Do
not pursue endless revision; what is achievable now is the best for now.
**Test**: invite 510 readers to read aloud and give feedback — is it clear or
obscure? Is it concise? Is the meaning clear?
## Decision-Making
When opinions differ:
- Compare which version is more accurate and more readable
- Do NOT cling to your own view (不执着于己见)
- If two people cannot decide, invite 510 to read and vote
- Remember: the translation is for the READERS, not for yourself
## Core Principle: Rejoice First (随喜)
Before flagging issues, affirm what is good. Professional translation companies
emphasize positive feedback to build translator confidence and good collaboration.
Criticism alone — however precise — breeds resistance and harms the final result.
In the Oriental Translation Workshop, rejoicing in others' merits cultivates
sympathetic joy (随喜), compassion, selflessness, and boundless merit — while
encouraging others' wholesome efforts.
**Practice**: develop eyes that SEE the merits in a translation. Rejoice with
genuine gladness. Examples:
- "So many technical terms and complex logic here — you handled it beautifully!"
- "This word choice is exactly right."
- "The prose is so clean and fluid!"
- "Excellent!" / "Good word choice!"
## Three Principles for Giving Suggestions
1. **Lower the self** — use compassionate, gentle, skillful language
2. **Be diligent and attentive** — find the actual problems
3. **Tier your suggestions** — make clear what MUST change, what COULD improve,
and what needs DISCUSSION
## Three-Tier Issue System
### Level 1: Spelling, Grammar, Format (拼写、语法、格式)
**Action**: fix directly, keep tracked changes visible.
May annotate for translator development:
- "MPI format uses American English — `toward` not `towards`."
- "Use `Chan` here, not `Zen`."
- "MPI format does not use diacritics — `Yogacara` not `Yogācāra`."
### Level 2: Omission, Mistranslation, Wordiness, Tone, Word Choice
(漏翻、错翻、啰嗦、语气问题、用词问题)
**Action**: preferably flag for translator to fix themselves; may also fix
directly with tracked changes.
Suggested language:
- "Did we miss something here?"
- "This sentence is quite long — could we split it into 23?"
- "The translation here differs from the original. It reads as if the teacher
is saying X, but I think he means Y. What do you think?"
- "This word feels a bit strong here — your thoughts?"
- (After direct adjustment) "I tightened this sentence — does this work?"
### Level 3: Citation Versions, Slightly Awkward Wording, Marginal Readability
(引用版本不当、用词稍微不当、阅读体验略差)
**Action**: flag and discuss with translator.
Suggested language:
- "I found another citation version that may be more concise — which do you prefer?"
- "Could we use this word instead? Might fit better."
- "Could you take another look at this passage? I feel readability could improve
but I'm not sure how — your thoughts?"
## Tone Guide
- Address the translator as 菩萨 (Bodhisattva) — respectful peer address
- Use questions, not commands: "Could we...?" "What do you think?" "Would this work?"
- Frame as collaborative inquiry, not correction
@@ -0,0 +1,171 @@
# Extracting `.docx.md` to `source.dj` + `bilingual.dj`
When the input is a `.docx.md` file (already pandoc markdown, not plain text), the
extraction differs from the standard DOCX→plain workflow. The markdown preserves
formatting artifacts that need specific handling.
## CN/EN boundary detection in merged lines
Pandoc markdown often merges CN and EN text on heading lines where the DOCX had
multiple runs in the same paragraph:
```
# **三、重视文化教育,重塑人生价值** Prioritize Cultural Education; Reshape Life Values {#三、...}
```
The boundary regex must account for whitespace on BOTH sides of `**` markers:
```python
# WRONG: \** then \s* — fails when there's space BEFORE * (值 *Realizing)
r'[\u4e00-\u9fff](?:\*{0,2})\s*([A-Za-z])'
# WRONG: \s* then \** — fails when there's space AFTER ** (值** Prioritize)
r'[\u4e00-\u9fff]\s*\**([A-Za-z])'
# CORRECT: whitespace on both sides of optional *
r'[\u4e00-\u9fff]\s*\**\s*([A-Za-z])'
```
Include CJK punctuation ranges in the character class:
`[\u4e00-\u9fff\u3000-\u303f\uff00-\uffef]`
## Anchor stripping
Strip BOTH `{#anchor}` (pandoc heading anchors) AND `[text](#link)` (markdown TOC links)
before further processing:
```python
def strip_anchors(s):
s = re.sub(r'\{#[^}]*\}', '', s) # {#anchor}
s = re.sub(r'\[([^\]]*)\]\([^)]*\)', r'\1', s) # [text](#link) → text
return s
```
## TOC handling — two critical guards
### Guard 1: Don't pair TOC CN entries with following EN lines
TOC entries often look like CN-heading-followed-by-EN (the standard pair pattern),
but the following EN is actually the next TOC entry or heading:
```
[一、营造禅意氛围,优化工作环境\t1](#anchor)
[二、重视慈善关爱...]
...
1、Create a Chan(Zen) Atmosphere; Optimize Your Environment
2、Focus on Compassion and Care; Build Good Relationships
```
If the last CN TOC entry is followed by a blank line then the first EN TOC entry,
the "CN → blank → EN" heading pattern will consume the first EN TOC entry.
Guard against this:
```python
def is_toc_line(line, cn_raw):
if re.search(r'\[.*\]\(.*\)', line): # markdown link
return True
if re.search(r'\t\d+', cn_raw): # tab + page number
return True
return False
```
Skip the CN→EN and CN→blank→EN patterns when `is_toc_line()` returns True.
These CN TOC entries should stay unpaired (en='') and get their EN from the
separate EN TOC list.
### Guard 2: Pair TOC EN entries forward, not backward
EN TOC entries appear as standalone non-CJK lines. They must be paired with
the FIRST unpaired CN (not the last):
```python
# CORRECT: forward iteration
for j in range(len(pairs)):
if not pairs[j][1] and has_cjk(pairs[j][0]):
pairs[j] = (pairs[j][0], en)
break
# WRONG: reverse iteration (pairs last-first, shifting everything)
for j in range(len(pairs)-1, -1, -1):
...
```
## Orphaned trailing `*` from italic splits
When a line has italicized EN text (`*Realizing Ultimate Value*`) and the split
point is at the `R` (after the opening `*` is consumed by the CN cleanup), the
EN text retains a trailing `*`: `Realizing Ultimate Value*`. Strip it:
```python
def clean_en(s):
s = re.sub(r'^\d+[、,.]\s*', '', s)
s = re.sub(r'\*+$', '', s) # orphaned italic close
return s.strip()
```
## `clean_cn` — operation order matters
Strip leading numbers BEFORE heading markers. A line like `1. # **营造禅意...`
starts with a digit, so `^#+\s*\**` won't match until the number is gone:
```python
def clean_cn(s):
s = re.sub(r'^\d+\.\s*', '', s) # leading number FIRST
s = re.sub(r'^#+\s*\**', '', s) # then heading markers
s = re.sub(r'\**\s*$', '', s) # trailing **
s = re.sub(r'\t\d+$', '', s) # trailing page number
return s.strip()
```
## Full extraction recipe
1. Read `.docx.md` text
2. For each line: strip anchors, detect CJK/EN
3. CJK lines: try `split_cnen()` first (merged CN+EN). If that gives EN, use it.
Otherwise look ahead for EN on next line or next+blank — but SKIP if TOC-like.
4. EN-only lines: pair forward with first unpaired CN.
5. Clean: strip heading markers, leading numbers, trailing page numbers.
6. Write `source.dj` (CN only) and `bilingual.dj` with proper markdown structure.
## bilingual.dj output format
Must follow the project convention (see reference bilingual.dj in any completed article):
```
# CN Title
# EN Title
---CN Subtitle
---EN Subtitle
CN Author
EN Author
- CN TOC item 1
- CN TOC item 2
...
- EN TOC item 1
- EN TOC item 2
...
CN body paragraph
EN body paragraph
CN section heading ← plain text, no # prefix
EN section heading
...
CN sub-heading ← plain text, e.g. "1. 创造精神财富"
EN sub-heading
```
- Title: `# ` prefix on both CN and EN
- Subtitle: `---` prefix (3 dashes, no space after)
- Author: plain text, one pair
- TOC: `- ` bullet, CN block then EN block (not interleaved), blank line between blocks
- Body headings: plain text, no `#` or `##` markers. Hierarchy conveyed by numbering:
`一、二、三、` for major sections, `1. 2. 3.` for sub-sections
- Body paragraphs: interleaved (CN line, EN line, blank)
- `source.dj` uses `# Title`, `---subtitle`, `## section headings` — different from bilingual.dj which uses plain body headings
@@ -0,0 +1,65 @@
# Edit Suggestions in bilingual.dj
When the user asks to add edit suggestions directly into bilingual.dj, use this
two-tier approach.
## Two files
- `bilingual.dj` — clean: inline corrections applied, NO `{% %}` comment lines
- `commented.dj` — same content + `{% ... %}` comment lines interleaved
This lets the user diff them side by side.
## Inline corrections
Apply directly to the English text. These are fixes the reviewer is confident about:
- Typos, mechanical issues (Chinese punctuation in EN, double periods, stray `*`, unbalanced quotes)
- Grammar fixes (subject-verb agreement, missing articles)
- Wording improvements (clunky literal translations → idiomatic English)
Apply with `patch` (mode='replace'). Verify uniqueness before
replacing — many EN paragraphs are long single lines, so match a unique
substring. Never use regex-based string replacement in `execute_code`.
## `{% %}` comment lines
For translation decisions worth documenting but not "correct" per se:
```
CN paragraph
EN paragraph
{% reason for the choice, alternative renderings %}
(blank)
```
The comment goes AFTER the EN line (before the blank separator). One comment per
issue. Keep them terse.
What to comment on:
- Literal translation of idioms (`单线程` → "single-threaded")
- Translation choices that differ from literal meaning (`精神利益` → "nourishing the spirit")
- Standard Buddhist terminology (`正命` → "Right Livelihood")
- Glosses added/dropped (`道场` — "(Dojo)" parenthetical removed)
- Idiom translations (`甘之若饴` → "as sweet as syrup")
- Paired terms where one rendering influences the other (`魔性` → "demon-nature" to parallel "Buddha-nature")
- Scripture citations with Sanskrit titles (`普贤行愿品` → "Gaṇḍavyūha Sūtra")
What NOT to comment on:
- Obvious corrections (typos, grammar)
- Names, dates, simple connectives
- Standard renderings with no interesting choice
## Pitfalls
- **Never split a paragraph mid-sentence** with a `{% %}` comment. Comments go
AFTER the full EN paragraph, before the blank separator. If a string
replacement inserts `\n{% %}` in the middle of a paragraph, it breaks the
interleaved structure.
- **Check for merged comments**: after inserting, scan for `{% ... %} ` followed
by EN text on the same line. These must be split so the EN text continues on
the next line.
- **Collapse triple+ blank lines**: comment insertions can create extra blanks.
Run `re.sub(r'\n\n\n+', '\n\n', text)` after all insertions.
@@ -0,0 +1,116 @@
# Proofreading: Manuscript vs Typeset
AGENTS.md defines two workflows: Translation (A) and Proofread (B).
The workflows below are Proofread mode — English comes from an existing
manuscript and is authoritative. Only flag mechanical/manuscript-level issues.
## Two extraction workflows
### A. Bilingual from DOCX (standard)
When the DOCX manuscript has both Chinese and English in 1:1 paragraph
correspondence, generate `bilingual.dj` directly from the DOCX:
1. `pandoc docx → plain text`
2. Extract Chinese-English pairs from body
3. Apply fixes: italicize Sanskrit on first occurrence, fix `N.Letter``N. Letter` spacing
4. Write bilingual.dj
The DOCX English is the authoritative target text. No PDF needed.
**Extraction approach**: start by adapting `scripts/gen-bilingual-docx.py`.
For articles where the body has strict CN→EN→CN→EN alternation, the simple
extraction in that script (CN line, blank, EN line, blank) works directly.
### A2. Bilingual from `.docx.md` (pandoc markdown output)
When working with an already-converted `.docx.md` file (pandoc markdown, not plain
text), use the techniques in `references/docx-md-extraction.md`. Key differences
from plain-text extraction: merged CN+EN on heading lines, `{#anchor}` and
`[text](#link)` artifacts, TOC pairing guards.
### B. Bilingual from PDF (when PDF is the typeset target)
sections that order CN content before EN content (CN heading → CN body → EN heading →
EN body), the simple alternation fails. Use block-based extraction instead:
1. Tag each non-blank line as CN or EN (via `has_cjk()`)
2. Join page-break split paragraphs: merge consecutive same-language paragraphs
only when the first is long (>30 chars), doesn't end with CJK/ASCII terminal
punctuation (`[。!?:).?!]$`), and isn't heading-like (starts with
`^[\dIVX]+[\.\s]` and <60 chars)
3. Group consecutive same-language items into blocks
4. Walk blocks: for each CN block, pair with the next EN block via `zip()`.
`min(len(cn), len(en))` handles translator-introduced paragraph splits.
**Page-break splits in pandoc plain-text output**: the DOCX→plain conversion
sometimes splits a Chinese paragraph mid-sentence (e.g. `白居` + `易、苏轼…`).
These appear as two consecutive CN lines separated by a blank. The join heuristic
above catches these reliably. For EN text, page-break splits are rare; the heading
detection (`^[\dIVX]+[\.\s]`, <60 chars) prevents false merges of EN headings
with following EN body paragraphs.
The DOCX English is the authoritative target text. No PDF needed.
### B. Bilingual from PDF (when PDF is the typeset target)
When the PDF English is the typeset "final" version and should be the target:
1. Extract DOCX Chinese paragraphs (source)
2. Extract PDF body text via `pdftotext -layout`
3. Clean PDF: remove slug lines, headers, page numbers, join hyphenation breaks
4. Match DOCX English paragraphs against PDF body to find positions
5. Segment PDF body at matched positions
6. Write bilingual.dj with Chinese source + PDF English target
**Pitfalls in PDF extraction:**
- Consecutive hyphenation breaks (e.g. `thou-` + `sand...al-` + `leviate`) — the join
loop must be recursive: after joining pair N, check if result still ends with `-`
and join with line N+2
- Lines with leading whitespace: use `lstrip()` before checking `n[0].islower()`
- Drop-cap artifacts: `L iving``Living`
- Trailing section numbers: `...viewpoints. 1)` — the ` 1)` is a PDF section marker
bleeding into the previous paragraph
### C. Edit suggestions (edit-suggestions.dj)
After generating bilingual.dj, scan for issues and write `edit-suggestions.dj`:
**Format**: follow the original document's section/chapter layout. Group suggestions
under the chapter headings where the issues occur. Use diff-style `-/+` notation.
**What to flag:**
- Garbled Chinese text (merged duplicate edits in source DOCX)
- Repeated words (`the The`)
- Chapter numbering mismatches (e.g. `九``VIII`)
- Translator notes in headings (`(某某翻,某某审)`)
- Missing quotes around dialogue/speech
## Common source DOCX issues
- Translator notes in Chinese headings: `(某某翻,某某审)` — delete for publication
- Merged duplicate edits: cut-paste errors where old+new text appear together
- `N.Letter` without space: `2.How``2. How`
- `the The` double article
- **Numbering mismatches**: CN and EN headings sometimes disagree (e.g. CN `3` vs EN `2.`).
The TOC usually has the correct number — flag the body heading for correction.
- **Doubled names**: `岳麓书院岳麓书院` — cut-paste artifacts in Chinese body text.
- **EN paragraph splits without CN counterpart**: translator sometimes renders one CN
paragraph as two EN paragraphs. The block-based extractor drops the extra EN paragraph
(as `min(len_cn, len_en)`). Flag in edit-suggestions so it can be manually merged or
the CN paragraph can be split.
## Sanskrit italicization
On first occurrence in body text, wrap with `*term*`. Track seen terms across
the full body. Terms: bodhisattva, bodhicitta, samsara, Dharma, karma, nirvana,
Sangha, sutra, Mahayana, Sravaka, Vinaya, Lamrim, Ksitigarbha, Samantabhadra,
Chan, Arhatship, Theravada.
## Proofread scope boundary
When proofreading a DOCX manuscript:
- **DO flag**: typos, double words, double punctuation, numbering mismatches,
garbled text, translator notes, duplicate names, capitalization errors.
- **Do NOT flag**: em-dash formatting (`—` vs `---`), terminology choices,
translation style, calques, word order. The manuscript English is authoritative.
- **Do NOT apply fixes** — write `edit-suggestions.dj` only.
- If the user asks for translation review separately, write findings to
`translation-findings.dj`.
@@ -0,0 +1,64 @@
# Terms Database Alignment
Batch-align translation glossary entries and body text against the MPI terms database.
## Module API (preferred)
Import directly in `execute_code` scripts — no subprocess, no server, no text parsing:
```python
import sys
sys.path.insert(0, '$MPI_PROJECT_ROOT/terms-search')
from search import search
results = search("三级修学", limit=5)
results = search("空性", loc="心经", src="DoT定稿", limit=5)
# returns list of {zh, en, loc, source} dicts
```
## Batch lookup pattern
```python
import sys
sys.path.insert(0, '$MPI_PROJECT_ROOT/terms-search')
from search import search
terms = ["三无漏学", "八步三禅", "闻思修", ...]
author_sources = {"DoT定稿", "内部特色词", "佛教术语", "经论名"}
for term in terms:
results = search(term, limit=10)
relevant = [r for r in results if r["source"] in author_sources]
for r in relevant:
print(f"{r['zh']}{r['en']} [{r['source']}]")
```
Or filter to a single authoritative source directly:
```python
results = search("三级修学", src="DoT定稿", limit=5)
```
## Priority ranking
When the same term has entries in multiple source tables, prefer:
1. DoT定稿 (highest authority — final translation decisions)
2. 内部特色词 (MPI internal terminology)
3. 佛教术语 (general Buddhist terminology)
4. 经论名 (sutra/shastra titles)
## Alignment workflow
1. Extract all Chinese glossary terms from `{% "TERM" ... %}` blocks in the .dj file
2. Extract body-text domain terms that may not have glossary entries
3. Batch-query each term against the HTTP API
4. Filter results to authoritative source tables
5. Compare DB canonical translation against current file translation
6. Flag mismatches where DB entry differs materially from current
7. Apply fixes with `patch` tool — fix both glossary comments AND body text occurrences
8. Verify with `grep` that no old terms remain
## Pitfalls
- `replace_all` can create doubled words when the surrounding context already contains the replacement string (e.g., "The Eight Steps" → "The The Eight Steps"). Prefer targeted single-replacement patches.
- Start patches from the bottom of the file upward to preserve line numbers.
- Some DB entries are contextual phrases (e.g., "珍惜法缘" → a full sentence), not standalone term translations. Use standalone term entries where available.
@@ -0,0 +1,284 @@
# Translation Pitfalls — MPI Buddhist Texts
Patterns found in CN→EN translation review. Add to this file as new patterns emerge.
## Terminology conflation
### 人生佛教/人间佛教 — distinct concepts
人生佛教 (Taixu's "Buddhism for Human Life") and 人间佛教 (Yinshun's "Humanistic Buddhism")
are distinct doctrinal positions in modern Chinese Buddhism. Do not conflate both into
"Humanistic Buddhism." When the source uses 人生佛教, render as "Buddhism for Human Life"
or "Human Life Buddhism." User may propose a deliberately non-standard rendering
("Buddhism for daily lives") — that's their call. Don't unilaterally pick from
the standard set without checking.
### 心性论 → buddha-nature (WRONG)
心性 (mind-nature) is broader than 佛性 (buddha-nature / tathāgatagarbha).
When a text discusses 心性 in the context of Confucian self-cultivation or general
Buddhist psychology, use "mind-nature" or "nature of mind." Reserve "buddha-nature"
only when the text explicitly references tathāgatagarbha doctrine.
### 恨 → resentment (WRONG)
恨 means "hatred," not "resentment." In the triad 羡慕嫉妒恨 (envy, jealousy, hatred),
the force is strong. "Resentment" is too mild.
### 感悟 → conversant / heartfelt (WRONG)
感悟 means experiential insight or realization. It is not intellectual familiarity
("conversant") or emotional warmth ("heartfelt"). Render as "insight," "realization,"
or "deep understanding."
### 关爱/关怀 → compassion (WRONG)
Chinese 关爱 and 关怀 mean "care" or "loving care." They are NOT 慈悲 (compassion / karuṇā).
Conflating them obscures two distinct Buddhist concepts.
Check every occurrence of "compassion" in a translation against the source:
- If source is 关爱/关怀 → "care"
- If source is 慈悲 → "compassion" (correct)
- If source is 悬壶济世 → "compassionate mission" (correct — the healing spirit)
### 生存层面 → making a living (WRONG)
生存层面 = the existential/survival dimension. Not just earning wages.
→ "survival-level needs" or "the level of basic existence"
### 修学 → "practice" (drops study dimension)
修学 combines 修 (practice/cultivation) and 学 (study/learning). Rendering only
as "practice" loses the study dimension. Use "practice and study" or
"cultivation and learning" — especially in 静心学堂/Dharma study contexts where
the academic dimension is emphasized.
### 信仰者 → "believers" (Christian connotation)
信仰者 = "people of faith" but in Buddhist context, "believers" carries Christian
overtones. Use "practitioners" or "adherents" to avoid the implication. Reserve
"believers" for contexts where the source explicitly uses 信徒 or where the
Christian parallel is the point.
## Loss of Dharma meaning
### 生生增上 → continuously elevate our life (INCOMPLETE)
生生 = life after life (multi-life Buddhist perspective). The single-life rendering
"continuously elevate our life" loses the Dharma meaning entirely.
→ "continuously elevate our life, life after life"
## Degree / register shifts
### "tantamount to" drops 几乎
几乎 = "almost." "tantamount to" = "is in fact." Dropping 几乎 strengthens the
claim. Source "几乎等同于一次全球化运动" = "almost equivalent to a globalization
movement," NOT "tantamount to a globalization movement."
### "untenable" for 都是不行的 (overstates)
都是不行的 = "is not acceptable / won't do." "Untenable" = "indefensible" or
"cannot be maintained." Too strong. Use "impermissible" or "is not acceptable."
### "monumental event" for 大事 (slight stretch)
大事 = "a major event" or "an event of importance." "Monumental" is typically
reserved for tasks, errors, or achievements (e.g. "monumental task,"
"monumental mistake"). "Event of great importance" or "landmark event" is more
idiomatic.
### "perennial" for 永恒 (wrong register)
永恒 = eternal/ultimate. "Perennial" = recurring (per year, per season). They
are not synonyms. Use "eternal" or "ultimate."
### 学部委员 → Member (UNDERSTATES)
学部委员 is CASS's highest academic title, equivalent to "Academician."
"Member" understates the prestige significantly. → "Academician" or
"Member of the Academic Divisions."
### 文明 → culture (WRONG)
文明 is "civilization," not 文化 "culture." When a text discusses 文明传播
(civilizational transmission), do not substitute "cultural transmission."
### 教制建设 → reforming (ADDS CONNOTATION)
教制建设 means "developing/building monastic institutions." Adding "reforming"
introduces a connotation of fixing something broken that is not in the source.
→ "developing monastic institutions" or "institutional development."
### 一荣俱荣、一损俱损 → too loose
This idiom has a conditional structure: "if one prospers, all prosper; if one
suffers, all suffer." Rendering as "thrived together and suffered together"
loses the mutual-dependence logic. → "shared prosperity and adversity alike"
or "rose and fell together."
### 成圣成贤 collapsing
圣 (sage) and 贤 (worthy) are distinct Confucian categories. Collapsing both
to "a sage" loses the distinction. → "sagehood and worthiness" or "a sage or worthy."
### "must" overuse from 应当/倡导
Source patterns 应当 (should), 倡导 (advocate/champion), 今后要 (going forward, should)
often get rendered as "must" by reflex. "must" in English is a strong directive
appropriate only for 一定要, 必须, 务必. Default to "should" or "ought to" for
recommendations. A whole section may be 倡导 without 一定 anywhere — don't
manufacture urgency the source doesn't have.
### 文明 → culture (WRONG)
文明 is "civilization," not 文化 "culture." When a text discusses 文明传播
(civilizational transmission), do not substitute "cultural transmission."
#### 因病返贫 → "back into poverty"
"返贫" means becoming poor due to illness, not returning to previous poverty. Use "into poverty" or "driven into poverty."
#### Diacritics: use DB form, not academic Sanskrit
| Wrong | Right | Source |
|---|---|---|
| `Mahāsthāmaprāpta` | `Mahasthamaprapta` | 佛教术语 |
| `Yogācārabhūmi Śāstra` | `Yogacarabhumi-Sastra` | 经论名 |
| `Avalokiteśvara` | `Guanyin` | 佛教术语 |
| `pravāraṇā` | `Pavarana` | BAICKZ |
Exception: `Kṣitigarbha` — DoT定稿 uses diacritics, so keep them.
When in doubt, search the DB and follow the highest-priority source. See dharma-translation skill `references/diacritics-convention.md`.
返贫 = become poor (from a non-poor state) due to medical costs. "Back" implies
the person was previously poor — not necessarily true. This is about medical bankruptcy.
→ "into poverty" or "fall into poverty" (no "back")
## Subject-shift calques
When the source uses an abstract/system noun as the grammatical subject (佛教,
文明, 宗教, 文化) and the target reflexively substitutes a more concrete
agent (Buddhist practitioners, civilization-builders, religious people, etc.),
the English is wrong: the source is *not* talking about people, it's talking
about the system.
**Pattern**: 佛教都被社会大众赋予期望 → EN drifts to "Buddhist practitioners
are looked upon with hope." Wrong subject — source is 佛教, not 佛教徒. Right:
"Buddhism is regarded with hope by the broader society."
**Detection**: For each translated sentence, find the *grammatical subject*
in the English and check it matches the *grammatical subject* in the Chinese.
If the English subject is a concrete agent and the Chinese is an abstract
system noun, it's a subject-shift calque.
## Factual inconsistencies across paired descriptions
When the same person, place, or thing is described in two different paragraphs
(intro + later reference), check that *every* descriptor matches: title,
affiliation, role, credentials. A translation can be factually inconsistent
even when each individual sentence is correct in isolation.
**Pattern**: Prof. Wei's credentials in paragraph 1: "Academician of the
Chinese Academy of Social Sciences (CASS) and research fellow at the
Institute of World Religions." Paragraph 5 (same person, same source
reference): "a member of the CASS academic committee and Director of the CASS
Buddhist Research Center." Two different titles for the same CASS affiliation.
One is right, the other is wrong.
**Detection**: For each named person, build a dict {name → {credential:
sentence_refs}} and check that all credentials in the dict match. Same
institution or title can have different renderings in different paragraphs.
## Calque checklist (subtle English calques of Chinese verbs)
These are common Chinese-verb → English-verb pairs where the English word
sounds natural in isolation but is a direct calque of the Chinese. They're
easy to miss in a first-pass review because each one parses correctly:
| Chinese verb | Wrong (calque) | Right (idiomatic) |
|---|---|---|
| 赋予 (entrust with) | "look to with hope" | "regard with hope" |
| 得到 (obtain) | "draw forth" | "draw on" / "gain" |
| 发挥 (bring into play) | "bring into full play" | "make the most of" |
| 承担 (assume) | "shoulder" | "take on" |
| 重视 | "attach importance to" | "value" / "emphasize" |
| 体现 | "embody" / "reflect" | "show" / "demonstrate" (when abstract) |
**Detection**: When the English uses an unusual verb that maps 1:1 to a
Chinese word, and the Chinese word is a high-frequency academic verb (发挥,
承担, 体现, 重视), check whether the English reads as a calque. A common
smell: the English verb is "correct" but more formal/dramatic than the
surrounding prose.
## Tonal coherence inside a parallel list
When a list of items in a section should have parallel structure (e.g. three
"champion X, oppose Y" items; six "developing X, strengthening Y" items),
check that the *verb choice* is consistent across the list. Inconsistency
within a parallel structure is a strong signal of drift.
**Pattern**: Section V lists "First, Buddhism should serve as... Second, it
must serve as... Third, it must serve as..." Source has 应当/要做 for all
three. The English should match: all three "should serve as" or all three
"must serve as." Mixing is a tell.
**Detection**: For each parallel-list section (First/Second/Third, etc.),
extract the verb (or other repeated slot) and verify it's identical. Drift
inside a parallel list is one of the easiest flow issues to catch
mechanically — just look for variance.
## Multi-pass review structure
Translation review benefits from three distinct passes, run separately, each
catching a different category of error:
1. **Pass 1: terminology + consistency + line count** — fast, mechanical.
Catches: 人生佛教/人间佛教 conflation, 修行/修学, 恨→resentment,
paired inconsistencies (Buddhism vs Buddhist practitioners), missing
content, wrong numerals.
2. **Pass 2: mechanical/formatting** — em-dash convention, double punctuation,
numbering mismatches, capitalisation typos, garbled text. Often skipped
if the file "looks clean." This pass is what makes the file safe to
publish; do it even when no content issues are obvious.
3. **Pass 3: flow/tonal/calques** — *read the full English as a piece of
prose*. Catch: dramatic verbs that read as calques ("draw forth,"
"into full play," "shoulder"), intensifier drift ("profoundly important"
× 3 in one section), consistency of "must"/"should" inside parallel
lists, subject misattribution in calque. Often the user will prompt
this pass with "are you sure it reads well?" or "do the words hang
together?" Treat that prompt as a signal to re-read the whole English
target, not just spot-check.
Pass 3 in particular is the one that catches the *most embarrassing* errors
— the ones where the English is grammatical and faithful but reads as
"translationese." Don't skip it.
## DoT定稿 term drift
### 念死 → recollection of death (WRONG per DoT定稿)
DoT定稿 has "Cultivating mindfulness of death" / 佛教术语 has "contemplating the
impermanence of death". The established term is "mindfulness of death", not
"recollection of death." → "mindfulness of death" / "death-mindfulness"
### 三级修学 → Three-Level Study Program (WRONG per DoT定稿)
DoT定稿 has "Three-Stage Practice." → "Three-Stage Practice"
### 下士道/中士道/上士道
DoT定稿: "Path for Persons of Small/Medium/Great Capacity" — not "path of the
initial/middle/great scope."
### 观音菩萨 → Avalokiteśvara (AVOID in MPI translations)
佛教术语 has "Guanshiyin/Guanyin Bodhisattva." Use "Guanyin Bodhisattva."
## Workflow pitfall
### Translating before consulting terms DB
Always search key terms BEFORE translating. The dharma-translation skill says to do
this, but it's easy to skip. Use the CLI: `$MPI_PROJECT_ROOT/terms-search/search.py <query>`.
Prioritize DoT定稿 > 内部特色词 > 佛教术语 > 经论名.
+78
View File
@@ -0,0 +1,78 @@
#!/usr/bin/env python3
"""Reference: reusable detection rules for Chinese→English translation review.
Adapt the rules list for each project's domain vocabulary."""
import csv, re, sys
def review_csv(csv_path):
rows = []
with open(csv_path) as f:
reader = csv.DictReader(f)
for r in reader:
rows.append((r.get('page', '') or '', r['Chinese'] or '', r['English'] or ''))
issues = []
def add(row_idx, cn, en, problem, suggestion):
issues.append({
'row': row_idx + 2,
'page': rows[row_idx][0],
'cn': cn, 'en': en,
'problem': problem,
'suggestion': suggestion
})
for i, (page, cn, en) in enumerate(rows):
if not cn or not en:
continue
# ── Add project-specific detection rules below ──
# Example: "Is we" → machine translation artifact
if re.search(r'\bIs we\b', en):
add(i, cn, en,
"'Is we' — literal MT of 是否/如果. Should be 'if we' or 'whether we'",
re.sub(r'\bIs we\b', 'if we', en))
# Example: Chinese punctuation in English text
if re.search(r'[,。;:!?、]', en):
add(i, cn, en,
"Chinese punctuation in English text",
"[Replace with English punctuation]")
# Example: unbalanced HTML tags
if en.count('<b>') != en.count('</b>'):
add(i, cn, en,
f"Unbalanced <b> tags (open={en.count('<b>')}, close={en.count('</b>')})",
"[Balance tags]")
# Example: unbalanced double quotes
if en.count('"') % 2 != 0:
add(i, cn, en,
f"Unbalanced quotes ({en.count(chr(34))} total)",
"[Balance quotation marks]")
# Example: term inconsistency check
# if re.search(r'TermA', en) and re.search(r'TermB', en) and ...
# ── Sanity checks ──
for i, (page, cn, en) in enumerate(rows):
if cn and not en:
print(f"WARNING row {i+2}: CN present but EN empty: {cn[:80]}")
cn_chars = re.findall(r'[\u4e00-\u9fff]', en)
if cn_chars:
print(f"WARNING row {i+2}: Chinese chars in EN: {cn_chars}")
if cn and en and cn.strip() == en.strip():
print(f"WARNING row {i+2}: CN==EN (untranslated): {cn[:60]}")
return issues
if __name__ == '__main__':
issues = review_csv(sys.argv[1])
print(f"Issues found: {len(issues)}")
for iss in issues:
print(f"\nCSV_ROW_{iss['row']} [{iss['page']}]")
print(f" CN: {iss['cn'][:120]}")
print(f" EN: {iss['en'][:120]}")
print(f" PROBLEM: {iss['problem']}")
print(f" SUGGEST: {iss['suggestion'][:150]}")
+139
View File
@@ -0,0 +1,139 @@
#!/usr/bin/env python3
"""Mechanical sweep for .dj translation review — run after patches or as final verification.
Usage: python3 sweep.py <source.dj> <target.dj> [--stale term1,term2] [--new term1,term2]
Checks:
1. Non-empty line count parity (source == target)
2. Heading count parity
3. Zero Markdown bold (**) in target (djot uses single *)
5. Zero common Chinese punctuation in target
6. Zero [text](#anchor) link artifacts in target TOC area (first 15 lines)
7. Zero unbalanced double-quotes in target
8. --stale: each listed string must appear ZERO times in target
9. --new: each listed string must appear at least once in target
"""
import re
import sys
CN_PUNCT = re.compile(r'[\u3000-\u303f\uff00-\uffef\u201c\u201d\u2018\u2019]')
def read_nonempty(path):
with open(path) as f:
return [l for l in f.read().rstrip('\n').split('\n') if l.strip()]
def main():
if len(sys.argv) < 3:
print("Usage: sweep.py <source.dj> <target.dj> [--stale a,b,c] [--new x,y,z]")
sys.exit(2)
src_path = sys.argv[1]
tgt_path = sys.argv[2]
stale_terms = []
new_terms = []
i = 3
while i < len(sys.argv):
if sys.argv[i] == '--stale' and i + 1 < len(sys.argv):
stale_terms = [t.strip() for t in sys.argv[i+1].split(',') if t.strip()]
i += 2
elif sys.argv[i] == '--new' and i + 1 < len(sys.argv):
new_terms = [t.strip() for t in sys.argv[i+1].split(',') if t.strip()]
i += 2
else:
i += 1
src_lines = read_nonempty(src_path)
tgt_lines = read_nonempty(tgt_path)
tgt_raw = open(tgt_path).read()
errors = 0
# 1. Line count
if len(src_lines) != len(tgt_lines):
print(f"[FAIL] Line count: src={len(src_lines)} tgt={len(tgt_lines)}")
errors += 1
else:
print(f"[OK] Line count: {len(src_lines)}")
# 2. Heading count
src_h = sum(1 for l in src_lines if l.startswith('## '))
tgt_h = sum(1 for l in tgt_lines if l.startswith('## '))
if src_h != tgt_h:
print(f"[FAIL] Headings: src={src_h} tgt={tgt_h}")
errors += 1
else:
print(f"[OK] Headings: {src_h}")
# 3. Unicode em/en-dash
em = tgt_raw.count('\u2014')
en = tgt_raw.count('\u2013')
if em or en:
print(f"[FAIL] Unicode dashes: em-dash={em} en-dash={en}")
errors += 1
else:
print("[OK] No Unicode em/en-dashes")
# 4. Markdown bold
bold = sum(1 for l in tgt_lines if '**' in l)
if bold:
print(f"[FAIL] Markdown bold (**): {bold} lines")
errors += 1
else:
print("[OK] No Markdown bold")
# 5. Chinese punctuation
cn = [(i+1, l[:60]) for i, l in enumerate(tgt_lines) if CN_PUNCT.search(l)]
if cn:
print(f"[FAIL] Chinese/smart punct: {len(cn)} lines")
for ln, snippet in cn[:5]:
print(f" L{ln}: {snippet}")
errors += 1
else:
print("[OK] No Chinese punctuation")
# 6. TOC link artifacts (first 15 lines)
toc_links = sum(1 for l in tgt_lines[:15] if re.search(r'\[.*?\]\(#', l))
if toc_links:
print(f"[FAIL] TOC has [text](#anchor) links: {toc_links}")
errors += 1
else:
print("[OK] TOC clean (no link artifacts)")
# 7. Unbalanced quotes
for i, l in enumerate(tgt_lines):
if l.count('"') % 2 != 0:
print(f"[FAIL] L{i+1}: Unbalanced quotes: {l[:80]}")
errors += 1
if errors == sum(1 for l in tgt_lines if l.count('"') % 2 != 0):
pass # errors already counted above
elif not any(l.count('"') % 2 != 0 for l in tgt_lines):
print("[OK] No unbalanced quotes")
# 8. Stale terms (must be absent)
for term in stale_terms:
count = tgt_raw.count(term)
if count > 0:
print(f"[FAIL] Stale term '{term}' still present: {count}")
errors += 1
else:
print(f"[OK] Stale term '{term}' absent")
# 9. New terms (must be present)
for term in new_terms:
count = tgt_raw.count(term)
if count == 0:
print(f"[FAIL] New term '{term}' not found")
errors += 1
else:
print(f"[OK] New term '{term}' found: {count}")
print(f"\n{'ALL CLEAN' if errors == 0 else f'{errors} ISSUE(S) FOUND'}")
sys.exit(0 if errors == 0 else 1)
if __name__ == '__main__':
main()