Proč překlad DOCX ztrácí tučné písmo? Nejprve nechte běh a pak mluvte o výměně celé sekce.

DOCX tučné písmo a kurzíva ztracené po překladu? Problém je asi v tom, že se vymění celý úsek a vyplaví se běh. Tento článek používá python-docx k uložení formátu běhu jeden po druhém a po uložení si jej znovu přečte a přijme. Pokud narazí na složitou strukturu nebo segment neodpovídá, přímo ji odmítne nahradit.

Po překladu DOCX se ztratí tučné písmo, kurzíva a velikost písma. Častým důvodem je, že obsah odstavce je přímo nahrazen celým textem, což smyje původní formát na úrovni běhu. Poté, co mnoho týmů dostane překlad, je běžnou reakcí, že ve Wordu chybí formát zvýraznění. Tento článek je vhodný pro vývojáře, kteří používají python-docx ke zpracování DOCX, a také pro editory, kteří potřebují doručovat dvojjazyčné dokumenty.

Zdá se, že odstavec má ve Wordu pouze jednu větu, ale v DOCX se může skládat z více běhů: běžný text, zdůrazněný text, změny velikosti písma a hypertextové odkazy a další struktury, které nepatří do běžného seznamu běhů. Po přečtení tohoto článku budete vědět, kde obvykle spočívá problém, jak odepsat překlady za běhu a kdy byste měli automatické nahrazení odmítnout.

Co mám dělat, když se formát DOCX po překladu ztratí? Závěr jednou větou

Nejprve omezte zpracování pouze na běžné odstavce běhu textu, zapište překlad jeden po druhém zpět podle původního pořadového čísla běhu, uložte jej a znovu si jej přečtěte pro přijetí; pokud narazí na složitou strukturu nebo segment neodpovídá, přímo odmítněte náhradu.

vaší situaciDoporučené postupydůvod
Odstavce mají pouze normální běh textuZapište překlady jeden po druhém podle pořadového čísla běhuHranice formátu pro každý běh jsou zachovány
Odstavce obsahují hypertextové odkazy, obrázky, pole, konce řádků nebo tabulátoryExplicitně odmítnout a převést do speciálního procesuKód tyto prvky tiše nezplošťuje
Počet nebo pořadí překladových segmentů není konzistentní s původním běhemMísto toho, abyste se zabývali stávajícími běhy, použijte strategie přeformátování nebo ruční kontroluNucená korespondence naruší formát
Je třeba potvrdit výsledek zpětného zápisuPo uložení soubor znovu otevřete a přijměte jej.Vyhněte se kontrole pouze objektů v paměti
Přímo přiřaďte hodnotu paragraph.textvyhnout se použitíStávající obsah odstavce bude nahrazen novým textem a formátování na úrovni běhu nebude automaticky zachováno.

Kde je problém: Nahrazením celého odstavce se vymaže formát běhu

Přímé přiřazení hodnoty paragraph.text nahradí stávající obsah odstavce novým textem. Styly na úrovni odstavce lze zachovat, ale původní formátování na úrovni běhu nebude automaticky zachováno. Toto chování je výslovně zdokumentováno v textové API python-docx.

Výsledek překladu vypadá přesně, ale formát je úplně pryč. To je pravděpodobně důvod.

Rozsah použití: Formát je zachován, ale to neznamená, že byly vyřešeny další problémy.

Testovací záznamy tohoto článku pocházejí z místně syntetizovaného DOCX, nikoli ze snímků obrazovky sázecího stroje. Řeší to "omezené nahrazení bez ztráty formátu". Neřeší automaticky přeuspořádání syntaxe mezi jazyky ani nezajišťuje, že stránkování zůstane po překladu nezměněno.

Nejprve omezte rozsah, který lze bezpečně upravit

Tento zhuštěný příklad přijímá pouze odstavce skládající se z běhu prostého textu. Pokud odstavec obsahuje hypertextové odkazy, obrázky, pole, konce řádků, tabulátory nebo jiné složité uzly XML, výslovně jej odmítněte a přesměrujte volajícího na specializovaný proces. Kód tyto prvky tiše nevyrovná.

