latex中biblatex参考文献的标点、分隔符、本地化字符串中英文切换

引言

在中文环境下使用中文的标点符号是一个常见的需求,所以有时我们需要对这些符号进行中英文(全半角)切换。latex中利用biblatex生成参考文献尽管具有超强的定制能力,但由于不同的内容具有不同的实现,因此很多符号具有不一样的接口,修改起来其实是比较麻烦的,所以这里做一个较为详细的总结。

参考文献中三个内容可能是需要切换中英文符号的,主要是标点(比如全角的和半角的,)、本地化字符串(比如中文的“和”与英文“and”)、分隔符(比如中文书名号与英文的双引号,中文的括号和英文的括号)等。
其中三者在引用的标注标签和文献著录表中可能有不同的的修改需求。

所以下面我们区分标注标签和文献著录表两个部分做总结,需要注意的是,下面的所有讲解biblatex-gb7714-2015为基础做的,尽管其保持了biblatex的原始接口,但由于考虑新功能的实现,还是有一些新增加的接口的。

引用标注标签中的中英文切换

引用标注标签中的切换内容相对较少,所以我们从它开始,主要以gb7714-2015ay样式为基础做示例(因为顺序编码制的数字标签相对比较简单)。

本地化字符串相对较少,主要是:和、等这两个。其默认设置如下

\DefineBibliographyStrings{english}{
	andincitecn = {和},
	andincite   = {\addcomma\space},
	andothersincitecn={等},
	andothersincite={et al\adddot},
}

通常情况下,我们默认使用gbcitelocal=gb7714-2015选项,那么对于中文的文献,其标注使用andincitecn、andothersincitecn,对于英文的文献其标注使用andincite、andothersincite。
如果使用选项gbcitelocal=chinese,不管中英文文献,都使用andincitecn、andothersincitecn。
如果使用选项gbcitelocal=english,不管中英文文献,andincite、andothersincite。

由于选项已经提供了足够的修改空间,所以我们通常只需要设置选择即可。
若需要更换不同的字符串,比如把和改成&符号等。
根据全局和局部的修改需求,可以做两种方式修改:

全局的修改,那么在导言区,修改:

\DefineBibliographyStrings{english}{
	andincite   = { \& },
}

若局部的修改,那么在文档任意位置上,修改:

\setlocalbibstring{andincite}{ \& }

比如要在某一幅图上修改本地化字符串,那么可以使用该命令,比如:

\begin{figure}[!htbp]
  \centering
  \fbox{\parbox{5cm}{example fig\\在双语图题中强制使用某种语言的方式}}
  \bicaption{具体见\cite{walls2013drought}}
    {See{\setlocalbibstring{andothersincite}{et al.}\cite{walls2013drought}}}\label{fig:bi:lang2}
\end{figure}

前述gbcitelocal设置是设置计数器gbcitelocalcase的数值,等于0是gb7714-2015选项,等于1是chinese选项,等于2是english选项。很多的局部修改可以利用计数器的局部修改来达成。

由于标注中通常只给英文作者的姓,所以英文姓名中的标点通常不用怎么考虑,中文自然也不用考虑。所以,主要要修改的标点包括:

  • 姓名与年份之间的标点:nameyeardelim,往往需要根据标注命令做不同的设置,因为像textcite这样的命令需要将作者姓名作为文中的内容
  • 多个文献之间的标点:multicitedelim
  • 相同作者压缩不同年份之间的标点:compcitedelim,textcitedelim
  • 相同作者相同年份压缩附加标签之间的标点:compextradelim
  • 包围整个标签或者年份的括号:bibleftparen,bibrightparen,mkbibleftborder,mkbibrightborder

因此我们可以在导言区做如下设置,那么默认情况将使用中文标点,当我们局部设定gbcitelocalcase计数器只为2时,就会使用英文标点。

