Pourquoi le texte traduit devient des carrés
Vous avez traduit le jeu, l'export s'est terminé sans erreur, et la boîte de dialogue est pleine de □□□. Ce n'est presque jamais un problème de traduction — c'est un problème de police, et il se corrige autrement que les deux pannes qu'on confond avec lui. Voici comment distinguer un glyphe manquant, un caractère supprimé et du mojibake, et comment corriger chacun dans Unity, TextMeshPro, Ren'Py et les outils à l'exécution.
L'export est terminé, le jeu s'est lancé, et chaque ligne de dialogue est une rangée de rectangles vides identiques. Rien n'est faux dans la traduction. Le texte du fichier est exactement ce que le fournisseur a renvoyé, et si vous ouvrez ce fichier dans un éditeur de texte, il se lit correctement. Ce qui a échoué, c'est la dernière étape de la chaîne : la police que le jeu remet au moteur de rendu n'a aucun dessin pour ces caractères.
Ce qu'est réellement un carré tofu
Une police est une table de correspondance entre un point de code Unicode et une forme. Quand on demande au moteur de rendu de dessiner un point de code que la police ne contient pas, il substitue le glyphe manquant de la police — le plus souvent un rectangle vide ou barré, appelé formellement .notdef et connu partout ailleurs comme un carré tofu. Un carré égale un caractère que la police n'a pas su dessiner. C'est tout le mécanisme.
Deux conséquences en découlent, utiles au diagnostic. D'abord, le nombre de carrés correspond au nombre de caractères : cinq caractères thaïs produisent cinq carrés, pas une suite plus courte de charabia. Ensuite, la chaîne est intacte en mémoire — le jeu peut toujours la mesurer, la comparer, la sauvegarder et la recharger. Seuls les pixels manquent. C'est pourquoi un menu traduit peut être totalement illisible et se naviguer correctement.
Trois symptômes, trois problèmes différents
L'essentiel de la confusion autour de "ma traduction est cassée" vient de gens qui appliquent à l'un le correctif d'un autre. Lisez la forme du dégât avant de changer quoi que ce soit.
- Des carrés □□□ — les caractères sont corrects, la police ne sait pas les dessiner. Corrigez la police.
- Des ???? — les caractères ont disparu. Quelque chose a réencodé la chaîne dans un jeu de caractères plus étroit et a remplacé tout ce qu'il ne pouvait pas représenter. Aucune police ne les ramènera. Corrigez l'encodage, ou choisissez une langue cible que le format peut contenir.
- Du latin charabia comme
テã‚スト, ouテキストaffiché enテキスト— du mojibake. Les octets sont bons, le décodeur est mauvais : un texte écrit dans un encodage est lu dans un autre. Corrigez l'encodage utilisé à la lecture.
Un séparateur rapide : les carrés comme le mojibake laissent un nombre d'octets à peu près proportionnel à l'original, mais le mojibake produit des caractères parasites visibles et variés tandis que le tofu produit des rectangles identiques et uniformes. Uniforme veut dire "police". Varié veut dire "encodage".
Carrés : un glyphe manquant
Le jeu a été livré avec une police couvrant seulement ce dont il avait besoin. Rien n'est cassé dans la chaîne de traitement — vous avez demandé un point de code que l'auteur n'a jamais inclus. Le correctif consiste toujours à donner au moteur de rendu une police qui possède le glyphe, soit en remplaçant la police, soit en ajoutant un repli que le moteur consulte quand la police principale ne trouve rien.
Points d'interrogation : les caractères ont été perdus
Quand une chaîne doit être réécrite dans un format qui stocke le texte dans un encodage historique sur un ou deux octets, chaque caractère hors de cet encodage doit devenir quelque chose. Par convention, ce quelque chose est ?. Shift-JIS et cp932 peuvent contenir le japonais, l'ASCII et pas grand-chose d'autre ; un champ strictement ASCII ne peut contenir ni grec, ni cyrillique, ni thaï, ni CJK. C'est une propriété du format de fichier, pas de la police, et cela se produit à l'export — quand le jeu lit le fichier, l'information a déjà disparu.
RuneTranslate a un moteur où cette limite est réelle, et elle est annoncée plutôt que cachée : YU-RIS réencode ses chaînes en cp932, ce qui convient à l'anglais et aux autres sorties latines mais livre le thaï en ?. Les cibles non cp932 sur ce moteur demandent un bidouillage de police qui n'existe pas encore.
Latin charabia : le mojibake
Du texte japonais écrit en Shift-JIS puis lu en UTF-8 (ou l'inverse) produit de longues suites de lettres latines accentuées et de caractères de tracé de cadres. Cela apparaît quand un outil écrit un fichier dans le mauvais encodage, ou quand le chargeur d'un jeu suppose un encodage que votre export n'a pas utilisé. Le correctif est d'écrire le fichier dans l'encodage attendu par le moteur — jamais de changer la police, ce qui ne changera rien.
Pourquoi le CJK et le thaï sont les plus touchés
Le latin demande une centaine de glyphes environ. Le japonais en demande plusieurs milliers, le chinois davantage. Les fichiers de polices sont volumineux, et les jeux embarquent la plus petite police qui couvre leur propre écriture : la couverture dont vous héritez dépend donc entièrement de la langue pour laquelle le jeu a été conçu.
- Un jeu conçu pour le japonais porte généralement les kana, les kanji courants et l'ASCII. Traduisez-le en russe, en grec, en thaï ou en coréen et chaque caractère non ASCII tombe.
- Un jeu conçu pour l'anglais ne porte généralement que du latin — donc le japonais, le chinois, le coréen, le thaï, le grec et le cyrillique échouent tous d'un coup.
- Le thaï est le pire cas en pratique : il est absent de toutes les polices de jeu courantes, et il demande en plus des voyelles et des marques de ton combinantes placées au-dessus et en dessous du caractère de base, si bien qu'une police qui a techniquement les points de code peut quand même mal le rendre.
- Le latin n'est pas automatiquement sûr. Le polonais, le tchèque, le hongrois, le turc, le vietnamien et le roumain utilisent des caractères latins étendus qu'une police conçue pour l'anglais ou le japonais omet souvent. RuneTranslate embarque une police plus large pour exactement ces cibles sur Ren'Py, parce que "le latin, ça passe" s'est révélé faux.
Unity et TextMeshPro en particulier
Unity a deux systèmes de texte et ils échouent différemment. Le Text uGUI historique utilise un objet Font. TextMeshPro — qu'utilisent la plupart des jeux modernes — n'utilise aucun fichier de police à l'exécution. Il utilise un TMP font asset : un atlas de textures d'images de glyphes pré-rendues, plus une table associant les points de code à des positions dans cet atlas.
C'est pourquoi un TMP font asset a un jeu de caractères figé. Quand le développeur l'a généré, il a choisi une plage de caractères — en général juste la langue qu'il livrait — et TMP a cuit exactement ces glyphes dans l'atlas. Un font asset statique ne pourra jamais rendre quoi que ce soit hors de ce jeu, quoi que vous lui donniez. Un font asset dynamique garde une référence au fichier de police source et peut matricer de nouveaux glyphes à la demande, ce qui est le seul mode capable de s'étendre à une langue que le développeur n'avait pas prévue.
L'échappatoire de TMP est la liste de repli. Chaque font asset a une liste m_fallbackFontAssets, et les TMP Settings ont une liste de repli globale ; quand l'asset principal n'a pas de glyphe pour un point de code, TMP parcourt ces listes pour en trouver un qui l'a. C'est le bon endroit où intervenir, parce que cela laisse la police du jeu responsable de tout ce qu'elle sait déjà dessiner — l'interface garde l'allure voulue et seuls les caractères qu'elle ne gère pas viennent d'ailleurs.
Corriger avec un outil à l'exécution
XUnity.AutoTranslator accroche le jeu pendant qu'il tourne et peut changer les polices depuis son fichier de configuration. Les réglages concernés, sous [Behaviour] :
OverrideFont— remplace la police utilisée par les composantsTextde l'interface Unity historique. Prend le nom d'une police que le jeu ou le système peut résoudre.OverrideFontTextMeshPro— remplace purement et simplement le TMP font asset. Pointez-le vers un fichier AssetBundle de police TMP, ou vers le nom d'un asset que le jeu possède déjà.FallbackFontTextMeshPro— le plus sûr des deux : ajoute une police que TMP ne consulte que pour les glyphes absents de l'asset du jeu, en laissant la typographie d'origine partout ailleurs.- tmp_font_assetbundles — la collection communautaire d'AssetBundles de polices TMP prêts à l'emploi vers lesquels
OverrideFontTextMeshProetFallbackFontTextMeshPropointent d'ordinaire. Ils sont construits par version d'Unity, et un bundle construit pour une version d'Unity différente de celle du jeu ne se chargera pas — faire correspondre la version est l'étape qu'on oublie.
Un outil à l'exécution est propre à une machine et à une configuration : il corrige le jeu sur le PC où il est installé, et toute autre personne qui lance ce build doit refaire la même installation. RuneTranslate sait lire et écrire le fichier _AutoGeneratedTranslations.txt du plugin, donc un projet qui l'utilise déjà n'est pas une impasse — voir la comparaison pour savoir où chaque approche convient.
Corriger au niveau des fichiers
RuneTranslate prend la route du repli directement dans les données du jeu. À l'export Unity, il localise les TMP Settings du jeu, un font asset utilisable comme modèle et une police, puis construit un nouveau TMP font asset en mode Dynamic autour d'une police embarquée qui couvre l'écriture cible, et l'ajoute à la liste de repli. Les entrées de repli existantes ne sont pas touchées, et la police du jeu reste principale — un jeu japonais traduit en thaï garde donc son style d'origine pour tout ce qui est latin et tire les glyphes thaïs de l'asset injecté.
Deux remarques honnêtes là-dessus. Cela demande que les TMP Settings, un modèle de font asset utilisable et un Font existent dans le même conteneur des ressources du jeu ; un jeu qui les dispose autrement peut passer à côté. Et quand l'injection est ignorée, l'export le dit dans ses avertissements au lieu de finir au vert — un export qui s'affiche en carrés ne doit pas ressembler à un export qui fonctionne. Si vous voyez cet avertissement, la route de l'outil à l'exécution ci-dessus est le plan de repli.
Ren'Py obtient le même résultat par un autre mécanisme, puisque Ren'Py n'a pas de TMP : RuneTranslate peut embarquer une police CJK ou non latine dans le build exporté et l'enregistrer via le config.font_replacement_map de Ren'Py, pour que le moteur la substitue partout où la police du jeu serait prise en défaut.
Liste de contrôle
- Regardez le dégât. Rectangles uniformes, caractères
?ou lettres en charabia — décidez lequel des trois vous avez avant de toucher à quoi que ce soit. - Si ce sont des
?, ouvrez le fichier exporté. Si les points d'interrogation sont dans le fichier, les caractères ont été perdus à l'écriture et aucune police n'y changera rien ; vérifiez si l'encodage de chaînes du moteur peut contenir votre langue cible. - Si ce sont des lettres en charabia, vérifiez l'encodage que le moteur attend pour ce fichier plutôt que la police.
- Si ce sont des carrés, confirmez que le contenu du fichier est correct — il l'est presque toujours — et traitez cela comme un travail de police.
- Sur Unity, préférez ajouter un repli plutôt que remplacer la police du jeu. Un remplacement change l'allure de toutes les chaînes, y compris celles qui s'affichaient bien.
- Si vous utilisez un AssetBundle de police TMP, faites-le correspondre à la version d'Unity du jeu.
- Réexportez et vérifiez les caractères précis qui échouaient, pas seulement la première ligne de dialogue. Le latin étendu et les marques thaïes survivent souvent à un contrôle rapide et échouent ailleurs.
Où aller ensuite
Pour le déroulé Unity complet — quel texte Unity expose réellement, et ce qui reste hors de portée — lisez comment traduire un jeu Unity et la page du moteur Unity. Le texte incrusté dans l'illustration plutôt que dans les données est un problème à part, avec un outil à part : voir la traduction d'images. Et la FAQ couvre le reste des surprises courantes du premier essai.
RuneTranslate est gratuit à l'usage, avec tous les moteurs et tous les fournisseurs débloqués, dont trois qui ne demandent aucune clé API. Il analyse les propres fichiers du jeu et exporte un build traduit jouable qui vous reste. Téléchargez-le ou parcourez les moteurs pris en charge.
Prêt à essayer RuneTranslate ?
L'offre gratuite débloque tous les moteurs et tous les fournisseurs de traduction. Supporter (3 $/mois) débloque la vitesse maximale.
Télécharger pour Windows
