✍️

upLaTeXでキリル文字/ギリシャ文字をまともに出力する方法

2021/10/27に公開

ロシア語を混ぜただけなのに

みなさん、日本語で書いたLaTeXの文章にロシア語やギリシャ語などを追加してみたらエラーが出て困ったこと、ありますか? だいたいの人はそういう経験があると思います。

まずは結論から

\usepackage[russian,japanese]{babel}
% キリル文字・ギリシャ文字を欧文扱いに
\usepackage[prefercjkvar]{pxcjkcat}
% ラテン1補助ブロックが和文扱いになるので、欧文扱いに戻す
% ひょっとすると他にも欧文扱いに戻すべきブロックがあるかも?
\cjkcategory{latn1}{noncjk}

% あるいは、pxcjkcatのオプションをprefercjkvarではなくprefernoncjkにする方法も
% その場合、記号の類が欧文判定されてしまうので、必要に応じて戻す

...

\begin{document}

\foreignlanguage{russian}{союз}はロシア語で「同盟」「連合」などを意味する言葉です。

TeXとフォントエンコーディング

TeXはUnicodeよりもはるかに古いソフトウェアです。従って、TeXは内部で独自のエンコーディングを使っています。

https://qiita.com/zr_tex8r/items/b40ca3478e4fe14868e5

この記事の後半にも書いてある通り、普通の状態だと、TeXが出力できる文字の中にキリル文字はありません。not set up for use with LaTeX.と言われておしまいです。

幸い、キリル文字やギリシャ文字を出力できるエンコーディングがあります。キリル文字を出力したいならT2Aなどを、ギリシャ文字を出力したいならLGRを使います。

エンコーディングを切り替えるにはfontencパッケージを使います。

\usepackage[T2A,LGR,T1]{fontenc} % アクセント付きを含むラテン文字用のT1をデフォルトにする

しかし、これでは全部T1になってしまい、キリル文字もギリシャ文字も組めません。

一応、全部をT2Aにすればキリル文字と基本的なラテン文字(ASCIIの範囲のやつとか)は組めるようなのですが、T2Aエンコーディングに含まれるラテン文字はAからZ、aからzの52文字だけです。æなどの文字はたぶん出力できないし、アクセント付き文字は無理矢理出力するのであまりきれいにならないはず。

https://qiita.com/zr_tex8r/items/297154ca924749e62471#その5ot1エンコーディングがアレ

T2Aだけを指定する場合、これに書いている「OT1エンコーディングの問題」のうちアクセント付き文字に関連するやつは全部起こってしまう気がします。たぶん。

残念ながら「キリル文字になったらT2Aに切り替え」みたいなことは難しそうなので、babelパッケージを利用して明示的に「ここはロシア語」「ここはギリシャ語」などのように書くしかなさそうです。

\usepackage[greek,russian,japanese]{babel}

...

\foreignlanguage{russian}{союз}はロシア語で「同盟」「連合」などを意味する言葉です。

とりあえず出力はできた、が……

字がおもいっきり間延びしてますね……。悪名高き、いわゆる「全角キリル文字」問題です。全角というか、全角幅ですね。

キリル文字やギリシャ文字を欧文扱いさせよう

upLaTeXはデフォルトでキリル文字やギリシャ文字を和文として扱います。というかラテン文字とか記号以外は全部和文として扱います。アルメニア文字もタミル文字も全部「和文」。

そもそも、日本語はTeXの貧弱なエンコーディングじゃ扱えません。じゃあupLaTeXはどうしてるのかというと、Unicodeで処理できるようにTeXエンジンを改造しています。すごい。
一方、欧文は普通のTeXと同じように処理しています。

https://qiita.com/zr_tex8r/items/5c14042078b20edbfb07

基本的なキリル文字やギリシャ文字は実は日本語フォントにたいてい含まれているので、一応表示されます。しかし、upLaTeXは全ての文字が全角幅という前提で「和文」の組版をするので、ロシア語を出力させると全角幅で出力されるというわけです。どうして……

そこで、pxcjkcatパッケージを使います。これにより、Unicodeのブロックごとに和文と欧文のどちらとして扱うかを指定できます。詳しくはパッケージのドキュメントを読んでください。

