latex3 / babel

The multilingual framework to localize LaTeX, LuaLaTeX and XeLaTeX
https://latex3.github.io/babel/
LaTeX Project Public License v1.3c
130 stars 35 forks source link

Language switching in tabular fails #97

Closed moewew closed 3 years ago

moewew commented 3 years ago

Related to https://github.com/latex3/babel/issues/93, originally reported at https://github.com/plk/biblatex/issues/1056.

Consider

\documentclass{article}
\usepackage[ngerman]{babel}

\begin{document}
\begin{tabular}{c}
  \begin{otherlanguage}{english}Hello\end{otherlanguage}
\end{tabular}
\end{document}

which fails with many nasty errors the likes of

! Argument of \bbl@iniline has an extra }.
<inserted text> 
                \par 
l.11 }

? 

in babel 3.50.

Whereas the same works perfectly fine outside of tabular

\documentclass{article}
\usepackage[ngerman]{babel}

\begin{document}
  \begin{otherlanguage}{english}Hello\end{otherlanguage}
\end{document}

or with additional braces

\documentclass{article}
\usepackage[ngerman]{babel}

\begin{document}
\begin{tabular}{c}
  {\begin{otherlanguage}{english}Hello\end{otherlanguage}}
\end{tabular}
\end{document}
PhelypeOleinik commented 3 years ago

That's because of & tokens in the .ini file. Doing the usual brace trick before and after iterating through the file seems to be enough:

\documentclass{article}
\usepackage[ngerman]{babel}

\makeatletter
\def\bbl@fetch@ini#1#2{%
  \bbl@exp{\def\\\bbl@inidata{%
    \\\bbl@elt{identification}{tag.ini}{#1}%
    \\\bbl@elt{identification}{load.level}{#2}}}%
  \openin\bbl@readstream=babel-#1.ini
  \ifeof\bbl@readstream
    \bbl@error
      {There is no ini file for the requested language\\%
       (#1). Perhaps you misspelled it or your installation\\%
       is not complete.}%
      {Fix the name or reinstall babel.}%
  \else
    \catcode`\[=12 \catcode`\]=12 \catcode`\==12
    \catcode`\;=12 \catcode`\|=12 \catcode`\%=14
    \bbl@info{Importing
                \ifcase#2 \or font and identification \or basic \fi
                data for \languagename\\%
              from babel-#1.ini. Reported}%
    \ifnum\iffalse{\fi`}=\z@\fi % <-------                         ADDED
    \loop
    \if T\ifeof\bbl@readstream F\fi T\relax % Trick, because inside \loop
      \endlinechar\m@ne
      \read\bbl@readstream to \bbl@line
      \endlinechar`\^^M
      \ifx\bbl@line\@empty\else
        \expandafter\bbl@iniline\bbl@line\bbl@iniline
      \fi
    \repeat
    \ifnum`{=\z@}\fi % <-------                                    ADDED
  \fi}
\makeatother

\begin{document}
\begin{tabular}{c}
  \begin{otherlanguage}{english}Hello\end{otherlanguage}
\end{tabular}
\end{document}
jbezos commented 3 years ago

In the context of ini files, & is always the actual ampersand character, so very likely the best option is to make it ‘other’.