Чому переклад DOCX втрачає жирний шрифт? Спочатку тримайте пробіг, а потім говорите про заміну всієї секції.
Жирний шрифт DOCX і курсив втрачені після перекладу? Проблема напевно в тому, що замінюється вся секція і змивається прогін. Ця стаття використовує python-docx для збереження формату виконання один за одним, а також перечитання та прийняття його після збереження. Якщо він зустріне складну структуру або сегмент не збігається, він прямо відмовиться замінити його.
— Тестове середовище — python-docx 1.2.0. Після збереження знову відкрийте файл для прийняття та перевірте, чи збережено номер серії та жирний шрифт.
- Затвердження структури даних не означає, що семантика є точною або макет залишається незмінним. Термінологію, номери та сторінку ще потрібно переглянути вручну або за допомогою рендерингу.
Жирний шрифт, курсив і розмір шрифту втрачаються після перекладу DOCX. Поширеною причиною є те, що вміст абзацу безпосередньо замінюється на весь текст, що змиває вихідний формат виконання. Коли багато команд отримують переклад, типова реакція полягає в тому, що в Word відсутній формат виділення. Ця стаття підходить для розробників, які використовують python-docx для обробки DOCX, а також для редакторів, яким потрібно надавати двомовні документи.
Здається, абзац у Word має лише одне речення, але в DOCX він може складатися з кількох прогонів: звичайного тексту, виділеного тексту, зміни розміру шрифту, а також гіперпосилань та інших структур, які не належать до звичайного списку прогонів. Прочитавши це, ви дізнаєтесь, у чому зазвичай криється проблема, як записувати переклади, які виконуються, і коли вам слід просто відхилити автоматичну заміну.
Що робити, якщо формат DOCX втрачається після перекладу? Висновок одним реченням
Спочатку обмежте обробку лише абзацами звичайного тексту, запишіть переклад один за одним відповідно до вихідного порядкового номера, збережіть його та перечитайте для прийняття; якщо він зустрічає складну структуру або сегмент не збігається, безпосередньо відхилити заміну.
| ваша ситуація | Рекомендовані практики | причина |
|---|---|---|
| Абзаци мають лише звичайний пробіг тексту | Запишіть переклади один за одним відповідно до порядкового номера виконання | Межі формату для кожного запуску зберігаються |
| Абзаци містять гіперпосилання, зображення, поля, розриви рядків або вкладки | Чітко відмовити та перевести на спецпроцес | Код тихо не згладжує ці елементи |
| Кількість або порядок сегментів перекладу не відповідає вихідному циклу | Замість того, щоб переглядати наявні тиражі, використовуйте стратегії переформатування або перегляд вручну | Примусове листування порушить формат |
| Необхідно підтвердити результат запису | Після збереження знову відкрийте файл і прийміть його. | Уникайте перевірки лише об’єктів у пам’яті |
Безпосередньо призначити значення paragraph.text | уникати використання | Існуючий вміст абзацу буде замінено новим текстом, і форматування на рівні виконання не буде автоматично збережено. |
У чому проблема: заміна всього абзацу змиє формат виконання
Безпосереднє призначення значення paragraph.text замінить існуючий вміст абзацу новим текстом. Стилі на рівні абзаців можна зберегти, але вихідне форматування на рівні виконання не буде автоматично збережено. Ця поведінка чітко задокументована в текстовий API python-docx.
Результат перекладу виглядає точним, але формат повністю зник. Можливо, це причина.
Сфера застосування: Формат збережено, але це не означає, що інші проблеми вирішено.
Тестові записи цієї статті походять із локально синтезованого DOCX, а не зі скріншотів механізму верстки. Це вирішує "обмежену заміну без втрати формату". Він не вирішує автоматично зміни міжмовного синтаксису, а також не забезпечує збереження сторінок після перекладу.
Спочатку обмежте діапазон, який можна безпечно змінити
Цей стислий приклад приймає лише абзаци, що складаються з звичайного тексту. Якщо абзац містить гіперпосилання, зображення, поля, розриви рядків, вкладки або інші складні вузли XML, явно відхиліть його та перенаправте абонента до спеціалізованого процесу. Код не зрівняє ці елементи мовчки.
Вхідні дані перекладу не є довільним списком рядків: кожен результат повинен мати порядковий номер оригінального циклу, а номер, порядок і тип мають збігатися перед початком модифікації. Перевірка розміщується перед записом, щоб уникнути виявлення проблем із наступними полями після оновлення наполовину.
Мінімальний тест, який можна виконувати багаторазово
Тестове середовище – python-docx==1.2.0. Англійська мова тут походить від рукописного фіксованого порівняння, яке використовується для перевірки структури та не вимагає машинного перекладу.
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))
Після збереження знову відкрийте translated-runs.docx, а потім прийміть його, щоб уникнути перевірки лише об’єктів у пам’яті.
Чому б не надати перекладачу кожен запуск окремо?
run — це межа формату, а не семантична межа. Журнал редагування Word також може розділяти слово на кілька циклів. Ізольовані переклади втратять контекст; порядок слів різних мов також може переносити наголос на початок або кінець речення.
Фактична генерація перекладу повинна надавати контекст як повні сегменти, а потім повертати підтверджені структуровані сегменти. Якщо повернутий результат не збігається з вихідною довжиною, не примушуйте його до наявного циклу. Потрібна чітка стратегія переформатування або перевірка вручну. Простий приклад у цій статті може містити лише три фрагменти, але це не можна узагальнити для всіх мов.
Розділіть прийняття на три рівні
| рівень | Перевірте вміст | Чи охоплює ця стаття |
|---|---|---|
| структура даних | Кількість виконання, порядок, жирний підпис і відновлення після збереження | Перевизначити цей обмежений приклад |
| смислове наповнення | Терміни, заперечні слова, дати, суми, пропуски | Не покритий; потребує самостійної коректури |
| візуальний макет | Відкат шрифту, розриви рядків, номери сторінок, переповнення таблиці | Не покритий; потрібно відобразити та перевірити ще раз |
_p і _r — це внутрішні властивості, які використовуються тут для перевірки XML. Під час оновлення python-docx вам потрібно виправити версію та повторно запустити тест. Не можна вважати, що внутрішня структура ніколи не зміниться. Коли вам потрібно обробити таблиці, верхні та нижні колонтитули, текстові поля та трасування редакцій, ви також повинні окремо перерахувати діапазони вмісту, оскільки document.paragraphs не може представити весь текст у документі.
Умова зупинки перед доставкою
Непідтримувані структури, невідповідні сегменти, відсутні шрифти, зміни важливих полів – будь-який із них має перешкоджати автоматичній доставці. Збережіть оригінальний файл як доступний лише для читання, запишіть переклад у новий файл і додайте мову, версію обробки та запис про прийняття вручну. Це кращий показник якості, ніж «вдало зберегти».
Якщо вам потрібно перейти від завантаження документів до процесу перекладу та перевірки, ви можете перевірити Портал продуктів OmniDoc. Приклади коду в цій статті є незалежними навчальними зразками бібліотеки з відкритим вихідним кодом і не представляють реалізацію поточного імпортера чи механізму макета OmniDoc. Існує лише один основний принцип: ставтеся до формату як до прийнятних даних, а не до перекладеного бонусу.
📊 Основне порівняння
| практика | Основні ризики | Рекомендації, наведені в статті |
|---|---|---|
Безпосередньо призначити значення paragraph.text | Форматування на рівні виконання не зберігається автоматично | Не використовується для абзаців, які потребують збереження форматування |
| Виконуйте окремі переклади один за одним | Контекст втрачається, зміна порядку слів може перемістити наголос | Надайте контекст як повні сегменти |
| Після того, як весь сегмент буде перекладено, натисніть «Виконати», щоб перевірити та записати його назад. | Якщо повернений результат не має такої ж довжини, як початковий прогін, це може бути важко відповідати. | Замість цього скористайтеся стратегією переформатування або перевіркою вручну |
🎯 Який спосіб вам підходить?
Якщо ваш абзац містить лише звичайний текст
Згідно з мінімальним прикладом у цій статті, спочатку перевірте серійний номер, кількість, порядок і тип, потім перепишіть один за одним, збережіть і перечитайте для прийняття.
Якщо ваш абзац містить гіперпосилання, поля або зображення
Безпосередньо відмовитися від автоматичної заміни та перевести її на спеціальний процес. Код тихо не згладжує ці структури.
Якщо ви надаєте офіційну двомовну документацію
Збережіть оригінальний файл як доступний лише для читання, запишіть переклад у новий файл і додайте мову, версію обробки та записи про прийняття вручну. Відсутні шрифти, зміни у важливих полях, невідповідні сегменти тощо повинні перешкоджати автоматичній доставці.
❓ Часті запитання (FAQ)
1. Чи буде втрачено жирність, якщо ви безпосередньо призначите значення абзацу.тексту?
засідання. Стилі на рівні абзаців можна зберегти, але вихідне форматування на рівні виконання не буде автоматично збережено.
2. Чому б не надати перекладачу кожен запуск окремо?
run є межею формату, а не семантичною межею. Ізольований переклад один за одним втрачає контекст, а порядок слів різних мов також може перенести наголос на початок або кінець речення.
3. Чи означає успішне збереження формату?
не можна. Структури даних прийняття файлів слід знову відкрити після збереження; смислове наповнення та візуальне оформлення потрібно перевіряти окремо.
4. На що слід звернути увагу під час оновлення python-docx?
Код використовує внутрішні властивості _p і _r. Потрібно виправити версію та повторно запустити тест. Не можна вважати, що внутрішня структура ніколи не зміниться.
📝 Підсумок
Існує лише один основний принцип: ставтеся до формату як до прийнятних даних, а не до перекладеного бонусу. Приклади коду в цій статті є незалежними навчальними зразками бібліотеки з відкритим вихідним кодом і не представляють реалізацію поточного імпортера чи механізму макета OmniDoc.
Спробуйте зараз: завантажте документ, щоб розпочати переклад, зберігаючи вихідний макет


