Perché la traduzione DOCX perde il grassetto? Continua prima la corsa, quindi parla della sostituzione dell'intera sezione.
DOCX grassetto e corsivo perso dopo la traduzione? Il problema probabilmente è che tutta la sezione viene sostituita e la fuga viene dilavata. Questo articolo utilizza python-docx per salvare il formato di esecuzione uno per uno e rileggerlo e accettarlo dopo il salvataggio. Se incontra una struttura complessa o il segmento non corrisponde, rifiuterà direttamente di sostituirlo.
Grassetto, corsivo e dimensione del carattere vengono persi dopo la traduzione DOCX. Il motivo comune è che il contenuto del paragrafo viene sostituito direttamente con l'intero testo, cancellando così il formato run-level originale. Dopo che molti team hanno ricevuto la traduzione, una reazione comune è che manca il formato di enfasi in Word. Questo articolo è adatto agli sviluppatori che utilizzano python-docx per elaborare DOCX, nonché agli editor che devono fornire documenti bilingue.
Un paragrafo sembra avere una sola frase in Word, ma in DOCX può essere composto da più sequenze: testo ordinario, testo enfatizzato, modifiche alla dimensione del carattere, collegamenti ipertestuali e altre strutture che non appartengono all'elenco delle sequenze ordinarie. Dopo aver letto questo, saprai dove si trova solitamente il problema, come riscrivere le traduzioni esecuzione per esecuzione e quando dovresti semplicemente rifiutare la sostituzione automatica.
Cosa devo fare se il formato DOCX viene perso dopo la traduzione? Conclusione di una frase
Innanzitutto limitare l'elaborazione ai soli paragrafi di testo ordinario, riscrivere la traduzione una per una in base al numero di sequenza di esecuzione originale, salvarla e rileggerla per accettazione; se incontra una struttura complessa o il segmento non corrisponde, rifiuta direttamente la sostituzione.
| la tua situazione | Pratiche consigliate | motivo |
|---|---|---|
| I paragrafi hanno solo il testo normale | Riscrivere le traduzioni una per una in base al numero di sequenza di esecuzione | I limiti del formato per ogni esecuzione vengono preservati |
| I paragrafi contengono collegamenti ipertestuali, immagini, campi, interruzioni di riga o tabulazioni | Rifiutare esplicitamente e trasferire al processo speciale | Il codice non appiattisce silenziosamente questi elementi |
| Il numero o l'ordine dei segmenti di traduzione non è coerente con la sequenza originale | Invece di limitarti alle esecuzioni esistenti, utilizza strategie di riformattazione o revisione manuale | La corrispondenza forzata interromperà il formato |
| È necessario confermare il risultato della riscrittura | Dopo aver salvato, riapri il file e accettalo. | Evitare di controllare solo gli oggetti in memoria |
Assegna direttamente il valore a paragraph.text | evitare di utilizzare | Il contenuto esistente del paragrafo verrà sostituito con il nuovo testo e la formattazione a livello di esecuzione non verrà mantenuta automaticamente. |
Dov'è il problema: la sostituzione dell'intero paragrafo cancellerà il formato di esecuzione
Assegnando direttamente un valore a paragraph.text si sostituirà il contenuto esistente del paragrafo con un nuovo testo. Gli stili a livello di paragrafo possono essere mantenuti, ma la formattazione originale a livello di esecuzione non verrà mantenuta automaticamente. Questo comportamento è esplicitamente documentato in API di testo python-docx.
Il risultato della traduzione sembra accurato, ma il formato è completamente scomparso. Questo è probabilmente il motivo.
Ambito di applicazione: il formato è preservato, ma ciò non significa che altri problemi siano stati risolti.
I record di test di questo articolo provengono da DOCX sintetizzati localmente, non da screenshot del motore di composizione. Ciò che risolve è la "sostituzione vincolata senza perdere il formato". Non risolve automaticamente i riarrangiamenti della sintassi tra lingue diverse, né garantisce che l'impaginazione rimanga invariata dopo la traduzione.
Limitare innanzitutto l'intervallo che può essere modificato in modo sicuro
Questo esempio condensato accetta solo paragrafi costituiti da testo semplice. Quando un paragrafo contiene collegamenti ipertestuali, immagini, campi, interruzioni di riga, tabulazioni o altri nodi XML complessi, rifiutalo esplicitamente e reindirizza il chiamante a un processo specializzato. Il codice non appiattirà questi elementi in modo silenzioso.
L'input della traduzione non è un elenco arbitrario di stringhe: ogni risultato deve avere il numero di serie dell'esecuzione originale e il numero, l'ordine e il tipo devono corrispondere prima che venga avviata la modifica. La convalida viene effettuata prima della scrittura per evitare di scoprire problemi con i campi successivi dopo l'aggiornamento a metà.
Un test minimo che può essere eseguito ripetutamente
L'ambiente di test è python-docx==1.2.0. L'inglese qui deriva da un confronto fisso scritto a mano, che viene utilizzato per verificare la struttura e non invoca la traduzione automatica.
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))
Dopo aver salvato, riaprire translated-runs.docx e poi accettarlo per evitare di controllare solo gli oggetti in memoria.
Perché non affidare ogni passaggio al traduttore individualmente?
run è un confine di formato, non un confine semantico. La cronologia delle modifiche di Word può anche dividere una parola in più esecuzioni. Le traduzioni isolate perderanno il contesto; l'ordine delle parole nelle diverse lingue può anche spostare l'accento all'inizio o alla fine della frase.
L'effettiva generazione della traduzione dovrebbe fornire il contesto sotto forma di segmenti completi e quindi restituire segmenti strutturati convalidati. Quando il risultato restituito non è uguale alla lunghezza originale, non forzarlo nella sequenza esistente. È necessaria una chiara strategia di riformattazione o una revisione manuale. Il semplice esempio in questo articolo può contenere solo tre frammenti, ma ciò non può essere generalizzato a tutte le lingue.
Suddividi l'accettazione in tre livelli
| livello | Controlla il contenuto | Questo articolo copre |
|---|---|---|
| struttura dei dati | Esegui quantità, ordine, firma in grassetto e recupero dopo il salvataggio | Sostituisci questo esempio limitato |
| contenuto semantico | Termini, parole negative, date, importi, omissioni | Non coperto; richiede una correzione di bozze indipendente |
| disposizione visiva | Rollback dei caratteri, interruzioni di riga, numeri di pagina, overflow della tabella | Non coperto; deve essere renderizzato e controllato di nuovo |
_p e _r sono le proprietà interne utilizzate qui per controllare XML. Quando si aggiorna python-docx, è necessario correggere la versione ed eseguire nuovamente il test. Non si può dare per scontato che la struttura interna non cambierà mai. Quando è necessario elaborare tabelle, intestazioni, piè di pagina, caselle di testo e tracce di revisione, è necessario anche enumerare separatamente gli intervalli di contenuto, poiché document.paragraphs non può rappresentare tutto il testo nel documento.
Condizione di arresto prima della consegna
Strutture non supportate, segmenti non corrispondenti, caratteri mancanti, modifiche a campi importanti: tutto ciò dovrebbe impedire la consegna automatica. Salvare il file originale in sola lettura, scrivere la traduzione in un nuovo file e allegare la lingua, la versione di elaborazione e il record di accettazione manuale. Questo è un indicatore di qualità migliore rispetto a "salvataggio riuscito".
Se devi passare dal caricamento dei documenti al processo di traduzione e revisione, puoi controllare Portale del prodotto OmniDoc. Gli esempi di codice contenuti in questo articolo sono esempi didattici di librerie open source indipendenti e non rappresentano l'implementazione dell'attuale importatore o motore di layout di OmniDoc. Esiste un solo principio fondamentale: trattare il formato come dati da accettare, piuttosto che come un bonus tradotto.
📊 Confronto fondamentale
| pratica | Principali rischi | Suggerimenti forniti nell'articolo |
|---|---|---|
Assegna direttamente il valore a paragraph.text | La formattazione a livello di esecuzione non viene mantenuta automaticamente | Non utilizzato per i paragrafi che devono preservare la formattazione |
| Esegui traduzioni isolate una per una | Si perde il contesto, i cambiamenti nell'ordine delle parole possono spostare l'enfasi | Fornire il contesto come segmenti completi |
| Dopo che il segmento completo è stato tradotto, premi Esegui per verificarlo e riscriverlo. | Se il risultato restituito non ha la stessa lunghezza della corsa originale, non può essere difficile corrispondere. | Utilizzare invece la strategia di riformattazione o la revisione manuale |
🎯Quale metodo è adatto a te?
Se il tuo paragrafo ha solo testo normale
Secondo l'esempio minimo in questo articolo, verificare prima il numero di serie, la quantità, l'ordine e il tipo, quindi riscrivere uno per uno, salvare e rileggere per l'accettazione.
Se il tuo paragrafo contiene collegamenti ipertestuali, campi o immagini
Rifiuta direttamente la sostituzione automatica e trasferiscila in un processo speciale. Il codice non appiattisce silenziosamente queste strutture.
Se stai consegnando documentazione bilingue formale
Salvare il file originale in sola lettura, scrivere la traduzione in un nuovo file e allegare la lingua, la versione di elaborazione e i record di accettazione manuale. Caratteri mancanti, modifiche in campi importanti, segmenti non corrispondenti, ecc. dovrebbero impedire la consegna automatica.
❓ Domande frequenti (FAQ)
1. Il grassetto andrà perso se assegni direttamente un valore a paragrafo.testo?
incontro. Gli stili a livello di paragrafo possono essere mantenuti, ma la formattazione originale a livello di esecuzione non verrà mantenuta automaticamente.
2. Perché non affidare ogni passaggio al traduttore individualmente?
run è un confine di formato piuttosto che un confine semantico. La traduzione isolata una per una perderà il contesto e l'ordine delle parole di lingue diverse potrebbe anche spostare l'enfasi all'inizio o alla fine della frase.
3. Il salvataggio riuscito significa che il formato è corretto?
non può. Le strutture dei dati di accettazione dei file devono essere riaperte dopo il salvataggio; il contenuto semantico e il layout visivo devono essere controllati separatamente.
4. A cosa dovrei prestare attenzione quando aggiorno python-docx?
Il codice utilizza le proprietà interne di _p e _r. È necessario correggere la versione ed eseguire nuovamente il test. Non si può dare per scontato che la struttura interna non cambierà mai.
📝 Riepilogo
Esiste un solo principio fondamentale: trattare il formato come dati da accettare, piuttosto che come un bonus tradotto. Gli esempi di codice contenuti in questo articolo sono esempi didattici di librerie open source indipendenti e non rappresentano l'implementazione dell'attuale importatore o motore di layout di OmniDoc.
Provalo subito: carica il documento per iniziare la traduzione, mantenendo il layout originale


