latex3 / babel

The babel system for LaTeX, LuaLaTeX and XeLaTeX
LaTeX Project Public License v1.3c
123 stars 34 forks source link

Interaction between babel and ltxtable #284

Closed SverreStausland closed 3 months ago

SverreStausland commented 4 months ago

Consider this MWE:

\documentclass{article}
\usepackage[main = american, norsk]{babel}
\usepackage{array, ltxtable}

\begin{document}

\begin{filecontents}[overwrite]{testing.tex}
\begin{longtable}{p{3em}X}
9999 & {\begin{otherlanguage}{norsk}Foo bar baz\end{otherlanguage}}\\
9999 & Foo bar baz\\
\end{longtable}
\end{filecontents}
\LTXtable{\linewidth}{testing.tex}

\end{document}

With babel v. 3.92 (compiled in Overleaf, pdflatex 2023), it produces this output:

babel01

With babel v. 24.1 (compiled in texlive with pdflatex), it produces this output:

babel02

The version numbers of array, tabularx, longtable , and ltxtable are the same for both compilations, and both are compiled with the same version of pdflatex, so the observed difference is due to changes in the babel package.

I don't know if this is to be considered a bug or not, but the current outcome is surely not the desired one in my case. Can this be fixed, or is some other solution to be preferred?

davidcarlisle commented 4 months ago

As I explained on tex.sx chat this is unrelated to the table packages,

\documentclass{article}
\usepackage[main = american, norsk]{babel}

\begin{document}

xxx \parbox[t]{5cm}{%
  \begin{otherlanguage}{norsk}Foo bar baz\end{otherlanguage}}

\bigskip

xxx \parbox[t]{5cm}{%
  \leavevmode\begin{otherlanguage}{norsk}Foo bar baz\end{otherlanguage}}

\end{document}

produces

image

due to a \write whatsit at the start of the language switch.

jbezos commented 4 months ago

It seems there is a change in behavior in the LaTeX kernel [edit: actually, in longtable], which now enters in vertical mode (formerly it didn’t; or exists horizontal mode, I’m not yet sure). The following test file prints ‘Vertical’ in current LaTeX, while Overleaf prints ‘Horizontal’:

\documentclass{article}

\usepackage{array, ltxtable}

\begin{document}

\begin{filecontents}[overwrite]{testing.tex}
\begin{longtable}{p{3em}X}
9999 & {\ifhmode Horizontal\else Vertical\fi}\\
9999 & {\ifhmode Horizontal\else Vertical\fi}\\
\end{longtable}
\end{filecontents}
\LTXtable{\linewidth}{testing.tex}

\end{document}
jbezos commented 4 months ago

@SverreStausland Just read David’s message, which gave me the workaround: use \leavevmode.

davidcarlisle commented 4 months ago

longtable now follows array

% \changes{v4.18}{2023/08/25}{Use \cs{everypar} to match array package, github 1128}%

so the strut is delayed in everypar (so if the p-entry starts wih a list you don't have a paragraph with just an invisible strut before the list

so while you see a change in behaviour for longtable it would always have been this way in a tabular using the array package, or as shown above in a standard parbox

davidcarlisle commented 4 months ago

@jbezos you could try to delay the write with \ifvmode\everypar{...}\else...} but it's a tricky area to ensure everypar survives at starts of sections and places.

In color.sty I just documented that \color may do this (footnote page 7 of grfguide) and made \textcolor always have \leavevmode so it does not have the issue, but always starts a paragraph so can not surround lists etc

jbezos commented 4 months ago

@davidcarlisle So longtable did change (@SverreStausland said the version was the same).

jbezos commented 4 months ago

As otherlanguage can be used in many contexts, I can’t change it hastly. I have to investigate.

davidcarlisle commented 4 months ago

@davidcarlisle So longtable did change (@SverreStausland said the version was the same).

https://chat.stackexchange.com/transcript/message/32722915#32722915 :-)

SverreStausland commented 4 months ago

@jbezos I looked through my two log files twice to make sure that the package versions were the same, and now that I'm doing the same one more time, I notice that the versions for longtable are indeed different ... Sorry! 😖

SverreStausland commented 4 months ago

@davidcarlisle @jbezos Can someone explain how exactly one should "use \leavemode" as a workaround?

davidcarlisle commented 4 months ago

@SverreStausland as I showed just make sure you don't start a vbox with \begin{otherlanguage} so use \leavevmode\begin{otherlanguage} or \mbox{}\begin{otherlanguage} in such a context.

SverreStausland commented 4 months ago

If I understood it correctly, @jbezos will investigate and see if there's a solution that doesn't require the user to insert \leavemode before \begin{otherlanguage} whenever it's used in a table. Did I understand that correctly?

davidcarlisle commented 4 months ago

@SverreStausland yes but it's tricky, for \color I decided to just document that it could happen and the user should add the correction at the start of vmode. For \textcolor I went the other way and always add \leavevmode but that's for small text fragments that should always be in a paragraph. So @jbezos may find a safe compromise, but this is a hard area (TeX really doesn't help) so I'd simply add them.

If in your document you always have \begin{otherlanguage}Text never \begin{otherlanguage}\begin{itemize} or similar, then you can simply define it locally to always start a paragraph so

\let\xxotherlanguage\otherlanguage
\def\otherlanguage{\leavevmode\xxotherlanguage}

But that is not a general solution

jbezos commented 4 months ago

I’ll investigate, but this doesn’t mean there will be a general solution. An option is to document \leavevmode will be necessary in some cases. Interestingly, the babel manual explains neither \foreignlanguage nor otherlanguage* enter in horizontal mode, but I missed a similar remark in otherlanguage. Very likely, and for compatibility reasons. the current behavior will stay (as \foreignlanguage stayed), but, well, I'd like to investigate.

jbezos commented 3 months ago

Finally the current behavior will stay for a couple of reasons: (1) backwards compatibility; (2) otherlanguage is the environment version of \selectlanguage and entering in horizontal mode doesn’t make much sense. I even considered an option to change the behavior, but I discarded it for reason 2. If a \leavevmode is always required in otherlanguage, there is the possibility to add it with:

\AddToHook{env/otherlanguage/before}{\leavevmode}

So, I’ll just document neither \selectlanguage nor otherlanguage change the current mode.