TeX・LaTeX と日本語

日本語の LaTeX を始めると、たいてい platexuplatex というコマンドを叩くことになります。ところが、その名前の実行ファイルはどこにもありません。両方とも euptex という一つのエンジンが読み込む フォーマット の名前で、platex と打った瞬間に画面へ出るのは「This is e-upTeX」の一行です。この一点を飲み込むと、日本語 TeX の分かりにくさは半分ほど消えます。このページでは、そもそもなぜ日本語に専用の仕組みが要ったのか、いま生きている三つの経路(pLaTeX/upLaTeX + dvipdfmx、LuaLaTeX + LuaTeX-ja、XeLaTeX)は何がどう違うのか、そして最初の一本をどれで書き始めるべきかを整理します。

なぜ日本語には専用のエンジンが要ったのか

第一の理由は単純で、もとの TeX は 1 つのフォントあたり 256 文字しか扱えなかった からです(初期は 128 文字)。数千字の常用漢字、さらに数万字の JIS 漢字を載せるには、フォントを 256 字ずつのサブフォントに切り刻むといった細工が要りました。第二の理由はもっと根が深く、組版の規則そのものが違う ことです。欧文の組版は「単語の切れ目で改行し、単語間の空白を伸縮させる」という前提の上に建っていますが、日本語には単語の区切りがありません。どこで改行してもよい代わりに、改行してはいけない場所 を規則として与える必要があります。

この「してはいけない場所」の規則が 禁則処理 です。句読点・閉じ括弧・長音符・小書き仮名は行頭に置かない、開き括弧は行末に置かない、といった約束を守らせます。加えて、和文と欧文が隣り合うときに入れる四分アキ(\xkanjiskip)、和文文字どうしの詰め(\kanjiskip)、約物の詰め、そして 縦組み。pTeX 系のエンジンはこれらを、行分割の候補それぞれに「この文字が行頭に来たら何点」という減点を割り当て、段落全体で減点の合計が最小になる分け方を選ぶ、という形で解いています。TeX がもともと持っていた「段落全体を見渡して最適な行分割を選ぶ」という設計に、日本語の規則を減点として流し込んだわけです。

platexuplatex の違い、そして両方が同じエンジンである話

違いは 扱える文字の範囲 です。platex は JIS X 0208 の枠内、uplatex は Unicode 全域。そして両者は別々のプログラムではなく、同じ euptex エンジンが読み込む別々のフォーマット です。TeX Live の texmf-dist/web2c/fmtutil.cnf を開くと、この関係がそのまま二行で書かれています。第一列がフォーマット名、第二列がそれを作るエンジン。どちらの行も第二列は euptex です。/learn/engines/latex-formats で説明されている「エンジンとフォーマットは別物」という話が、日本語では特にはっきり形に出ているわけです。

fmtutil.cnf
# texmf-dist/web2c/fmtutil.cnf -- format, engine, hyphenation, ini file
platex   euptex language.dat *platex.ini
uplatex  euptex language.dat *uplatex.ini

# and so the banner names the engine, not the command you typed:
$ platex  ... This is e-upTeX, Version 3.141592653-p4.1.1-u1.30-... (utf8.euc)   (preloaded format=platex)
$ uplatex ... This is e-upTeX, Version 3.141592653-p4.1.1-u1.30-... (utf8.uptex) (preloaded format=uplatex)

このバナーは読みごたえがあります。3.141592653 はクヌースが凍結した TeX の版番号そのもの、p4.1.1 は pTeX 拡張の版、u1.30 は upTeX 拡張の版——三世代の履歴が一行に積み重なっています。末尾の括弧も見どころで、platex(utf8.euc)uplatex(utf8.uptex)。原稿はどちらも UTF-8 で書きますが、エンジン内部で漢字を保持する符号が違う のです。この差は抽象的な話ではなく、そのまま実害として出ます。platex に JIS X 0208 の外の字——たとえば「髙」「𠮷」「鷗」——を食わせると、次のエラーで止まります。

log
! LaTeX Error: Unicode character ^^e9^^ab^^99 (U+9AD9)
               not set up for use with LaTeX.

# same file, same class, run through uplatex instead: compiles silently.

実務上の結論は単純です。新しく pLaTeX 系で書き始める理由はほとんどありません。uplatex を使ってください。 人名の異体字、旧字、絵文字ではない補助漢字、韓国語や中国語の引用——どれも珍しくないのに、platex ではそこで止まります。platex を選ぶ理由が残るのは、投稿先のクラスファイルが pLaTeX 専用に書かれている場合と、既存の原稿を引き継ぐ場合だけです。なお pTeX 系のエンジンとマクロは、現在は 日本語 TeX 開発コミュニティ が保守しています。

いま生きている三つの経路

日本語を組む道筋は、実質的に三本です。upLaTeX から DVI を経て dvipdfmx で PDF にする伝統的な経路LuaLaTeX に luatexja を載せて直接 PDF を出す経路、そして XeLaTeX に xeCJK を載せる経路。四本目として pdfLaTeX + CJKutf8 もありますが、これは本文を \begin{CJK}{UTF8}{min} で囲む必要があり、禁則も本格的ではないので、英語論文に日本語を数語だけ差し込むような用途に限られます。三本の違いは、フォントの扱い方と、PDF に至るまでの道のりの長さです。

