Eine japanische Zeile kennt keine Wortzwischenräume, und dennoch steht ein mit LaTeX gesetzter japanischer Absatz an beiden Rändern bündig. Der Trick heißt \kanjiskip, ein Leim, dessen natürliche Breite null ist, der sich aber dehnt – unter jsarticle bei 10pt gemessen: 0.0pt plus 0.92473pt minus 0.0924pt. Meist ist er gar nicht vorhanden; sobald eine Zeile enger oder weiter werden muss, quillt zwischen je zwei Zeichen ein wenig davon hervor. Was der westliche Satz dem Wortzwischenraum überlässt, verteilt das Japanische dünn über jede Zeichenfuge der Zeile. Diese Seite geht diese Maschinerie durch – den japanischen Leim, die Umbruchverbote (kinsoku), den vertikalen Satz und Ruby –, also jenen Apparat, den TeX für das Japanische aufbauen musste und der im Westen kein Gegenstück hat, durchweg mit gemessenen Zahlen.
\kanjiskip und \xkanjiskip: der Abstand, den niemand getippt hat
Der japanische Satz fügt automatisch zwei verschiedene Leimarten ein. \kanjiskip steht zwischen zwei japanischen Zeichen, \xkanjiskip an der Grenze zwischen Japanisch und Lateinisch. Entscheidend ist die natürliche Breite: unter jsarticle bei 10pt beträgt \kanjiskip 0.0pt plus 0.92473pt minus 0.0924pt und \xkanjiskip 2.5pt plus 1.49994pt minus 0.59998pt. Der erste ist standardmäßig null und dehnt sich nur, wenn es sein muss – deshalb bleibt das Zeichenraster intakt und die Zeilen stehen trotzdem bündig. Der zweite ist stets 2,5pt breit – deshalb öffnet sich beim Schreiben von 日本語 and abc beiderseits des lateinischen Wortes eine Lücke, obwohl niemand ein Leerzeichen getippt hat. Wer beide auseinanderhält, kann die meisten Debatten über japanische Abstände auf die Frage zurückführen, von welchem Leim gerade die Rede ist.
% 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}Nachgemessen stimmt alles. Unter jsarticle bei 10pt ist 日本語テキスト 64,72778pt breit und ABC 21,8056pt. Zusammen wären das 86,53338pt, doch 日本語ABCテキスト misst 91,53339pt. Die Differenz von 5,00001pt sind zweimal 2,5pt \xkanjiskip, eingefügt zwischen 語 und A sowie zwischen C und テ. Zum Beweis: Nach \noautoxspacing ergibt dieselbe Box wieder 86,53339pt, genau die Summe. Und noch eines: 日本語 misst 27,74048pt, exakt das Dreifache der 9,24683pt eines einzelnen Kanji – zwischen diesen Zeichen steht \kanjiskip, ohne die Breite zu vergrößern, denn seine natürliche Größe ist null.
| Parameter | Auf der pTeX-Seite | Auf der LuaTeX-ja-Seite | Vorgabe in jsarticle bei 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 auf ein Zeichen | \ltjsetparameter{prebreakpenalty={...}} | 10000 für Satzzeichen und schließende Klammern |
postbreakpenalty | \postbreakpenalty auf ein Zeichen | \ltjsetparameter{postbreakpenalty={...}} | 10000 für öffnende Klammern |
jcharwidowpenalty | \jcharwidowpenalty=... | \ltjsetparameter{jcharwidowpenalty=...} | 500 |
inhibitxspcode | \inhibitxspcode auf ein japanisches Zeichen | \ltjsetparameter{jaxspmode={...}} | 2 bei der vollbreiten öffnenden Klammer, 1 bei schließenden und 。, 3 bei Kanji |
xspcode | \xspcode auf ein lateinisches Zeichen | \ltjsetparameter{alxspmode={...}} | 3 für A, 2 für ., 1 für ( |
Diese Vorgaben ändern sich mit der Klasse, und genau das prägt den Charakter einer Seite. Dieselbe Messung unter jlreq liefert für \kanjiskip 0.0pt plus 2.5pt und für \xkanjiskip 2.5pt plus 2.5pt minus 1.25pt. Da ein Kanji in jlreq bei 10pt genau 10pt breit ist, beträgt die Dehnung ein Viertel eines Geviertzeichens – das Zweieinhalbfache des Zehntels, das jsclasses zulässt. jlreq ist also darauf angelegt, den Zeichenabstand zum Ausgleich deutlich stärker zu öffnen, und das Verhalten am rechten Rand ändert sich sichtbar. Wirkt ein Dokument nach einem Klassenwechsel „anders", sollten diese beiden Werte zuerst per \typeout verglichen werden.
Warum vollbreite Klammern keinen Extraabstand bekommen: Breiten und \inhibitxspcode
Weil die Klammer selbst erklärt: „auf dieser Seite kein Abstand". \inhibitxspcode weist jedem japanischen Zeichen einen Wert von 0 bis 3 zu, der regelt, wie \xkanjiskip daran andocken darf; in jsarticle trägt die vollbreite öffnende Klammer ( den Wert 2, die schließende ) und der Punkt 。 den Wert 1, ein gewöhnliches Kanji 3. Die Messung entscheidet: 日本語(ABC)テキスト ergibt 105,02704pt, also neun vollbreite Zeichen (9 × 9,24683pt) plus die 21,8056pt von ABC – kein einziger \xkanjiskip. Vollbreite Klammern führen ohnehin Weißraum in ihrem eigenen Geviert mit; weitere 2,5pt wären sichtbar zu viel, also untersagt die Klammer sie. Die Manuskriptkonvention – lateinische Buchstaben und Ziffern halbbreit, japanische Satzzeichen und Klammern vollbreit – ist deshalb nicht nur Optik, sondern Voraussetzung dafür, dass diese Abstandslogik greift. Setzt man eine halbbreite ( in japanischen Text, gelten stattdessen die Regeln von \xspcode (( trägt 1), und die Abstände fallen ganz anders aus.
% (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}}Hier lauert die Falle beim Übertragen von Einstellungen zwischen pLaTeX und LuaLaTeX: Die Werte 1 und 2 von \inhibitxspcode sind in LuaTeX-jas jaxspmode genau umgekehrt nummeriert. Die Messung beweist es. Setzt man auf der pTeX-Seite \inhibitxspcode für das Kanji 語 auf 1, verschwindet der Abstand aus A語 (19,24684pt auf 16,74684pt) und bleibt in 語A erhalten. Setzt man in LuaTeX-ja jaxspmode für dasselbe Zeichen auf 1, geschieht das Gegenteil: Der Abstand verschwindet aus 語A (19,24713pt auf 16,74713pt) und bleibt in A語. Die Quelle von LuaTeX-ja benennt die Modi: 1 heißt preonly, 2 heißt postonly, also „Abstand nur vor / nur nach diesem japanischen Zeichen erlauben". pTeX’ 1 bedeutet „nur danach". Beide Systeme stimmen in den Worten überein und widersprechen sich in den Zahlen. Wer die Einstellungen mechanisch kopiert, setzt den Abstand auf die falsche Seite. Beim Portieren besser die Namen preonly und postonly schreiben statt der Ziffern. Eine Warnung zur LuaTeX-ja-Seite: kein Leerzeichen nach dem Komma. Mit Leerzeichen meldet TeX Live 2024 ! Missing number, treated as zero. und wendet danach trotzdem 0 an – der Abstand entfällt auf beiden Seiten statt auf einer.
Kinsoku: Umbruchverbote mit \prebreakpenalty und \postbreakpenalty
Kinsoku ist die Regel, die bestimmte Zeichen vom Zeilenanfang oder -ende fernhält. Satzzeichen 。、, schließende Klammern )」』 und die kleinen Kana ゃ ぁ dürfen keine Zeile beginnen; öffnende Klammern (「『 dürfen keine beenden. Welches Zeichen welche Seite meidet, liefern die japanischen Schriftmetriken (JFM) zusammen mit der Klasse, und TeX setzt es nicht als Verbot, sondern als Strafwert um. Bricht die Zeile unmittelbar vor dem Punkt 。 oder der schließenden Klammer ), rutscht dieses Zeichen an den Anfang der nächsten Zeile – deshalb setzt jsarticle sowohl \prebreakpenalty。 als auch \prebreakpenalty) auf 10000. Bricht sie direkt nach der öffnenden Klammer (, bleibt diese am Zeilenende zurück, also ist auch \postbreakpenalty( 10000. Nach TeX-Konvention ist 10000 eine unendliche Strafe, faktisch ein Verbot. Der Vorzug dieser Bauweise: Das Verbot wird abstufbar. Man schreibt 10000 für „niemals" oder 200 für „lieber nicht", und der Umbruchalgorithmus wägt es gegen alles Übrige ab. Der westliche Satz kennt Kinsoku gar nicht; dies ist Maschinerie, die pTeX zu TeX hinzugefügt hat.
% 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}Weil es als Strafwert formuliert ist, konnte der japanische Satz einen Parameter ausbilden, für den es im Westen überhaupt kein Gegenstück gibt: \jcharwidowpenalty, in jsarticle wie in ltjsarticle standardmäßig 500. Er gewichtet den Fall, dass ein einzelnes japanisches Zeichen allein auf der letzten Zeile eines Absatzes stehen bleibt – das japanische Pendant zur Hurenkind-Zeile. Entscheidend ist die Mäßigung des Wertes: kein absolutes Verbot, sondern „es lohnt, die übrigen Zeilen etwas enger zu setzen, aber nicht, den Satzspiegel dafür zu opfern". In der Praxis probiert man bei einem hartnäckigen Absatz zuerst \jcharwidowpenalty=1000, bevor man den Text ändert. Hilft auch das nicht, ist es oft schneller, die Prosa um ein Zeichen zu kürzen oder zu verlängern.
Vertikalen Satz einschalten: die Option tate und plext
Heute schaltet man es über eine Klassenoption ein. \documentclass[tate]{jlreq} läuft unter uplatex wie unter lualatex, \documentclass[tate]{ltjsarticle} unter LuaLaTeX. Die pLaTeX-Familie bringt zudem eigene Vertikalklassen mit, utarticle und utbook, die sich unverändert mit uplatex übersetzen lassen. Vertikaler Satz ist für TeX nicht nur deshalb besonders, weil Zeilenrichtung und Stapelrichtung die Plätze tauschen, sondern weil dasselbe Zeichen eine andere Glyphe verlangt. Satzzeichen und Klammern müssen für den vertikalen Satz neu positioniert und gedreht werden. Deshalb führt pTeX von Anfang an zwei Familien von Schriftkodierungen – JY für horizontal, JT für vertikal –, und in einer als \tate deklarierten Box wird automatisch die JT-Seite gewählt. Für all das gibt es im westlichen Satz kein Gegenstück.
% 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 wideZweistellige Zahlen oder Einheiten aufrecht und nebeneinander in vertikalem Text zu setzen, heißt Tate-chu-yoko. Die Schreibweise hängt vom Weg ab. \tatechuyoko{31} definiert allein jlreq und funktioniert unter uplatex wie unter lualatex, solange jlreq im Spiel ist; ltjsarticle kennt es nicht, dort ergibt \tatechuyoko ein ! Undefined control sequence. Auf der LuaTeX-ja-Seite heißt es \rensuji{31} und stammt aus lltjext (oder aus den Vertikalklassen ltjtarticle und ltjtbook); pLaTeX kennt dasselbe \rensuji{31} aus dem Paket plext. plext war ASCIIs Erweiterung für den vertikalen Satz und kümmert sich neben \rensuji um Tabellen, Boxen und deren Schreibrichtung – sein Erkennungszeichen ist das Argument in spitzen Klammern wie in \begin{minipage}<t>{10zw}, das die Richtung ausdrücklich angibt und nötig ist, um eine horizontale Tabelle in ein vertikales Dokument zu setzen. lltjext ist das Gegenstück auf der LuaTeX-ja-Seite, in Namen und Argumentkonventionen nahezu eine Abschrift. Klemmt der vertikale Satz, prüft man zuerst, ob die Klasse eine tate-Option annimmt, und dann, ob plext oder lltjext geladen ist.
Ruby (Furigana) und Betonungspunkte: welches Paket
Die heutige Antwort lautet: pxrubrica unter (u)pLaTeX, luatexja-ruby unter LuaLaTeX. Beide schreiben \ruby{...}{...}, doch pxrubrica unterscheidet die beiden Ruby-Arten, die JIS X 4051 und JLReq definieren – und verlangt eine Entscheidung. Ein senkrechter Strich teilt die Lesung zeichenweise: \ruby{漢字}{かん|じ} ist Mono-Ruby, je eine Lesung über jedem Kanji. Gruppen-Ruby, eine durchlaufende Kana-Folge über der ganzen Verbindung, muss ausdrücklich angefordert werden: \ruby[g]{漢字}{かんじ}. Erhält ein zweizeichiges Wort eine ungeteilte Lesung ohne Strich und ohne Option, erscheint ! Package pxrubrica Error: Group count mismatch between the ruby and the body (2 <> 1). Betonungspunkte liefert dasselbe Paket als \kenten{重要}. Für Leichtes genügt das \ruby aus okumacro, das den jsclasses beiliegt – es setzt stets Gruppen-Ruby, \ruby{漢字}{かんじ} funktioniert dort also unmittelbar. Zu beachten: Auf CTAN liegt zudem ein Paket namens schlicht ruby – Werner Lembergs Ruby aus dem CJK-Paket, in TeX Live 2024 in Version 4.8.5 – eine ganz andere Linie.
| Paket | Weg | Was es leistet |
|---|---|---|
pxrubrica | pLaTeX / upLaTeX / LuaLaTeX / XeLaTeX | Mono- gegen Gruppen-Ruby, Steuerung des Überhangs und Betonungspunkte über \kenten |
luatexja-ruby | nur LuaLaTeX | in LuaTeX-ja integriertes Ruby, das den Zeilenumbruch weniger stört |
okumacro | pLaTeX / upLaTeX | liegt den jsclasses bei; schnelles \ruby und \kenten, ohne Teilungssyntax |
ruby | die CJK-Paketfamilie (pdfLaTeX und Verwandte) | Werner Lembergs eigene Linie; nicht Teil des japanischen TeX-Stapels, also nicht mischen |
\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 characterHier ein Unfall, der kaputtgeht, ohne einen Fehler zu erzeugen. Sowohl pxrubrica als auch okumacro definieren \ruby, und beide zu laden erzeugt nicht einmal eine Warnung – wer zuletzt kommt, überschreibt stillschweigend. Lädt man okumacro nach pxrubrica und setzt dann \ruby{漢字}{かん|じ}, wird der Strich in かん|じ nicht mehr als Mono-Ruby-Trenner gelesen, sondern als vollbreite senkrechte Linie gedruckt (mit pxrubrica allein verteilt sich die Lesung sauber auf die beiden Kanji). Im Protokoll steht nichts, man merkt es erst im PDF. Genau ein Paket laden, das \ruby definiert. Wer mit jsclasses arbeitet und okumacro lädt, streicht diese Zeile beim Wechsel zu pxrubrica.
Was JLReq ist: die W3C-„Requirements for Japanese Text Layout" und die Klasse jlreq
JLReq ist das W3C-Dokument „Requirements for Japanese Text Layout", eine systematische, für Implementierende lesbare Darstellung japanischer Seitengestaltung, Zeilenkomposition, Umbruchverbote, Ruby und Interpunktionsbehandlung. Zuvor lebte dieses Wissen als angesammeltes Handwerk der Druckereien; seine Veröffentlichung war deshalb bedeutsam: Webbrowser wie E-Book-Reader beziehen sich heute auf dasselbe Dokument. Die Klasse jlreq ist dieses Dokument, in LaTeX umgesetzt, verfasst von Noriyuki Abe. Die mit TeX Live 2024 ausgelieferte Klassendatei nennt in ihren Eingangskommentaren die zugrunde gelegte Fassung: (based on JLReq 20200811). jlreq zu wählen heißt also nicht bloß, „eine neuere Klasse zu nehmen", sondern die Begründung des Satzspiegels auf ein öffentliches Dokument zu stützen.
Die praktische Folge: Man schreibt die Feinjustierungen nicht mehr selbst. Vertikaler Satz ist eine einzige tate-Option, \jlreqsetup erlaubt es, Parameter der Zeilenkomposition beim Namen zu setzen, und die Vorgaben für Kinsoku und Ruby folgen bereits JLReq. Umgekehrt vergrößert der unveränderte Wechsel eines bestehenden jsarticle-Dokuments zu jlreq die Dehnung von \kanjiskip, ändert die Zeilendichte und kann sogar den Seitenumfang verschieben. Eine vernünftige Grenze: jlreq für ein Dokument, das jetzt beginnt; jsclasses, wenn das Aussehen eines vorhandenen Manuskripts erhalten bleiben muss. In beiden Fällen existieren \kanjiskip, \xkanjiskip, \prebreakpenalty und \jcharwidowpenalty unter denselben Namen – die letzte Feinabstimmung bleibt immer in eigener Hand.