Dlaczego w tłumaczeniu DOCX traci się pogrubienie? Najpierw zachowaj bieg, a potem porozmawiaj o wymianie całej sekcji.

Pogrubienie i kursywa DOCX utracone po tłumaczeniu? Problem prawdopodobnie polega na tym, że wymienia się całą sekcję i wybieg zostaje wypłukany. W tym artykule zastosowano python-docx do zapisywania formatu uruchamiania jeden po drugim, a po zapisaniu ponownie go przeczytaj i zaakceptuj. Jeśli napotka złożoną strukturę lub segment nie będzie pasował, bezpośrednio odmówi jego wymiany.

Pogrubienie, kursywa i rozmiar czcionki zostaną utracone po tłumaczeniu DOCX. Najczęstszym powodem jest to, że treść akapitu jest bezpośrednio zastępowana całym tekstem, co zamazuje oryginalny format na poziomie działania. Gdy wiele zespołów otrzymuje tłumaczenie, typową reakcją jest brak formatu wyróżnienia w programie Word. Ten artykuł jest odpowiedni dla programistów używających Pythona-docx do przetwarzania DOCX, a także redaktorów, którzy muszą dostarczać dokumenty dwujęzyczne.

Wydaje się, że akapit w programie Word ma tylko jedno zdanie, ale w formacie DOCX może składać się z wielu ciągów: zwykłego tekstu, tekstu wyróżnionego, zmian rozmiaru czcionki oraz hiperłączy i innych struktur, które nie należą do zwykłej listy przebiegów. Po przeczytaniu tego będziesz wiedział, gdzie zwykle leży problem, jak zapisywać tłumaczenia uruchamiane po uruchomieniu i kiedy powinieneś po prostu odrzucić automatyczną zamianę.

Co powinienem zrobić, jeśli format DOCX zostanie utracony po tłumaczeniu? Wniosek w jednym zdaniu

Najpierw ogranicz przetwarzanie tylko do zwykłych akapitów tekstu, zapisz tłumaczenie jedno po drugim zgodnie z oryginalnym numerem porządkowym, zapisz je i przeczytaj ponownie do akceptacji; jeśli napotka złożoną strukturę lub segment nie pasuje, bezpośrednio odrzuć zamiennik.

twoja sytuacjaZalecane praktykipowód
Akapity mają tylko normalny tekstZapisz tłumaczenia jedno po drugim, zgodnie z numerem porządkowym przebieguGranice formatu dla każdego przebiegu zostają zachowane
Akapity zawierają hiperłącza, obrazy, pola, podziały wierszy lub tabulatoryWyraźnie odmów i przekaż do specjalnego procesuKod nie spłaszcza tych elementów po cichu
Liczba lub kolejność segmentów tłumaczenia jest niezgodna z wersją pierwotnąZamiast ograniczać się do istniejących serii, użyj strategii ponownego formatowania lub ręcznego przegląduPrzymusowa korespondencja zakłóci format
Należy potwierdzić wynik zapisu zwrotnegoPo zapisaniu otwórz ponownie plik i zaakceptuj go.Unikaj sprawdzania tylko obiektów w pamięci
Bezpośrednio przypisz wartość do paragraph.textunikaj używaniaIstniejąca treść akapitu zostanie zastąpiona nowym tekstem, a formatowanie na poziomie wykonania nie zostanie automatycznie zachowane.

Gdzie jest problem: zastąpienie całego akapitu spowoduje wymazanie formatu przebiegu

Bezpośrednie przypisanie wartości do paragraph.text spowoduje zastąpienie dotychczasowej treści akapitu nowym tekstem. Style na poziomie akapitu można zachować, ale oryginalne formatowanie na poziomie wykonania nie zostanie automatycznie zachowane. To zachowanie jest wyraźnie udokumentowane w Tekstowe API Pythona-docx.

Wynik tłumaczenia wygląda na dokładny, ale format całkowicie zniknął. Prawdopodobnie to jest powód.

Zakres zastosowania: Format został zachowany, ale nie oznacza to, że inne problemy zostały rozwiązane.

