# Format page numbers in biblatex

Consider the following biblatex/biber minimal example:

\documentclass{article}

\usepackage{filecontents}
\begin{filecontents*}{references.bib}
@article{abc,
author  = {A Author},
title   = {The title},
journal = {Journal of Journals},
volume  = {12},
number  = {34},
year    = {1234},
pages   = {12345-23456}
}
\end{filecontents*}

\usepackage{biblatex,siunitx}

\begin{document}

\nocite{*}

\printbibliography

Current page number format: 12345--23456

Ideal page number format: \num{12345}--\num{23456}

\end{document}


I'd like to format the page numbers using siunitx's \num command, yielding a range that looks like this:

How can I do that?

We can modify the command \mknormrange to wrap all page numbers in siunitx's \num command. Then we only need to make sure to apply \mknormrange also to the pages field format (it normally is not applied to that field because Biber does enough pre-processing already).

biblatex is quite lenient as to what is regarded as a page number and allows strings other than integers to pass as page numbers (for example 122a, iv), this solution only applies \num to those strings passing the stricter \ifinteger test. The original definition of the macros modified here can be found in biblatex.sty. Essentially we just add the \ifinteger test at each call to \blx@range@out@value and wrap the page number in \num if it is true. For example the original definition of \blx@normrange@process was

\def\blx@normrange@process#1#2{%
\blx@range@out@value{#1\bibrangedash#2}}


\def\blx@normrange@process#1#2{%
\ifinteger{#1}
{\ifinteger{#2}}
{\@secondoftwo}
{\blx@range@out@value{\num{#1}\bibrangedash\num{#2}}}
{\blx@range@out@value{#1\bibrangedash#2}}}


In total

\documentclass{article}

\usepackage{biblatex,siunitx}

\DeclareFieldFormat{pages}{\mkpageprefix[pagination][\mknormrange]{#1}}

\makeatletter
\def\blx@normrange@split#1{%
\def\blx@normrange@abort{%
\ifinteger{#1}
{\blx@range@out@value{\num{#1}}}
{\blx@range@out@value{#1}}}%
\blx@imc@ifpages{#1}
{\blx@normrange@range#1\bibrangedash\bibrangedash&}
{\blx@normrange@abort}}

\def\blx@normrange@range#1\bibrangedash#2\bibrangedash#3&{%
\ifblank{#3}
{\blx@normrange@hyphen#1--&}
{\ifblank{#2}
{\ifinteger{#1}
{\blx@range@out@value{\num{#1}\bibrangedash}}
{\blx@range@out@value{#1\bibrangedash}}}
{\ifblank{#1}
{\ifinteger{#2}
{\blx@range@out@value{\bibrangedash\num{#2}}}
{\blx@range@out@value{\bibrangedash#2}}}
{\blx@range@process{#1}{#2}}}}}

\def\blx@normrange@hyphen#1-#2-#3&{%
\ifblank{#3}
{\blx@normrange@abort}
{\ifblank{#2}
{\ifblank{#1}
{\let\blx@tempb\@empty}
{\def\blx@tempb{#1}}%
\blx@normrange@hyphen@i#3&}
{\ifblank{#1}
{\ifinteger{#2}
{\blx@range@out@value{\bibrangedash\num{#2}}}
{\blx@range@out@value{\bibrangedash#2}}}
{\blx@range@process{#1}{#2}}}}}

\def\blx@normrange@hyphen@i#1-#2&{%
\def\blx@range@out@value@numdash{\blx@range@out@value{\num{#1}\bibrangedash}}%
\ifblank{#1#2}
{\expandafter\ifinteger\expandafter{\blx@tempb}
{\expandafter\blx@range@out@value@numdash
\expandafter{\blx@tempb}}
{\expandafter\blx@range@out@value
\expandafter{\blx@tempb\bibrangedash}}}
{\notblank{#1}
{\ifdefempty\blx@tempb
{\ifinteger{#1}
{\blx@range@out@value{\bibrangedash\num{#1}}}
{\blx@range@out@value{\bibrangedash#1}}}
{\expandafter\blx@range@process
\expandafter{\blx@tempb}{#1}}}
{\blx@normrange@hyphen@i#2&}}}

\def\blx@normrange@process#1#2{%
\ifinteger{#1}
{\ifinteger{#2}}
{\@secondoftwo}
{\blx@range@out@value{\num{#1}\bibrangedash\num{#2}}}
{\blx@range@out@value{#1\bibrangedash#2}}}
\makeatother

\usepackage{filecontents}
\begin{filecontents*}{\jobname.bib}
@article{abc,
author  = {A Author},
title   = {The title},
journal = {Journal of Journals},
volume  = {12},
number  = {34},
year    = {1234},
pages   = {12345-23456},
}
\end{filecontents*}