XeLaTeX, nohyphen, space and babel/polyglossia

Consider this MWE

\documentclass[french]{article}
\usepackage{babel}
\usepackage{hyphenat}

\begin{document}
\section{without relax}
Cambridge : University (A)

\nohyphens{Cambridge} : University (B)

\texttt{Cambridge} : University (C)

\verb|Cambridge| : University (D)

\section{with relax}

Cambridge\relax : University (E)

\nohyphens{Cambridge}\relax : University (F)

\texttt{Cambridge}\relax : University (G)

\verb|Cambridge|\relax : University (H)
\end{document}


If we run it with pdfLaTeX or LuaLaTeX, all the colon are well aligned.

But if we run it with XeLaTeX, it seems that there some spurious spaces (section 1), which can be cancelled with relax. Why did we get this behavior? If we don't load babel or polyglossia, the output is also ok.

Any idea?

• For context: github.com/plk/biblatex/issues/979 – moewe Mar 24 '20 at 17:25
• You shouldn't add a space before the : in the input. Type simply Cambridge:. – Ulrike Fischer Mar 24 '20 at 17:41
• @UlrikeFischer But the space is supposed to be valid, and french uses XeTeX interchars to remove it. I've traced the code and I don't understand why \ifdim\lastskip >1sp returns false when executed at the colon in those 2 cases. – Javier Bezos Mar 24 '20 at 17:50
• historically, inded, the space is supposed to be valid. – Maïeul Mar 24 '20 at 18:01
• That's interesting: {\language\l@french Cambridge} : University works, but {\language\l@english Cambridge} : University doesn't. A bug in XeTeX? – Javier Bezos Mar 24 '20 at 18:05

It looks as if one can get around the problem for \nohyphens by inserting a zero width space (but I didn't test with many fonts):

\documentclass[french]{article}
\usepackage{babel}
\usepackage{hyphenat}

\begin{document}

Cambridge : University (A)

\nohyphens{Cambridge} : University (B)

\nohyphens{Cambridge}: University (C)

\renewcommand{\nohyphens}[1]{{{\language\langwohyphens #1}^^^^200b}}

Cambridge : University (A)

\nohyphens{Cambridge} : University (B)

\nohyphens{Cambridge}: University (C)
\end{document}


A similar trick works for \verb:

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

\begin{document}
Cambridge : University (A)

\verb|Cambridge| : University (C)

\makeatletter
\def\verb@egroup{\global\let\verb@balance@group\@empty\egroup^^^^200d}
\makeatother

Cambridge : University (A)

\verb|Cambridge| : University (C)

\end{document}


• Nice trick. I still think it's a bug in XeTeX, which is inserting the language switch at the wrong place. – Javier Bezos May 18 '20 at 15:58
• @JavierBezos It looks as if it is waiting for the next glyph. – Ulrike Fischer May 18 '20 at 16:14
• Thank you for the workaround. That's more than I hoped for. You mention not having tested this with many fonts, but is this something that would be font dependent (if the font doesn't have U+200B or a non-zero-width U+200B)? Fortunately, the zero-width space didn't show up when the text copy-and-pasted (at least in my tests), but it is a bit annoying to have to deal with XeLaTeX separately (the fix won't be acceptable for pdfTeX). – moewe May 18 '20 at 17:53
• @moewe I'm not sure if not some .notdef char can appear if the font doesn't have the glyph. – Ulrike Fischer May 18 '20 at 17:56
• I see. One would hope that a font designer would put it in, it doesn't seem to be be terribly time consuming to create that glyph. Is there a quick way to test if the glyph exists in the current font? – moewe May 18 '20 at 17:58

This is just a comment. I am not a French TeX user, and I don't know which is preferred in writing: a thin space before colon : or without thin space before colon:. Just compare by the following pictures that are outputs of the following with different options (with/out \FBsetspaces{colon}{0.5}{0}{0}):

\documentclass[french]{article}
\usepackage{babel}
\usepackage{hyphenat}

\FBsetspaces{colon}{0.5}{0}{0}

\begin{document}
\section{all without relax}
Cambridge : University (A)

\nohyphens{Cambridge} : University (B)

\texttt{Cambridge} : University (C)

\verb|Cambridge| : University (D)

\section{all with relax}

Cambridge\relax : University (E)

\nohyphens{Cambridge}\relax : University (F)

\texttt{Cambridge}\relax : University (G)

\verb|Cambridge|\relax : University (H)

\section{with relax just for typewriter and verbatim}

Cambridge : University (E)

\nohyphens{Cambridge} : University (F)

\texttt{Cambridge}\relax : University (G)

\verb|Cambridge|\relax : University (H)

\section{all without manual space}

Cambridge: University (E)

\nohyphens{Cambridge}: University (F)

\texttt{Cambridge}: University (G)

\verb|Cambridge|: University (H)
\end{document}


• PDFLaTeX with \FBsetspaces{colon}{0.5}{0}{0}

• XeLaTeX with \FBsetspaces{colon}{0.5}{0}{0}

• PDFLaTeX without \FBsetspaces{colon}{0.5}{0}{0}

• XeLaTeX without \FBsetspaces{colon}{0.5}{0}{0}

• The underlying issue is the same whether we want a thin space with \FBsetspaces{colon}{0.5}{0}{0} or take the default normal space. So I don't think this addresses the underlying issue. – moewe May 20 '20 at 16:23
• I think the author of package knows about this problem and s/he defined this command. Anyway for more details read french-babel. – user108724 May 20 '20 at 17:43
• But if you compare the XeLaTeX example with \FBsetspaces{colon}{0.5}{0}{0} and without, the only difference is that the excess space is smaller. It is still there (lines B and D). The question was specifically about getting rid of the excess space in lines B and D compared to lines A and C (the input is analogous, yet the output is different). – moewe May 21 '20 at 9:18