(Answer rewritten following release of bib2gls
v1.0.)
There's a new command line application called bib2gls
that can be used to convert .bib
files to a format that can be input using glossaries-extra
's \GlsXtrLoadResources
command. The record
package option is required. The application requires at least Java 7, although newer versions are recommended (Java 7 has reached its end of life and is now deprecated). It also needs at least v1.12 of glossaries-extra
, but works better with the latest version.
The application performs two functions in one:
- fetches the information from the
.bib
file(s) according to the information found in the .aux
file (like bibtex
);
- performs hierarchical sorting and collates locations (like
makeindex
or xindy
).
This means you can use JabRef to manage the entries. Unlike makeindex
, xindy
and bibtex
, the file created by bib2gls
isn't the formatted list but the entry definitions provided in the order obtained from sorting. Only those entries that were selected from the .bib
file are defined and since they have been defined in the appropriate order, the glossary can simply be displayed using \printunsrtglossary
(or \printunsrtglossaries
), which is provided by glossaries-extra
.
The record
package option automatically switches on undefaction=warn
, which means that if you try to reference (with \gls
etc) an undefined entry then you just get a warning instead of an error. On the first LaTeX run the entries aren't defined (as with \cite
). This means that iterative commands like \glsaddall
don't work. Instead you can use selection=all
in the options of \GlsXtrLoadResources
.
If you already have existing .tex
files containing all your entry definitions (that's loaded with \input
or \loadglsentries
) then you can use the supplementary application convertgls2bib
to convert it to a .bib
file for use with bib2gls
. For example, suppose entries.tex
contains:
\newglossaryentry{sample}{name={sample},description={an example}}
\newabbreviation{html}{HTML}{Hypertext Markup Language}
\newterm[plural=geese]{goose}
\newterm[see={[\seealsoname]goose}]{duck}
then
convertgls2bib entries.tex entries.bib
will create the file entries.bib
that contains:
% Encoding: UTF-8
@entry{sample,
name = {sample},
description = {an example}
}
@abbreviation{html,
short = {HTML},
long = {Hypertext Markup Language}
}
@index{goose,
plural = {geese}
}
@index{duck,
seealso = {goose}
}
The .bib
encoding can be changed using --bibenc
<encoding> and the .tex
encoding can be specified using --texenc
<encoding>. For example:
convertgls2bib --texenc UTF-8 --bibenc UTF-8 entries.tex entries.bib
The .bib
format doesn't permit spaces in labels so you can use --space-sub
<replacement> to replace spaces with <replacement>. For example:
convertgls2bib --space-sub '-' entries.tex entries.bib
or
convertgls2bib --space-sub '' entries.tex entries.bib
Remember that you'll need to make the relevant changes in your \gls
etc argument to reflect this substitution.
bib2gls
has a primitive LaTeX interpreter to allow it to deduce the sort
value if omitted. If you use @preamble
to provide commands, bib2gls
will try to add them to the interpreter's list of known commands. You can store the @preamble
code in separate .bib
files if the provided commands are used in entries defined in multiple .bib
files. It may be that you don't want the interpreter to pick up some command definitions, so you could divide the @preamble
up into two files, say glossdefs-interpret.bib
and glossdefs-nointerpret.bib
.
For example, suppose I need:
\providecommand{\strong}[1]{\textbf{\color{red}#1}}
\providecommand{\swap}[2]{#2 (#1)}
and suppose I start with just one .bib
file called entries.bib
:
@preamble{"\providecommand{\strong}[1]{\textbf{\color{red}#1}}
\providecommand{\swap}[2]{#2 (#1)}"}
@index{example,
name={\strong{\swap{stuff}{example}}}
}
@index{sample}
@index{test}
@index{foo}
@index{bar}
Here's the test document test.tex
:
\documentclass{article}
\usepackage{color}
\usepackage[record,style=indexgroup]{glossaries-extra}
\GlsXtrLoadResources[src={entries},selection=all]
% adjust indexgroup style:
\renewcommand{\glstreenamefmt}[1]{#1}
\renewcommand{\glstreegroupheaderfmt}[1]{\textbf{#1}}
\begin{document}
\printunsrtglossaries
\end{document}
The build process is:
pdflatex test
bib2gls --group test
pdflatex test
(The --group
switch is needed because I'm using a glossary style that has letter groups.) The result looks like:

Inspecting test.glstex
(the file created by bib2gls
) shows that the sort
value for example
is
sort={redexample (stuff)}
This is because bib2gls
has picked up the definitions of both \strong
and \swap
from @preamble
, so it expands
\strong{\test{stuff}{example}
to
\textbf{\color{red}example (stuff)}
and then ignores \textbf
and \color
leaving redexample (stuff)
, which is why the example
entry ends up in the R letter group.
I can use interpret-preamble=false
to prevent bib2gls
from trying to interpret the contents of @preamble
(it will just write the contents to the .glstex
file):
\GlsXtrLoadResources[
src={entries},% definitions are in entries.bib
selection=all,% select all entries
interpret-preamble=false% don't interpret @preamble
]
Now the document looks like:

Inspecting the .glstex
file shows that the sort
value for example
has been set as:
sort={stuffexample}
This is because bib2gls
now doesn't recognise \strong
or \swap
so it interprets \strong{\test{stuff}{example}}
as simply stuffexample
, which is why example
now ends up in the S letter group. What's needed is for bib2gls
to pick up the definition of \swap
but not \strong
, so I need to create the file glossdefs-nointerpret.bib
that contains:
@preamble{"\providecommand{\strong}[1]{\textbf{\color{red}#1}}"}
and glossdefs-interpret.bib
that contains:
@preamble{"\providecommand{\swap}[2]{#2 (#1)}"}
The document is now:
\documentclass{article}
\usepackage{color}
\usepackage[record,style=indexgroup]{glossaries-extra}
\GlsXtrLoadResources[src={glossdefs-nointerpret},interpret-preamble=false]
\GlsXtrLoadResources[src={glossdefs-interpret,entries},selection=all]
% adjust indexgroup style:
\renewcommand{\glstreenamefmt}[1]{#1}
\renewcommand{\glstreegroupheaderfmt}[1]{\textbf{#1}}
\begin{document}
\printunsrtglossaries
\end{document}
which now results in:

You can have multiple \GlsXtrLoadResources
. Any definitions found in @preamble
will be remembered for the next resource set so the above can also be:
\documentclass{article}
\usepackage{color}
\usepackage[record,style=indexgroup]{glossaries-extra}
\GlsXtrLoadResources[src={glossdefs-nointerpret},interpret-preamble=false]
\GlsXtrLoadResources[src={glossdefs-interpret}]
\GlsXtrLoadResources[src={entries},selection=all]
% adjust indexgroup style:
\renewcommand{\glstreenamefmt}[1]{#1}
\renewcommand{\glstreegroupheaderfmt}[1]{\textbf{#1}}
\begin{document}
\printunsrtglossaries
\end{document}
You can have multiple .bib
files listed in src
, in which case they'll all be sorted together. Each \GlsXtrResources
set is sorted independently of the other sets. Suppose testfile1.bib
contains:
@index{duck}
@index{zebra}
@index{aardvark}
and testfile2.bib
contains:
@index{caterpillar}
@index{bee}
@index{wombat}
and test.tex
contains:
\documentclass{article}
\usepackage[record,style=indexgroup]{glossaries-extra}
\GlsXtrLoadResources[src={testfile1,testfile2},selection=all]
% adjust indexgroup style:
\renewcommand{\glstreenamefmt}[1]{#1}
\renewcommand{\glstreegroupheaderfmt}[1]{\textbf{#1}}
\begin{document}
\printunsrtglossaries
\end{document}
then the result is

However, if I load the .bib
files using two separate resource commands:
\documentclass{article}
\usepackage[record,style=indexgroup]{glossaries-extra}
\GlsXtrLoadResources[src={testfile1},selection=all]
\GlsXtrLoadResources[src={testfile2},selection=all]
% adjust indexgroup style:
\renewcommand{\glstreenamefmt}[1]{#1}
\renewcommand{\glstreegroupheaderfmt}[1]{\textbf{#1}}
\begin{document}
\printunsrtglossaries
\end{document}
then the result is a bit weird:

but I can make use of this to alter the normal letter grouping:
\documentclass{article}
\usepackage[record,style=indexgroup]{glossaries-extra}
\GlsXtrLoadResources[src={testfile1},
group={Group 1},
selection=all]
\GlsXtrLoadResources[src={testfile2},
sort={letter-nocase-reverse},
group={Group 2},
selection=all]
% adjust indexgroup style:
\renewcommand{\glstreenamefmt}[1]{#1}
\renewcommand{\glstreegroupheaderfmt}[1]{\textbf{#1}}
\begin{document}
\printunsrtglossaries
\end{document}
(For illustrative purposes, I've sorted the second set differently.) This produces:

If you have any abbreviations you need to set the abbreviation style before the resource command. For example, suppose entries-abbrv.bib
contains:
@string{ssi={server-side includes}}
@string{html={hypertext markup language}}
@abbreviation{shtml,
short="shtml",
long= ssi # " enabled " # html,
description={a combination of \gls{html} and \gls{ssi}},
seealso={html,ssi}
}
@abbreviation{html,
short ="html",
long = html,
description={a markup language for creating web pages}
}
@abbreviation{ssi,
short="ssi",
long = ssi,
description={a simple interpreted server-side scripting language}
}
and test.tex
contains:
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[record,style=indexgroup]{glossaries-extra}
\setabbreviationstyle{long-short-sc-desc}
\GlsXtrLoadResources[src={entries-abbrv}]
\begin{document}
First use: \gls{shtml}. Next use: \gls{shtml}.
\printunsrtglossaries
\end{document}
Note that although shtml
has been used in the document, the dependent entries html
and ssi
are automatically selected. The build process is still:
pdflatex test
bib2gls --group test
pdflatex test
This is different to makeglossaries
which requires an extra makeglossaries
and pdflatex
to index the dependents. However the corresponding locations aren't picked up until a subsequent bib2gls
and pdflatex
call. Then the result looks like:

I can suppress the indexing in the glossary by changing the format to glsignore
, which bib2gls
recognises as a special ignored location:
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[record,style=indexgroup]{glossaries-extra}
\setabbreviationstyle{long-short-sc-desc}
\GlsXtrLoadResources[src={entries-abbrv}]
\begin{document}
First use: \gls{shtml}. Next use: \gls{shtml}.
\GlsXtrSetDefaultNumberFormat{glsignore}
\printunsrtglossaries
\end{document}

If I want to use the long-short-sc
style instead I can tell bib2gls
to ignore the description
field provided in the .bib
file:
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[record,style=indexgroup]{glossaries-extra}
\setabbreviationstyle{long-short-sc}
\GlsXtrLoadResources[src={entries-abbrv},
ignore-fields={description}]
\begin{document}
First use: \gls{shtml}. Next use: \gls{shtml}.
\printunsrtglossaries
\end{document}
This produces:

If I change my mind and decide I actually want normal upper case short forms instead of using \textsc
I can tell bib2gls
to change the case of the short
field:
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[record,style=indexgroup]{glossaries-extra}
\setabbreviationstyle{long-short}
\GlsXtrLoadResources[src={entries-abbrv},
short-case-change={uc},
ignore-fields={description}]
\begin{document}
First use: \gls{shtml}. Next use: \gls{shtml}.
\printunsrtglossaries
\end{document}
This produces:

Now let's suppose I've been using the \newdualentry
example command described in the glossaries
manual. The closest matching entry type is @dualentryabbreviation
, so I'm going to change entries-abbrv.bib
to use that instead of @abbreviation
:
@string{ssi={server-side includes}}
@string{html={hypertext markup language}}
@dualentryabbreviation{shtml,
short="shtml",
long= ssi # " enabled " # html,
description={a combination of \gls{html} and \gls{ssi}},
seealso={html,ssi}
}
@dualentryabbreviation{html,
short ="html",
long = html,
description={a markup language for creating web pages}
}
@dualentryabbreviation{ssi,
short="ssi",
long = ssi,
description={a simple interpreted server-side scripting language}
}
The document needs the abbreviations
package option, otherwise all the terms and abbreviations will end up in the main
glossary:
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[record,abbreviations,style=indexgroup]{glossaries-extra}
\setabbreviationstyle{long-short-sc}
\GlsXtrLoadResources[src={entries-abbrv}]
\begin{document}
First use: \gls{shtml}. Next use: \gls{shtml}.
\printunsrtglossaries
\end{document}
This produces:

Here's an example of a hierarchical index. The file entries.bib
contains:
@index{birds}
@index{duck,parent={birds}}
@index{goose,plural={geese},parent={birds}}
@index{swan,parent={birds}}
@index{chicken,parent={birds}}
@index{vegetable}
@index{cabbage,parent={vegetable}}
@index{minerals}
@index{quartz,parent={minerals}}
@index{corundum,parent={minerals}}
@index{amber,parent={minerals}}
@index{gypsum,parent={minerals}}
@index{aardvark}
@index{bard}
@index{buzz}
@index{item}
@index{subitem,parent={item}}
@index{subsubitem,parent={subitem}}
@index{parentid,name={parent name}}
@entry{child,parent={parentid},description={an example}}
The file test.tex
contains:
\documentclass{article}
\usepackage[record,stylemods={mcols},style=mcolindexgroup]{glossaries-extra}
\GlsXtrLoadResources[src={entries.bib}]
% adjust mcolindexgroup style:
\renewcommand{\glstreenamefmt}[1]{#1}
\renewcommand{\glstreegroupheaderfmt}[1]{\textbf{#1}}
\begin{document}
\gls{duck}.
\gls{quartz}, \gls{corundum}, \gls{amber}.
\gls{aardvark}, \gls{bard}, \gls{buzz}.
\gls{vegetable}, \gls{cabbage}.
\gls{subsubitem}.
\gls{child}.
\printunsrtglossaries
\end{document}
The resulting document looks like:

The duck's siblings haven't been selected, so the duck entry looks a little lonely. We can neaten the list by flattening the duck, which involves adjusting the name
, text
and parent
to shift it up one hierarchical level. The parent bird
entry is then no longer required and can be removed.
\documentclass{article}
\usepackage[record,stylemods={mcols},style=mcolindexgroup]{glossaries-extra}
\GlsXtrLoadResources[src={entries.bib},
flatten-lonely=postsort% flatten lonely children
]
% adjust mcolindexgroup style:
\renewcommand{\glstreenamefmt}[1]{#1}
\renewcommand{\glstreegroupheaderfmt}[1]{\textbf{#1}}
\begin{document}
\gls{duck}.
\gls{quartz}, \gls{corundum}, \gls{amber}.
\gls{aardvark}, \gls{bard}, \gls{buzz}.
\gls{vegetable}, \gls{cabbage}.
\gls{subsubitem}.
\gls{child}.
\printunsrtglossaries
\end{document}
This now produces:

The duck has now been flattened but not the cabbage. This is because the parent entry (vegetable) has been indexed in the document, so it can't be removed. The cabbage can be flattened by changing the flatten lonely rule but its parent still can't be removed:
\documentclass{article}
\usepackage[record,stylemods={mcols},style=mcolindexgroup]{glossaries-extra}
\GlsXtrLoadResources[src={entries.bib},
flatten-lonely=postsort,% flatten lonely children
flatten-lonely-rule=discard unrecorded
]
% adjust mcolindexgroup style:
\renewcommand{\glstreenamefmt}[1]{#1}
\renewcommand{\glstreegroupheaderfmt}[1]{\textbf{#1}}
\begin{document}
\gls{duck}.
\gls{quartz}, \gls{corundum}, \gls{amber}.
\gls{aardvark}, \gls{bard}, \gls{buzz}.
\gls{vegetable}, \gls{cabbage}.
\gls{subsubitem}.
\gls{child}.
\printunsrtglossaries
\end{document}
The result is:

The bib2gls
user manual contains a full description of all entry types, but here's a summary:
@entry
required fields: description
and name
or parent
. If name
is omitted it's obtained from the parent name. If sort
is omitted it's obtained from name
.
@symbol
required fields: name
or parent
. If name
is omitted description
is also required and the name
is obtained from the parent name. If sort
is omitted it's obtained from the entry's label.
@number
as @symbol
@index
no required fields. If name
is omitted it's taken from the entry's label. If sort
is omitted it's obtained from the name
.
@abbreviation
required fields: long
and short
. If sort
is omitted it's taken from the short
field.
@acronym
as @abbreviation
@dualentry
required fields: name
and description
. If sort
is omitted it's taken from name
. This also creates a corresponding entry with the label dual.
label that has the name
and description
flipped.
@dualentryabbreviation
required fields: short
, long
, description
. The primary entry is an abbreviation (sorted according to short
) and the dual entry is a regular term (sorted according to long
).
@dualsymbol
required fields: name
and symbol
. This creates a corresponding entry with the label dual.
label that has the name
and symbol
flipped.
@dualnumber
as @dualsymbol
@dualabbreviation
required fields: short
, long
, dualshort
and duallong
. This creates a corresponding abbreviation with the label dual.
label that has the short
and dualshort
flipped and long
and duallong
flipped.
@dualacronym
as @dualabbreviation
The base glossaries
package provides the fields: name
, description
, parent
, descriptionplural
, text
, first
, plural
, firstplural
, symbol
, symbolplural
, sort
, type
, user1
, user2
, user3
, user4
, user5
, user6
, nonumberlist
, see
, short
, shortplural
, long
and longplural
and (if \makenoidxglossaries
) loclist
.
For the .bib
file it's best to avoid sort
, type
and nonumberlist
. There's greater flexibility with the \GlsXtrLoadResources
options. Don't set loclist
as it's a private field with its own custom format.
The extension package provides additional fields: category
, alias
, seealso
and (if the record
option is used) group
.
In addition bib2gls
recognises the fields: dualshort
, dualshortplural
, duallong
, duallongplural
, dualplural
. It also provides fields for its own private use (so don't use these in the bib
file, but you can access them in the document when provided): location
, dual
, childcount
.
The glossaries-accsupp
package (\usepackage[accsupp]{glossaries-extra}
) provides: access
, textaccess
, firstaccess
, pluralaccess
, firstpluralaccess
, symbolaccess
, symbolpluralaccess
, descriptionaccess
, descriptionpluralaccess
, longaccess
, shortaccess
, longpluralaccess
, shortpluralaccess
.
The glossaries-prefix
package provides: prefix
, prefixplural
, prefixfirst
and prefixfirstplural
.
If you provide your own fields using commands like \glsaddkey
, put the definition before the first instance of \GlsXtrLoadResources
.
text
defaults to the same value asname
,plural
defaults totext
withs
appended); it's possible to add custom fields, so there isn't a fixed set of fields (e.g.glossaries-accsup.sty
,glossaries-prefix.sty
andglossaries-extra.sty
add extra fields); thetype
field may need changing according to the document; abbreviations may need different handling.