Vstup překladu není libovolný seznam řetězců: každý výsledek musí mít sériové číslo původního běhu a před zahájením úpravy se musí všechny shodovat číslo, pořadí a typ. Ověření je umístěno před zápisem, aby se předešlo problémům s následnými poli po aktualizaci v polovině.

Minimální test, který lze spouštět opakovaně

Testovací prostředí je python-docx==1.2.0. Angličtina zde pochází z ručně psaného pevného srovnání, které se používá k ověření struktury a nevyvolává strojový překlad.

from docx import Document
from docx.oxml.ns import qn

def replace_plain_runs(paragraph, translated):
    if any(child.tag not in {qn("w:pPr"), qn("w:r")}
           for child in paragraph._p):
        raise ValueError("paragraph contains unsupported structures")
    runs = paragraph.runs
    for run in runs:
        if any(child.tag not in {qn("w:rPr"), qn("w:t")}
               for child in run._r):
            raise ValueError("run contains a field, image or control")
    if len(translated) != len(runs):
        raise ValueError("segment count mismatch")
    for index, item in enumerate(translated):
        if (not isinstance(item, dict) or item.get("id") != index
                or not isinstance(item.get("text"), str)
                or any(ch in item["text"] for ch in "\t\r\n")):
            raise ValueError("segment identity or text mismatch")
    for run, item in zip(runs, translated):
        run.text = item["text"]

def signature(paragraph):
    return [(r.text, r.bold, r.italic) for r in paragraph.runs]

doc = Document()
p = doc.add_paragraph()
p.add_run("请在 ")
p.add_run("周五之前").bold = True
p.add_run(" 提交报告。")
before = signature(p)
try:
    replace_plain_runs(p, [{"id": 0, "text": "Incomplete"}])
    raise AssertionError("bad segments accepted")
except ValueError:
    assert signature(p) == before

replace_plain_runs(p, [
    {"id": 0, "text": "Submit the report "},
    {"id": 1, "text": "before Friday"},
    {"id": 2, "text": "."},
])
doc.save("translated-runs.docx")
restored = Document("translated-runs.docx").paragraphs[0]
assert restored.text == "Submit the report before Friday."
assert restored.runs[1].bold is True
assert len(restored.runs) == 3
complex_p = doc.add_paragraph("keep")
complex_p.runs[0].add_break()
try:
    replace_plain_runs(complex_p, [{"id": 0, "text": "reject"}])
    raise AssertionError("line break accepted")
except ValueError:
    assert complex_p.text == "keep\n"
print("PASS count mismatch: no partial write")
print("PASS save/reopen: 3 runs, emphasis preserved")
print("PASS unsupported control: rejected")
print(signature(restored))

Po uložení znovu otevřete translated-runs.docx a poté jej přijměte, abyste se vyhnuli kontrole pouze objektů v paměti.

Proč nedat každý běh překladateli jednotlivě?

run je hranice formátu, nikoli sémantická hranice. Historie úprav aplikace Word může také rozdělit slovo do několika běhů. Izolované překlady ztratí kontext; slovosled různých jazyků může také přesunout důraz na začátek nebo konec věty.

Vlastní generování překladu by mělo poskytnout kontext jako úplné segmenty a poté vrátit ověřené strukturované segmenty. Pokud vrácený výsledek není stejný jako původní délka, nevnucujte jej do stávajícího běhu. Vyžaduje se jasná strategie přeformátování nebo ruční kontrola. Jednoduchý příklad v tomto článku může obsahovat pouze tři fragmenty, ale nelze to zobecnit na všechny jazyky.

Rozdělte přijetí do tří úrovní

úroveňZkontrolujte obsahPokrývá tento článek
datová strukturaPo uložení spusťte množství, objednávku, tučný podpis a obnoveníPřepište tento omezený příklad
sémantický obsahTermíny, záporná slova, data, částky, vynecháníNepokryté; vyžaduje nezávislou korekturu
vizuální rozvrženíVrácení písma, zalomení řádků, čísla stránek, přetečení tabulekNepokryté; je třeba vykreslit a znovu zkontrolovat

