12

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,
    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}
% Does not work anymore with the latest Biber
% \DeclareSourcemap{
%  \maps[datatype=bibtex]{
%     \map{
%     \step[fieldsource=author, 
%             match={Charles},
%             replace=\regexp{\{\\relax \x20Ch\}arles}]
%   }
%  }
% }
\addbibresource{\jobname.bib}
\begin{document}

\cite{Book1}

\cite{Book2}

\cite{Book3}

\cite{Book4}
\end{document}

enter image description here

3
  • 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.
    – moewe
    Mar 24, 2018 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, 2018 at 21:53
  • 1
    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).
    – Szabolcs
    Sep 30, 2020 at 12:40

3 Answers 3

11

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

\addbibresource{\jobname.bib}
\begin{document}

\cite{Book1}

\cite{Book2}

\cite{Book3}

\cite{Book4}
\end{document}

enter image description here

12
  • 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".
    – ienissei
    Mar 27, 2018 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.
    – moewe
    Mar 27, 2018 at 10:15
  • 1
    @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...+
    – moewe
    Mar 27, 2018 at 10:35
  • 1
    @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.
    – moewe
    Mar 27, 2018 at 16:27
  • 1
    Will look into it and post anything good I come up with. Thanks for the help so far.
    – ienissei
    Mar 27, 2018 at 16:48
6

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 [Fix in edit below].

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}
\addbibresource{\jobname.bib}

\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}

enter image description here

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 [now solved] 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.


Edit: In the comments below, @andc discovered a bug in the above code and, while I do not have time to investigate it properly, I do have a newer version of the code that does not have this bug. As a bonus, this edit also solves the previous problem with accented first letters.

Here is the code:

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

\map[foreach=\blx@csv@datamodel@names,overwrite=true]{%
    \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)(.+?)(?:(\-(?:Chr?|Th|Ph|[B-DF-HJ-NP-TV-XZ](?:l|r)|(?:À|Â|Ä|Ç|É|È|Ê|Ë|Î|Ï|Ô|Ö|Ù|Û|Ü|Ÿ|Æ|Œ)|\w))(.+?))?(?=\Z|\s+and\s+)},
        replace=\regexp{$1 family=$3, prefix=$2\\relax, given=$4$5$6$7, given-i=\{$4$6\}}]
    \step[fieldsource=\regexp{$MAPLOOP},
        match=\regexp{(prefix=\,)},
        replace=\regexp{}]
}
2
  • 1
    With your code there is the problem if we have two authors and name of second one begins with digraph, eg author = {Doe, John and Smith, Friedrich}, we get warning from biber: WARN - Invalid namepart '' found in extended name format name 'author' in entry 'Book1', ignoring and incorrect output: Doe and Fr. An Important Book. Publisher, 2012.
    – andc
    Jul 3, 2022 at 13:00
  • 1
    @andc Sorry for the delay, I don't connect very often. If I test the code I wrote in this answer, the bug does happen. If I run my current code, it no longer does. So what I will do is post the new code in an edit. I don't have time to figure out the differences.
    – ienissei
    Sep 6, 2022 at 19:59
4

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,
    address = "Turnhout",
    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\}}]
    }
  }
}

\addbibresource{\jobname.bib}
\begin{document}

\cite{Book1}

\cite{Book2}

\cite{Book3}

\cite{Book4}
\end{document}

enter image description here

2
  • I think @moewe's answer already did both things :)
    – ienissei
    Mar 27, 2018 at 8:56
  • 1
    @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.
    – moewe
    Mar 27, 2018 at 10:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .