Japanese typesetting methods

The first decision in Japanese LaTeX typesetting is not which package to load but which route to take. Three are alive today: upLaTeX + dvipdfmx, LuaLaTeX + LuaTeX-ja, and XeLaTeX + zxjatype. The same .tex file goes down all three, and all three embed the same body font in the PDF. What differs is speed, which packages still work, and where things break. Japanese is the reason TeX grew a second typesetting model at all — per-character glue, vertical writing, line-break prohibition — and these three routes are three implementations of it. This page settles the choice with numbers measured on TeX Live 2024.

The three routes for Japanese LaTeX, and where the knowledge lives

The real difference between the three is which layer of the system holds the Japanese knowledge. In upLaTeX it sits inside the engine: vertical writing, line-break prohibition and inter-character glue are part of a typesetter written in C, which is why it is fast. In LuaLaTeX the knowledge sits in Lua callbacks — LuaTeX-ja walks the node list LuaTeX has just built and applies the Japanese rules to it, which is why it is slower and far easier to modify. In XeLaTeX it sits in a macro package, zxjatype (which loads xeCJK underneath), a general CJK mechanism tuned for Japanese rather than a Japanese engine. The output paths differ too: only upLaTeX goes through DVI and hands it to dvipdfmx; the other two write PDF directly.

RouteEngineOutputJapanese fonts
uplatex + dvipdfmxe-upTeX (pTeX family)DVI, then PDFthrough TFM/VF; dvipdfmx does the embedding
lualatex + luatexjaLuaTeXPDF directlyOpenType directly; chosen with \setmainjfont
xelatex + zxjatypeXeTeXXDV, then PDF (xdvipdfmx)system fonts too; zxjafont is the usual helper

One piece of Japanese TeX history hides in the bottom right of that table. dvipdfmx began as an extension of Mark A. Wicks's dvipdfm with multibyte and CID support — a tool built for Japanese. XeTeX then adopted it as its own output stage, where it became xdvipdfmx. In an actual TeX Live 2024 installation, dvipdfmx is a symbolic link to xdvipdfmx. A converter written for Japanese now runs the final step of every XeTeX document, Japanese or not.

How much slower is LuaLaTeX? The same source down all three routes

Compiling the same ten-page Japanese document under TeX Live 2024 took 0.31 s with uplatex + dvipdfmx, 0.59 s with lualatex (ltjsarticle), and 0.74 s with xelatex (bxjsarticle + zxjatype). That is roughly 1 : 1.9 : 2.4, and the ratio holds for a one-page file too — most of the gap is startup and typesetting itself, not document length. Nobody minds 0.3 s versus 0.6 s once; anyone running latexmk -pvc and rebuilding on every save will feel it. That, more than nostalgia, is why the pLaTeX route has not died after two decades. All three PDFs subset-embed the same Harano Aji Mincho, and pdftotext recovers correct Japanese from all three, so the fast route is not the low-quality one.

terminal
# route 1 -- fastest; DVI in between
uplatex main.tex && dvipdfmx main.dvi
ptex2pdf -l -u main            # the same two steps in one command

# route 2 -- LuaTeX-ja, PDF straight out
lualatex main.tex

# route 3 -- XeTeX via zxjatype
xelatex main.tex

Choosing the document class: jsclasses, jlreq, ltjsclasses, bxjscls

Once the route is chosen the class almost chooses itself: jsarticle (from jsclasses) or jlreq for upLaTeX, ltjsarticle (from ltjsclasses) or jlreq for LuaLaTeX, bxjsarticle (from bxjscls) for XeLaTeX. With one exception — jlreq supports pLaTeX, upLaTeX and LuaLaTeX, but not XeLaTeX. Feeding \documentclass{jlreq} to xelatex produces ! Undefined control sequence. and then tumbles on into ! LaTeX Error: Missing \begin{document}. The idea that fixing the class lets you swap engines freely is true, but XeLaTeX is not among the engines you can swap to.

ClassEngines it runs onCharacter
jsarticlepLaTeX / upLaTeXHaruhiko Okumura's jsclasses (jsbook for books); the de facto standard with the deepest back catalogue
jlreqpLaTeX / upLaTeX / LuaLaTeXdesigned against the W3C JLReq document; vertical writing is one tate option
ltjsarticleLuaLaTeX onlythe jsclasses ported onto LuaTeX-ja; the easiest migration target
bxjsarticlepdfLaTeX / XeLaTeX / LuaLaTeX / (u)pLaTeXbxjscls: a thin cross-engine layer, and the entry point to the XeLaTeX route

