Whole-block segments cover paired formatting (strong/em/s), not just links

The model mangles Markdown it can see (Seed-X dropped the ** and the
glued-on colon in '**Pagerite**: ...'), so emphasis now crosses stripped,
inline in its sentence, and the syntax is weight-mapped back like links.
Also fix _place_marks swallowing trailing punctuation into the inner text
(end at the slice's last unit) — same-language round trips are now exact.
This commit is contained in:
2026-09-03 03:46:26 +00:00
parent 081ab979f3
commit a47a96ca30
3 changed files with 98 additions and 75 deletions
+23 -17
View File
@@ -376,13 +376,14 @@ fragment is parsed with the project's own markdown-it setup
tasklist label wrapping, so token text stays byte-identical to the source)
and split into the runs a model may touch: paragraph/heading/table-cell text
(merged across soft line breaks), image alt texts and captions, footnote
bodies. A block of plain text and inline **links stays whole** — link texts
cross inline, in sentence context (see below). Everything else never leaves
the server: code spans and
bodies. A block of plain text, inline **links and paired text formatting**
(strong/em/s) **stays whole** — link and formatted texts cross inline, in
sentence context, with the Markdown stripped (see below). Everything else
never leaves the server: code spans and
fences, URLs and autolinks, link/image *destinations*, `{...}` spans
(placeholders like `{dates}` as well as attrs), reference and footnote
labels, container fences, GFM alert markers (`[!NOTE]`), raw HTML — and all
markup punctuation (`*`, `|`, `[]()`, `:::`), which is a run boundary.
labels, container fences, GFM alert markers (`[!NOTE]`), raw HTML — and the
remaining markup punctuation (`|`, `:::`), which is a run boundary.
Chunks with no segments (a lone `{dates}`, container fences, pure
code/HTML) are never dispatched at all (`needs_translation`); every
language renders them from the original chunk. Each segment is accompanied
@@ -404,24 +405,29 @@ near-deterministic, so an immediate retry would re-fail; the fragment stays
pending and gets another chance on restart or `DELETE /_api/translations`).
`Data.trans` therefore only ever holds clean translated Markdown.
Link-carrying blocks are the one place a segment is not spliced verbatim:
a label translated apart from its sentence comes back grammatically
incompatible with it (case government, particles, word order), so the
block crosses whole and the server re-inserts the link markdown into the
translated block. The boundaries are found by **text processing alone**
Link- and formatting-carrying blocks are the one place a segment is not
spliced verbatim: a label translated apart from its sentence comes back
grammatically incompatible with it (case government, particles, word
order), and shown the Markdown the model mangles it (Seed-X dropped the
`**` and the glued-on colon in `**Pagerite**: …`), so the block crosses
whole — all Markdown stripped — and the server re-inserts the link and
formatting syntax into the translated block. The boundaries are found by
**text processing alone**
markers on the wire are hopeless (an earlier sentinel-masking design let
the model see and mangle exactly that punctuation: Seed-X renumbered the
tokens and turned `![` into `¡¡…!!`). Each link's weight ratio in the
tokens and turned `![` into `¡¡…!!`). Each mark's weight ratio in the
source block (word units before its text boundaries over the block total;
CJK ideographs count as one unit each, kana runs as one — no spaces to
count words by) is applied to the translation's units. Placement is
approximate and drift accumulates across several links in one block — the
count words by) is applied to the translation's units; the inner text ends
at its last unit, so punctuation and whitespace between the mark and the
next word stay outside it. Placement is
approximate and drift accumulates across several marks in one block — the
accepted trade: better a coherent sentence with a slightly shifted link
than separately translated snippets that don't fit together. A boundary
that maps to an empty slice degrades to the source link text rather than
emitting a broken `[](url)`. Blocks mixing in any other inline markup
(emphasis, code spans, images) don't qualify and still split into runs at
those boundaries.
that maps to an empty slice degrades to the source text rather than
emitting a broken `[](url)` or `**`. Blocks mixing in any other inline
markup (code spans, images, raw HTML) don't qualify and still split into
runs at those boundaries.
Punctuation is the translator's own job: Seed-X tends to "finish" short
labels (titles, nav items) with a comma or period the source never had.