[Tex/LaTex] biblatex: Switching languages for *citations* according to the bibentry’s “hyphenation” field

babelbiblatexcitinghyphenationlanguages

Quoting from section 3.1.2.1 of the biblatex manual:

[The babel] option controls which
language environment is used if the
babel package is loaded and a
bibliography entry includes a
hyphenation field […]. Note that
biblatex automatically adjusts to
the main document language if babel
is loaded. In multilingual documents,
it will also continually adjust to the
current language as far as citations
and the default language of the
bibliography is concerned. This option
is for switching languages on a
per-entry basis within the
bibliography.

Suppose that, in a text with the main language "ngerman", I cite a bibentry with the hyphenation field "english". By default, the in-text-citation will use the hyphenation pattern for "ngerman". That is, if the citation style uses author names, titles or even full bibliographic data, hyphenation of these items is prone to be wrong. Case in point: The author William A. Fischel (an American) should be hyphenated "Fis-chel", but German hyphenation patterns will result in "Fi-schel".

My current workaround is to include any such author in TeX's hyphenation exception list, but this is clumsy and error-prone for longer texts. (Manually enclosing every citation in an appropriate otherlanguage environment is not an option for the same reasons.) My envisaged solution is to use the "hyphenation" field to automatically switch to the correct language in-text for every citekey. biblatex provides an \AtEveryCitekey hook (to be used only in the preamble), so this should be possible in principle. In the following example, I show that switching languages on a one-time basis is possible using \AtNextCitekey.

\documentclass{article}

\usepackage[english,ngerman]{babel}

\usepackage[style=authoryear,babel=hyphen]{biblatex}

\usepackage{filecontents}

\begin{filecontents}{\jobname.bib}
@book{Fis85,
  hyphenation = {english},
  author = {Fischel, William A.},
  year = {1985},
  title = {The economics of zoning laws: A property rights approach to American land use planning},
  location = {Baltimore},
  publisher = {Johns Hopkins University Press},
}
\end{filecontents}

\addbibresource{\jobname.bib}

\textwidth=290pt

% My current workaround: Include author names in the hyphenation exception list
% \hyphenation{Fis-chel}

% My envisaged solution: At every citekey, switch to the language defined in the bibentry's
%     "hyphenation" field. This doesn't work because babel strips away the escape character "\"
%     from "\thefield{hyphenation}"
% \AtEveryCitekey{\selectlanguage{\thefield{hyphenation}}}

\begin{document}

Dies hier ist ein Blindtext zum Testen von Textausgaben \autocite{Fis85}.

% The following code line shows that my envisaged solution (see above) would work if
%     "\thefield{hyphenation}" would be expanded to (in this case) "english"
%     (Note: "\AtNextCitekey" is the "one-time" variant of  "\AtEveryCitekey"
\AtNextCitekey{\selectlanguage{english}}

Dies hier ist ein Blindtext zum Testen von Textausgaben \autocite{Fis85}.

Dies hier ist ein Blindtext zum Testen von Textausgaben \autocite{Fis85}.

\printbibliography

\end{document}

So why doesn't my envisaged solution work? Trying

\AtEveryCitekey{\selectlanguage{\thefield{hyphenation}}}

results in the the following error message:

Package babel Error: You haven't defined the language thefield{hyphenation}

That is, instead of expanding \thefield{hyphenation} to "english" (as I naively assumed), babel strips away away the escape character \ from \thefield{hyphenation} and then complains about an unknown language. (According to section 7 of the babel manual, this stripping away is done for reasons of compatibility with the german package (which uses the syntax \selectlanguage{\german}.)

Sifting through biblatex.sty, I found the following code snippet that patches internal babel commands. It may well reveal what needs to be done to properly expand \thefield{hyphenation} to "english" in my above example — but to be honest, I have no clue what this code snippet does exactly.

\def\blx@mkbabel{%
  \patchcmd\bbl@set@language
    {\select@language}
    {\blx@langsetup\languagename\select@language}%
    {\ifdef\blx@thelangenv
       {\def\blx@beglang{%
          \blx@clearlang
      \begingroup
          \blx@imc@iffieldundef{hyphenation}
            {}
            {\blx@hook@initlang
         \def\blx@endlang{%
               \blx@hook@endlang
               \csname end\blx@thelangenv\endcsname
               \endgroup}%
             \csname\blx@thelangenv\expandafter\endcsname
               \expandafter{\abx@field@hyphenation}}}}
       {}%
     \blx@langsetup\bbl@main@language}
    {\blx@err@patch{'babel' package}%
     \blx@mknobabel}}

Long story, short question: How can I make my envisaged solution work, i.e. automatically switch languages for citations according to the bibentry's "hyphenation" field?

Best Answer

I think this works:

\makeatletter
\AtEveryCitekey{%
\blx@langsetup\abx@field@hyphenation%
\blx@hyphenreset%
}
\makeatother

In \abx@field@hyphenation is hyphenation value. Probably it needs some testing, if it is set.


edit:

Some time ago, I was looking at biblatex language switching because of problem with my citation style[1]. I didn't understand this code at all, so I ended with ugly hack[2].

But when I looked yesterday on biblatex's patch of babel you posted, I have found line

\blx@langsetup\languagename\select@language

Function \blx@langsetup uses edef to define \blx@languagename, which is used by macro \blx@hyphenreset to load hyphenation patterns, and then loads localization strings for given language. So in fact, instead of

\blx@langsetup\abx@field@hyphenation%

it is possible to use just

\edef\blx@languagename{\abx@field@hyphenation}%

Then there is problem with French language. When used as the main document language, instead of

... (Fis-
el 1985)...

there is

...(FISCHEL
1985)...

I think there is issue only with French, I tried Czech, Russian and Spanish and they worked correctly.

With babel, we can solve this issue with

\select@language\abx@field@hyphenation%

but, polyglossia in xelatex has same issue and this trick is there not working, I don't know how to fix that.

Anyway, if you don't need French with polyglossia, this is the current solution

\makeatletter
\AtEveryCitekey{%
\ifcsdef{abx@field@hyphenation}{%
\edef\blx@languagename{\abx@field@hyphenation}%
\select@language\abx@field@hyphenation%
\blx@hyphenreset%
}{}%
}
\makeatother

[1] Biblatex - using two languages in one reference entry

[2] Biblatex - using two languages in one reference entry

Related Question