# Two or three letter initials in bibliography with Biblatex (again)

In French and some other European langages, given names should be abreviated keeping digraphs and trigraphs.

• John should be abreviated as J.
• Clare should be abreviated as Cl.
• Charles should be abreviated as Ch.
• Christine should be abreviated as Chr.
• Philippe should be abreviated as Ph.
• etc.

The classical solution was to modify the given name in the bibliographical data from

Charles

to

{\relax Ch}arles

A nice macro written by Yves de Saint-Pern uses the search and replace option with regexp in Biber/Biblatex to iterate over your bib file and insert on the fly

\relax in the author field.

However, the latest Biber breaks this possibility. A bib entry with a \relax in the author field will result in a faulty *.bbl file with unmatched braces. See here and here.

The only workaround is to use Biber extended name format which is cumbersome :

• It makes it impossible to edit your bibliography file in a GUI application
• It is a lot of manual work

Is there a possibility to modify Biber's initials creation routine to create correct giveni field if the given name starts with a list of digraphs and trigraphs ?

I include a MWE below :

\documentclass{article}
\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
% Extended name format
@book{Book1,
author = {family=Doe, given=Charles, given-i={Ch}},
title  = {An Important Book},
publisher = {Publisher},
date = {2012},
}
@book{Book2,
author = {Dolittle, Charlotte},
title  = {Another Important Book},
publisher = {Publisher},
date = {2014},
}
@book{Book3,
author = {Theodore Smith},
title  = {A very Important Book},
publisher = {Publisher},
date = {2016},
}

@book{Book4,
author = "Arnoux, Mathieu and Gazeau, Véronique and Demetz, Christine",
publisher = "Brepols",
shorttitle = "Les chanoines réguliers de la province de Rouen",
title = "{Des clercs au service de la réforme. Études et documents sur les chanoines réguliers de la province de Rouen}",
year = "2000"
}
\end{filecontents}
\usepackage[style=verbose,giveninits=true, backend=biber]{biblatex}
% Does not work anymore with the latest Biber
% \DeclareSourcemap{
%  \maps[datatype=bibtex]{
%     \map{
%     \step[fieldsource=author,
%             match={Charles},
%             replace=\regexp{\{\\relax \x20Ch\}arles}]
%   }
%  }
% }
\begin{document}

\cite{Book1}

\cite{Book2}

\cite{Book3}

\cite{Book4}
\end{document}


