CJK(pdfLaTeX / XeLaTeX)

TeX は 256 文字のフォントを前提に設計されました。漢字は数万字あります。1994 年に始まった CJK パッケージの答えは身も蓋もないもので、フォントを 256 字ずつの断片に切り刻み、次の文字が属する断片だけを読み込ませる、というものでした。いま pdfLaTeX で中国語の段落を組んでも、出てくる PDF に埋め込まれているのは文字どおりそれ——gbsnu4egbsnu5bgbsnu65 と、Unicode のブロックごとに 1 つずつのサブフォントです。このページが扱うのは pTeX 系の外側の CJK、つまり pdfLaTeX の CJKCJKutf8、XeLaTeX の xeCJK、中国語のための ctex、韓国語のための kotex です。どの経路もまずフォントで転ぶので、TeX Live 2024 が実際に何を持っているのかも併せて示します。

pdfLaTeX で中国語・韓国語を組む — CJKutf8 はまだ動く

pdfLaTeX に縛られていても中国語と韓国語は組めます。 TeX Live 2024 では \usepackage{CJKutf8} を足して本文を CJK* 環境で囲むだけで、追加のフォント導入なしにそのまま通ります。実測でも、簡体字(gbsn)・繁体字(bsmi)・韓国語(mj)・日本語(min)のいずれも一発でコンパイルが完了し、PDF には Type 1 のサブフォントが埋め込まれました。作者は Werner Lemberg、著作権表示は 1994〜2021 年、TeX Live 同梱版は 4.8.5(2021 年 10 月 16 日)です。「もう動かない古物」ではなく「凍結された現役」だと考えてください。ただし CJK パッケージが読めるのは、あらかじめ TeX 用に変換されたフォントだけです。OS にインストールした OpenType フォントは使えません。ここが XeLaTeX との決定的な差です。

latex
% pdflatex — simplified Chinese, no extra fonts needed
\documentclass{article}
\usepackage{CJKutf8}
\begin{document}
\begin{CJK*}{UTF8}{gbsn}
这是一段中文,混排 English words 也没问题。
\CJKfamily{gkai}换成楷体。
\end{CJK*}
\end{document}

環境の第 1 引数がエンコーディング、第 2 引数が フォントファミリ です。ここに何を書けるかは、手元にどの変換済みフォントがあるかで決まります。TeX Live 2024 で素のまま通ったのは下表の 8 つで、song だけは Font cyberb30 at 600 not found で落ちました——Cyberbit という別途入手が必要なフォントを前提にしているからです。もう一つ、初学者が必ず一度は踏むのが環境の外に漢字を書いてしまう事故です。このとき出るのは ! LaTeX Error: Unicode character 日 (U+65E5) not set up for use with LaTeX. で、文字 1 つにつきエラーが 1 個出ます。段落を丸ごと環境の外に置くと数十個のエラーが流れるので、ログの先頭だけを見て原因を見誤らないようにしてください。

ファミリ言語実体TeX Live 2024
gbsn簡体字中国語Arphic GB 宋体(arphic同梱・そのまま通る
gkai簡体字中国語Arphic GB 楷体(arphic同梱・そのまま通る
bsmi繁体字中国語Arphic Big5 明朝(arphic同梱・そのまま通る
bkai繁体字中国語Arphic Big5 楷書(arphic同梱・そのまま通る
mj韓国語UHC 明朝(uhc同梱。kotex のほうが上位互換
min日本語Wadalab 明朝(wadalab同梱。upLaTeX のほうが上位互換
goth日本語Wadalab ゴシック(wadalab同梱・そのまま通る
maru日本語Wadalab 丸ゴシック(wadalab同梱・そのまま通る
song中国語Cyberbit(別途入手)Font cyberb30 at 600 not found で失敗

CJKCJK* の違いは、飾りではなく実害の有無です。CJK.sty のコメントがそのものずばりを書いています——「CJK* は CJK 文字のあとの空白を飲み込むが、CJK は飲み込まない」。原稿では中国語の一文をソース中で改行するのが普通ですが、その改行は TeX にとって空白 1 個です。CJK 環境では 汉字之间不应该 出现空格。 のように文の途中に空きが残り、CJK* 環境では 汉字之间不应该出现空格。 と正しく詰まりました。中国語・日本語では CJK* を選ぶのが既定の判断です。同じ理由で、\begin{CJK*}{UTF8}{gbsn} の直後は必ず改行してください——同じ行に置いた文字は CJK として解釈される前に読み込まれてしまいます。フォントを途中で変えたいときは \CJKfamily{gkai} を使い、環境を入れ子にする必要はありません。

日本語を pdfLaTeX で組まざるを得ないときは、CJK の上に載る bxcjkjatype(ZR 氏、TeX Live 2024 同梱版は v0.5・2023 年 7 月 23 日)が段違いに楽です。\usepackage[whole]{bxcjkjatype} と書けば文書全体が自動的に包まれるので CJK* 環境を自分で書く必要がなく、改行の空白も和欧間の空きも面倒を見てくれます。実測でも ソース中で改行しても空白は入りません。 と正しく詰まり、埋め込まれたのは IPAex 明朝を Type 1 化した ipaex-type1 でした。とはいえ、これはあくまで pdfLaTeX に縛られたときの回避策です。エンジンを選べるなら次節以降を読んでください。

XeLaTeX で CJK — xeCJK のフォント設定でつまずく場所

xeCJK は XeLaTeX 専用で、フォント名の書き方ひとつでコンパイルが通るか落ちるかが決まります。 何も設定せずに \usepackage{xeCJK} だけ書いても、実測ではエラーゼロで PDF が出ます。既定で Fandol Song が読み込まれるからです。しかしそれは中国語のフォントです。同じ文書に韓国語を混ぜると、ログに Missing character: There is no 한 (U+D55C) in font [FandolSong-Regular.otf] が並び、終了コードは 0 のままハングルだけが PDF から消えます。テキスト抽出で確かめても、韓国語の一文はまるごと存在しませんでした。CJK 混在の文書で xeCJK を使うなら、スクリプトごとにフォントを明示するのが必須です。

latex
% xelatex — one font per script; file names, not family names
\documentclass{article}
\usepackage{xeCJK}
\setCJKmainfont{FandolSong-Regular.otf}[
  BoldFont   = FandolSong-Bold.otf,
  ItalicFont = FandolKai-Regular.otf]
\setCJKsansfont{FandolHei-Regular.otf}
\newCJKfontfamily\korean{UnBatang.ttf}
\begin{document}
这是一段中文。{\korean 한국어 문장입니다.}
\end{document}

ここで効いてくるのが XeTeX はフォントを OS に問い合わせる という性質です。\setCJKmainfont{FandolSong-Regular.otf} はファイル名なので TeX ツリーから解決できて通りますが、同じフォントを \setCJKmainfont{Fandol Song} とファミリ名で書くと ! Package fontspec Error: The font "Fandol Song" cannot be found. で落ちます。TeX Live に入っているのに、です。逆に OS 側にあるフォント——macOS の Songti SCPingFang SCHiragino Sans——はファミリ名で問題なく通りました。よく貼られる \setCJKmainfont{Noto Sans CJK SC} も、Noto CJK は TeX Live に同梱されていない ので、OS に自分で入れていなければ The font "Noto Sans CJK SC" cannot be found. になります。原則は単純で、TeX ツリーのフォントはファイル名(拡張子込み)で、OS のフォントはファミリ名で指定します。この挙動そのものは XeTeX のページで詳しく扱っています。

フォントが片付いたら、次は空きの調整です。xeCJK\xeCJKsetup{...} に和欧間・和文間の空きを制御する鍵を持っていて、CJKglue が漢字どうしの空き、CJKecglue が漢字と欧文のあいだの空きにあたります。TeX Live 2024 の既定値は CJKglue0pt plus 0.08\baselineskipCJKecglue~——つまり 漢字と英単語のあいだには通常の単語間空きが 1 つ入ります。pTeX の \kanjiskip\xkanjiskip を知っている読者向けに言えば、思想は同じで既定値が違う、という関係です(そちらは和文組版の詳細のページが扱います)。句読点の詰めは PunctStyle で、行分割の許可は AllowBreakBetweenPuncts で切り替えます。なお xeCJK を LuaLaTeX で読み込むと ! Critical Package xeCJK Error: The xeCJK package requires XeTeX to function. で止まります。名前のとおり、代用は効きません。

中国語なら ctex — 使い方と fontset の落とし穴

中国語の文書なら、xeCJK を直接触るより ctex を使うほうが早いです。 \documentclass{ctexart}ctexrepctexbookctexbeamer もあります)か、既存のクラスに \usepackage[UTF8]{ctex} を足すだけで、字体・行間・見出しの体裁・句読点の詰め・章番号の漢数字化までまとめて中国語の慣習に合わせてくれます。ctex は エンジンを自動判別 します。実装は素朴で、ctex-engine-<エンジン名>.def というファイルが存在するかを見るだけ。対応は xelatex・lualatex・pdflatex・uplatex・aplatex で、それ以外だと Engine '...' is not yet supported, ctex will abort! と言って止まります。TeX Live 2024 同梱版は 2.5.10 です。

latex
% xelatex or lualatex — fandol is the only fontset TeX Live guarantees
\documentclass[fontset=fandol]{ctexart}
\begin{document}
\section{中文标题}
这是一段中文,混排 English words。今天是\today\end{document}

問題はエンジンではなくフォントセットのほうです。ctex は OS も自動判別しようとします——Windows なら windows、macOS なら mac、それ以外は fandol。macOS の判定方法が愉快で、/System/Library/Fonts/Menlo.ttc というファイルがあるかどうかを見ています。等幅のプログラミング用フォントの有無で OS を当てているわけです。この自動判別は当たっているうちは快適ですが、外れると派手に転びます。実測では、fontset を書かずに ctexart を走らせたとき、XeLaTeX は通ったのに LuaLaTeX は ! Package fontspec Error: The font "STHeiti" cannot be found. で落ち、pdfLaTeX は ! Critical Class ctexart Error: CTeX fontset 'mac' is unavailable in current mode. で落ちました。結論は一つで、fontset= は必ず自分で書くこと。TeX Live に必ず入っている中国語フォントは Fandol だけなので、配布する文書には fontset=fandol が安全です。それでも pdfLaTeX では CTeX fontset 'fandol' is unavailable in current mode. になります——fandol は Unicode エンジン専用だからです。pdfLaTeX の ctex は内部で CJKutf8CJKpunctCJKspace を読み込む設計で、Windows 系のフォントを前提にしています。中国語で pdfLaTeX を使うなら、ctex ではなく CJKutf8gbsn に降りるのが現実的です。

韓国語は kotex — 一行でどのエンジンでも通る

韓国語は \usepackage{kotex} の一行だけで、pdfLaTeX でも XeLaTeX でも LuaLaTeX でも通ります。 これが CJK 三言語のなかでいちばん素直な状況です。仕掛けは kotex.sty を開けば分かります——このファイルはパッケージというより 振り分け装置 で、\directlua\XeTeXrevision の有無を見て、pdfTeX なら kotexutf(cjk-ko)、XeTeX なら xetexko、LuaTeX なら luatexko という 中身のまったく違う三つのパッケージ のどれかを読み込みます。オプションもそのまま下流へ渡されるので、書く側は経路を意識しなくて済みます。フォントも実際に同梱されていて、実測では pdfLaTeX 経路が Nanum 明朝の Type 1(nanumtype1)を、XeLaTeX 経路が UnBatang(unfonts-core)を埋め込みました。どちらもテキスト抽出が正しく通ります。

latex
% pdflatex, xelatex or lualatex — all three work unchanged
\documentclass{article}
\usepackage[hangul]{kotex}
\begin{document}
\section{한국어 시험}
오늘은 \today 입니다.
\end{document}

[hangul] を付けると見出し語と日付も韓国語になります。実測では \today2026년 8월 13일、図表の見出しが 그림 1: に変わりました(このオプションが無いと August 13, 2026 のままです)。フォントを差し替えるときは、XeLaTeX の名前解決の癖がここでも噛みます——\setmainhangulfont{UnBatang}! Package fontspec Error: The font "UnBatang" cannot be found. で落ち、\setmainhangulfont{UnBatang.ttf} は通りました。UnBatang.ttf は TeX ツリーの中にあるのに、ファミリ名では見つからないわけです。xetexko を直接読み込むこともできますが、kotex 経由なら経路を意識せずに済むぶん、共著や投稿では扱いが楽になります。

TeX Live に実際に入っている CJK フォント

TeX Live 2024 のフォントツリーには Noto CJK が一切入っていません。 NotoSansCJKNotoSerifCJK という名前のファイルは 1 つも見つからず、TeX Live の noto パッケージが提供するのは NotoSerif・NotoSans・NotoSansMono——つまりラテン系だけです。ウェブで見かける \setCJKmainfont{Noto Sans CJK SC} が動くのは、書いた人が OS 側に Noto CJK を入れていたからにすぎません。配布する文書やコンテナの中でその行を書くと、他人の環境で確実に落ちます。実際に同梱されているものは下表のとおりで、中国語だけが極端に薄いのが分かります——OpenType は Fandol 一族のみ、あとは CJK パッケージ用に変換済みの Arphic です。日本語(Harano Aji・IPAex)と韓国語(Un フォント・Baekmuk・Nanum)のほうが選択肢は多く残っています。

TeX Live パッケージ言語形式使う経路
fandol中国語OpenTypexeCJK の既定・ctexfontset=fandol
arphic中国語Type 1 サブフォントCJKutf8gbsngkaibsmibkai
arphic-ttf中国語TrueTypeUnicode エンジンでファイル名指定
haranoaji日本語OpenTypeLuaTeX-ja・zxjatype などの既定
ipaex日本語TrueTypeUnicode エンジンでファイル名指定
wadalab日本語Type 1 サブフォントCJKutf8mingothmaru
unfonts-core韓国語TrueTypexetexkoluatexko の既定
nanumtype1韓国語Type 1 サブフォントpdfLaTeX の kotex(cjk-ko)
uhc韓国語Type 1 サブフォントCJKutf8mj

どの経路を選ぶか

エンジンを自由に選べるなら、中国語は ctex + XeLaTeX/LuaLaTeX、韓国語は kotex、日本語は upLaTeX か LuaTeX-ja が既定の答えです。 CJKCJKutf8 に降りるのは、pdfLaTeX を要求するクラスやテンプレートに縛られているとき——学会の投稿規定などがこれにあたります。日本語だけは事情が違い、禁則・JFM・ルビ・縦組みといった要求が絡むと、pTeX 系や LuaTeX-ja が持つ蓄積に xeCJK は届きません。日本語の経路比較は「日本語組版の方法」、和文の細かい詰めは「和文組版の詳細」に譲ります。言語をまたぐ文書——ドイツ語の本文に中国語の引用を挟むような場合——は、babelpolyglossia とフォント切り替えの話になるので「多言語」のページが本体です。

  • 中国語\documentclass[fontset=fandol]{ctexart} を XeLaTeX か LuaLaTeX で。fontset は必ず明示します。
  • 韓国語\usepackage{kotex}。エンジンは問いません。見出し語も韓国語にするなら [hangul]
  • pdfLaTeX から動けないCJKutf8CJK* 環境。中国語は gbsnbsmi、韓国語は kotex(内部で cjk-ko に落ちます)。
  • XeLaTeX で複数のスクリプトを混ぜるxeCJK\newCJKfontfamily をスクリプトごとに。設定しないと足りない字が黙って消えます。
  • 日本語 → このページの範囲外です。upLaTeX か LuaTeX-ja を選んでください。