多语言

关于 LaTeX 多语言文档,最常见的建议是「pdfLaTeX 用 babel,XeLaTeX 用 polyglossia」。这条建议已经过时了。 TeX Live 2024 收录的 babel 是 2024 年 2 月版,同时支持 pdfTeX、XeTeX 和 LuaTeX,能用 \babelfont 为各语言分配系统字体,并在 LuaTeX 上自带一套 Unicode 双向算法实现。在本机上数一数,babel 的区域设置定义有 297 个语言目录、387 个 .ini 文件。而 polyglossia 依赖 fontspec,因此 在 pdfLaTeX 下根本无法启动。本页将围绕排版混合文字体系的文档,讲清楚该选哪一个、如何切换语言,以及断字和字体会在哪里悄无声息地出问题,并附上每种故障产生的真实消息。

babel 与 polyglossia 的区别:该用哪一个

没有特别理由的话,就用 babel 它不挑引擎,区域数据更多,也是两者中开发最活跃的。TeX Live 2024 收录的 babel 是 2024/02/07 v24.2——版本号采用年份,是因为一年之内会发布好几次。它由 Johannes Braams 编写,现由 Javier Bezos 接手维护。相对的,polyglossia2024/03/07 v2.1,其宏包描述行自称「面向 XeLaTeX 与 LuaLaTeX 的现代多语言排版」,README 里则自我介绍为「面向这两种引擎用户的 babel 替代方案」。可见二者并非并列的选项,而是包含关系:babel 覆盖全域,polyglossia 只覆盖 Unicode 引擎。 在 pdfLaTeX 下加载 polyglossia 时,中止它的并不是 polyglossia 本身,而是其依赖:! Fatal Package fontspec Error: The fontspec package requires either XeTeX or LuaTeX.

项目babelpolyglossia
enginespdfTeX、XeTeX、LuaTeX 全部支持仅 XeTeX 与 LuaTeX(必须有 fontspec)
locale data297 个语言目录、387 个 .ini(TeX Live 2024 实测)242 个 gloss 文件,宣称支持 80 多种语言
declaring\usepackage[french,english]{babel},最后一个是主语言\setmainlanguage{...}\setotherlanguage{...},副语言必须显式声明
switching\selectlanguage{...}(整块)与 \foreignlanguage{...}{...}(行内)同样这两个,另加 \text 加语言名,如 \textgreek{...}
fonts\babelfont{rm}{...} 按语言或文字体系分配(仅限 Unicode 引擎)使用 fontspec 的 \newfontfamily\greekfont{...} 之类
bidi在 LuaTeX 上,bidi=basic 是 babel 自带的 Unicode 实现;在 XeTeX 上则委托给 bidi 宏包方向控制完全委托给 bidi(XeTeX)与 luabidi(LuaTeX)
licenseLPPL(维护状态 maintained,当前维护者 Javier Bezos)MIT 许可证

切换语言:selectlanguage 与 foreignlanguage

成段的范围用 \selectlanguage{french},句中的片语用 \foreignlanguage{french}{...} 前者自此一直生效,后者只作用于其参数之内。改变的不只是断字规则。\tableofcontents 会变成「Table des matières」,章号前的词会变成「Chapitre」——这就是 文档字符串(document strings) 的翻译,也是 babel 在实务中最大的价值所在。更值得注意的是,排出来的文字本身也变了。据西文排版那一页的实测,Bonjour: oui! 在无设置时占 58.48572pt,而在 [french]{babel} 之下伸展到 62.37366pt,用 pdftotext 抽取则返回 Bonjour : oui !。法语在高位标点前留四分之一空白的排版规则,已作为真实的空白落在冒号与感叹号之前。请把 babel 理解为「应用某语言排版习惯」的工具,而非「给语言贴标签」的工具。

latex
% babel: the LAST option is the main language of the document
\usepackage[russian,french,english]{babel}
...
\foreignlanguage{french}{Bonjour : oui !}   % inline, one phrase
\selectlanguage{french}                     % from here on
\tableofcontents                            % now "Table des matieres"

% polyglossia (XeLaTeX / LuaLaTeX only)
\usepackage{polyglossia}
\setmainlanguage{english}
\setotherlanguage{greek}     % secondary languages must be declared
\textgreek{...}             % \text + language name

当某语言没有断字模式时会怎样

得到的是警告而非错误,文本会照英语规则断字。 原因是 TeX 的一项限制:断字模式无法在运行时载入,而是在构建格式时烧进去的。TeX Live 2024 的 language.dat 在扣除别名行后列出 87 种语言,而 babel 提供 .ldf 的语言比这更多,两者因此对不上。比如用 \usepackage[albanian,english]{babel} 选择阿尔巴尼亚语,就会看到 Package babel Warning: No hyphenation patterns were preloaded for the language 'Albanian' into the format.,其后跟着 Now I will use the patterns preloaded for \language=0 instead。而 \language=0 正是 Knuth 最初的 hyphen.tex,也就是美式英语。PDF 照常生成,退出码也是 0——只是阿尔巴尼亚语的单词按英语规则被断开了。除非去读日志,否则不会有任何提示。对策是安装带有该语言模式的宏包并用 fmtutil 重建格式,或者在 Unicode 引擎上使用 \babelprovide[import]{...}

