DOCX 翻訳で太字が失われるのはなぜですか?まずは走行を続けてから、セクション全体を交換することについて話し合います。
DOCX の太字と斜体は翻訳後に失われますか?問題はセクションごと入れ替わり、ランが流されてしまうことだろう。この記事では、python-docx を使用して実行形式を 1 つずつ保存し、保存後に再読み込みして受け入れます。複雑な構造に遭遇した場合、またはセグメントが一致しない場合は、その置換を直接拒否します。
・テスト環境はpython-docx 1.2.0です。保存後、ファイルを再度開いて承認し、実行番号と太字が保持されているかどうかを確認します。
- データ構造の承認は、セマンティクスが正確であること、またはレイアウトが変更されていないことを意味するものではありません。用語、番号、ページングは依然として手動またはレンダリングを使用して確認する必要があります。
DOCX の翻訳後、太字、斜体、フォント サイズが失われます。一般的な理由は、段落のコンテンツがテキスト全体に直接置き換えられ、元のランレベル形式が洗い流されてしまうことです。多くのチームが翻訳を完了した後、よくある反応は、Word の強調形式が欠落しているというものです。この記事は、Python-docx を使用して DOCX を処理する開発者、およびバイリンガル ドキュメントを提供する必要がある編集者に適しています。
Word では、段落は 1 つの文だけであるように見えますが、DOCX では、通常のテキスト、強調されたテキスト、フォント サイズの変更、ハイパーリンク、および通常の段落リストに属さないその他の構造など、複数の段落で構成されている場合があります。これを読むと、問題が通常どこにあるのか、実行ごとに翻訳を書き戻す方法、および自動置換を拒否する必要がある場合がわかります。
翻訳後に DOCX の形式が失われた場合はどうすればよいですか?一文の結論
まず、処理を通常のテキスト実行段落のみに制限し、元の実行シーケンス番号に従って翻訳を 1 つずつ書き戻し、保存して承認のために再読み込みします。複雑な構造に遭遇した場合、またはセグメントが一致しない場合は、置換を直接拒否します。
| あなたの状況 | 推奨される実践方法 | 理由 |
|---|---|---|
| 段落には通常のテキストのみが続きます | 実行シーケンス番号に従って、翻訳を 1 つずつ書き戻します。 | 各実行のフォーマット境界は保持されます |
| 段落にはハイパーリンク、画像、フィールド、改行、またはタブが含まれています | 明示的に拒否し、特別なプロセスに移す | コードはこれらの要素を静かにフラット化するわけではありません |
| 翻訳セグメントの数または順序が元の実行と一致しません。 | 既存の実行に無理強いするのではなく、再フォーマット戦略または手動レビューを使用します。 | 強制的な通信はフォーマットを破壊します |
| ライトバック結果を確認する必要がある | 保存後、ファイルを再度開いて受け入れます。 | メモリ内のオブジェクトのみをチェックすることを避ける |
paragraph.textに値を直接代入 | 使用を避ける | 段落の既存のコンテンツは新しいテキストに置き換えられ、実行レベルの書式設定は自動的には保持されません。 |
問題はどこにありますか: 段落全体を置き換えると実行形式が無効になります
paragraph.text に値を直接割り当てると、段落の既存のコンテンツが新しいテキストに置き換えられます。段落レベルのスタイルは保持できますが、元のランレベルの書式設定は自動的には保持されません。この動作はpython-docx テキスト APIに明示的に文書化されています。
翻訳結果は正確に見えますが、形式が完全に失われています。おそらくこれが理由です。
適用範囲: 形式は保持されますが、その他の問題が解決されるわけではありません。
この記事のテスト レコードは、植字エンジンのスクリーンショットではなく、ローカルで合成された 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 の編集履歴により、単語が複数の実行に分割される場合もあります。単独の翻訳では文脈が失われます。異なる言語の語順によって、強調が文の先頭または末尾に移動する場合もあります。
実際の翻訳生成では、コンテキストを完全なセグメントとして提供し、検証された構造化セグメントを返す必要があります。返された結果が元の長さと同じでない場合は、それを既存の実行に強制的に組み込まないでください。明確な再フォーマット戦略または手動レビューが必要です。この記事の簡単な例では 3 つのフラグメントを保持するだけですが、これをすべての言語に一般化できるわけではありません。
受け入れを 3 つのレベルに分割する
| レベル | 内容を確認してください | この記事でカバーされていますか? |
|---|---|---|
| データ構造 | 保存後、実行、番号、注文、太字署名、復元 | この制限された例をカバーします |
| 意味的内容 | 用語、否定語、日付、金額、省略 | カバーされていません。 独立した校正が必要です |
| 視覚的配置 | フォントの元に戻し、行改行、ページ番号、テーブルオーバーフロー | カバーされていません。 レンダリングはもう一度チェックする必要があります |
ここでXMLをチェックするために使われる内部プロパティは_pと_rです。 python-docxをアップグレードする際は、バージョンを修正してテストを再度実行する必要があります。内部構造が全く変わらないとは限りません。 表、ヘッダー、フッター、テキストボックス、リビジョントレースを扱う際は、document.paragraphsが文書内のすべてのテキストを表現できないため、内容範囲を別々に列挙してください。
交付前的停止条件
サポートされていない構造、セグメントの不一致、フォントの欠落、重要なフィールドの変更など、いずれも自動配信をブロックすべきです。 元のファイルを読み取り専用で保存し、新しいファイルに翻訳を書き込み、言語、処理版、手動の承認記録を添付します。これは「成功裏に保存する」よりも品質をよく表しています。
もし文書のアップロードから翻訳とレビューのプロセスに移行する必要があるなら、OmniDoc製品エントリーをチェックしてみてください。 この記事のコード例は独立したオープンソースライブラリのチュートリアルであり、OmniDocのインポーターやレイアウトエンジンの現在の実装を反映するものではありません。 基本原則はシンプルです。フォーマットを受け入れるべきデータとして扱い、翻訳された付属物として扱うこと。
📊 コア比較
| 方法 | 主なリスク | 記事で示されたアドバイス |
|---|---|---|
paragraph.textに直接値を割り当ててください | ランレベルのフォーマットは自動的に保持されません | フォーマットが必要な段落には使われていません |
| 孤立翻訳を一つずつ実行します | 文脈の喪失や語順の変更により強調セクションがずれることがあります | 完全な文で文脈を提供すること |
| 文と段落を全文翻訳した後、実行ボタンを押して確認し、書き返します | 返された結果が元のランの長さと等しくない場合、手動でマッチングすることはできません | フォーマット再調整戦略や手動レビューへの切り替え |
🎯 どの方法があなたに合いますか?
段落が通常のテキストだけなら実行してください
この記事の最小の例によると、まずシリアル番号、数量、順序、タイプを確認し、各項目を書き戻し、保存し、再度読み込みを行って受け入れます。
段落にハイパーリンク、ドメイン、画像が含まれている場合
自動交換を直接拒否し、専用の処理プロセスに切り替えてください。 コードはこれらの構造を静かに平坦化するものではありません。
もしあなたが正式なバイリンガル文書を届けている場合
元のファイルを読み取り専用で保存し、新しいファイルに翻訳を書き込み、言語、処理バージョン、手動受理レコードを添付します。 フォントの欠落、重要なフィールドの変更、不一致のセグメントなどの問題はすべて自動配信からブロックすべきです。
❓ よくある質問(FAQ)
1. 直接給 paragraph.text 赋值会丢加粗吗?
はい。 段落レベルのスタイルは保持できますが、元のランレベルの形式は自動的に保持されません。
2. なぜ各ランを別々に翻訳者に割り当てないのでしょうか?
runはフォーマットの境界であり、意味的な境界ではありません。 翻訳を一つずつ切り離すと文脈を失い、異なる言語の語順が文の始まりや終わりに重点が変わることがあります。
3. セーブが成功したということは、フォーマットが正しいということでしょうか?
いいえ。 保存後は、データ構造を受け入れるためにファイルを再度開く必要があります。 意味的な内容やビジュアルレイアウトも別途確認する必要があります。
4. python-docxのアップグレード時に注意すべき点は何ですか?
コードは_pと_rの内部特性を利用しているため、バージョンを修正してテストを再度実行する必要があります。内部構造が全く変わらないとは限りません。
📝 概要
基本原則はシンプルです。フォーマットを受け入れるべきデータとして扱い、翻訳された付属物として扱うこと。 この記事のコード例は独立したオープンソースライブラリのチュートリアルであり、OmniDocのインポーターやレイアウトエンジンの現在の実装を反映するものではありません。


