我无法参数化 babel 的 \foreignlanguage 命令

我无法参数化 babel 的 \foreignlanguage 命令

在一篇比较印欧语系的文档中,我尝试定义一些简写符号,用于标记不同语言的文本,并正确地将它们连字符连接起来。作为一名刚接触 LaTeX 的程序员,我也使用这样的案例来学习 LaTeX 语言。

通过将代码简化为最小的工作示例,含义可能已经丢失。我尝试做的是为所有可以传递给的语言建立简写符号巴别塔作为\foreignlanguage参数,并将其封装成几个不同的命令,标记每种语言中单词的语法角色。

但这段简短的代码仍然很好地展示了问题。当我重新定义巴别塔命令\foreignlanguage利用其参数执行一些可见的操作,其工作原理如下:

\documentclass[]{article}
\usepackage[french,dutch]{babel}
\usepackage{xstring}
\renewcommand{\foreignlanguage}[2]{A: #1 {\small #2} B: {\huge #1} #2}
\newcommand{\said}[2][nl]{
    \foreignlanguage{{\IfStrEqCase{#1}{{fr}{french}}[dutch]}}{\textit{``#2''}}}
\begin{document}
\said{Niets}

\said[fr]{Rien}

\end{document}

这样做的结果很好:

使用自定义“外语”命令的工作示例

至少这证明了我的定义\newcommand{\said}具有有效的语法,对于\foreignlanguage需要 2 个参数的命令。现在,如果我注释掉 redefining 行\renewcommand{\foreignlanguage},那么原始的巴别塔定义\foreignlanguage{<language>}{<text>}再次生效,则代码停止工作。我收到这些错误消息的循环

  • \said 的使用与其定义不符。\said{Niets}
  • \@firstoftwo 的参数有一个额外的 }。\said{Niets}
  • 段落在 \@firstoftwo 完成之前结束。\said{Niets}

日志对此进行了扩展:

! Use of \\said doesn't match its definition.
\@ifnextchar ... \reserved@d =#1\def \reserved@a {
                                                  #2}\def \reserved@b {#3}\f...
l.8 \said{Niets}
If you say, e.g., `\def\a1{...}', then you must always
put `1' after `\a', since control sequence names are
made up of letters only. The macro here has not been
followed by the required stuff, so I'm ignoring it.

! Argument of \@firstoftwo has an extra }.
<inserted text> 
                \par 
l.8 \said{Niets}
I've run across a `}' that doesn't seem to match anything.
For example, `\def\a#1{...}' and `\a}' would produce
this error. If you simply proceed now, the `\par' that
I've just inserted will cause me to report a runaway
argument that might be the root of the problem. But if
your `}' was spurious, just type `2' and it will go away.

Runaway argument?
! Paragraph ended before \@firstoftwo was complete.
<to be read again> 
                   \par 
l.8 \said{Niets}
I suspect you've forgotten a `}', causing me to apply this
control sequence to too much text. How can we recover?
My plan is to forget the whole thing and hope for the best.

如果我注释掉

\said{Niets}

我得到了同样的错误消息

\said[fr]{Rien}

可能在到达第二行之前错误堆栈就已经满了。

有什么区别巴别塔\foreignlanguage我的虚拟重新定义,这使得代码无法工作巴别塔的?

答案1

不幸的是,来自的几个命令xstring无法完全扩展。您需要使用的每个案例\IfStrEqCase来定义一个存储适当值的辅助宏。以下是执行此操作的一种方法:

示例输出

\documentclass{article}

\usepackage[french,dutch]{babel}
\usepackage{xstring}

\newcommand{\expandlangabbr}[2]{\IfStrEqCase{#1}%
  {{fr}{\xdef#2{french}}}%
  [\xdef#2{dutch}]}

\newcommand{\said}[2][nl]{\expandlangabbr{#1}{\mylang}%
  \foreignlanguage{\mylang}{\textit{``#2''}}}

\begin{document}

\said{Niets}

\said[fr]{Rien}

\end{document}

答案2

你需要能够完全扩展为语言名称的东西,但\IfStrEqCase只提供以下说明:排版它。

您可以使用提供的可扩展版本xparse

\documentclass[]{article}
\usepackage[T1]{fontenc}
\usepackage[french,dutch]{babel}

\usepackage{xparse}

\ExplSyntaxOn
\NewExpandableDocumentCommand{\xIfStrEqCase}{mmm}
 {
  \str_case:nnF { #1 } { #2 } { #3 }
 }
\ExplSyntaxOff

\newcommand{\said}[2][nl]{%
  \foreignlanguage
    {\xIfStrEqCase{#1}{{fr}{french}}{dutch}}
    {(\languagename) \textit{``#2''}}%
}

\begin{document}

\said{Niets}

\said[fr]{Rien}

\end{document}

\xIfStrEqCase宏接受三个参数,例如\IfStrEqCase,但后面的参数是必需的。

\xIfStrEqCase{<string>}{{<string-a>}{code-a}...}{<default code>}

我添加了代码(\languagename)只是为了确定选择了哪种语言。

在此处输入图片描述

答案3

其他答案给了我新的勇气和新的搜索条件。我找到了一个替代解决方案,它允许我轻松地为我需要的每个命令定义单独的语言版本。

这是我的代码,将我的宏命令定义为\saidnl{text}\saidfr{text}等等,而不是\said[nl]{text}\said[fr]{text}等等。

\documentclass[]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc} % for french: OT1 encoding should not be used for French
\usepackage[english,german,french,dutch]{babel}
\usepackage{xstring}

\newcommand{\dodefcommandlang}[4]{%
    \expandafter\newcommand\csname #1#2\endcsname[1]{\foreignlanguage{#3}{#4}}%
}
\newcommand{\defcommandlang}[2]{%
    \dodefcommandlang{#1}{nl}{dutch}{#2}
    \dodefcommandlang{#1}{de}{ngerman}{#2}
    \dodefcommandlang{#1}{fr}{french}{#2}
    \dodefcommandlang{#1}{en}{english}{#2}
}
\defcommandlang{said}{\textit{,,#1''}}  %defines \saidnl, \saidde, \saidfr, \saiden
\defcommandlang{name}{\textbf{#1}}   %defines \namenl, \namede, \namefr, \nameen

\newcommand{\testphrase}{Andere übertragen das am besten den Geschwistern.
 Reële benodigdheden worden soms onverschillig veronachtzaamd.
 L’embryon de l'Organisation des Nations unies se montrait
 une casse-noisettes ambivalente.
 More than one-third of registered voters oppose the measure.}
\begin{document}
\show\saidnl
\show\saidde
\show\saidfr
\show\saiden
\show\namenl
\show\namede
\show\namefr
\show\nameen

\saidnl{\showhyphens{{\languagename} \testphrase}\testphrase}

\saidde{\showhyphens{{\languagename} \testphrase}\testphrase}

\saidfr{\showhyphens{{\languagename} \testphrase}\testphrase}

\saiden{\showhyphens{{\languagename} \testphrase}\testphrase}
\end{document}

与以下解决方案相比安德鲁·斯旺埃格尔,很好地回答了我的参数化问题,这种替代方案的优点是宏命令在文档的开头“编译”一次,而不是在文档中每次使用时都编译,这种情况非常常见。我现在不再参数化宏命令,而是参数化宏命令的定义。这样做的缺点是我将拥有数十个这样的宏命令。

Thw\show\showhyphens命令在日志文件中给出了这个结果,这正是它应该的样子:

> \saidnl=\long macro:
#1->\foreignlanguage {dutch}{\textit {,,#1''}}.
l.25 \show\saidnl

> \saidde=\long macro:
#1->\foreignlanguage {ngerman}{\textit {,,#1''}}.
l.26 \show\saidde

> \saidfr=\long macro:
#1->\foreignlanguage {french}{\textit {,,#1''}}.
l.27 \show\saidfr

> \saiden=\long macro:
#1->\foreignlanguage {english}{\textit {,,#1''}}.
l.28 \show\saiden

> \namenl=\long macro:
#1->\foreignlanguage {dutch}{\textbf {#1}}.
l.29 \show\namenl

> \namede=\long macro:
#1->\foreignlanguage {ngerman}{\textbf {#1}}.
l.30 \show\namede

> \namefr=\long macro:
#1->\foreignlanguage {french}{\textbf {#1}}.
l.31 \show\namefr

> \nameen=\long macro:
#1->\foreignlanguage {english}{\textbf {#1}}.
l.32 \show\nameen

Underfull \hbox (badness 10000) in paragraph at lines 34--34
[] \T1/cmr/m/n/10 dutch An-dere über-tra-gen das am bes-ten den Ge-schwis-tern.
 Re-ële be-no-digd-he-den wor-den soms on-ver-schil-lig ver-on-acht-zaamd. L'em
bryon de l'Organisation des Na-ti-ons unies se mon-trait une casse-noisettes am
-bi-va-lente. More than one-third of re-gis-tered vo-ters op-pose the me-a-sure.

\hbox(6.8872+1.94397)x16383.99998, glue set 227.21642 []

Underfull \hbox (badness 10000) in paragraph at lines 36--36
[] \T1/cmr/m/n/10 ger-man An-de-re über-tra-gen das am be-sten den Ge-schwi-ste
rn. Reële be-no-digd-he-den wor-den soms on-ver-schil-lig ve-ro-nachtzaamd. L'e
mbryon de l'Organisation des Na-ti-ons unies se mon-trait une casse-noisettes a
m-bi-va-len-te. Mo-re than one-third of re-gi-ste-red vo-ters op-po-se the mea-su
-re.

\hbox(6.8872+1.94397)x16383.99998, glue set 267.23941 []

Underfull \hbox (badness 10000) in paragraph at lines 38--38
[] \T1/cmr/m/n/10 french An-dere über-tra-gen das am bes-ten den Ges-ch-wis-ter
n. Reële be-no-digd-he-den wor-den soms on-ver-schil-lig ve-ro-nacht-zaamd. L'e
m-bryon de l'Or-ga-ni-sa-tion des Na-tions unies se mon-trait une casse-noisett
es am-bi-va-lente. More than one-third of re-gis-te-red vo-ters op-pose the mea-
sure.

\hbox(6.8872+1.94397)x16383.99998, glue set 267.33745 []

Underfull \hbox (badness 10000) in paragraph at lines 40--40
[] \T1/cmr/m/n/10 en-glish An-dere über-tra-gen das am besten den Geschwis-tern
. Reële ben-odigdhe-den wor-den soms on-ver-schillig veronachtza-amd. L'embryon
 de l'Organisation des Na-tions unies se mon-trait une casse-noisettes am-biva-
lente. More than one-third of reg-is-tered vot-ers op-pose the mea-sure.

\hbox(6.8872+1.94397)x16383.99998, glue set 227.13641 []

相关内容