https://hakuoku.hatenablog.com/entry/2017/10/10/231839

\usepackage[prefercjkvar]{pxcjkcat}
% «»などの文字が和文扱いされてしまうので、欧文扱いにする
\cjkcategory{latn1}{noncjk}

ようやくまともな出力ができました。

それでも、つらい

https://hakuoku.hatenablog.com/entry/2017/10/10/203424

upLaTeXは欧文か和文かをUnicodeブロックごとに指定しないといけないので、柔軟さには欠けてしまいます。一応個別に指定することも不可能ではないようですが……

https://hakuoku.hatenablog.com/entry/2017/12/01/164550

あと、キリル文字にアクセント記号を振ってみたら(U+0301「合成用ダイアクリティカルマーク」と結合させる)、inputencが「U+0301なんて文字、うちじゃ扱えないよ!」と叫んで死にました。欧文はUnicodeにちゃんと対応してるわけじゃないので……
upLaTeXでロシア語の教科書を書くのは厳しそう。なんらかの方法はあるかもしれませんが……(あったら教えてください)

і問題

なんとキリル文字の代表的なフォントエンコーディングであるT2Aにはウクライナ語などで使われるіがありません。なのでラテン文字のiに置換されます。

は?

これが気に食わない人はT2AではなくX2を使ってください。ただし、X2にはラテン文字が一切(ASCIIの文字すら)入っていないので、ウクライナ語の文章にラテン文字を混ぜるときにT1に戻す必要があります。

\usepackage[X2, T1]{fontenc}

https://tex.stackexchange.com/questions/130541/temporarily-change-font-encoding-with-fontenc

こうやってfontencを読み込んでおくと、babelのロシア語対応パッケージは自動でT2AではなくX2を選んでくれます。

そしてLuaTeXへ……

日本語とロシア語やギリシャ語を混ぜるのはupLaTeXでも可能ということが分かりました。

ただ、それ以上に「変」なことをするならLuaTeXの採用を検討した方がいいと思います。upLaTeXはあくまで「欧文は古いLaTeXのまま」なんですよ。キリル文字にアクセントをつけたいとか、キリル文字の中でもほとんど使われない文字を出力したいとか、そういうのは……
Unicodeとフォントという2021年じゃ当たり前のはずの文明が使えない場所で異常な多言語対応をするのは、少なくともTeX/LaTeXを完全理解していない人間には不可能だと思います。本当に。

私はキリル文字にアクセントを付ける必要があったので、LuaTeXに移行する決断をしました。あと、フォントエンコーディングだの欧文和文のカテゴリ分けだので消耗したくないし……普通のソフトみたいにフォント指定したいし……(まあ欧文和文のカテゴリに関してはLuaTeX-jaパッケージを使う以上完全には逃れられない気もしますが)

LuaTeXではjsclassesが使えないのですが、他にも文書クラスはいろいろあるので問題ありません。

ただし、技術系同人誌界隈で広く使われているRe:VIEWは、基本的にはupLaTeX前提です。LuaTeXでも使えるjlreqをベースにしたテンプレートもありますが、開発途上で、いろいろ足りていません。(現在Re:VIEWのバージョンはもう5.2なので、以前に比べればだいぶ進んでいるとは思いますが)

Re:VIEW 3 以上で LuaTeX への対応を進めています。ただし、現状では LuaTeX を使うユーザーが LaTeX についての十分な知識を持っており、問題を自己解決できるだけの能力があることを前提としています。

https://review-knowledge-ja.readthedocs.io/ja/latest/faq/faq-tex.html#c551233824ecf453a34665a6a62cedc4

Re:VIEWを諦めてLuaTeXを直書きするか、諦めてupLaTeXで足掻くか、Re:VIEW+jlreq+LuaTeXという茨の道を進むか。
正直1つ目が一番簡単だと思います

追記: Re:VIEW+jlreq+LuaLaTeXは思っていたより簡単でした。review-jlreqはLuaLaTeXでも問題なく使えます。ただし、LuaLaTeXの知識は必要ですし、まだ実装されてない命令があります。シンタックスハイライトとか。
まあ、エラーを見つつreview-jsbookの実装を参考にしながら自分でマクロを書けば、なんとかなるはず。たぶん。

Discussion