3

Problem

I'm creating a custom biblatex style, and wanted to have a support for bibstrings similar to what the month field has on the common implementations. That is, if I put something in brackets, {something}, then the content, something, is rendered in the field. But if I have something without brackets it is interpreted as a bibstring and converted to its definition.

I can partially achive that by checking if the content of the field is a bibstring, through \ifbibstring (and friends). However, that only works if the content is always within brackets. If it isn't biber gives and error and does not passes the field for further processing.

For example, the code below generates the warning message

WARN - BibTeX subsystem: /tmp/M3YJZ8wGD7/mwe.bib_28410.utf8, line 21, warning: undefined macro "mytitle"

and that makes biber to not create that field into the .bbl file. I found a similar error on biblatex/biber: using strings macros from one file in multiple refsections, but that doesn't address my problem.

MWE

This is my minimal implementation to demonstrate my problem.

% !BIB program = biber
\documentclass{article}

\usepackage{filecontents}
\begin{filecontents}{\jobname.bib}
  @test{test1,
    title = {A},
    year = {1995},
  }

  @test{test2,
    title = {B},
    year = {1994},
  }

  @test{test3,
    title = {mytitle},
    year = {1998},
  } 

  @test{test4,
    title = mytitle,
    year = {1998},

  }
\end{filecontents}

\begin{filecontents}{test.dbx}
  \DeclareDatamodelFields[type=field, datatype=literal]{title}

  \DeclareDatamodelFields[type=field, datatype=datepart]{year}

  \DeclareDatamodelEntryfields[test]{%
    year,%
    title%
  }
\end{filecontents}

\begin{filecontents}{english-test.lbx}
  \InheritBibliographyExtras{english}

  % Bibliography strings
  \NewBibliographyString{mytitle}

  \DeclareBibliographyStrings{%
    inherit = {american},
    mytitle = {{my title}{my title}},
  }
\end{filecontents}

