# How to pass a macro as the argument to \selectlanguage

The following mwe throws the error You haven't defined the language lang yet.

\documentclass{article}
\usepackage[american]{babel}
\newcommand{\lang}{american}
\selectlanguage{\lang}
\begin{document}
Hello!
\end{document}


I can see that \lang is not being expanded properly inside \selectlanguage, but why does this happen and how do I fix it?

I also tried putting a space before \lang, in which case it does get expanded, but Babel now does not recognize the language because of the space.

-

The definition of \selectlanguage is equivalent to

\newcommand{\selectlanguage}[1]{%
\bbl@push@language
\aftergroup\bbl@pop@language
\bbl@set@language{#1}%
}


where \bbl@push@language and \bbl@pop@language are maintenance macros to do and undo the language specific adjustments. Now, let's look at the important macro, which is defined by something equivalent to

\newcommand\bbl@set@language[1]{%
\edef\languagename{%
\ifnum\escapechar=\expandafter\string#1%
\@empty
\else
\string#1\@empty
\fi
}%
\select@language{\languagename}
[...]
}


where I omit the rest, which is inessential. The macro \select@language will expand its argument before doing anything else.

The code makes the assumption that \escapechar is set to its normal value (that is, 92). This complicated approach has historic reasons; in olden times, before LaTeX2e, there were a number of extensions to LaTeX for coping with different languages; for being friendly to the users accustomed to write \german whenever they wanted to switch to German, \selectlanguage was defined to accept both

\selectlanguage{german}


and

\selectlanguage{\german}


Let's see what happens with your \selectlanguage{\lang}. LaTeX does

\edef\languagename{%
\ifnum\escapechar=\expandafter\string\lang%
\@empty
\else
\string#1\@empty
\fi
}%


The conditional \ifnum wants to see a number and finds \escapechar (a numeric parameter), a relation symbol (<, = or >) and finds =, then another number; TeX performs expansion when looking for a number, so it expands \expandafter, which triggers the expansion of \string. After this expansion, what remains on the input stream is

\ifnum\escapechar=\lang


where \lang are five tokens, because the macro name \lang has been “stringified”. The conditional is true, because \ (when \ has category code 12) is an alternative way to say 92. Thus the “true branch” is followed, which makes lang\@empty remain on the input stream and so we get the equivalent of

\def\languagename{lang\@empty}


The \@empty will be get rid of later. This explains your error message.

If you say \selectlanguage{american}, instead, the conditional would be false and TeX would follow the “false branch” ending with

\def\languagename{american\@empty}


which is what's wanted.

What to do? If you want to use such a syntax, define your own version of \selectlanguage:

\newcommand{\xselectlanguage}[1]{%
\begingroup\edef\x{\endgroup
\noexpand\selectlanguage{#1}}\x
}


so you'll even be free to have more complex setups like

\newcommand{\lang}{\UKorUS english}
\newif\ifUK % conditional start out false
\newcommand{\UKorUS}{\ifUK UK\else US\fi}
%\UKtrue

[...]

\xselectlanguage{\lang}


and you'll get USenglish until you uncomment the \UKtrue line.

-

Use \expandafter trick:

\documentclass{article}
\usepackage[american]{babel}
\newcommand{\lang}{american}
\expandafter\selectlanguage\expandafter{\lang}
\begin{document}
Hello!
\end{document}


Note: In babel package, \selectlanguage{\foo} is equivalent to \selectlanguage{foo}. This is a feature by design “for historial reasons”. See the remarks of command \bbl@set@language in the document of babel.

-

Try this:

\documentclass{article}
\usepackage[greek, american]{babel}
\def\lang#1{\selectlanguage{#1}}
\begin{document}
\lang{american}
Hello!
\lang{greek}
Hello!
\end{document}

-
This doesn't answer the question (see the title). –  pts Oct 6 '13 at 18:33
@pts Sorry I should have expanded on the answer. \lang{\greek} or \lang{\american} also works. –  Yiannis Lazarides Oct 6 '13 at 18:43