_p a _r jsou interní vlastnosti používané zde pro kontrolu XML. Při upgradu python-docx musíte opravit verzi a znovu spustit test. Nemůžete předpokládat, že vnitřní struktura se nikdy nezmění. Když potřebujete zpracovat tabulky, záhlaví, zápatí, textová pole a stopy revizí, musíte také samostatně vyčíslit rozsahy obsahu, protože document.paragraphs nemůže reprezentovat veškerý text v dokumentu.

Stav zastavení před dodáním

Nepodporované struktury, neodpovídající segmenty, chybějící písma, změny důležitých polí, to vše by mělo zabránit automatickému doručení. Uložte původní soubor jako pouze pro čtení, zapište překlad do nového souboru a připojte jazyk, verzi zpracování a záznam o ručním přijetí. To je lepší ukazatel kvality než „úspěšně uložit".

Pokud potřebujete přejít od nahrávání dokumentů k procesu překladu a kontroly, můžete se podívat na Produktový portál OmniDoc. Příklady kódu v tomto článku jsou ukázky nezávislých výukových knihoven s otevřeným zdrojovým kódem a nepředstavují implementaci aktuálního importéru nebo modulu rozložení OmniDoc. Existuje pouze jeden základní princip: považovat formát za data, která mají být přijata, spíše než za přeložený bonus.

📊 Srovnání jádra

praxeHlavní rizikaNávrhy uvedené v článku
Přímo přiřaďte hodnotu paragraph.textFormátování na úrovni běhu není automaticky zachovánoNepoužívá se pro odstavce, které potřebují zachovat formátování
Spusťte izolované překlady jeden po druhémKontext je ztracen, změny slovosledu mohou přesunout důrazPoskytněte kontext jako úplné segmenty
Po přeložení celého segmentu stiskněte Spustit pro ověření a zapište jej zpět.Pokud vrácený výsledek není stejně dlouhý jako původní běh, nemůže být těžké s ním souhlasit.Místo toho použijte strategii přeformátování nebo ruční kontrolu

🎯 Která metoda je pro vás vhodná?

Pokud váš odstavec obsahuje pouze normální text

Podle minimálního příkladu v tomto článku nejprve ověřte sériové číslo, množství, objednávku a typ, poté jeden po druhém odepište, uložte a znovu přečtěte pro přijetí.

Pokud váš odstavec obsahuje hypertextové odkazy, pole nebo obrázky

Přímo odmítněte automatickou výměnu a převeďte ji do speciálního procesu. Kód tyto struktury tiše nezplošťuje.

Pokud dodáváte formální dvojjazyčnou dokumentaci

Uložte původní soubor jako pouze pro čtení, zapište překlad do nového souboru a připojte záznamy o jazyce, verzi zpracování a ručním přijetí. Chybějící písma, změny v důležitých polích, neshodné segmenty atd. by měly bránit automatickému doručení.

❓ Často kladené otázky (FAQ)

1. Ztratí se tučné písmo, pokud přímo přiřadíte hodnotu do odstavce.text?

zasedání. Styly na úrovni odstavce lze zachovat, ale původní formátování na úrovni běhu nebude automaticky zachováno.

2. Proč nedat každý běh překladateli jednotlivě?

run je spíše hranicí formátu než sémantickou hranicí. Izolovaný překlad jeden po druhém ztratí kontext a slovosled různých jazyků může také přesunout důraz na začátek nebo konec věty.

3. Znamená úspěšné uložení, že je formát v pořádku?

nemůže. Datová struktura přijetí souboru by měla být po uložení znovu otevřena; sémantický obsah a vizuální uspořádání je třeba zkontrolovat samostatně.

4. Na co bych měl dávat pozor při upgradu python-docx?

Kód využívá vnitřní vlastnosti _p a _r. Musíte opravit verzi a znovu spustit test. Nemůžete předpokládat, že vnitřní struktura se nikdy nezmění.

📝 Shrnutí

Existuje pouze jeden základní princip: považovat formát za data, která mají být přijata, spíše než za přeložený bonus. Příklady kódu v tomto článku jsou ukázky nezávislých výukových knihoven s otevřeným zdrojovým kódem a nepředstavují implementaci aktuálního importéru nebo modulu rozložení OmniDoc.

Vyzkoušejte to hned: Nahrajte dokument a začněte překládat při zachování původního rozvržení

Aktualizováno 2026-11-14