\begin{filecontents}{test.bbx}
  \RequireBibliographyStyle{standard}

  % map language
  \DeclareLanguageMapping{english}{english-test}

  % Dummy driver for testing
  \DeclareBibliographyDriver{test}{%
    \usebibmacro{begentry}%
    \printfield{title}%
    \newunit%
    \printfield{year}%
    \newunit%
    \usebibmacro{finentry}%
  }

  \DeclareFieldFormat[test]{title}{%
    \ifbibstring{#1}{\bibstring{#1}}{#1}%
  }
\end{filecontents}

\usepackage[backend=biber, bibstyle=test]{biblatex}
\addbibresource{\jobname.bib}


\begin{document}

  \nocite{*}
  \printbibliography

\end{document}

Current output:

enter image description here

Expected output:

enter image description here

Question

Note that I'm expecting the same behavior with the bibstrings like month. If I have the field without the brackets, the case of test4 entry in .bib, that should be converted using the definition of the bibstring. But if I have the same definition with brackets, like in test3, the content should be printed instead.

How can I achieve that with a custom style?

  • BibTeX/Biber interpret field contents without braces as 'BibTeX MACRO/@string' (the former is defined in a .bst, the latter in the .bib). So your plan goes wrong at the parsing stage if mytitle is not a @string. – moewe Jun 30 '17 at 20:59
  • Would you be OK with simply adding the braces and letting biblatex check if the bibstring exists? (I.e. use your test3 approach?) That is what many biblatex fields do that accept keywords and literal text. - Maybe I should better ask: What is it about the brace-less approach you need? Are you very likely to end up in a situation where you have the same field contents once with braces and once without. – moewe Jun 30 '17 at 21:01
  • Well, I am defining it so I can do both. But I want to be as general as possible. So, I was thinking to have the brace-less option and then when it has braces it will be interpreted as content (as in my example). Is there a way to convert the bibstrings in the .lbx into a .bst automatically? – adn Jun 30 '17 at 21:15
  • I don't think we can turn .lbxs into a .bst. That wouldn't help much here. biblatex only uses one central .bst that should not be modified (in theory it could be, but we really shouldn't), so that approach is out. Instead of using your .lbx file you could of course define a new .bib with @string entries and load that as well, then you could use the brace-less approach. – moewe Jul 1 '17 at 6:07
  • 1
    I use @string definitions extensively and they work just the same with Biblatex as they did with BibTeX. – cfr Jul 2 '17 at 20:22
3

There are at least two notions of 'string' here. Neither does on its own what you want. Only a combination of the two can do that.

@strings

Firstly, there is @string. @string is a way to insert the same text into multiple .bib entries without having to re-type the entire text every time. This features works entirely on the .bib file level.

A @string entry has an ID (just like the entry key of a usual .bib entry) and can be called by that name.

@string{brontostring = {On the Theory of Brontosauruses}}

The contents of a @string can be used by giving the string ID as a field value without the braces.

@book{foo,
  author = {Anne Elk},
  title  = brontostring,
  date   = {1970},
}

Biber (or BibTeX) resolves these strings immediately when reading the .bib file. One caveat is that @strings must be defined before they can be used. In particular you can't use arbitrary text without braces, only known @strings work. We are then left with

@book{foo,
  author = {Anne Elk},
  title  = {On the Theory of Brontosauruses},
  date   = {1970},
}

When the entry is processed further there is no indication left that the text stems from a @string.

This would allow you to inject arbitrary text into an entry. The text would not be changeable by biblatex, but you could change it by loading different .bib files with different definitions for the same string. This is what ieeetran does with IEEEabrv.bib and IEEEfull.bib. You load either IEEEabbrv.bib to get abbreviated journal name or IEEEfull.bib to get full journal names.

For all intents and purpses month strings work in a similar way. jan is a @string for 1, feb for 2 and so on.

@strings don't use braces in the .bib file when they are used as field values.

bibliography strings

Then there is a second, completely unrelated concept of 'strings', namely bibstrings. Those are the ones you refer to with \ifbibstring, \bibstring and \NewBibliographyString. Bibstrings are part of biblatex's localisation feature and allow you to translate certain terms into other languages. Normally they are defined in the .lbx files, but their values can be overridden in the preamble as well.

Bibstrings can be used with \bibstring{<bibstringid>} where <bibstringid> is the name of a bibstring defined with \NewBibliographyString. Ideally <bibstringid> will also have received a value in the .lbx file, otherwise <bibstringid> is printed in bold.

The entire date handling is much more complicated, but for this answer we can assume that biblatex has a function called \mkbibmonth that maps 1 to \bibstring{january}, 2 to \bibstring{february} etc. So when \mkbibmonth{7} is called, this results in \bibstring{july} and so 'July' is printed in your document if English is the active language or 'Juli' if German is the active language.

A more simple and more typical example for bibstrings is the pubstate field. The field format for pubstate is

\DeclareFieldFormat{pubstate}{\ifbibstring{#1}{\bibstring{#1}}{#1}}

There are some predefined strings you can use for the pubstate field, for example inpress, forthcoming, submitted. If you use one of those, i.e. you have

pubstate = {inpress},

in one of your .bib entries, then biblatex does not print "inpress" in the document, instead it uses the translation of that term as given in the bibstring. (Of course biblatex would happily use any other bibstring you give it as well, pubstate = {january} would work as well.) The field is printed as is if there is no bibstring with that name, so pubstate = {foonostring} would simply print 'foonostring'.

With bibstrings the input in the .bib file always features braces.

Comparison of the two string types

As far as I know there are no other combinations of @strings and bibstrings in biblatex that works in exactly the same way. I strongly suspect that the month @strings were only implemented for backwards compatibility reasons.

So as we have seen there are in general two ways to create context-dependent output.

  1. @strings resolved by the backend
  2. (.lbx) bibstrings resolved by biblatex

Which one is more approriate depends on your use case. @strings seem more appropriate if you just want to save on typing, or if you want to have a way to switch between several forms of input (long vs short journal names). In general @strings are not tied to languages or locales. Bibstrings are the way to go if you want true localisation.

I can't quite tell by the example from your question which of the two approaches would be more useful in your use case.

Can we get what you want?

If you insist on the scheme you described in your question, then that is almost possible by combining the two approaches. I don't think that is a particularly good idea, but let's go.

For each possible value without braces, you need to define a @string with a replacement text. If you want a portable solution, this needs to be done in a special .bib file that you will need to load in all of your projects.

@string{bracelessa = {bracelessa}}
@string{bracelessb = {bracelessb}}

Then make the bibstrings bracelessa, bracelessb known to biblatex

\NewBibliographyString{bracelessa}
\NewBibliographyString{bracelessb}

and define them

\DeclareBibliographyStrings{%
  inherit = {american},
  bracelessa = {{A title}{A t\addddot}},
  bracelessb = {{B title}{B t\addddot}},
}

Then use the field format

\DeclareFieldFormat[test]{title}{\ifbibstring{#1}{\bibstring{#1}}{#1}}

for the field in question.

Now

title = bracelessa,

will print 'A title' in your document.

Why does that not give you exactly what you describe?

Firstly, the braceless input is not arbitrary. You need to define both a @string and an appropriate bibstring. Secondly, title = {something} will not always render something. If you write title = {bracelessa} 'A title' will come out instead. Collisions can be made harder by choosing more ridiculous names for the bibstrings, but they will always be possible since there is no way to find out if a field value was given directly or via a @string.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.