Détails de la composition japonaise

Une ligne de japonais ne comporte aucune espace entre les mots, et pourtant un paragraphe japonais composé par LaTeX s'aligne parfaitement sur les deux marges. Le secret tient dans une colle nommée \kanjiskip, dont la largeur naturelle est nulle mais qui s'étire : mesurée sous jsarticle en 10pt, elle vaut 0.0pt plus 0.92473pt minus 0.0924pt. La plupart du temps elle n'existe pas ; dès qu'une ligne doit être resserrée ou élargie, il en sourd un peu entre chaque paire de caractères. Ce que la composition occidentale confie à l'espace-mot, le japonais le répartit finement sur chaque jointure de caractères de la ligne. Cette page parcourt cette mécanique — la colle japonaise, les interdictions de coupure (kinsoku), l'écriture verticale et les ruby —, l'appareillage que TeX a dû se construire pour le japonais et qui n'a pas d'équivalent occidental, chiffres mesurés à l'appui.

\kanjiskip et \xkanjiskip : l'espace que vous n'avez pas tapée

La composition japonaise insère automatiquement deux colles différentes. \kanjiskip se place entre deux caractères japonais ; \xkanjiskip se place à la frontière entre japonais et latin. La différence décisive est leur largeur naturelle : sous jsarticle en 10pt, \kanjiskip vaut 0.0pt plus 0.92473pt minus 0.0924pt et \xkanjiskip 2.5pt plus 1.49994pt minus 0.59998pt. La première est nulle par défaut et ne s'étire qu'en cas de nécessité — d'où une grille de caractères intacte et des lignes malgré tout justifiées. La seconde mesure toujours 2,5pt — d'où l'écart qui s'ouvre de part et d'autre du mot latin dans 日本語 and abc, sans que personne ait tapé d'espace. Une fois ces deux colles distinguées, la plupart des discussions sur les espacements japonais se ramènent à « de laquelle parle-t-on ? ».

latex
% measure it yourself: put this in the body and read the .log
\typeout{kanjiskip  = \the\kanjiskip}
\typeout{xkanjiskip = \the\xkanjiskip}
\sbox0{日本語テキスト}\typeout{plain = \the\wd0}
\sbox0{日本語ABCテキスト}\typeout{mixed = \the\wd0}
\sbox0{ABC}\typeout{latin = \the\wd0}

La mesure confirme tout. Sous jsarticle en 10pt, 日本語テキスト fait 64,72778pt de large et ABC 21,8056pt. Additionnés, on attend 86,53338pt ; or 日本語ABCテキスト mesure 91,53339pt. L'écart de 5,00001pt correspond à deux fois 2,5pt de \xkanjiskip, insérés entre 語 et A puis entre C et テ. Preuve : après \noautoxspacing, la même boîte revient à 86,53339pt, exactement la somme. Et encore : 日本語 mesure 27,74048pt, précisément le triple des 9,24683pt d'un kanji isolé — \kanjiskip se glisse entre ces caractères sans rien ajouter à la largeur, puisque sa taille naturelle est nulle.

ParamètreCôté pTeXCôté LuaTeX-jaValeur par défaut dans jsarticle en 10pt
kanjiskip\kanjiskip=...\ltjsetparameter{kanjiskip=...}0.0pt plus 0.92473pt minus 0.0924pt
xkanjiskip\xkanjiskip=...\ltjsetparameter{xkanjiskip=...}2.5pt plus 1.49994pt minus 0.59998pt
prebreakpenalty\prebreakpenalty suivi d'un caractère\ltjsetparameter{prebreakpenalty={...}}10000 pour ponctuation et parenthèses fermantes
postbreakpenalty\postbreakpenalty suivi d'un caractère\ltjsetparameter{postbreakpenalty={...}}10000 pour les parenthèses ouvrantes
jcharwidowpenalty\jcharwidowpenalty=...\ltjsetparameter{jcharwidowpenalty=...}500
inhibitxspcode\inhibitxspcode suivi d'un caractère japonais\ltjsetparameter{jaxspmode={...}}2 sur la parenthèse ouvrante pleine chasse, 1 sur les fermantes et 。, 3 sur les kanji
xspcode\xspcode suivi d'un caractère latin\ltjsetparameter{alxspmode={...}}3 pour A, 2 pour ., 1 pour (