The one surprise class selection always has in store is that the same 10pt does not mean the same size. Set a document in jsarticle at 10pt, measure one kanji, and it is 9.24683pt wide — because the class file says \def\Cjascale{0.924690} and loads the Japanese font at 0.924690 times the Latin size. Do the same in jlreq and a kanji is exactly 10pt. Swapping jsarticle for jlreq therefore changes the line length, the characters per line and the whole text block. Plan a migration as a re-layout, not as a like-for-like comparison.

latex
% route 1: uplatex main.tex && dvipdfmx main.dvi
\documentclass[uplatex,dvipdfmx]{jsarticle}
\begin{document}
日本語と English を混ぜた段落です。約物(かっこ)も混じります。
\end{document}
latex
% route 2: lualatex main.tex
\documentclass{ltjsarticle}
\usepackage{luatexja-fontspec}
\setmainjfont{Harano Aji Mincho}
\setsansjfont{Harano Aji Gothic}
\begin{document}
日本語と English を混ぜた段落です。約物(かっこ)も混じります。
\end{document}

What the pLaTeX route costs you: fontspec, unicode-math, microtype

The price of that speed is that the pLaTeX route shuts you out of the modern OpenType-based packages as a group. \usepackage{fontspec} stops with ! Fatal Package fontspec Error: The fontspec package requires either XeTeX or (LuaTeX, on the next line), and unicode-math answers ! Package unicode-math Error: Cannot be run with uptex!. The nasty one is microtype: it does not error. It writes Package microtype Warning: You don't seem to be using pdftex, luatex or xetex. into the log and then silently does nothing — loaded, but inert, which is the hardest kind of breakage to notice. Meanwhile graphicx, hyperref and tikz work normally as long as the driver matches, so this is not "only old packages work". The border runs exactly along OpenType and micro-typography.

Garbled PDF bookmarks: hyperref and pxjahyper

Write a Japanese section heading under (u)pLaTeX with hyperref and only the PDF bookmarks come out garbled: the body text is perfect, the outline panel is nonsense. The cause is that hyperref pours the heading's UTF-8 bytes straight into a UTF-16BE string. Look inside the generated .out file and you find \376\377\000\346\000\227\000\245… — every byte padded with a null. Add \usepackage{pxjahyper} and the same heading becomes \376\377\145\345\147\054\212\236…, that is 0x65E5 0x672C 0x8A9E, the three characters of 日本語. If you use hyperref on (u)pLaTeX, treat pxjahyper as mandatory. Under LuaLaTeX with LuaTeX-ja, plain hyperref already emits correct UTF-16BE and no extra package is needed.

latex
% (u)pLaTeX: load pxjahyper AFTER hyperref, or the outline panel is garbage
\documentclass[uplatex,dvipdfmx]{jsarticle}
\usepackage{hyperref}
\usepackage{pxjahyper}
\begin{document}
\section{日本語の見出し}
本文。
\end{document}

So which route should you pick?

For anything new, choose LuaLaTeX with LuaTeX-ja (ltjsarticle or jlreq). In exchange for a third of a second you get Unicode end to end, access to system fonts, working fontspec, unicode-math and microtype, and bookmarks that are simply correct. If your department's thesis template or a conference style file assumes jsclasses, or if build time genuinely matters in a tight edit loop, stay on upLaTeX + dvipdfmx — it is not the legacy path, it is still the fastest one. Pick XeLaTeX + zxjatype when you already have a XeLaTeX document and need to add Japanese to it; there is little reason to choose it for Japanese alone. There is no longer any reason to start a new document on plain platex: uplatex widens the range of characters you can set (a difference covered on “Character encoding and newlines”).

  • New document, no institutional constraintlualatex with ltjsarticle (or jlreq); Unicode, system fonts and microtype all available.
  • An existing template assumes jsclasses, or build speed mattersuplatex + dvipdfmx; ptex2pdf -l -u collapses it into one command.
  • You already have a XeLaTeX documentbxjsarticle + zxjatype + zxjafont; note that jlreq does not run under XeLaTeX.
  • Using hyperref on (u)pLaTeX? Load pxjahyper. "Only the bookmarks are garbled" is almost always this.
  • microtype is inert on (u)pLaTeX — it warns and does nothing. If you want it, take the Lua or Xe route.