Skip to content

Commit f524ad4

Browse files
josixclaude
andcommitted
feat: add review-rendered-diff skill for viewing translation changes on rendered pages
Builds a page before and after a PO change in isolation (temp locale_dirs, no changes to the working tree or ../cpython), then highlights each changed paragraph on the real rendered HTML and screenshots it: - small edits as inline red/green diffs - new translations and heavy rewrites as stacked before/after blocks Also lists the skill in README and ignores its default output dir. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014pJTfUKUkCc4HFprcvhxRe
1 parent 3276402 commit f524ad4

4 files changed

Lines changed: 437 additions & 1 deletion

File tree

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
---
2+
name: review-rendered-diff
3+
description: Use when a reviewer needs to see how changed PO translations look on the rendered Python docs page — before/after comparison, red/green inline diff on the built HTML, or screenshots of changed paragraphs for a PR description or review comment.
4+
argument-hint: <po-file> [--base <git-ref>] [--new <git-ref>]
5+
---
6+
7+
# review-rendered-diff
8+
9+
Show translation changes **inside the real rendered page**, each changed paragraph outlined,
10+
one screenshot per paragraph plus an overview image. Each entry is shown one of three ways:
11+
12+
| Change | Shown as | Picked when (`--mode auto`) |
13+
|---|---|---|
14+
| Edit of an existing translation | **inline**: deleted text red with strikethrough, inserted green | default |
15+
| English → Chinese (new translation) | **two blocks**: gray「原文 (English)」above green「譯文」 | base msgstr empty, or the old rendered text is <20% CJK |
16+
| Heavy rewrite of a translation | **two blocks**: red「修改前」above green「修改後」 | text ≥30 chars and >50% of characters changed |
17+
18+
Two blocks are used where a character diff would be solid red and green. Short text, such as
19+
headings and table cells, always stays inline. Force a style with `--mode inline|blocks`, or
20+
tune the rewrite cut-off with `--rewrite-threshold` (default 0.5). Each report line names the
21+
mode used, e.g. `[blocks: rewritten, 87% changed]`.
22+
23+
## Run it
24+
25+
From the repo root:
26+
27+
```bash
28+
uv run --no-project --with polib --with beautifulsoup4 --with playwright --with pillow \
29+
python .claude/skills/review-rendered-diff/scripts/render_diff.py howto/logging.po --base origin/3.15
30+
```
31+
32+
| Flag | Default | Use |
33+
|---|---|---|
34+
| `--base` | `origin/3.15` | "before" version (fetch it first; SSH may fail, see below) |
35+
| `--new` | working-tree file | "after" version as a git ref, e.g. a PR branch |
36+
| `--out` | `.render-review/<po without .po>/` | where screenshots and builds go; with several POs, one subfolder per PO |
37+
| `--context` | `140` | px of surrounding page kept above/below each paragraph |
38+
39+
Common targets:
40+
41+
| Review | Command arguments |
42+
|---|---|
43+
| Uncommitted edits | `<po> --base HEAD` |
44+
| A PR branch | `<po> --base origin/3.15 --new <branch>` |
45+
| One past commit, all its POs | `$(git show --name-only --format= <sha> -- '*.po') --base <sha>^ --new <sha>` |
46+
47+
Each PO takes about 40 seconds, because the page is built twice. The script prints one
48+
line per changed entry (`L<entry line>: diff-N.png`), plus the diff page path and
49+
`all-diffs.png`.
50+
51+
Before reporting, open a couple of PNGs with Read. To share them, use SendUserFile on
52+
`all-diffs.png` if you have it. As a subagent, return the absolute paths instead. Or drag
53+
the images into a GitHub comment.
54+
55+
## How it works (why it is safe)
56+
57+
- **Isolated builds:** each version's PO goes into its own temp `locale_dirs`, and
58+
`sphinx-build` runs on that one `.rst` into `--out/build-{old,new}/`. The working-tree PO
59+
and `../cpython/Doc/locales` are never touched.
60+
- **Changed entries** are found by comparing msgstr per `(msgctxt, msgid)` with polib.
61+
- **Locating paragraphs:** roles, inline literals and links are dropped first, because
62+
`` :meth:`~Handler.setFormatter` `` renders as `setFormatter()`. The longest remaining plain
63+
run is matched against the rendered text, and the smallest enclosing block is used.
64+
- **Two blocks in tables and lists** go inside the cell or item, so the table and list
65+
structure survives.
66+
- **Diff on text, not HTML:** a character diff of the rendered text, applied to text nodes only,
67+
so links, inline code and `` anchors keep working.
68+
69+
## Gotchas
70+
71+
- **Do not use `make build` for this.** It hard-links the PO into `../cpython`, runs
72+
`git pull` on cpython, and swapping the PO in place risks losing uncommitted edits.
73+
- **Exit code 1 is normal.** Sphinx fails on unrelated CPython redirect warnings
74+
(`library/functions.html redirects to ...`). The script judges success by whether the HTML
75+
exists. On failure, read `build-*/build.log`.
76+
- **`SKIPPED (paragraph not found)`** means the entry has no rendered paragraph, e.g. an index
77+
entry or code block, or its msgid no longer matches the `../cpython` sources (the page
78+
shows English). Check `../cpython` is on the same branch as the PO. A trailing ` ::`
79+
literal-block marker is already handled, so it is not the cause. For a skip you cannot
80+
explain, grep the new msgstr's plain text in `build-new/html/<po>.html`.
81+
- **A paragraph containing several changed entries** is highlighted once, and later entries
82+
report "already highlighted".
83+
- **Inline diffs fragment small CJK edits** (e.g. 可能~~不是~~ shows only the changed
84+
characters). That is accurate. If a reviewer finds a paragraph choppy, rerun with
85+
`--mode blocks` or a lower `--rewrite-threshold`.
86+
- **Do not judge a rewrite by `SequenceMatcher.ratio()`.** Common CJK characters keep
87+
matching, so a fully rewritten paragraph still scored 0.45. The script measures the share
88+
of changed characters instead.
89+
- **A large new translation** (a whole file) makes one screenshot per paragraph, e.g. 147 for
90+
`howto/logging.po`. Point reviewers to `<po>-diff.html` rather than `all-diffs.png`.
91+
- **Labels use the entry's first line** (the `#:` comment), not the msgstr line.
92+
- **No `../cpython`:** run `make prepare_deps` once.
93+
- **SSH to GitHub resets:** fetch over HTTPS:
94+
`git -c credential.helper='!gh auth git-credential' fetch https://github.com/python/python-docs-zh-tw.git 3.15:refs/remotes/origin/3.15`
95+
96+
## Not for
97+
98+
- Checking reST validity: use `make lint` / `sphinx-lint`.
99+
- Judging translation quality: use the `validate-translation` skill. This skill only
100+
visualizes changes.

0 commit comments

Comments
 (0)