\DeclareDelimFormat[cite,parencite,pagescite]{nameyeardelim}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{\addcomma\addspace}{,}}
\DeclareDelimFormat[textcite]{nameyeardelim}{\addthinspace}
\renewcommand*{\multicitedelim}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{\addsemicolon\addspace}{;}}
\renewcommand*{\compcitedelim}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{\addcomma\addspace}{,}}
\renewcommand*{\textcitedelim}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{\addcomma\addspace}{,}}
\renewcommand*{\compextradelim}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{\addcomma\addspace}{,}}
\renewcommand*{\bibleftparen}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{(}{(}}
\renewcommand*{\bibrightparen}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{)}{)}}
\renewcommand*{\mkbibleftborder}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{(}{(}}
\renewcommand*{\mkbibrightborder}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{)}{)}}

比如:

\documentclass{article}
\usepackage{ctex}
\usepackage[backend=biber,style=gb7714-2015ay,gbcitelocal=chinese]{biblatex}

\DeclareDelimFormat[cite,parencite,pagescite]{nameyeardelim}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{\addcomma\addspace}{,}}
\DeclareDelimFormat[textcite]{nameyeardelim}{\addthinspace}
\renewcommand*{\multicitedelim}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{\addsemicolon\addspace}{;}}
\renewcommand*{\compcitedelim}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{\addcomma\addspace}{,}}
\renewcommand*{\compextradelim}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{\addcomma\addspace}{,}}
\renewcommand*{\bibleftparen}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{(}{(}}
\renewcommand*{\bibrightparen}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{)}{)}}
\renewcommand*{\mkbibleftborder}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{(}{(}}
\renewcommand*{\mkbibrightborder}{\ifnumcomp{\value{gbcitelocalcase}}{=}{2}{)}{)}}

\DefineBibliographyStrings{english}{
        andincitecn       = {和},
        andothersincitecn = {等},
}

\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}

@article{Aaa_2021,
author = {Aaa, A. A. and Bbb, B. B. and Ccc, C. C.},
title = {Title title title title title},
journal = {Nature},
volume = {11},
number = {1},
pages = {11-12},
year = {2021},
type = {Journal Article}
}

@article{Aaa_2018,
author = {Aaa, A. A. and Bcc, B. B. and Caa, C. C.},
title = {Title title title title title},
journal = {Science},
volume = {11},
number = {1},
pages = {11-12},
year = {2018},
type = {Journal Article}
}

@article{Aaa_2018a,
author = {Aaa, A. A. and Bcc, B. B. and Caa, C. C.},
title = {Title title title title titleA},
journal = {Science},
volume = {11},
number = {2},
pages = {11-12},
year = {2018},
type = {Journal Article}
}

@article{Bbb_2019,
author = {Bbb, A. A. and Bcc, B. B. and Ccc, C. C.},
title = {Title title title title title},
journal = {eCell},
volume = {11},
number = {1},
pages = {11-12},
year = {2018},
type = {Journal Article}
}
\end{filecontents}
\addbibresource[location=local]{\jobname.bib}

\begin{document}

中文段落\cite{Aaa_2018,Aaa_2018a}\cite{Aaa_2021,Aaa_2018}\cite{Aaa_2018,Bbb_2019}
中文段落\textcite{Aaa_2018,Aaa_2018a},\textcite{Aaa_2021,Aaa_2018} 发现 \parencite{Aaa_2018,Bbb_2019}

{
\defcounter{gbcitelocalcase}{2}
english paragraph \cite{Aaa_2018,Aaa_2018a}\cite{Aaa_2021,Aaa_2018}\cite{Aaa_2018,Bbb_2019}
english paragraph \textcite{Aaa_2018,Aaa_2018a},  \textcite{Aaa_2021,Aaa_2018} find \parencite{Aaa_2018,Bbb_2019}

}
\printbibliography
\end{document} 

就可以得到中文段落中使用中文标点,英文段落中使用英文标点,其中英文段落使用\defcounter{gbcitelocalcase}{2}局部化计数器。正常情况下,中文文献中没有英文段落,所以也无需进行局部设置。

