Pourquoi la traduction DOCX perd-elle le gras ? Gardez d'abord la course, puis parlez du remplacement de la section entière.

DOCX gras et italique perdus après traduction ? Le problème est probablement que toute la section est remplacée et que la piste est emportée. Cet article utilise python-docx pour enregistrer le format d'exécution un par un, puis le relire et l'accepter après l'enregistrement. S'il rencontre une structure complexe ou si le segment ne correspond pas, il refusera directement de le remplacer.

Le gras, l'italique et la taille de la police sont perdus après la traduction DOCX. La raison courante est que le contenu du paragraphe est directement remplacé par le texte entier, ce qui efface le format d'origine au niveau de l'exécution. Une fois que de nombreuses équipes ont obtenu la traduction, une réaction courante est que le format d'accentuation dans Word manque. Cet article convient aux développeurs qui utilisent python-docx pour traiter DOCX, ainsi qu'aux éditeurs qui doivent livrer des documents bilingues.

Un paragraphe semble ne contenir qu'une seule phrase dans Word, mais dans DOCX, il peut être composé de plusieurs passages : texte ordinaire, texte souligné, changements de taille de police, ainsi que des hyperliens et autres structures qui n'appartiennent pas à la liste de passages ordinaire. Après avoir lu ceci, vous saurez où se situe généralement le problème, comment réécrire les traductions étape par étape et quand vous devez simplement rejeter le remplacement automatique.

Que dois-je faire si le format DOCX est perdu après la traduction ? Conclusion en une phrase

Limitez d'abord le traitement aux seuls paragraphes de texte ordinaires, réécrivez la traduction une par une en fonction du numéro de séquence d'exécution d'origine, enregistrez-la et relisez-la pour acceptation ; s'il rencontre une structure complexe ou si le segment ne correspond pas, rejetez directement le remplacement.

votre situationPratiques recommandéesraison
Les paragraphes n'ont que du texte normalRéécrivez les traductions une par une en fonction du numéro de séquence d'exécutionLes limites de format pour chaque exécution sont préservées
Les paragraphes contiennent des hyperliens, des images, des champs, des sauts de ligne ou des tabulationsRefuser explicitement et transférer vers un processus spécialLe code n'aplatit pas tranquillement ces éléments
Le nombre ou l'ordre des segments de traduction n'est pas cohérent avec l'exécution d'origineAu lieu de vous concentrer sur les exécutions existantes, utilisez des stratégies de reformatage ou une révision manuelleLa correspondance forcée perturbera le format
Besoin de confirmer le résultat de la réécritureAprès avoir enregistré, rouvrez le fichier et acceptez-le.Évitez de vérifier uniquement les objets en mémoire
Attribuer directement une valeur à paragraph.textéviter d'utiliserLe contenu existant du paragraphe sera remplacé par un nouveau texte et le formatage au niveau de l'exécution ne sera pas automatiquement conservé.

Où est le problème : le remplacement du paragraphe entier effacera le format d'exécution

L'attribution directe d'une valeur à paragraph.text remplacera le contenu existant du paragraphe par un nouveau texte. Les styles au niveau du paragraphe peuvent être conservés, mais le formatage d'origine au niveau de l'exécution ne sera pas automatiquement conservé. Ce comportement est explicitement documenté dans API de texte python-docx.

Le résultat de la traduction semble précis, mais le format a complètement disparu. C'est probablement la raison.

Champ d'application : Le format est conservé, mais cela ne signifie pas que d'autres problèmes ont été résolus.

Les enregistrements de test de cet article proviennent de DOCX synthétisés localement, et non de captures d'écran du moteur de composition. Ce qu'il résout, c'est "un remplacement contraint sans perte de format". Il ne résout pas automatiquement les réarrangements syntaxiques entre langues, ni ne garantit que la pagination reste inchangée après la traduction.

Limitez d'abord la plage qui peut être modifiée en toute sécurité

Cet exemple condensé n'accepte que les paragraphes constitués du texte brut. Lorsqu'un paragraphe contient des hyperliens, des images, des champs, des sauts de ligne, des tabulations ou d'autres nœuds XML complexes, rejetez-le explicitement et redirigez l'appelant vers un processus spécialisé. Le code n’aplatira pas ces éléments en silence.

L'entrée de traduction n'est pas une liste arbitraire de chaînes : chaque résultat doit avoir le numéro de série de l'exécution d'origine, et le numéro, l'ordre et le type doivent tous correspondre avant de commencer la modification. La validation est effectuée avant l'écriture pour éviter de découvrir des problèmes avec les champs suivants après une mise à jour à mi-chemin.

Un test minimal qui peut être exécuté à plusieurs reprises

L'environnement de test est python-docx==1.2.0. L'anglais provient ici d'une comparaison fixe manuscrite, qui sert à vérifier la structure et ne fait pas appel à la traduction automatique.

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))

Après avoir enregistré, rouvrez translated-runs.docx puis acceptez-le pour éviter de vérifier uniquement les objets en mémoire.

Pourquoi ne pas confier chaque passage au traducteur individuellement ?

run est une limite de format, pas une limite sémantique. L'historique des modifications de Word peut également diviser un mot en plusieurs exécutions. Les traductions isolées perdront leur contexte ; l'ordre des mots dans différentes langues peut également déplacer l'accent vers le début ou la fin de la phrase.