• Short answer: We can't change Biber's initial routine. Your only chance is that this is changed on the Biber side. Or that someone essentially does the RegEx to use the extended name format for you. Mar 24 '18 at 13:37
• It is just impossible to deal with all these hacky edge cases which insert macros into fields. One of the primary goals of biber is sorting and such macros have to be stripped for sorting, naturally. Such macro stripping and UTF8 conversion (without which sorting doesn't work - you can't properly sort \"A without conversion to UTF-8, for example) is basically a hard/impossible problem in general without slow state parsing. So, I have to concentrate on UTF-8 conversion and not stripping arbitrary macro constructions. @moewe's solution is the best idea.
– PLK
Mar 24 '18 at 21:53
• A workaround which may be acceptable for some use cases is to use the bibtex backend instead of the default biber (i.e. backend=bibtex option to the package). Then \relax will work, but the functionality of biblatex will be limited. Check the biblatex documentation, section 3.15, to see what are the specific limitations (I don't have a very good understanding of this topic). Sep 30 '20 at 12:40

If you can live with inputting names always as "Family, Given" we can automate using the extended name format.

\makeatletter
\def\do#1{%
\ifcsundef{blx@csv@datamodel@names}
{\csdef{blx@csv@datamodel@names}{#1}}
{\csappto{blx@csv@datamodel@names}{,#1}}}
\dolistcsloop{blx@datamodel@names}

\DeclareSourcemap{
\maps[datatype=bibtex]{
\map[foreach=\blx@csv@datamodel@names]{
\step[fieldsource=\regexp{$MAPLOOP}, match=\regexp{(\A|\s+and\s+)([a-z'\s]+)?\s*(.+?)\,\s+(Chr?|Th|Ph|[B-DF-HJ-NP-TV-XZ](?:l|r)|\w)(.+?)(?=\Z|\s+and\s+)}, replace=\regexp{$1 family=$3, prefix=$2, given=$4$5, given-i=\{$4\}}] } } } \makeatother  Splits off the initials with regexp and passes the name to the extended name format. This is now automatically done for all known name fields. The regex has been adapted from Two or three letter initials in bibliography with Biblatex. \documentclass{article} \usepackage{filecontents} \begin{filecontents}{\jobname.bib} % Extended name format @book{Book1, author = {Doe, Charles and Potter, William}, title = {An Important Book}, publisher = {Publisher}, date = {2012}, } @book{Book2, author = {Dolittle, Charlotte}, title = {Another Important Book}, publisher = {Publisher}, date = {2014}, } @book{Book3, author = {Smith, Theodore}, title = {A very Important Book}, publisher = {Publisher}, date = {2016}, } @book{Book4, address = "Turnhout", author = "Arnoux, Mathieu and Gazeau, Véronique and Demetz, Christine", publisher = "Brepols", shorttitle = "Les chanoines réguliers de la province de Rouen", title = "{Des clercs au service de la réforme. Études et documents sur les chanoines réguliers de la province de Rouen}", year = "2000" } \end{filecontents} \usepackage[style=verbose,giveninits=true, backend=biber]{biblatex} \makeatletter \def\do#1{% \ifcsundef{blx@csv@datamodel@names} {\csdef{blx@csv@datamodel@names}{#1}} {\csappto{blx@csv@datamodel@names}{,#1}}} \dolistcsloop{blx@datamodel@names} \DeclareSourcemap{ \maps[datatype=bibtex]{ \map[foreach=\blx@csv@datamodel@names]{ \step[fieldsource=\regexp{$MAPLOOP},
match=\regexp{(\A|\s+and\s+)([a-z'\s]+)?\s*(.+?)\,\s+(Chr?|Th|Ph|[B-DF-HJ-NP-TV-XZ](?:l|r)|\w)(.+?)(?=\Z|\s+and\s+)},
replace=\regexp{$1 family=$3, prefix=$2, given=$4$5, given-i=\{$4\}}]
}
}
}
\makeatother

\begin{document}

\cite{Book1}

\cite{Book2}

\cite{Book3}

\cite{Book4}
\end{document}


• Thank you very much. Do you think it would be possible to scan for a "von" part and label it as a prefix? Otherwise names get sorted in the bibliography and indexed as "von Savigny, Friedrich", whereas they should be "Savigny, Friedrich von". Mar 27 '18 at 8:49
• @ienissei I'll see what I can do later. But this is going to be really tricky. Essentially that would mean re-building BibTeX's name parsing with RegExp in Biber. Mar 27 '18 at 10:15
• @ienissei You'll also want to catch "de la" and "van de" etc., so we probably need ([a-z\s]+), I'll have a look later if that really works...+ Mar 27 '18 at 10:35
• @ienissei Thanks. ' is included in the answer now. I noticed that we get warnings about empty name parts now if the name does not have a "von" part. I'm quite sure these can be safely ignored, but they are present in the .blg file, so that's a bit annoying. I tried to also parse the Jr. part, but failed miserably. Mar 27 '18 at 16:27
• Will look into it and post anything good I come up with. Thanks for the help so far. Mar 27 '18 at 16:48

I have slightly modified the above answer to apply to authors and editors and to the abbreviation of Philippe.

\documentclass{article}
\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
@book{Book1,
author = {Doe, Charles and Potter, William},
title  = {An Important Book},
publisher = {Publisher},
date = {2012},
}
@book{Book2,
author = {Dolittle, Charlotte},
title  = {Another Important Book},
publisher = {Publisher},
date = {2014},
}
@book{Book3,
author = {Smith, Philippe},
title  = {A very Important Book},
publisher = {Publisher},
date = {2016},
}

@book{Book4,
editor = "Arnoux, Theodore and Gazeau, Véronique and Demetz, Christine",
publisher = "Brepols",
shorttitle = "Les chanoines réguliers de la province de Rouen",
title = "{Des clercs au service de la réforme. Études et documents sur les chanoines réguliers de la province de Rouen}",
year = "2000"
}
\end{filecontents}
\usepackage[style=verbose,giveninits=true, backend=biber]{biblatex}

\DeclareSourcemap{
\maps[datatype=bibtex]{
\map{
\step[fieldsource=author,
match=\regexp{(\A|\s+and\s+)(.+?)\,\s+(Chr?|Th|Ph|\w)(.+?)(?=\Z|\s+and\s+)},
replace=\regexp{$1 family=$2, given=$3$4, given-i=\{$3\}}] \step[fieldsource=editor, match=\regexp{(\A|\s+and\s+)(.+?)\,\s+(Chr?|Th|Ph|\w)(.+?)(?=\Z|\s+and\s+)}, replace=\regexp{$1 family=$2, given=$3$4, given-i=\{$3\}}]
}
}
}

\begin{document}

\cite{Book1}

\cite{Book2}

\cite{Book3}

\cite{Book4}
\end{document}


• I think @moewe's answer already did both things :) Mar 27 '18 at 8:56
• @ienissei Indeed, but I have to admit that I had forgotten to add the necessary code to the MWE. So my answer in its first version contained the full RegExp in the explanatory bit, but a less powerful RegExp in the MWE. I have since fixed this, and also updated the answer even more. Mar 27 '18 at 10:24

Here is another attempt based on @moewe's solution. It should fix some of the problems discovered in comments.

It does not fix the issue with accented letters. I have no idea why they do not get parsed properly into the given-i field.

MWE

\documentclass{article}

\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
@book{Book1,
author = {Savigny, Friedrich Carl von},
title  = {An Important Book},
publisher = {Publisher},
date = {2012},
}
@book{Book2,
author = {de La Vaissière, Claude-Henri},
title  = {Another Important Book},
publisher = {Publisher},
date = {2014},
}
@book{Book3,
author = {Durand, Jean-Philippe},
title  = {A very Important Book},
publisher = {Publisher},
date = {2016},
}
@book{Book4,
author = {de La Boétie, Étienne},
title  = {A very Important Book},
publisher = {Publisher},
date = {2016},
}
@book{Book5,
author = {Doe, Charles-Édouard},
title  = {A very Important Book},
publisher = {Publisher},
date = {2016},
}
@book{Book6,
author = {Dolittle, Étienne-Marie},
title  = {A very Important Book},
publisher = {Publisher},
date = {2016},
}
\end{filecontents}

\usepackage[style=verbose,giveninits=true, backend=biber]{biblatex}

\makeatletter
\def\do#1{%
\ifcsundef{blx@csv@datamodel@names}
{\csdef{blx@csv@datamodel@names}{#1}}
{\csappto{blx@csv@datamodel@names}{,#1}}}
\dolistcsloop{blx@datamodel@names}

\DeclareSourcemap{
\maps[datatype=bibtex]{
\map[foreach=\blx@csv@datamodel@names]{
\step[fieldsource=\regexp{$MAPLOOP}, match=\regexp{(\A|\s+and\s+)([a-z'\s]+)?\s*(.+?)\,\s+(Chr?|Th|Ph|[B-DF-HJ-NP-TV-XZ](?:l|r)|\w(?=\w+-))([\w\s]+)(?:(-)(Chr?|Th|Ph|[B-DF-HJ-NP-TV-XZ](?:l|r)|\w)([\w\s]+))?(?=\Z|\s+and\s+)}, replace=\regexp{$1 family=$3, prefix=$2, given=$4$5$6$7$8, given-i=\{$4$6$7\}}]
\step[fieldsource=\regexp{$MAPLOOP}, match=\regexp{(prefix=\,)}, replace=\regexp{}] } } } \makeatother \begin{document} Friedrich Carl von Savigny:\par \cite{Book1}\medskip Claude-Henri de La Vaissière:\par \cite{Book2}\medskip Jean-Philippe Durand:\par \cite{Book3}\medskip Étienne de La Boétie:\par \cite{Book4}\medskip Charles-Édouard Doe:\par \cite{Book5}\medskip Étienne-Marie Dolittle:\par \cite{Book6} \end{document}  As can be noted from the output above: • Names with von parts work properly (no support for Jr parts). • When a person has several first names, only the first one gets abbreviated (this is common practice when using several initial letters for a single name). • When a person has a composed name, including a hyphen, both parts of the name are properly abbreviated. And, as a workaround for the problem with accented letters, the regexp I use tries to minimise the number of cases in which we will use extended name format, so as to preserve native parsing of names (and the accented letters). At the moment, it means that: • Single or multiple first names starting with an accented letter will keep it • Accented initials in composed names will be converted to the non-accented version, as shown in the sample above. Here is the detailed code, largely inspired from @moewe: \def\do#1{% \ifcsundef{blx@csv@datamodel@names} {\csdef{blx@csv@datamodel@names}{#1}} {\csappto{blx@csv@datamodel@names}{,#1}}} \dolistcsloop{blx@datamodel@names} \DeclareSourcemap{ \maps[datatype=bibtex]{ \map[foreach=\blx@csv@datamodel@names]{ \step[fieldsource=\regexp{$MAPLOOP},
match=\regexp{(\A|\s+and\s+)([a-z'\s]+)?\s*(.+?)\,\s+(Chr?|Th|Ph|[B-DF-HJ-NP-TV-XZ](?:l|r)|\w(?=\w+-))([\w\s]+)(?:(-)(Chr?|Th|Ph|[B-DF-HJ-NP-TV-XZ](?:l|r)|\w)([\w\s]+))?(?=\Z|\s+and\s+)},
replace=\regexp{$1 family=$3, prefix=$2, given=$4$5$6$7$8, given-i=\{$4$6$7\}}] \step[fieldsource=\regexp{$MAPLOOP},
match=\regexp{(prefix=\,)},
replace=\regexp{}]
}
}
}


Stripping it down, in case someone else wants to toy with the regexp:

• (\A|\s+and\s+): Look for name boundaries ("and" is the separator). Matches $1. • ([a-z'\s]+)?: Look for the von part, which only interests us when it is lowecased (as it will influence sorting). Matches $2.
• \s*(.+?)\,\s+: Look for the last name, followed by a comma. Matches $3. • (Chr?|Th|Ph|[B-DF-HJ-NP-TV-XZ](?:l|r)|\w(?=\w+-)): Look for the strings that should be used as inits in the first name, or alternatively, take the first letter (\w), but only if the first name is composite (look ahead for \w+-, i.e. letters followed by a hyphen). This allows us to exclude some accented initials from the test, so as to preserve them. Matches $4.
• ([\w\s]+): Look for the rest of the first name, including any subsequent first names. Matches $5. • (?:(-)(Chr?|Th|Ph|[B-DF-HJ-NP-TV-XZ](?:l|r)|\w)([\w\s]+))?: In case the name is a composite one, repeat the last two steps, but look for a starting hyphen (matches $6), then the initial string or letter (matches $7, no need to look ahead here), then the rest of the first name (matches $8).
• (?=\Z|\s+and\s+): Look ahead for name boundaries = end.

Also, biber issues warnings when given a an empty von part. Hence, we need a second step to look for prefix=\, and clear it.