reutenauer / polyglossia

An alternative to Babel for XeLaTeX and LuaLaTeX
http://www.ctan.org/pkg/polyglossia
MIT License
190 stars 51 forks source link

\selectlanguage is processed in the aux-file #593

Closed u-fischer closed 1 year ago

u-fischer commented 1 year ago

at every language change polyglossia writes a \selectlanguage to the aux-file which is then as far as I can see more or less fully processed at the next compilation. This doesn't make much sense: you are in a group in the aux-file and most settings are lost again when the file ends and so it only slows down the compilation without much gain.

As an example take french. One of its key adds code to the begindocument hook and so the following document not only processes this five times in the aux at the second compilation:

\selectlanguage *[variant=french,autospacing=true,thincolonspace=false,autospaceguillemets=true,autospacetypewriter=false,frenchfootnote=false,frenchitemlabels=false,itemlabels=\textemdash ,itemlabeli=\textemdash ,itemlabelii=\textemdash ,itemlabeliii=\textemdash ,itemlabeliv=\textemdash ]{french}

but it also blows up the begindocument hook tremendously which lots of repetitions of the same code:

> Document-level (top-level) code (executed last):
>     -> \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \undefined \else \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 
'frenchfootnote' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }
{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \undefined \els
e \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi 
\iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only
 supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \undefined \else \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .
\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@ite
mi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootn
ote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \undefined \else \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supporte
d if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcomman
d {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \undefined \else \long \def \french@makefntex
t ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \if
defstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only supported if French is main l
anguage!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \undefined \else \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefnt
ext \french@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemi
i }{\french@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@la
nguage }{french}{\ifx \@makefntext \undefined \else \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supported if French is main language!}
}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@item
iv }}{\xpg@warning {Option 'frenchitemlabels' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \undefined \else \long \def \french@makefntext ##1{\parindent 1em \noindent
 \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language 
}{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only supported if French is main language!}}\else \let \@makefnt
ext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \undefined \else \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\
xpg@warning {Option 'frenchfootnote' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcomm
and {\labelitemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefn
text \undefined \else \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supported if French is main language!}}\else \let \@makefntext \xpg@
orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'fr
enchitemlabels' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \undefined \else \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty
 \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labe
litemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \
iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \undefined \else \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 'frenchfoo
tnote' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }{\french@i
temiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \undefined \else \long \d
ef \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@
frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only supported
 if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \undefined \else \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi
 ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renew
command {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdef
string {\xpg@main@language }{french}{\ifx \@makefntext \undefined \else \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supported if Frenc
h is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcommand {\labeli
temiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \undefined \else \long \def \french@makefntext ##1{\par
indent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring 
{\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only supported if French is main language!}}
\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \undefined \else \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \frenc
h@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\frenc
h@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{f
rench}{\ifx \@makefntext \undefined \else \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supported if French is main language!}}\else \le
t \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg
@warning {Option 'frenchitemlabels' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \undefined \else \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \if
x \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{
\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only supported if French is main language!}}\else \let \@makefntext \xpg@o
rig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \undefined \else \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warnin
g {Option 'frenchfootnote' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labe
litemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemlabels' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi \iffrench@frenchfootnote \ifdefstring {\xpg@main@language }{french}{\ifx \@makefntext \unde
fined \else \long \def \french@makefntext ##1{\parindent 1em \noindent \quad \ifx \@thefnmark \empty \else \@thefnmark .\space \fi ##1} \let \@makefntext \french@makefntext \fi }{\xpg@warning {Option 'frenchfootnote' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makef
ntext \fi \iffrench@frenchitemlabels \ifdefstring {\xpg@main@language }{french}{\renewcommand {\labelitemi }{\french@itemi }\renewcommand {\labelitemii }{\french@itemii }\renewcommand {\labelitemiii }{\french@itemiii }\renewcommand {\labelitemiv }{\french@itemiv }}{\xpg@warning {Option 'frenchitemla
bels' only supported if French is main language!}}\else \let \@makefntext \xpg@orig@makefntext \fi 
\documentclass{article}
\usepackage{polyglossia}
\setdefaultlanguage{french}
\setotherlanguage{english}

\begin{document}

french

\begin{english}
english
\end{english}

french

\begin{english}
english
\end{english}

french

\begin{english}
english
\end{english}

french

\begin{english}
english
\end{english}

french

\begin{english}
english
\end{english}

\makeatletter\write\@mainaux{\noexpand\ShowHook{begindocument}}\makeatother

\end{document}
jspitz commented 1 year ago

I think we do this to get proper language setting in the toc and other lists. Probably we can omit the \selectlanguage settings outside of the \@writefile statements, but I am reluctant to touch this now as we had all sorts of issues with this.

So this is for later.

u-fischer commented 1 year ago

I think we do this to get proper language setting in the toc and other lists.

Sorry but this doesn't make sense. You are not doing any typesetting here or in other places where the aux-file is read.

The issue came up as in the next LaTeX release we want to offer hooks with arguments and this requires more parsing of the hook code and the fact that polyglossia filled up the hook in such an unrestricted way lead to a dramatic slow down: https://github.com/latex3/latex2e/issues/1078

We will adjust the LaTeX code but polyglossia should at least avoid to add code to hooks through a command like \selectlanguage which is used many times in the document. So please adjust the definition of frenchitemlabels and don't use \AfterPreamble there.

jspitz commented 1 year ago

Ulrike, you are almost always right with your analyses, and I take it seriously that we have something wrong here most probably. But I need time to dig in and understand the issue and the history that led to this situation. As I plan a release shortly after the next LaTeX release, I do not want to touch this now.

jspitz commented 1 year ago

(I'll check if I can solve the French problem before that, though. Keep you posted)

jspitz commented 1 year ago

I have submitted a change to gloss-french to the effect that itemlabels and footnote definitions are only written once, and not via a hook, but at the first main language selection in the document body.

Can you please check if this cures the main performance issue with French?

jspitz commented 1 year ago

A closer look revealed that this is not only non-sensical, but potentially harmful, so I fixed it now after some testing.