在一篇比较印欧语系的文档中,我尝试定义一些简写符号,用于标记不同语言的文本,并正确地将它们连字符连接起来。作为一名刚接触 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 []