
Problema
Estoy creando un estilo biblatex personalizado y quería tener un soporte para bibstrings similar al que month
tiene el campo en las implementaciones comunes. Es decir, si pongo algo entre corchetes {something}
, entonces el contenido, something
se representa en el campo. Pero si tengo algo sin corchetes, se interpreta como una cadena y se convierte a su definición.
Puedo lograrlo parcialmente verificando si el contenido del campo es un bibstring, a través de \ifbibstring
(y amigos). Sin embargo, eso sólo funciona si el contenido siempre está entre paréntesis. Si no es biber da error y no pasa el campo para su posterior procesamiento.
Por ejemplo, el siguiente código genera el mensaje de advertencia
ADVERTENCIA - Subsistema BibTeX: /tmp/M3YJZ8wGD7/mwe.bib_28410.utf8, línea 21, advertencia: macro no definida "mytitle"
y eso hace que Biber no cree ese campo en el .bbl
archivo. Encontré un error similar enbiblatex/biber: uso de macros de cadenas de un archivo en múltiples secciones de referencia, pero eso no soluciona mi problema.
MWE
Esta es mi implementación mínima para demostrar mi problema.
% !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}
Salida de corriente:
Rendimiento esperado:
Pregunta
Tenga en cuenta que espero el mismo comportamiento con baberos como month
. Si tengo el campo sin corchetes, el caso de test4
la entrada en .bib
, debe convertirse usando la definición de bibstring. Pero si tengo la misma definición entre corchetes, como en test3
, el contenido debería imprimirse.
¿Cómo puedo lograr eso con un estilo personalizado?
Respuesta1
Aquí hay al menos dos nociones de "cuerda". Tampoco lo hace por sí solo lo que quieres. Sólo una combinación de los dos puede lograr eso.
@string
s
En primer lugar, hay @string
. @string
es una forma de insertar el mismo texto en varias .bib
entradas sin tener que volver a escribir el texto completo cada vez. Esta característica funciona completamente a .bib
nivel de archivo.
Una @string
entrada tiene un ID (igual que la clave de entrada de una .bib
entrada habitual) y se le puede llamar por ese nombre.
@string{brontostring = {On the Theory of Brontosauruses}}
El contenido de a @string
se puede utilizar proporcionando el ID de cadena como valor de campo.sinlos brackets.
@book{foo,
author = {Anne Elk},
title = brontostring,
date = {1970},
}
Biber (o BibTeX) resuelve estas cadenas inmediatamente al leer el .bib
archivo. Una advertencia es que @string
los s deben definirse antes de poder usarse. En particular, no puedes usar texto arbitrario sin llaves, solo @string
trabajos conocidos. Nos quedamos entonces con
@book{foo,
author = {Anne Elk},
title = {On the Theory of Brontosauruses},
date = {1970},
}
Cuando la entrada se procesa más, no queda ninguna indicación de que el texto proviene de un archivo @string
.
Esto le permitiría inyectar texto arbitrario en una entrada. El texto no se podrá cambiar con biblatex
, pero se puede cambiar cargando diferentes .bib
archivos con diferentes definiciones para la misma cadena. Esto es lo que ieeetran
hace con IEEEabrv.bib
y IEEEfull.bib
. Puede cargar IEEEabbrv.bib
para obtener el nombre abreviado de la revista o IEEEfull.bib
para obtener los nombres completos de la revista.
Para todos los efectos, las cadenas de meses funcionan de manera similar.
jan
es un @string
for 1
, feb
for 2
y así sucesivamente.
@string
Los s no usan llaves en el .bib
archivo cuando se usan como valores de campo.
cadenas de bibliografía
Luego hay un segundo concepto de "cuerdas", que no tiene ninguna relación, es decir, las cuerdas de babero. Esos son a los que te refieres con \ifbibstring
, \bibstring
y \NewBibliographyString
. Bibstrings son parte de biblatex
la función de localización de y le permiten traducir ciertos términos a otros idiomas. Normalmente se definen en los .lbx
archivos, pero sus valores también se pueden anular en el preámbulo.
Las cadenas de baberos se pueden usar con \bibstring{<bibstringid>}
dónde <bibstringid>
está el nombre de una cadena de baberos definida con \NewBibliographyString
. Lo ideal <bibstringid>
es que también haya recibido un valor en el .lbx
archivo, de lo contrario <bibstringid>
se imprime en negrita.
El manejo completo de la fecha es mucho más complicado, pero para esta respuesta podemos asumir que biblatex
tiene una función llamada \mkbibmonth
que asigna 1 a \bibstring{january}
, 2 a \bibstring{february}
, etc. Entonces, cuando \mkbibmonth{7}
se llama, esto da como resultado que \bibstring{july}
se imprima 'julio' en su documento si está en inglés. es el idioma activo o 'Juli' si el alemán es el idioma activo.
Un ejemplo más simple y típico de tirantes es el pubstate
campo. El formato de campo para pubstate
es
\DeclareFieldFormat{pubstate}{\ifbibstring{#1}{\bibstring{#1}}{#1}}
Hay algunas cadenas predefinidas que puede utilizar para el pubstate
campo, por ejemplo
inpress
, forthcoming
, submitted
. Si usas uno de esos, es decir, tienes
pubstate = {inpress},
en una de sus .bib
entradas, entonces biblatex
no imprime "inpress" en el documento, sino que utiliza la traducción de ese término tal como figura en el bibstring. (Por supuesto, biblatex
también usaría cualquier otro bibstring que le dé, pubstate = {january}
también funcionaría). El campo se imprime tal como está si no hay un bibstring con ese nombre, por lo que pubstate = {foonostring}
simplemente imprimiría 'foonostring'.
Con bibstrings
la entrada en el .bib
archivo siempre aparecen llaves.
Comparación de los dos tipos de cadenas.
Hasta donde yo sé, no hay otras combinaciones de @strings
y baberos biblatex
que funcionen exactamente de la misma manera. Sospecho firmemente que los meses @string
solo se implementaron por razones de compatibilidad con versiones anteriores.
Como hemos visto, en general hay dos formas de crear resultados dependientes del contexto.
@string
s resuelto por el backend- (
.lbx
) tirantes resueltos porbiblatex
Cuál es más apropiado depende de su caso de uso.
@string
Esto parece más apropiado si solo desea ahorrar al escribir, o si desea tener una forma de cambiar entre varias formas de entrada (nombres de revistas largos o cortos). En general, @string
los s no están vinculados a idiomas o configuraciones regionales. Los baberos son el camino a seguir si desea una verdadera localización.
No puedo decir con el ejemplo de su pregunta cuál de los dos enfoques sería más útil en su caso de uso.
¿Podemos conseguir lo que quieres?
Si insiste en el esquema que describió en su pregunta, entonces eso es casi posible combinando los dos enfoques. No creo que sea una buena idea, pero vámonos.
Para cada valor posible sin llaves, debe definir a @string
con un texto de reemplazo. Si desea una solución portátil, debe hacerlo en un .bib
archivo especial que deberá cargar en todos sus proyectos.
@string{bracelessa = {bracelessa}}
@string{bracelessb = {bracelessb}}
Luego haz que los baberos bracelessa
, bracelessb
conocidos porbiblatex
\NewBibliographyString{bracelessa}
\NewBibliographyString{bracelessb}
y definirlos
\DeclareBibliographyStrings{%
inherit = {american},
bracelessa = {{A title}{A t\addddot}},
bracelessb = {{B title}{B t\addddot}},
}
Luego use el formato de campo.
\DeclareFieldFormat[test]{title}{\ifbibstring{#1}{\bibstring{#1}}{#1}}
para el campo en cuestión.
Ahora
title = bracelessa,
imprimirá 'Un título' en su documento.
¿Por qué eso no te da exactamente lo que describe?
En primer lugar, la entrada sin llaves no es arbitraria. Es necesario definir tanto a @string
como apropiado bibstring
. En segundo lugar, title = {something}
no siempre se renderizará something
. Si escribes title = {bracelessa}
'Un título' aparecerá en su lugar. Las colisiones se pueden hacer más difíciles eligiendo nombres más ridículos para las cadenas de baberos, pero siempre serán posibles ya que no hay manera de saber si un valor de campo se proporcionó directamente o mediante un archivo @string
.