経路クラスとパッケージ性格と向き不向き
uplatex + dvipdfmxjlreqjsarticle(jsclasses)速い。縦組みの実績が最も厚い。学会クラスの指定が来がち。PDF まで二手かかる
lualatex + luatexjajlreqltjsarticle(ltjsclasses)OS の OpenType フォントをそのまま使え、直接 PDF。Unicode に最も強い。ビルドは遅い
xelatex + xeCJKbxjsarticle(bxjscls)などフォント指定が手軽。中国語・韓国語との混植に強い。細かな和文規則は luatexja に劣る
pdflatex + CJKutf8article + CJK パッケージ英文の中に数語だけ。本文を \begin{CJK}{UTF8}{min} で囲む必要があり、本文全体には向かない

なぜ日本語だけ DVI を経由するのか

pTeX 系のエンジンが PDF を直接書き出せないから です。pdfTeX が PDF 出力を内蔵したのに対し、pTeX は TeX 本来の出力形式である DVI を吐くところで仕事を終えます。その DVI を PDF に変換するのが dvipdfmx で、和文フォントの埋め込みと縦組みの座標変換を引き受けています。つまり日本語の伝統的な経路は「組版」と「PDF 生成」を二人で分担する構成です。手元で uplatex を通してから dvipdfmx にかけると、数百バイトの .dvi が数キロバイトの PDF になり、pdffonts で覗くと HaranoAjiMincho が CID Type 0C として埋め込まれている のが見えます。

shell
$ uplatex doc.tex      # typeset -> doc.dvi
$ dvipdfmx doc.dvi     # convert  -> doc.pdf
$ pdffonts doc.pdf
# HaranoAjiMincho-Regular   CID Type 0C   Identity-H   emb yes

# dvipdfmx is a symlink to xdvipdfmx: one binary serves both
# the Japanese .dvi route and XeTeX's .xdv output.

ちなみに dvipdfmx の実体は xdvipdfmx へのシンボリックリンク です。一つのバイナリが、日本語の .dvi と XeTeX が出す .xdv の両方を面倒みています。日本語のために磨かれた変換器が、そのまま XeTeX の出力段として世界中で使われているわけで、日本発の道具が TeX の本流に組み込まれた例と言えます。埋め込まれる 原ノ味フォント(Harano Aji) も同様で、TeX Live に標準で入っているため、和文フォントを別途買わなくても最初の PDF が出ます。

最初の一本はどれで書き始めるか

\documentclass{jlreq} と書いて、lualatex で通してください。 理由は品質だけではありません。阿部紀行さんによる jlreq は W3C の「日本語組版処理の要件(JLReq)」に沿って設計されたクラスですが、実務上いちばんありがたいのは LuaLaTeX でも upLaTeX でも pLaTeX でも、同じソースがそのまま動く ことです。エンジンは自動判定され、必要なら platexuplatexlualatex をクラスオプションで明示もできます。つまり最初の選択が後戻りできない決断になりません。実際、同じ .texuplatexlualatex の両方に通しても、どちらも原ノ味明朝を埋め込んだ PDF が出ます。

latex
% runs unchanged under lualatex, uplatex and platex
\documentclass{jlreq}
\begin{document}
こんにちは、\LaTeX。日本語の組版です。
\end{document}

フォントを変えたくなったら、LuaLaTeX では luatexja-fontspec を読み込み、\setmainjfont で明朝、\setsansjfont でゴシックを指定します。伝統的な系統に寄せる場合は、pLaTeX/upLaTeX 用の jsclassesjsarticlejsbook)、LuaLaTeX 専用の ltjsclassesltjsarticle など)が定番です。ただし ltjsarticle を選んだなら、コンパイラも LuaLaTeX に揃えること——このクラスとエンジンの食い違いが、日本語まわりで最も多い事故です。

最初につまずくところ

日本語が出ない・化けるときの原因は、ほぼ 原稿の文字コードクラスとエンジンの不一致 のどちらかです。文字コードは UTF-8 で保存 してください。かつては EUC-JP・Shift_JIS・ISO-2022-JP が併存し、nkf のような変換ツールが必需品でしたが、いまはその必要がありません。upTeX と LuaTeX は Unicode ネイティブで、現行の pLaTeX も UTF-8 入力を前提にしています。古い原稿を引き継ぐときだけ、変換が要ります。もう一つの落とし穴は改行コードで、LF と CRLF が同じファイルに混ざると、原因の見えにくい崩れ方をすることがあります。

  • pdflatex で日本語の本文を書かない。エラーや文字化けを見たら、まずコンパイラの設定を疑う。CJKutf8 を使う場合でも \begin{CJK}{UTF8}{min} の囲みが要る。
  • ltjsarticleluatexja を読むなら lualatexjsarticle なら uplatex。クラスがエンジンを決めるので、エディタのビルド設定も一緒に変える。
  • platex! LaTeX Error: Unicode character ... not set up for use with LaTeX. が出たら、その字は JIS X 0208 の外。uplatex に切り替えれば通ることが多い。
  • 共著では、エンジン名・文字コード・クラス名の三つを README に一行で書いておく。この三つが揃わないと相手の手元で再現しない。
  • 投稿先が platex 前提のクラスファイルを配っている場合は素直に従う。ただし提出前に、異体字が本文に紛れ込んでいないか確認する。