Ces valeurs par défaut varient selon la classe, et c'est ce qui donne à une page son caractère. La même mesure sous jlreq donne 0.0pt plus 2.5pt pour \kanjiskip et 2.5pt plus 2.5pt minus 1.25pt pour \xkanjiskip. Comme un kanji en jlreq à 10pt fait exactement 10pt, l'étirement représente un quart de cadratin — soit deux fois et demie le dixième que concèdent les jsclasses. jlreq est donc conçue pour justifier en ouvrant nettement plus l'approche, et le comportement en fin de ligne change visiblement. Si un document « ne rend plus pareil » après un changement de classe, comparez d'abord ces deux valeurs avec \typeout.

Pourquoi les parenthèses pleine chasse ne reçoivent pas d'espace : chasses et \inhibitxspcode

Parce que la parenthèse elle-même déclare : « pas d'espace de ce côté ». \inhibitxspcode attribue à chaque caractère japonais une valeur de 0 à 3 réglant la façon dont \xkanjiskip peut s'y accrocher ; dans jsarticle, la parenthèse ouvrante pleine chasse ( porte 2, la fermante ) et le point 。 portent 1, un kanji ordinaire porte 3. La mesure tranche : 日本語(ABC)テキスト fait 105,02704pt, soit neuf caractères pleine chasse (9 × 9,24683pt) plus les 21,8056pt d'ABCpas un seul \xkanjiskip. Les parenthèses pleine chasse embarquent déjà du blanc dans leur propre cadratin ; 2,5pt de plus se verraient, aussi la parenthèse les interdit-elle. Respecter la convention de saisie — lettres latines et chiffres en demi-chasse, ponctuation et parenthèses japonaises en pleine chasse — n'est donc pas qu'une question d'allure : c'est ce qui permet à cette logique d'espacement de s'appliquer. Glissez une ( demi-chasse dans du japonais et ce sont les règles de \xspcode qui prennent le relais (( porte 1), avec un espacement tout autre.

latex
% (u)pLaTeX: inspect and change how xkanjiskip attaches to one character
\typeout{open  paren = \the\inhibitxspcode`(}   % 2 in jsarticle
\typeout{close paren = \the\inhibitxspcode`)}   % 1 in jsarticle
\inhibitxspcode`(=3   % allow the gap on both sides after all

% LuaLaTeX: same idea, other name -- and NO space after the comma
\ltjsetparameter{jaxspmode={`(,preonly}}

Voici le piège quand on transporte des réglages entre pLaTeX et LuaLaTeX : les valeurs 1 et 2 de \inhibitxspcode sont numérotées à l'envers dans le jaxspmode de LuaTeX-ja. La mesure le prouve. Côté pTeX, mettez \inhibitxspcode à 1 pour le kanji 語 : l'espace disparaît de A語 (19,24684pt ramenés à 16,74684pt) et subsiste dans 語A. Dans LuaTeX-ja, mettez jaxspmode à 1 pour le même caractère : c'est l'inverse, l'espace quitte 語A (19,24713pt ramenés à 16,74713pt) et subsiste dans A語. La source de LuaTeX-ja nomme ses modes : 1 est preonly, 2 est postonly, c'est-à-dire « autoriser l'espace seulement avant / seulement après ce caractère japonais ». Le 1 de pTeX signifie « seulement après ». Les deux systèmes s'accordent sur les mots et se contredisent sur les chiffres. Copier les réglages mécaniquement place l'espace du mauvais côté. Pour porter, écrivez les noms preonly et postonly plutôt que les chiffres. Une réserve côté LuaTeX-ja : pas d'espace après la virgule. Avec une espace, TeX Live 2024 signale ! Missing number, treated as zero. puis applique tout de même 0 — l'espace disparaît des deux côtés au lieu d'un seul.

Kinsoku : interdire la coupure avec \prebreakpenalty et \postbreakpenalty