按文字体系切换字体:最常见的失败

声明了语言,并不会连字体一起带来。 这是多语言文档中最常见的事故。在 XeLaTeX 下声明 \setotherlanguage{russian} 并写 \textrussian{Русский},由于默认的 Latin Modern 没有西里尔字母,那一段就会从纸面上消失。不会报错。只有日志里会逐字出现类似 Missing character: There is no Р (U+0420) in font [lmroman10-regular] 的行。退出码是 0,PDF 也生成了,只是俄语部分一片空白——论难以察觉,无出其右。对策是按文字体系分配字体:babel 用 \babelfont[russian]{rm}{...},polyglossia 用 fontspec 的 \newfontfamily\russianfont{...}。不过 \babelfont 仅限 Unicode 引擎;在 pdfLaTeX 下调用会得到未定义控制序列错误 \babelfont ->\bbl@error@ {only-lua-xe}。要在 pdfLaTeX 上处理非拉丁文字,走的不是字体而是 fontenc 编码这条路——西里尔用 T2A,希腊语用 LGR

latex
% XeLaTeX / LuaLaTeX: give each script a font that actually has it
\usepackage[russian,greek,english]{babel}
\babelfont{rm}{Latin Modern Roman}
\babelfont[russian]{rm}{Times New Roman}
\babelfont[greek]{rm}{Times New Roman}

% pdfLaTeX has no \babelfont: match the encoding instead
% \usepackage[T2A,LGR,T1]{fontenc}   % Cyrillic, Greek, Latin

% Without this the text is simply absent and the log says:
%   Missing character: There is no Р (U+0420) in font [lmroman10-regular]

从右到左(RTL):阿拉伯语与希伯来语请用 LuaLaTeX

若要认真做双向排版,LuaLaTeX 是唯一选择。 这不是偏好问题,而是功能所在的问题。babel 用 bidi= 选项挑选双向处理方式,而由 babel 自身实现 Unicode 双向算法的 bidi=basic 只能在 LuaTeX 上运行。在 XeLaTeX 下指定它,会被直白告知结果将是错的:! Package babel Error: The bidi method 'basic' is available only in luatex. I'll continue with 'bidi=default', so expect wrong results.。XeLaTeX 一侧的选项是 bidi=bidi,即委托给外部的 bidi 宏包——但仅仅加载它就会得到警告 Package babel Warning: Some functions for 'bidi=bidi' are tentative. They might not work as expected and their behavior could change in the future.。polyglossia 处境相同,因为它同样把方向控制交给了 bidiluabidi。在 LuaLaTeX 上把 \babelprovide[import, main]{arabic}\babelfont{rm}{...} 结合起来,阿拉伯语与英语混排的文档可以零警告通过。

也可以直接使用 bidi 宏包本身:\setRTL(别名 \setRL)让其后的文流转为从右到左,\setLTR(别名 \setLR)再转回来。在 XeTeX 下方向无法自动判定,因此凡是 LR 与 RL 相接之处都需要显式标记——真正吃力的正是这份手工标注的量。LuaTeX 的 bidi=basic 则按 Unicode 规则自动判定这些边界,并且连表格、边距等版面也一并翻转。对于波斯语这类虽属 RTL 却在数字处理上另有惯例的语言,babel 还提供 bidi.mapdigits 之类更细的调整。结论很简单:凡是含阿拉伯语、希伯来语或波斯语的文档,一开始就用 LuaLaTeX 反而最快。

latex
% LuaLaTeX: babel handles direction with its own Unicode implementation
\usepackage[bidi=basic]{babel}
\babelprovide[import, main]{arabic}
\babelfont{rm}{Geeza Pro}
% mixed Arabic and English needs no manual direction marks here

% XeLaTeX must delegate to the bidi package, which babel calls tentative
% \usepackage[bidi=bidi]{babel}
% \setRTL   % or \setRL  -- switch the flow right-to-left
% \setLTR   % or \setLR  -- switch it back

那么到底该怎么选

判断的起点不是「我要混排哪些语言」,而是 「我要用哪个引擎排版」。拉丁文字加上少量西里尔与希腊文字,用 pdfLaTeX 加 babel 加 fontenc 完全跑得通;但若想使用系统字体,或涉及阿拉伯语、希伯来语、印度系文字,就需要 Unicode 引擎。只有在这一点定下来之后,babel 与 polyglossia 的取舍问题才会出现。CJK 则是另一回事:日文由 pTeX 系引擎及其类负责,而 pTeX 世界之外的中文、韩文、日文属于 CJKutf8xeCJKctexkotex 的地盘——两者都有各自的专页。

  • 以拉丁文字为主,混有少量西里尔或希腊文字 → pdfLaTeX 加 babelfontencT2A / LGR)。无需改动既有流程。
  • 想使用系统字体,或混排多种文字体系 → XeLaTeX 或 LuaLaTeX 加 babel\babelfont
  • 涉及阿拉伯语、希伯来语或波斯语(RTL) → LuaLaTeX 加 babel 的 bidi=basic。该模式在 XeLaTeX 上不可用。
  • 选择 polyglossia 的理由 → 已有为它写好的文档,或所需语言只有它支持。若是新项目,babel 更稳妥。
  • 日文、中文、韩文 → 走专用路线(日文排版系列页面与 CJK 页面)。