
Проблема
Я создаю собственный стиль biblatex и хочу иметь поддержку bibstrings, похожую на ту, что month
есть у поля в общих реализациях. То есть, если я помещаю что-то в скобки, {something}
, то содержимое, something
, отображается в поле. Но если у меня есть что-то без скобок, оно интерпретируется как bibstring и преобразуется в его определение.
Я могу частично добиться этого, проверив, является ли содержимое поля bibstring, через \ifbibstring
(и друзей). Однако это работает только если содержимое всегда находится в скобках. Если это не так, biber выдает ошибку и не передает поле для дальнейшей обработки.
Например, приведенный ниже код генерирует предупреждающее сообщение
ПРЕДУПРЕЖДЕНИЕ - Подсистема BibTeX: /tmp/M3YJZ8wGD7/mwe.bib_28410.utf8, строка 21, предупреждение: неопределенный макрос "mytitle"
и это заставляет biber не создавать это поле в .bbl
файле. Я нашел похожую ошибку наbiblatex/biber: использование строковых макросов из одного файла в нескольких секциях ссылок, но это не решает мою проблему.
МВЭ
Это моя минимальная реализация для демонстрации моей проблемы.
% !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}
Выходной ток:
Ожидаемый результат:
Вопрос
Обратите внимание, что я ожидаю того же поведения с bibstrings, например month
. Если у меня есть поле без скобок, случай записи test4
в .bib
, который должен быть преобразован с использованием определения bibstring. Но если у меня есть то же определение со скобками, например в test3
, вместо этого должно быть выведено содержимое.
Как этого добиться с помощью индивидуального стиля?
решение1
Здесь есть как минимум два понятия «строка». Ни одно из них само по себе не делает то, что вам нужно. Только их комбинация может это сделать.
@string
с
Во-первых, есть @string
. @string
есть способ вставить один и тот же текст в несколько .bib
записей без необходимости каждый раз перепечатывать весь текст. Эта функция работает исключительно на .bib
уровне файла.
Запись @string
имеет идентификатор (точно так же, как ключ входа обычной .bib
записи) и может быть вызвана по этому имени.
@string{brontostring = {On the Theory of Brontosauruses}}
Содержимое a @string
можно использовать, указав идентификатор строки в качестве значения поля.безбрекеты.
@book{foo,
author = {Anne Elk},
title = brontostring,
date = {1970},
}
Biber (или BibTeX) разрешает эти строки немедленно при чтении файла .bib
. Одно предостережение заключается в том, что @string
s должны быть определены до того, как их можно будет использовать. В частности, вы не можете использовать произвольный текст без фигурных скобок, @string
работают только известные s. Затем мы остаемся с
@book{foo,
author = {Anne Elk},
title = {On the Theory of Brontosauruses},
date = {1970},
}
При дальнейшей обработке записи не остается никаких указаний на то, что текст происходит из @string
.
Это позволит вам вводить произвольный текст в запись. Текст не будет изменяться с помощью biblatex
, но вы можете изменить его, загрузив разные .bib
файлы с разными определениями для одной и той же строки. Это то, что ieeetran
происходит с IEEEabrv.bib
и IEEEfull.bib
. Вы загружаете либо IEEEabbrv.bib
для получения сокращенного названия журнала, либо IEEEfull.bib
для получения полных названий журналов.
По сути, строки месяцев работают аналогичным образом.
jan
Это @string
for 1
, feb
for 2
и так далее.
@string
не используйте фигурные скобки в .bib
файле, если они используются в качестве значений полей.
библиографические строки
Затем есть вторая, совершенно не связанная концепция «строк», а именно bibstrings. Это те, на которые вы ссылаетесь с помощью \ifbibstring
, \bibstring
и \NewBibliographyString
. Bibstrings являются частью biblatex
функции локализации и позволяют вам переводить определенные термины на другие языки. Обычно они определяются в .lbx
файлах, но их значения также могут быть переопределены в преамбуле.
Bibstrings можно использовать с , \bibstring{<bibstringid>}
где <bibstringid>
— имя bibstring, определенное с \NewBibliographyString
. В идеале <bibstringid>
также будет иметь значение в .lbx
файле, в противном случае <bibstringid>
будет напечатано жирным шрифтом.
Вся обработка дат намного сложнее, но для этого ответа мы можем предположить, что biblatex
есть функция, \mkbibmonth
которая сопоставляет 1 с \bibstring{january}
, 2 с \bibstring{february}
и т. д. Поэтому при \mkbibmonth{7}
вызове это приводит к \bibstring{july}
тому, что в вашем документе печатается «Июль», если активным языком является английский, или «Юли», если активным языком является немецкий.
Более простой и типичный пример для bibstrings — это pubstate
поле. Формат поля pubstate
для
\DeclareFieldFormat{pubstate}{\ifbibstring{#1}{\bibstring{#1}}{#1}}
Есть несколько предопределенных строк, которые вы можете использовать для pubstate
поля, например
inpress
, forthcoming
, , submitted
. Если вы используете одну из них, то есть у вас есть
pubstate = {inpress},
в одной из ваших .bib
записей, то biblatex
не печатает "inpress" в документе, вместо этого он использует перевод этого термина, как указано в bibstring. (Конечно, biblatex
с радостью использовал бы и любую другую bibstring, которую вы ему укажете, pubstate = {january}
это тоже сработает.) Поле печатается как есть, если bibstring с таким именем отсутствует, поэтому pubstate = {foonostring}
просто печатает 'foonostring'.
При bibstrings
вводе в .bib
файле всегда присутствуют фигурные скобки.
Сравнение двух типов струн
Насколько мне известно, других комбинаций @strings
и bibstrings, biblatex
которые работают точно так же, нет. Я сильно подозреваю, что месяцы @string
были реализованы только из соображений обратной совместимости.
Итак, как мы увидели, в целом существует два способа создания контекстно-зависимого вывода.
@string
s решено бэкэндом- (
.lbx
) bibstrings разрешеныbiblatex
Какой из них более подходит, зависит от вашего варианта использования.
@string
s кажутся более подходящими, если вы просто хотите сэкономить на наборе текста или если вы хотите иметь возможность переключаться между несколькими формами ввода (длинные и короткие названия журналов). В целом @string
s не привязаны к языкам или локалям. Bibstrings — это то, что вам нужно, если вам нужна настоящая локализация.
На примере вашего вопроса я не могу точно сказать, какой из двух подходов будет более полезным в вашем случае.
Можем ли мы получить то, что вы хотите?
Если вы настаиваете на схеме, которую вы описали в своем вопросе, то это почти возможно, если объединить два подхода. Я не думаю, что это особенно хорошая идея, но давайте.
Для каждого возможного значения без скобок вам нужно определить a @string
с текстом замены. Если вам нужно портативное решение, это нужно сделать в специальном .bib
файле, который вам нужно будет загрузить во все ваши проекты.
@string{bracelessa = {bracelessa}}
@string{bracelessb = {bracelessb}}
Затем сделайте нагрудные струны bracelessa
, bracelessb
известныеbiblatex
\NewBibliographyString{bracelessa}
\NewBibliographyString{bracelessb}
и определить их
\DeclareBibliographyStrings{%
inherit = {american},
bracelessa = {{A title}{A t\addddot}},
bracelessb = {{B title}{B t\addddot}},
}
Затем используйте формат поля
\DeclareFieldFormat[test]{title}{\ifbibstring{#1}{\bibstring{#1}}{#1}}
для рассматриваемой области.
Сейчас
title = bracelessa,
напечатает «Заголовок» в вашем документе.
Почему это не дает вам именно то, что вы описываете?
Во-первых, ввод без скобок не является произвольным. Вам нужно определить как a, так @string
и соответствующий bibstring
. Во-вторых, title = {something}
не всегда будет отображать something
. Если вы напишете title = {bracelessa}
'A title', то вместо этого выйдет . Коллизии можно усложнить, выбрав более нелепые имена для bibstrings, но они всегда будут возможны, поскольку нет способа узнать, было ли задано значение поля напрямую или через @string
.