biblatex: Preserve capitalisation in inproceedings/booktitle

From the bibliography style file apa.bbx,

\DeclareFieldFormat[inproceedings]{booktitle}{#1}

doesn't work because the booktitle field is set with \printfield[apacase]{booktitle}, where the apacase formatting directive is defined as

\DeclareFieldFormat{apacase}{\MakeSentenceCase*{#1}}

To preserve the source casing for the booktitle field in the @inproceedings entry type you can redefine the booktitle bibliography macro or the apacase directive in your document preamble. An example of the latter approach is:

\DeclareFieldFormat{apacase}{%
  \ifboolexpr{ test {\ifentrytype{inproceedings}}
    and ( test {\ifcurrentfield{booktitle}}
          or test {\ifcurrentfield{booksubtitle}} ) }
    {#1}{\MakeSentenceCase*{#1}}}

To avoid sentence casing in all but original titles (origtitle) and title add-ons use

\DeclareFieldFormat{apacase}{#1}

instead. Since biblatex-apa relies only on the starred variant \MakeSentenceCase* you can avoid all sentence casing by adding \DeclareCaseLangs{} to the preamble and making use of the hyphenation field in your bib file.

Note that you can avoid protecting some words from down-casing via the subtitle field. For example:

   title = {Being proactive},
   subtitle = {Where action research meets design research},

One can preserve specific capitalisation by simply putting the letter of question in curly braces. So

@inproceedings{Cole2005,
   author = {Cole, Robert and Purao, Sandeep and Rossi, Matti and Sein, Maung},
   booktitle = {{Proceedings} of the 26th {International} {Conference} on {Information} {Systems}},
   title = {{Being proactive: Where action research meets design research}},
   year = {2005}
}

will do the job. But most times it is way easier to put the whole line in curly braces, just as it is done with the title.


As I was looking for a convenient solution, at least for me, I wrote a little Python script that parses my local bib file produced by Mendeley. This script puts booktitles in two curly brackets.

import re
import fileinput

library = 'path/to/file'

import re

def re_sub_verbose(pattern, replace, string):
  def substitute(match):
    return match.expand(replace)

  result = re.sub(pattern, substitute, string)

  return result

for line in fileinput.input(library, inplace=1):
    print re_sub_verbose("booktitle = \{(.*)\},", "booktitle = {{\\1}},", line)