Zapisy testów w tym artykule pochodzą z lokalnie syntetyzowanego DOCX, a nie zrzutów ekranu silnika składu. Rozwiązaniem jest „ograniczona wymiana bez utraty formatu". Nie rozwiązuje to automatycznie zmian w składni międzyjęzykowych ani nie gwarantuje, że stronicowanie pozostanie niezmienione po tłumaczeniu.

Najpierw ogranicz zakres, który można bezpiecznie modyfikować

W tym skróconym przykładzie akceptowane są tylko akapity składające się z tekstu zwykłego. Jeśli akapit zawiera hiperłącza, obrazy, pola, podziały wierszy, tabulatory lub inne złożone węzły XML, należy go jawnie odrzucić i przekierować osobę wywołującą do wyspecjalizowanego procesu. Kod nie spłaszczy tych elementów po cichu.

Dane wejściowe tłumaczenia nie są dowolną listą ciągów znaków: każdy wynik musi mieć numer seryjny oryginalnego przebiegu, a liczba, kolejność i typ muszą być zgodne przed rozpoczęciem modyfikacji. Walidacja dokonywana jest przed zapisem, aby uniknąć wykrycia problemów z kolejnymi polami po aktualizacji w połowie.

Minimalny test, który można uruchamiać wielokrotnie

Środowisko testowe topython-docx==1.2.0. Język angielski pochodzi z odręcznego, stałego porównania, które służy do weryfikacji struktury i nie wymaga tłumaczenia maszynowego.

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 zapisaniu otwórz ponownie translated-runs.docx, a następnie zaakceptuj go, aby uniknąć sprawdzania tylko obiektów w pamięci.

Dlaczego nie przekazać każdego przebiegu tłumaczowi indywidualnie?

run jest granicą formatu, a nie granicą semantyczną. Historia edycji programu Word może również podzielić słowo na wiele przebiegów. Pojedyncze tłumaczenia stracą kontekst; kolejność słów w różnych językach może również przenieść akcent na początek lub koniec zdania.

Rzeczywiste wygenerowanie tłumaczenia powinno zapewnić kontekst w postaci pełnych segmentów, a następnie zwrócić zweryfikowane segmenty strukturalne. Jeżeli zwrócony wynik nie jest taki sam jak długość pierwotna, nie wciskaj go na siłę w istniejący przebieg. Wymagana jest jasna strategia ponownego formatowania lub ręczny przegląd. W prostym przykładzie zawartym w tym artykule można zachować tylko trzy fragmenty, ale nie można tego uogólnić na wszystkie języki.

Podziel akceptację na trzy poziomy

poziomSprawdź zawartośćCzy ten artykuł obejmuje
struktura danychUruchom ilość, zamówienie, pogrubiony podpis i odzyskiwanie po zapisaniuZastąp ten ograniczony przykład
treść semantycznaTerminy, słowa negatywne, daty, kwoty, pominięciaNieobjęte; wymaga samodzielnej korekty
układ wizualnyWycofywanie czcionek, łamanie wierszy, numerowanie stron, przepełnienie tabeliNieobjęte; należy wyrenderować i sprawdzić ponownie

_p i _r to wewnętrzne właściwości używane tutaj do sprawdzania XML. Podczas aktualizacji Pythona-docx musisz naprawić wersję i ponownie uruchomić test. Nie można zakładać, że struktura wewnętrzna nigdy się nie zmieni. Jeśli zachodzi potrzeba przetwarzania tabel, nagłówków, stopek, pól tekstowych i śladów wersji, należy również osobno wyliczyć zakresy treści, ponieważ document.paragraphs nie może reprezentować całego tekstu w dokumencie.

Zatrzymaj warunek przed dostawą

Nieobsługiwane struktury, niedopasowane segmenty, brakujące czcionki, zmiany w ważnych polach – wszystko to powinno uniemożliwić automatyczne dostarczanie. Zapisz oryginalny plik jako tylko do odczytu, zapisz tłumaczenie do nowego pliku i dołącz język, wersję przetwarzania oraz protokół ręcznej akceptacji. Jest to lepszy wskaźnik jakości niż „pomyślne zapisanie".

Jeśli chcesz przejść od przesyłania dokumentów do procesu tłumaczenia i recenzji, możesz sprawdzić Portal produktów OmniDoc. Przykłady kodu w tym artykule są niezależnymi przykładami bibliotek open source i nie reprezentują implementacji bieżącego importera ani silnika układu OmniDoc. Jest tylko jedna podstawowa zasada: traktuj format jako dane do zaakceptowania, a nie przetłumaczony bonus.

📊 Porównanie rdzeni

praktykaGłówne zagrożeniaSugestie podane w artykule
Bezpośrednio przypisz wartość do paragraph.textFormatowanie na poziomie działania nie jest zachowywane automatycznieNieużywane w przypadku akapitów, które wymagają zachowania formatowania
Uruchom pojedyncze tłumaczenia jedno po drugimKontekst został utracony, zmiany kolejności słów mogą spowodować przesunięcie akcentuPodaj kontekst w postaci pełnych segmentów
Po przetłumaczeniu całego segmentu naciśnij przycisk Uruchom, aby zweryfikować i zapisać go ponownie.Jeśli zwrócony wynik nie jest tej samej długości co pierwotny przebieg, dopasowanie nie będzie trudne.Zamiast tego użyj strategii ponownego formatowania lub ręcznego przeglądu

🎯 Która metoda jest dla Ciebie odpowiednia?

Jeśli akapit ma tylko normalny tekst

Zgodnie z minimalnym przykładem w tym artykule, najpierw sprawdź numer seryjny, ilość, zamówienie i typ, a następnie napisz jeden po drugim, zapisz i ponownie przeczytaj w celu akceptacji.

Jeśli akapit zawiera hiperłącza, pola lub obrazy

Bezpośrednio odrzuć automatyczną wymianę i przenieś ją do specjalnego procesu. Kod nie spłaszcza tych struktur po cichu.

Jeśli dostarczasz formalną dokumentację dwujęzyczną

Zapisz oryginalny plik jako tylko do odczytu, zapisz tłumaczenie w nowym pliku i dołącz język, wersję przetwarzania oraz zapisy ręcznej akceptacji. Brakujące czcionki, zmiany w ważnych polach, niedopasowane segmenty itp. powinny uniemożliwić automatyczne dostarczenie.

❓ Często zadawane pytania (FAQ)

1. Czy pogrubienie zostanie utracone, jeśli bezpośrednio przypiszesz wartość do tekstu akapitu?

spotkanie. Style na poziomie akapitu można zachować, ale oryginalne formatowanie na poziomie wykonania nie zostanie automatycznie zachowane.

2. Dlaczego nie przekazać każdego przebiegu tłumaczowi indywidualnie?

run jest granicą formatu, a nie granicą semantyczną. Pojedyncze tłumaczenia jedno po drugim stracą kontekst, a kolejność słów w różnych językach może również przesunąć nacisk na początek lub koniec zdania.

3. Czy pomyślne zapisanie oznacza, że format jest prawidłowy?

nie mogę. Struktury danych akceptacji plików należy po zapisaniu ponownie otworzyć; treść semantyczną i układ wizualny należy sprawdzić osobno.

4. Na co powinienem zwrócić uwagę podczas aktualizacji python-docx?

W kodzie wykorzystywane są wewnętrzne właściwości _p i _r. Musisz poprawić wersję i ponownie uruchomić test. Nie można zakładać, że struktura wewnętrzna nigdy się nie zmieni.

📝 Podsumowanie

Jest tylko jedna podstawowa zasada: traktuj format jako dane do zaakceptowania, a nie przetłumaczony bonus. Przykłady kodu w tym artykule są niezależnymi przykładami bibliotek open source i nie reprezentują implementacji bieżącego importera ani silnika układu OmniDoc.

Wypróbuj teraz: prześlij dokument, aby rozpocząć tłumaczenie, zachowując oryginalny układ

Zaktualizowano 2026-11-14