Unexpected clash between babel and pgf spy

The following example taken from the pgfplots manual (p. 121) works fine only if the line loading babel is commented

\documentclass{article}

\usepackage[frenchb]{babel} % this is the troubelsome line

\usepackage{pgfplots}
\usetikzlibrary{spy}

\begin{document}
\begin{tikzpicture}[spy using outlines=
{circle, magnification=6, connect spies}]
\begin{axis}[no markers,grid=major,
every axis plot post/.append style={thick}]
{(0, 0.0) (0, 0.9) (1, 0.9) (2, 1) (3, 0.9) (80,
0)};
{(0, 0.0) (0, 0.9) (2, 0.9) (3, 1) (4, 0.9) (80,
0)};
{(0, 0.0) (0, 0.9) (3, 0.9) (4, 1) (5, 0.9) (80,
0)};
{(0, 0.0) (0, 0.9) (4, 0.9) (5, 1) (6, 0.9) (80,
0)};
\coordinate (spypoint) at (axis cs:3,1);
\coordinate (magnifyglass) at (axis cs:60,0.7);
\end{axis}
\spy [blue, size=2.5cm] on (spypoint)
in node[fill=white] at (magnifyglass);
\end{tikzpicture}

\end{document}


I get the following error

Runaway argument?
[fill=white] at (magnifyglass);
! Paragraph ended before \tikz@lib@spy@parse@opta was complete.
\par


which I fail to interpret.

I'm using the TeX Live distribution that ships with Ubuntu but I manually installed in my texmf folder more recent version of some packages including pgf and pgfplots.

Do you have any idea of what I could do to be able to use both babel and the spy library?

-

The french language sets the ; as an active character: use \shorthandoff{;} before the picture and \shorthandon{;} after the picture to not have problems.

\documentclass{article}

\usepackage[frenchb]{babel}

\usepackage{pgfplots}
\usetikzlibrary{spy}

\begin{document}
\shorthandoff{;}
\begin{tikzpicture}[spy using outlines=
{circle, magnification=6, connect spies}]
\begin{axis}[no markers,grid=major,
every axis plot post/.append style={thick}]
{(0, 0.0) (0, 0.9) (1, 0.9) (2, 1) (3, 0.9) (80,
0)};
{(0, 0.0) (0, 0.9) (2, 0.9) (3, 1) (4, 0.9) (80,
0)};
{(0, 0.0) (0, 0.9) (3, 0.9) (4, 1) (5, 0.9) (80,
0)};
{(0, 0.0) (0, 0.9) (4, 0.9) (5, 1) (6, 0.9) (80,
0)};
\coordinate (spypoint) at (axis cs:3,1);
\coordinate (magnifyglass) at (axis cs:60,0.7);
\end{axis}
\spy [blue, size=2.5cm] on (spypoint)
in node[fill=white] at (magnifyglass);
\end{tikzpicture}
\shorthandon{;}
\end{document}


Notice that the previous MWE raise the following warnings

Package frenchb.ldf Warning: OT1 encoding should not be used for French.


that can be avoided by means of:

\usepackage[T1]{fontenc} % before babel
\usepackage[frenchb]{babel}


and:

Package pgfplots Warning: running in backwards compatibility mode unsuitable tick labels; missing features).


solvable through:

\usepackage{pgfplots}
\pgfplotsset{compat=1.6} % change this according to the current version of pgfplots

-

TikZ is usually intelligent with regard to active characters and so does not normally need the \shorthandon, \shorthandoff pair. However, the spy library did not include the checks that TikZ uses when matching its command and only defines a variant for whatever catcode semi-colon has at load-time. Since babel shifts its catcode changes to \begin{document}, this means that the \spy command tests against the wrong catcode. One fix is, as Claudio says, to return the semi-colon to its original state. Another fix is to augment the spy library by TikZ's intelligent semi-colon handling. The following code does this second method.

\documentclass{article}
%\url{http://tex.stackexchange.com/q/74860/86}
\usepackage[frenchb]{babel} % this is the troubelsome line

\usepackage{pgfplots}
\usetikzlibrary{spy}

\makeatletter
\def\tikz@lib@spy@parse@opt[#1]{%
\let\tikz@spy@next=\tikz@lib@spy@parse@opta%
\ifnum\the\catcode\;=\active\relax
\let\tikz@spy@next=\tikz@lib@spy@parse@opta@activesemicolon
\fi
\pgfutil@ifnextchar x{\tikz@spy@next[#1]}{\tikz@spy@next[#1]}%]
}
{
\catcode\;=\active
\gdef\tikz@lib@spy@parse@opta@activesemicolon[#1]on#2in node#3;{%
}
}
\makeatother

\begin{document}

\begin{tikzpicture}[spy using outlines=
{circle, magnification=6, connect spies}]
\begin{axis}[no markers,grid=major,
every axis plot post/.append style={thick}]
{(0, 0.0) (0, 0.9) (1, 0.9) (2, 1) (3, 0.9) (80,
0)};
{(0, 0.0) (0, 0.9) (2, 0.9) (3, 1) (4, 0.9) (80,
0)};
{(0, 0.0) (0, 0.9) (3, 0.9) (4, 1) (5, 0.9) (80,
0)};
{(0, 0.0) (0, 0.9) (4, 0.9) (5, 1) (6, 0.9) (80,
0)};
\coordinate (spypoint) at (axis cs:3,1);
\coordinate (magnifyglass) at (axis cs:60,0.7);
\end{axis}
\spy [blue, size=2.5cm] on (spypoint)
in node[fill=white] at (magnifyglass);
\end{tikzpicture}

\end{document}


Result:

(Though I guess the real result is that it compiles.)

-