键盘上没有弯引号“ ”这个键。LaTeX 文档里之所以还是能排出像样的引号,是因为连打两个反引号、再连打两个撇号之后,字体的连字(ligature)机制会把它们改写成真正的引号——和把 f 加 i 变成 fi 用的是同一套机器。本页顺着这条线索一路走下去:怎样把引号排对,csquotes 的 \enquote 如何按语言换形状并自动处理嵌套,以及 quote、quotation、verse 三个环境如何把引文单独排成一块。
弯引号是怎么来的:两个反引号的真相
答案藏在字体里。TeX 读取字体时会去查 .tfm(字体度量文件),而 .tfm 里带着一份连字程序:一张表,规定哪个字符后面跟着哪个字符时应替换成第三个字形。引号的替换就直接写在这张表上。把 T1 编码的 Computer Modern 罗马体 ecrm1000.tfm 反编译出来,反引号那一项写着 (LIG O 140 O 20)——「反引号后面再跟一个反引号,就换成八进制 20 号字形」。八进制 20 号正是 \textquotedblleft,即左双引号。撇号那一项形状相同,(LIG O 47 O 21) 指向右双引号 \textquotedblright。
有意思的地方在这里。同一个文件里 f 那一项写着 (LIG C i O 14)——「f 后面跟着 i,就换成 fi 字形」。也就是说,引号,和铅字时代用了几百年的 fi 连字,对 TeX 来说是同一条指令。高德纳把为字母对设计的机构原封不动地挪用到了标点上。两个连字符变成 en dash 也在同一张表里,写作 (LIG O 55 O 173)。「打进去的字符不会原样出来」这个 TeX 给人的第一个意外,就是从这张小表里来的。
% Two backticks open a quotation, two apostrophes close it.
``A quotation set the TeX way.''
% One of each gives the single marks.
`A quotation inside a quotation.'
% Adjacent closing marks collide; a thin space keeps them apart.
``He said `yes.'\thinspace''| 输入 | 排出的字形 | 说明 |
|---|---|---|
`` | “ | 左双引号,由连字合成 |
'' | ” | 右双引号,两个撇号 |
` | ‘ | 左单引号,不经过连字 |
' | ’ | 右单引号;撇号也是同一字形 |
" | ” 或 " | 不要使用,见下一节 |
为什么直接打 " 会排出错的引号(OT1 与 T1 的区别)
直接打 ASCII 的直引号 ",会因为当前用的字体编码不同而以两种方式出错。在 LaTeX 默认的 OT1 编码下,ot1enc.def 把 \textquotedblright 放在第 34 号位——正是 ASCII 里 " 的位置。于是 "quoted" 排出来是 ”quoted”:开头和结尾都是右引号。而加上 \usepackage[T1]{fontenc} 之后,t1enc.def 在同一个 34 号位放的是 \textquotedbl,即打字机式的竖直引号,同样的输入就一直是 "quoted",永远不会变弯。序言区里的一行,改变的只是错误的样子,不是错误本身。撇号一侧也是同样的道理。当你确实需要一个竖直的 '——代码片段,或是不能变弯的标识符——请用 \textquotesingle,这是 TS1 的字符,2020 年以后的内核无需额外宏包即可使用,在 \texttt 里也不会变弯。
% Default OT1: slot 34 holds the CLOSING double mark.
% "quoted" -> ”quoted” (two closing marks)
\documentclass{article}
% With T1: slot 34 holds an upright typewriter quote.
% "quoted" -> "quoted" (never curls)
\usepackage[T1]{fontenc}
% Either way, this is what you want instead:
``quoted''实践中守住三条就不会出事。第一,原稿里不要打 "——用一次全局查找替换清理干净最稳妥。第二,加上 \usepackage[T1]{fontenc},不是为了修 34 号位,而是为了正确的断词和带重音字符。第三,用 LuaLaTeX 或 XeLaTeX 时,直接输入 UTF-8 的“ ”是完全可行的:字体通过 Unicode 寻址,不经过连字机制,而且原稿的样子和输出一致。代价是引号的形状被写死在原稿里,所以多语言文档还是下一节的 \enquote 更好用。
\enquote 与手动输入引号的区别
区别一句话就能说清:手打记录的是字形,\enquote 记录的是「这里是引文」这件事。载入 csquotes 宏包后写 \enquote{…},纸面上究竟落下哪个字形,由当前选定的引号样式决定。嵌套还是自动的。\enquote 内部会数嵌套深度(计数器叫 \csq@qlevel),第一层用外层引号,再往里用内层引号。至于是美式的外双内单,还是英式的外单内双,那已经是样式定义要操心的事,不是你的事。
\usepackage[T1]{fontenc}
\usepackage[english]{babel}
\usepackage[autostyle=true]{csquotes}
% ...
\enquote{He said \enquote{yes} to me.}
% -> “He said ‘yes’ to me.”
\begin{otherlanguage}{ngerman}
\enquote{Er sagte \enquote{ja} zu mir.}
\end{otherlanguage}
% -> „Er sagte ‚ja‘ zu mir.“
\begin{otherlanguage}{french}
\enquote{Il a dit \enquote{oui}.}
\end{otherlanguage}
% -> « Il a dit “oui”. »上面三行都是同一个 \enquote,写法也完全一样,排出来的引号却各不相同。起作用的是 autostyle=true,这个选项让引号样式跟随 babel/polyglossia 的当前语言。只要切换语言,引号就跟着变,原稿里不会出现任何按语言分支的代码。需要强制排出内层引号时,用带星号的 \enquote*{…}。若想在序言区里固定下来,\setquotestyle{german} 可以直接指定。
写下语义还带来第二个好处:错误变得可以被发现。手打的引号少了一个,编译时不会有任何抱怨,要等印出来才看见。\enquote 追踪嵌套深度,所以引号不配对时会以 Package csquotes Error: Unbalanced groups or invalid nesting 或 Still 1 quote open. 停下来。在三百页论文里用眼睛核对引号的活儿,就此换成编译输出的一行。相邻引号相撞的问题 csquotes 也一并接手:每个样式定义里都带着一个 紧排值,写作 [0.05em] 之类,当外层与内层引号同时开或同时闭时自动插入——正是过去手打时要用 \thinspace 补的那一手。
各语言的引号:“ ”、„ “、« »、「 」
引号的形状因语言而异,而且连「哪个是开、哪个是闭」都不一样。中文的“ ”和‘ ’、日语的「 」和『 』、德语的„ “、法语的« … »,做的是同一件事,字形、朝向、高度却都对不上。csquotes 把这件事抽象成引号样式,csquotes.def 里带了 29 种语言的定义,英语、德语、法语、西班牙语、日语都在其中。日语样式定义相当朴素:外层 「 」,内层 『 』,紧排值是 [0pt]——全角引号本来就不会互相碰撞,无需再收紧。
| 样式名 | 外层 | 内层 | 说明 |
|---|---|---|---|
american | “ ” | ‘ ’ | english 的默认变种 |
british | ‘ ’ | “ ” | 内外与美式相反 |
german | „ “ | ‚ ’ | 闭引号就是英语的开引号字形 |
french | « » | “ ” | 引号内侧要加不可断空格 |
spanish | « » | “ ” | 续段时在行首重复 » |
japanese | 「 」 | 『 』 | 紧排为 0pt,全角字符不会相撞 |
这张表里藏着几处值得记住的反转。德语的 guillemets 变种用 \guillemotright 开、用 \guillemotleft 闭——也就是说 »…« 与法语的 « … » 朝向完全相反。法语要求引号内侧留一个不可断空格,csquotes 为此专门准备了 \mkfrenchopenquote 这个钩子。而西班牙语样式里还定义了 中间标记:多段落引文中,第二段起在行首重复一个 »,这是拉丁系排版的传统做法,\DeclareQuoteStyle 专门留了一个参数位给它。
有两条实践上的提醒。第一,csquotes.def 覆盖 29 种语言,没有韩语和中文样式。若有需要,可以用 \DeclareQuoteStyle 自行定义,或者直接借用字形一致的现成样式——现代横排的中文和韩文都可以照搬 american。第二,注意 babel 的语言快捷记号。德语 babel 会把 " 变成活动字符,让它后接反引号得到 \glqq、后接撇号得到 \grqq;这是个经典手法,但会把原稿绑死在德语上。单语言文档没问题,多语言的话还是靠 \enquote 更省事。
quote 和 quotation 的区别
区别只落在一点上:段落分隔用什么来显示。引文一旦超过三四行(大约四十个词),惯例就是不再用引号嵌在句子里,而是左右留白、单独立块。从这里开始有两条路。翻开 classes.dtx 的定义会看到,两个环境都建立在 list 之上,不同的只是传入的参数。quote 只设 \rightmargin\leftmargin,不加首行缩进。quotation 另外设了 \listparindent 1.5em、\itemindent \listparindent 和 \parsep 0pt plus 1pt:每段首行缩进 1.5em,段间空白几乎压到零——正是正文那种「靠缩进分段」的做法。
\begin{quote}
One paragraph, indented from both margins,
with no first-line indent at all.
\end{quote}
\begin{quotation}
First paragraph of a longer quotation. Its first line is indented.
Second paragraph. The indent, not blank space, marks the break,
which is why quotation is the right choice past one paragraph.
\end{quotation}| 环境 | 首行缩进 | 段间空白 | 适合 |
|---|---|---|---|
quote | 无 | 常规段落空白 | 单段引文、题辞、并列的短行 |
quotation | 1.5em | 几乎为零(0pt plus 1pt) | 跨段落的长引文、含对话的摘录 |
verse | −1.5em(悬挂) | 常规段落空白 | 诗歌、歌词,以及换行本身有含义的文本 |
这里提醒一个初学者常犯的错:英语排版里 单独立块的引文不加引号。缩进本身就是「这里是引文」的信号,再加一对“ ”等于把同一句话说两遍。quote 和 quotation 完全不插入引号,正是这一惯例的直接体现。别的传统未必如此——日文排版有时即使另起一块也保留 「 」,各领域、各出版社的做法并不一致。无论采用哪种,全文统一都比选哪一种更要紧。
排诗歌与歌词的 verse 环境
换行本身带有含义的文字要用 verse。行末由你用 \\ 决定,节与节之间用空行分开。看 classes.dtx 的定义,verse 把 \itemindent 设成 负的 1.5em,同时给 \leftmargin 加上 1.5em,这一组搭配产生的就是悬挂缩进。当一行诗排不下而折行时,只有折下来的部分往里缩 1.5em,于是读者一眼就能分清「新的一行」和「只是折过来的续行」。两个参数,诗的行结构就不会被版心宽度毁掉。
\begin{verse}
Roses are red, \\
Violets are blue, \\
This stanza ends here.
A new stanza starts after the blank line, and a line long enough to
run over gets a hanging indent so it still reads as a single verse.
\end{verse}\blockquote 按长度自动在行内与整块之间切换
csquotes 干脆把「在 quote 和 quotation 之间手动挑选」这件事整个取消了。\blockquote{…} 会实际测量内容长度,超过阈值就排成单独的块引文,不超过就排成带引号的行内引文。默认是 thresholdtype=lines、阈值 3 行,块引文使用的环境是 quote。用 \SetBlockThreshold{5} 和 \SetBlockEnvironment{quotation} 可以改;想按词数衡量就写 thresholdtype=words 配 threshold=50。此外 parthreshold 默认开启,因此引文内部只要有显式的分段或换行,无论长短一律排成块——正符合「多段引文必定另起一块」的直觉。
\usepackage[autostyle=true]{csquotes}
\SetBlockThreshold{3} % default: 3 lines
\SetBlockEnvironment{quote} % default: the quote environment
% ...
% Short -> stays inline, with quotation marks around it:
\blockquote{Brevity is the soul of wit.}
% Longer than the threshold -> set as an indented block, no marks:
\blockquote{A passage that runs past three printed lines of text is
set off on its own instead, and csquotes reaches that decision by
measuring the material rather than by asking the author to choose
between the quote and the quotation environment by hand.}
% Block quotation that also prints a citation (page 67 of doe2020):
\blockcquote[][67]{doe2020}{The argument develops over several
sentences and is long enough to be set as a block.}想让引文和出处一起排出来,就用 \blockcquote 及其行内版 \textcquote。写法是 \blockcquote[⟨前注⟩][⟨后注⟩]{⟨文献键⟩}{⟨正文⟩},后注通常放页码。实际调用哪个引用命令由 \SetCiteCommand 配置,所以同一份原稿在 biblatex 和 natbib 下都能用。若只要行内引用、且无论长短都必须带引号,请改用 \textquote{…}——与 \blockquote 不同,它绝不会切换成块。外语引文另有 \foreignblockquote{⟨语言⟩}{…}(引号与断词都随该语言)和 \hyphenblockquote{⟨语言⟩}{…}(只切换断词)。
顺带说说 csquotes 的来历。写这个宏包的是 Philipp Lehman,也就是 biblatex 的作者;版权声明记录了他从 2003 年到 2011 年的维护期,2015 年起由 Joseph Wright 接手(TeX Live 2024 收录的是 v5.2n)。知道引文与文献引用是同一个人重新设计的,就不难理解 \blockcquote 为何能和 biblatex 咬合得那么顺。
到底该用哪一个
- 简短的行内引用 →
\enquote{…}。字形由语言决定,嵌套与配对检查都自动。 - 单段的独立引文 →
quote。不需要宏包,也不加引号。 - 多段落的长引文 →
quotation(用首行缩进区分段落)。 - 诗歌或歌词 →
verse(\\结束一行,空行结束一节,折行悬挂)。 - 把长短判断交出去 →
\blockquote(默认 3 行;parthreshold使含分段的引文必成块)。 - 引文连同出处 →
\blockcquote/\textcquote(通过\SetCiteCommand接 biblatex 或 natbib)。 - 多语言文档 →
\usepackage[autostyle=true]{csquotes}与 babel/polyglossia 搭配使用。
最后一点。上面这些环境内部都建立在 list 之上,所以和 itemize 一样,会在自身前后加入垂直空白,也可以嵌套。想细调引文内部的断行位置,请看「换行与分段」;一般的缩进与居中请看「文本对齐」;引文周边常用的破折号与省略号,请看「引号与破折号」。