Le kinsoku est la règle qui écarte certains caractères du début ou de la fin de ligne. La ponctuation 。、, les parenthèses fermantes )」』 et les petits kana ゃ ぁ ne peuvent commencer une ligne ; les parenthèses ouvrantes (「『 ne peuvent en terminer une. Quel caractère répugne à quel côté est fourni par les métriques de police japonaises (JFM) et par la classe, et TeX l'implémente non comme une interdiction mais comme une pénalité. Coupez juste avant le point 。 ou la parenthèse fermante ) et ce caractère tombe en tête de la ligne suivante — d'où \prebreakpenalty。 et \prebreakpenalty) à 10000 dans jsarticle. Coupez juste après la parenthèse ouvrante ( et celle-ci reste orpheline en fin de ligne : \postbreakpenalty( vaut donc 10000 aussi. Par convention TeX, 10000 est une pénalité infinie, c'est-à-dire une interdiction pure. L'avantage de cette construction, c'est que l'interdiction devient graduable : on écrit 10000 pour « jamais » ou 200 pour « plutôt pas », et l'algorithme de coupure l'arbitre avec le reste. La composition occidentale ignore complètement la notion de kinsoku ; il s'agit d'une mécanique que pTeX a ajoutée à TeX.

latex
% read the shipped values, then relax one of them
\typeout{full stop  = \the\prebreakpenalty`。}   % 10000
\typeout{open paren = \the\postbreakpenalty`(}  % 10000
\prebreakpenalty`〜=200        % discourage, do not forbid
\jcharwidowpenalty=1000        % dislike a lone character on the last line

% the LuaTeX-ja spelling of the same three settings
\ltjsetparameter{prebreakpenalty={`〜, 200}}
\ltjsetparameter{jcharwidowpenalty=1000}

Parce qu'il s'exprime en pénalité, le japonais a pu se doter d'un paramètre sans aucun équivalent occidental : \jcharwidowpenalty, dont la valeur par défaut est 500 dans jsarticle comme dans ltjsarticle. Il pèse contre le fait de laisser un unique caractère japonais échoué sur la dernière ligne d'un paragraphe — la veuve, version japonaise. Le point important est la modération de la valeur : ce n'est pas une interdiction, mais « cela vaut de resserrer un peu les autres lignes, pas de saccager la page ». En pratique, devant un paragraphe qui s'obstine à finir sur un caractère seul, essayez \jcharwidowpenalty=1000 avant de récrire quoi que ce soit. Si cela ne suffit pas, ajouter ou retirer un caractère de texte est souvent la solution la plus rapide.

Comment activer l'écriture verticale : l'option tate et plext

Aujourd'hui, on l'active par une option de classe. \documentclass[tate]{jlreq} fonctionne sous uplatex comme sous lualatex, et \documentclass[tate]{ltjsarticle} sous LuaLaTeX. La famille pLaTeX fournit en outre des classes verticales dédiées, utarticle et utbook, qui se compilent telles quelles avec uplatex. L'écriture verticale est particulière pour TeX non seulement parce que le sens de la ligne et celui de l'empilement s'échangent, mais parce que le même caractère exige un autre dessin. Ponctuation et parenthèses doivent être repositionnées et pivotées en composition verticale. C'est pourquoi pTeX embarque dès l'origine deux familles d'encodages de police — JY pour l'horizontal, JT pour le vertical — et, dans une boîte déclarée \tate, le côté JT est choisi automatiquement. Rien de tout cela n'a d'équivalent dans la composition occidentale.

latex
% vertical writing, three ways that all compile on TeX Live 2024
\documentclass[tate,uplatex]{jlreq}     % uplatex; also works under lualatex
\documentclass[tate]{ltjsarticle}       % lualatex
\documentclass[uplatex]{utarticle}      % uplatex, dedicated vertical class

% tate-chu-yoko: a short horizontal run inside vertical text
平成\tatechuyoko{31}% jlreq only -- under uplatex or lualatex
平成\rensuji{31}% plext (pLaTeX) and lltjext (LuaTeX-ja)

% zw is the width of one full-width character, zh its height;
% \begin{minipage}<t>{10zw} sets a vertical box ten characters wide

Composer des nombres à deux chiffres ou des unités droits et côte à côte au sein d'un texte vertical s'appelle le tate-chu-yoko. L'écriture dépend de la voie. \tatechuyoko{31} n'est défini que par jlreq et fonctionne sous uplatex comme sous lualatex tant que l'on utilise jlreq ; ltjsarticle ne le connaît pas, et \tatechuyoko y produit ! Undefined control sequence. Côté LuaTeX-ja, la forme est \rensuji{31}, fournie par lltjext (ou par les classes verticales ltjtarticle et ltjtbook) ; pLaTeX dispose du même \rensuji{31} dans le package plext. plext était l'extension d'ASCII pour la composition verticale ; outre \rensuji, il gère tableaux, boîtes et leur sens d'écriture — sa signature est l'argument entre chevrons, comme dans \begin{minipage}<t>{10zw}, qui déclare explicitement le sens et sert à insérer un tableau horizontal dans un document vertical. lltjext en est la contrepartie côté LuaTeX-ja, quasi transcrite tant pour les noms que pour les conventions d'arguments. En cas de souci en vertical, vérifiez d'abord si la classe accepte une option tate, puis si plext ou lltjext est chargé.

Ruby (furigana) et points d'emphase : quel package choisir

La réponse actuelle est : pxrubrica sous (u)pLaTeX, luatexja-ruby sous LuaLaTeX. Les deux s'écrivent \ruby{...}{...}, mais pxrubrica distingue les deux sortes de ruby que définissent JIS X 4051 et JLReq — et impose de choisir. Une barre verticale scinde la lecture caractère par caractère : \ruby{漢字}{かん|じ} donne du mono-ruby, une lecture par kanji. Le ruby de groupe, une suite de kana au-dessus du composé entier, doit être demandé explicitement : \ruby[g]{漢字}{かんじ}. Donnez à un mot de deux caractères une lecture non scindée, sans barre ni option, et vous obtenez ! Package pxrubrica Error: Group count mismatch between the ruby and the body (2 <> 1). Les points d'emphase viennent du même package : \kenten{重要}. Pour du léger, le \ruby d'okumacro, livré avec les jsclasses, suffit — il compose toujours du ruby de groupe, si bien que \ruby{漢字}{かんじ} y fonctionne directement. Attention : CTAN héberge aussi un package nommé simplement ruby — celui de Werner Lemberg, issu du package CJK, en version 4.8.5 dans TeX Live 2024 — une lignée tout à fait distincte.

PackageVoieCe qu'il apporte
pxrubricapLaTeX / upLaTeX / LuaLaTeX / XeLaTeXmono-ruby ou ruby de groupe, contrôle du débord, points d'emphase par \kenten
luatexja-rubyLuaLaTeX seulementruby intégré à LuaTeX-ja, moins gênant pour la coupure des lignes
okumacropLaTeX / upLaTeXlivré avec les jsclasses ; \ruby et \kenten rapides, sans syntaxe de scission
rubyla famille du package CJK (pdfLaTeX et consorts)la lignée distincte de Werner Lemberg ; hors de la pile TeX japonaise, à ne pas mélanger
latex
\usepackage{pxrubrica}
...
\ruby{漢字}{かん|じ}     % mono ruby: the bar splits the reading per character
\ruby[g]{漢字}{かんじ}   % group ruby: one run over the word -- [g] is required
\kenten{重要}            % emphasis dots beside each character

Voici un accident qui casse sans produire la moindre erreur. pxrubrica et okumacro définissent tous deux \ruby, et les charger ensemble ne déclenche même pas un avertissement : le dernier chargé l'emporte en silence. Chargez okumacro après pxrubrica, puis composez \ruby{漢字}{かん|じ} : la barre de かん|じ n'est plus lue comme séparateur de mono-ruby mais imprimée comme un trait vertical pleine chasse (avec pxrubrica seul, la lecture se répartit correctement sur les deux kanji). Rien n'apparaît dans le journal : on ne s'en aperçoit qu'en regardant le PDF. Ne chargez qu'un seul package définissant \ruby. Si vous êtes sous jsclasses et chargez déjà okumacro, supprimez cette ligne en passant à pxrubrica.

Qu'est-ce que JLReq : les « Requirements for Japanese Text Layout » du W3C et la classe jlreq

JLReq est le document du W3C intitulé « Requirements for Japanese Text Layout », exposé systématique et lisible par les implémenteurs de la mise en page japonaise, de la composition des lignes, des interdictions de coupure, des ruby et du traitement de la ponctuation. Jusque-là, ce savoir vivait comme métier accumulé des imprimeries ; sa publication a donc compté : navigateurs web et liseuses se réfèrent aujourd'hui au même texte. La classe jlreq est ce document implémenté en LaTeX, écrite par Noriyuki Abe. Le fichier de classe livré avec TeX Live 2024 indique dans ses commentaires d'en-tête l'édition suivie : (based on JLReq 20200811). Choisir jlreq n'est donc pas seulement « prendre une classe plus récente » : c'est fonder la mise en page sur un document public.

La conséquence pratique : on cesse d'écrire soi-même les réglages fins. L'écriture verticale tient dans une option tate, \jlreqsetup permet de fixer les paramètres de composition par leur nom, et les valeurs par défaut du kinsoku et des ruby suivent déjà JLReq. À l'inverse, basculer tel quel un document jsarticle existant vers jlreq élargit l'étirement de \kanjiskip, modifie la densité des lignes et peut déplacer la pagination. Une frontière raisonnable : jlreq pour un document qui commence, jsclasses quand il faut préserver l'aspect d'un manuscrit existant. Dans les deux cas, \kanjiskip, \xkanjiskip, \prebreakpenalty et \jcharwidowpenalty portent les mêmes noms : le dernier réglage reste toujours entre vos mains.