文献著录表中的中英文切换

类似的文献著录表本地化字符串,也是由选项控制中英文的选择的。
通常情况下,我们默认使用gbbiblocal=gb7714-2015选项,那么对于中文的文献,使用andcn、andothercn、bytranslatorcn、incn,对于英文的文献其标注使用and、andothers、bytranslator、in。
如果使用选项gbbiblocal=chinese,不管中英文文献,都使用andcn、andotherscn、bytranslatorcn、incn。
如果使用选项gbbiblocal=english,不管中英文文献,and、andothers、bytranslator、in。

由于选项已经提供了足够的修改空间,所以我们通常只需要设置选择即可。
若需要更换不同的字符串,比如把和改成符号等。
通常做全局的修改即可,比如:

\DefineBibliographyStrings{english}{
	and   = {、},
}

文献表中标点相对更多,所以稍复杂一些。而且也可以有不同的选择方式:比如中文文献使用中文的标点英文文献使用英文标点,或者全部文献使用中文标点,或者全部文献使用英文标点。
由于文献表的本地化字符串默认是中英文区分的,但标点默认是使用英文的,所以我们不能使用gbbiblocal这一个选项同时来控制标点,所以可以增加新的控制选项。

如果只是简单的修改,我们也不需要增加选项,直接修改即可:

姓名内部的标点用如下接口修改:

\def\gbcaselocalset{%
\renewrobustcmd*{\bibinitperiod}{}%
\renewcommand*{\revsdnamepunct}{}%
\renewrobustcmd*{\bibinitdelim}{}%
}

姓名之间的标点,用如下接口修改:

\DeclareDelimFormat[bib,biblist]{nameyeardelim}{,}%\addcomma\addspace
\DeclareDelimFormat[bib,biblist]{multinamedelim}{,}
\DeclareDelimFormat[bib,biblist]{finalnamedelim}{,}
\DeclareDelimFormat[bib,biblist]{andothersdelim}{,}
\renewcommand{\aftertransdelim}{,}

文献著录条目中各单元的分隔标点,页面前标点,出版地址后标点,用如下接口修改:

\DeclareDelimFormat{bibpagespunct}{\iffieldequalstr{userd}{chinese}{,}{,}}
\renewcommand*{\newunitpunct}{,}
\renewcommand*{\finentrypunct}{\iffieldequalstr{userd}{chinese}{。}{\adddot}}
\renewcommand{\publocpunct}{\iffieldequalstr{userd}{chinese}{:}{\addcolon\addspace}}

文献条目著录项的包围标点则需要从域格式进行修改,比如:期刊文献的标题用书名号或者双引号标记出来:

\DeclareFieldFormat[article]{title}{\iffieldequalstr{userd}{chinese}{《#1》}{\mkbibquote{#1}\isdot}}

更多的内容可以参考:chinese-erj.bbx,gb7714-CCNU.bbx,gb7714-CCNUay.bbx。

需要注意的是:由于要实现在某些域信息缺失情况下的标点变换,标点的实现需要利用不同的机制来处理,比如:作者年份制文献表中的article类型,考虑中文全局的标点,考虑年份信息是否前移,考虑期刊名是否存在,考虑卷信息是否存在,这里面产生了比较复杂的组合,简单依赖标点的延迟输出机制可能不够,需要在利用在不同的层次上做分别处理组合起来达成最终的期望目的,详见journal+issuetitle\bbx@opt@mergedate@none宏的变化。

小结

初步总结了latex中基于biblatex生成参考文献的标点等内容的中英文切换方法,以便读者使用。

需要注意的是这篇文章给出的是整体切换的方法,若是要根据文献内容的中英文区分,则情况不同,通常情况(gblocal=gb7714-2015)下,文献的本地化字符串本来就是区分中英文的,只有标点默认是英文的,那么还需要对上述的标点做语言判断后设置,具体可以参考chinese-erj.cbx,gb7714-CCNU.cbx,gb7714-CCNUay.cbx,issue50等。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