如何将宏作为参数传递给 \selectlanguage

如何将宏作为参数传递给 \selectlanguage

以下 mwe 抛出错误You haven't defined the language lang yet

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

我可以看到\lang内部没有被正确扩展\selectlanguage,但是为什么会发生这种情况,我该如何解决它?

我也尝试在 之前添加一个空格\lang,在这种情况下它确实会扩展,但是由于这个空格,Babel 现在无法识别该语言。

答案1

的定义\selectlanguage等同于

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

其中\bbl@push@language\bbl@pop@language是维护宏,用于执行和撤消特定于语言的调整。现在,让我们看看重要的宏,它的定义相当于

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

我省略了其余部分,这是不必要的。宏\select@language将在执行其他任何操作之前先扩展其参数。

代码假设设置\escapechar为其正常值(即 92)。这种复杂的方法有历史原因;在 LaTeX2e 之前的古代,LaTeX 有许多扩展来应对不同的语言;为了方便习惯于\german在想要切换到德语时书写的用户,\selectlanguage它被定义为同时接受

\selectlanguage{german}

\selectlanguage{\german}

让我们看看你的会发生什么\selectlanguage{\lang}。LaTeX 会

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

条件\ifnum希望看到一个数字并找到\escapechar(一个数字参数)、一个关系符号(<=>)并找到=,然后是另一个数字;TeX 在寻找数字时会进行扩展,因此它会扩展\expandafter,从而触发 的扩展\string。经过这次扩展,输入流中剩下的是

\ifnum\escapechar=`\lang

其中\lang有五个标记,因为宏名称\lang已被“字符串化”。条件为真,因为`\(当\类别代码为 12 时)是 92 的另一种说法。因此遵循“真分支”,这使得lang\@empty保留在输入流中,因此我们得到等同于

\def\languagename{lang\@empty}

稍后将会\@empty删除。这解释了您的错误消息。

如果你说\selectlanguage{american},那么条件将为假,TeX 将遵循“假分支”,最后

\def\languagename{american\@empty}

这正是想要的。

该怎么办?如果您想使用这样的语法,请定义自己的版本\selectlanguage

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

所以你甚至可以自由地进行更复杂的设置,例如

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

[...]

\xselectlanguage{\lang}

USenglish直到你取消注释该行,你才会得到结果\UKtrue

答案2

使用\expandafter技巧:

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

笔记:babel包中,\selectlanguage{\foo}相当于。这是“出于历史原因”而设计的功能。请参阅文​​档中\selectlanguage{foo}命令的备注。\bbl@set@languagebabel

答案3

尝试这个:

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

相关内容