La génération de traduction réelle doit fournir un contexte sous forme de segments complets, puis renvoyer des segments structurés validés. Lorsque le résultat renvoyé n’a pas la même longueur que l’original, ne le forcez pas dans l’exécution existante. Une stratégie de reformatage claire ou une révision manuelle est requise. L’exemple simple de cet article peut conserver seulement trois fragments, mais cela ne peut pas être généralisé à toutes les langues.

Divisez l'acceptation en trois niveaux

niveauVérifier le contenuCet article couvre-t-il
structure des donnéesExécuter la quantité, la commande, la signature en gras et la récupération après sauvegardeRemplacer cet exemple restreint
contenu sémantiqueTermes, mots négatifs, dates, montants, omissionsNon couvert ; nécessite une relecture indépendante
disposition visuelleRestauration des polices, sauts de ligne, numéros de page, débordement de tableauNon couvert ; doit être rendu et vérifié à nouveau

_p et _r sont les propriétés internes utilisées ici pour vérifier XML. Lors de la mise à niveau de python-docx, vous devez corriger la version et réexécuter le test. Vous ne pouvez pas supposer que la structure interne ne changera jamais. Lorsque vous devez traiter des tableaux, des en-têtes, des pieds de page, des zones de texte et des traces de révision, vous devez également énumérer les plages de contenu séparément, car document.paragraphs ne peut pas représenter tout le texte du document.

Condition d'arrêt avant la livraison

Structures non prises en charge, segments incompatibles, polices manquantes, modifications apportées à des champs importants : tous ces éléments devraient empêcher la livraison automatique. Enregistrez le fichier original en lecture seule, écrivez la traduction dans un nouveau fichier et joignez la langue, la version de traitement et l'enregistrement d'acceptation manuelle. C'est un meilleur indicateur de qualité que « enregistrer avec succès ».

Si vous devez passer du téléchargement de documents au processus de traduction et de révision, vous pouvez consulter Portail des produits OmniDoc. Les exemples de code présentés dans cet article sont des exemples pédagogiques de bibliothèques open source indépendantes et ne représentent pas l'implémentation de l'importateur ou du moteur de mise en page actuel d'OmniDoc. Il n’y a qu’un seul principe fondamental : traiter le format comme une donnée à accepter, plutôt que comme un bonus traduit.

📊 Comparaison de base

pratiquePrincipaux risquesSuggestions données dans l'article
Attribuer directement une valeur à paragraph.textLe formatage au niveau de l'exécution n'est pas automatiquement conservéNon utilisé pour les paragraphes qui doivent conserver la mise en forme
Exécutez les traductions isolées une par uneLe contexte est perdu, les changements dans l'ordre des mots peuvent déplacer l'accentFournir du contexte sous forme de segments complets
Une fois le segment complet traduit, appuyez sur Exécuter pour le vérifier et le réécrire.Si le résultat renvoyé n’est pas de longueur égale à l’exécution originale, il ne peut pas être difficile de correspondre.Utilisez plutôt une stratégie de reformatage ou une révision manuelle

🎯 Quelle méthode vous convient ?

Si votre paragraphe ne contient que du texte normal

Selon l'exemple minimal de cet article, vérifiez d'abord le numéro de série, la quantité, la commande et le type, puis réécrivez un par un, enregistrez et relisez pour acceptation.

Si votre paragraphe contient des hyperliens, des champs ou des images

Rejetez directement le remplacement automatique et transférez-le vers un processus spécial. Le code n’aplatit pas discrètement ces structures.

Si vous fournissez une documentation formelle bilingue

Enregistrez le fichier original en lecture seule, écrivez la traduction dans un nouveau fichier et joignez les enregistrements de langue, de version de traitement et d'acceptation manuelle. Les polices manquantes, les modifications apportées aux champs importants, les segments incompatibles, etc. devraient tous empêcher la livraison automatique.

❓ Questions fréquemment posées (FAQ)

1. L'audace sera-t-elle perdue si vous attribuez directement une valeur à paragraphe.text ?

réunion. Les styles au niveau du paragraphe peuvent être conservés, mais le formatage d'origine au niveau de l'exécution ne sera pas automatiquement conservé.

2. Pourquoi ne pas confier chaque passage au traducteur individuellement ?

run est une limite de format plutôt qu'une limite sémantique. Une traduction isolée une par une perdra son contexte, et l'ordre des mots des différentes langues peut également déplacer l'accent vers le début ou la fin de la phrase.

3. L'enregistrement réussi signifie-t-il que le format est correct ?

ne peut pas. Les structures de données d'acceptation de fichier doivent être rouvertes après l'enregistrement ; le contenu sémantique et la présentation visuelle doivent être vérifiés séparément.

4. À quoi dois-je faire attention lors de la mise à niveau de python-docx ?

Le code utilise les propriétés internes de _p et _r. Vous devez corriger la version et réexécuter le test. Vous ne pouvez pas supposer que la structure interne ne changera jamais.

📝Résumé

Il n’y a qu’un seul principe fondamental : traiter le format comme une donnée à accepter, plutôt que comme un bonus traduit. Les exemples de code présentés dans cet article sont des exemples pédagogiques de bibliothèques open source indépendantes et ne représentent pas l'implémentation de l'importateur ou du moteur de mise en page actuel d'OmniDoc.

Essayez-le maintenant : téléchargez le document pour lancer la traduction, en conservant la mise en page d'origine.

Mis à jour le 2026-11-14