
Ich möchte eine Umgebung generieren, die sich je nach einem dafür angegebenen Argument leicht ändert. Der Grund dafür sind unterschiedliche Gebietsschemas im Dokument. Ich habe einen Befehl definiert, der das Argument entsprechend dem übergebenen Argument EmitLanguageStr
bestimmt . Zum Beispiel . Weitere Informationen finden Sie in diesen Fragen: [otherlanguage
\EmitLanguageStr[en] -> english
1,2]. Hier ist die Umgebung im abgespeckten Zustand.
\renewenvironment{abstract}[1][en]{%
\section*{\EmitAbstractStr[#1]}
\begin{otherlanguage}{\EmitLanguageStr[#1]}
\@author\par
\textbf{\EmitTitle[#1]}\par
}{%
\end{otherlanguage}
}
Es stellte sich heraus, dass andere Leute das gleiche Problem hatten (Q), aber die Lösung hat bei mir nicht ganz funktioniert. Die Antwort legt nahe, dass das Umschließen der Umgebung auf eine von zwei Arten eine Erweiterung des Arguments ermöglichen würde:
% Create a macro
\newcommand\testlang{english}
% Expand the argument once:
\newenvironment{Otherlanguage}[1]{%
\expandafter\otherlanguage\expandafter{#1}%
}{\endotherlanguage}
% Alternative: argument is fully expanded
\newenvironment{Otherlanguage}[1]{%
\begingroup
\edef\temp{\endgroup\noexpand\otherlanguage{#1}}%
\temp
}{\endotherlanguage}
% usage
\begin{Otherlanguage}{\testlang}
...
\end{Otherlangauge}
Erstens gibt Babel ohne diese Wrapper eine Fehlermeldung aus, dass die Sprache EmitLanguageStr[en]
nicht definiert ist. Dies wurde in der verlinkten Frage behandelt. Die vorgestellten Lösungen erzeugen jedoch eine andere Art von Fehler: Use of \EmitLanguageStr doesn't match its definition
.
Wie kann der Befehl richtig erweitert werden?
Hier ist ein vollständiges Beispiel der Situation. Dies funktioniert, aber durch das Ändern des Arguments von Otherlanguage
zu dem im Kommentar wird der beschriebene Fehler ausgelöst.
\documentclass[a4paper,12pt]{article}
\usepackage{ifthen}
\usepackage{pgffor}
\makeatletter
\newcommand\SetDefaultValue[2]{%
\global\@namedef{#2:#1}{%
{\scriptsize (Use {\tt\textbackslash #2[#1]} to replace this text.)}%
}%
}
\newcommand\MakeLocaleVar[2][en,fi]{%
\foreach \n in {#1}{%
\expandafter\SetDefaultValue\expandafter{\n}{#2}
}%
\expandafter\newcommand\csname #2\endcsname[2][]{%
\ifthenelse{\equal{##1}{}}{%
\foreach \n in {#1}{%
\global\@namedef{#2:\n}{##2}%
}%
}{%
\global\@namedef{#2:##1}{##2}%
}%
}%
\expandafter\newcommand\csname Emit#2\endcsname[1][en]{\@nameuse{#2:##1}}%
}
% Variables set in document
\MakeLocaleVar{Title}
\MakeLocaleVar{Year}
%\newenvironment{Otherlanguage}[1]{%
% \expandafter\otherlanguage\expandafter{#1}%
%}{\endotherlanguage}
\newenvironment{Otherlanguage}[1]{%
\begingroup
\edef\temp{\endgroup\noexpand\otherlanguage{#1}}%
\temp
}{\endotherlanguage}
\MakeLocaleVar{AbstractStr}
\AbstractStr[en]{ABSTRACT}
\AbstractStr[fi]{TIIVISTELMÄ}
\MakeLocaleVar{LanguageStr}
\LanguageStr[en]{english}
\LanguageStr[fi]{finnish}
\renewenvironment{abstract}[1][en]{%
\section*{\EmitAbstractStr[#1]}
\begin{Otherlanguage}{english}%\EmitLanguageStr[#1]
\@author\par
\textbf{\EmitTitle[#1]}\par
\EmitYear\par
\par
}{%
\end{Otherlanguage}
}
\makeatother
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[finnish, english]{babel}
\author{Handsome Devil}
\Year{2019}
\Title[en]{Title in English}
\Title[fi]{Otsikko suomeksi}
\begin{document}
\selectlanguage{english}
\begin{abstract}
Abstract environment in English.
\end{abstract}
\begin{abstract}[fi]
Abstract environment in Finnish.
\end{abstract}
\end{document}
Antwort1
\MakeLocaleVar{LanguageStr}
Ursachen, die \EmitLanguageStr
wie folgt definiert werden:
\newcommand\EmitLanguageStr[1][en]{\@nameuse{LanguageStr:#1}}%
\EmitLanguageStr
verarbeitet ein optionales Argument.
\EmitLanguageStr
Wenn Sie sich via ansehen \show\EmitLanguageStr
, werden Sie Folgendes finden:
> \EmitLanguageStr=macro:
->\@protected@testopt \EmitLanguageStr \\EmitLanguageStr {en}.
Ein Blick auf \@protected@testopt
die Erträge:
> \@protected@testopt=macro:
#1->\ifx \protect \@typeset@protect \expandafter \@testopt \else \@x@protect #1
\fi .
Ein Blick auf \@testopt
die Erträge:
> \@testopt=\long macro:
#1#2->\kernel@ifnextchar [{#1}{#1[{#2}]}.
Ein Blick auf \kernel@ifnextchar
die Erträge:
> \kernel@ifnextchar=\long macro:
#1#2#3->\let \reserved@d =#1\def \reserved@a {#2}\def \reserved@b {#3}\futurele
t \@let@token \@ifnch .
Ein Blick auf \@ifnch
die Erträge:
> \@ifnch=macro:
->\ifx \@let@token \@sptoken \let \reserved@c \@xifnch \else \ifx \@let@token \
reserved@d \let \reserved@c \reserved@a \else \let \reserved@c \reserved@b \fi
\fi \reserved@c .
Ein Blick auf \@xifnch
die Erträge:
> \@xifnch=macro:
->\futurelet \@let@token \@ifnch .
Wie Sie sehen , ist bei der Überprüfung auf das Vorhandensein des optionalen Arguments über viel Herumspielen mit nicht erweiterbaren \let
- und -Zuweisungen erforderlich .\futurelet
\kernel@ifnextchar [
Liefert daher \EmitLanguageStr
nicht nur die Zeichentoken, die den Namen der Sprache bilden. Es liefert auch eine Menge nicht erweiterbarer Zuweisungstoken wie \let
und \futurelet
zur Überprüfung auf das Vorhandensein des optionalen Arguments.
Diese Token verschwinden nicht in einem reinen Erweiterungskontext, während die Ermittlung des Namens der Sprache zur Übergabe als Argument an eine Umgebung ein reiner Erweiterungskontext wäre. Nach der Erweiterung verbleiben diese nicht erweiterbaren Zuweisungstoken im Tokenstrom, da die Erweiterung zwar in (La)TeXs "Schlehe" stattfindet, die Durchführung der Zuweisungen jedoch im "Magen" von (La)TeX erfolgt.
Also kurz gesagt:
Solange \EmitLanguageStr
ein optionales Argument verarbeitet wird, wobei die Techniken zum Erkennen des Vorhandenseins eines optionalen Arguments selbst nicht erweiterbare Zuweisungstoken beinhalten, die während der Erweiterung nicht verschwinden, können Sie es nicht \EmitLanguageStr
in reinen Erweiterungskontexten verwenden, um nur die Token zu erhalten, die den Namen der Sprache bilden.
Man kann aber beispielsweise eine Variante von \EmitLanguageStr
mit einem zusätzlichen Argument erstellen, das Token enthält, an die der ausgegebene String als Argument übergeben werden soll. Ich nenne dieses Makro \PassLanguageStrTo
:
\documentclass[a4paper,12pt]{article}
\usepackage{ifthen}
\usepackage{pgffor}
\makeatletter
\newcommand\SetDefaultValue[2]{%
\global\@namedef{#2:#1}{%
{\scriptsize (Use {\tt\textbackslash #2[#1]} to replace this text.)}%
}%
}
\newcommand\PassFirstToSecond[2]{#2{#1}}%
\newcommand\MakeLocaleVar[2][en,fi]{%
\foreach \n in {#1}{%
\expandafter\SetDefaultValue\expandafter{\n}{#2}%%%%
}%
\expandafter\newcommand\csname #2\endcsname[2][]{%
\ifthenelse{\equal{##1}{}}{%
\foreach \n in {#1}{%
\global\@namedef{#2:\n}{##2}%
}%
}{%
\global\@namedef{#2:##1}{##2}%
}%
}%
\expandafter\newcommand\csname Emit#2\endcsname[1][en]{\@nameuse{#2:##1}}%
\expandafter\newcommand\csname Pass#2To\endcsname[2][en]{%
\expandafter\expandafter\expandafter\PassFirstToSecond
\expandafter\expandafter\expandafter{\csname#2:##1\endcsname}{##2}%
}%
}
% Variables set in document
\MakeLocaleVar{Title}
\MakeLocaleVar{Year}
\MakeLocaleVar{AbstractStr}
\AbstractStr[en]{ABSTRACT}
\AbstractStr[fi]{TIIVISTELMÄ}
\MakeLocaleVar{LanguageStr}
\LanguageStr[en]{english}
\LanguageStr[fi]{finnish}
\renewenvironment{abstract}[1][en]{%
\section*{\EmitAbstractStr[{#1}]}%%%%
\PassLanguageStrTo[{#1}]{\begin{otherlanguage}}%
\@author\par
\textbf{\EmitTitle[{#1}]}\par
\EmitYear\par
\par
}{%
\end{otherlanguage}%%%%
}
\makeatother
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[finnish, english]{babel}
\author{Handsome Devil}
\Year{2019}
\Title[en]{Title in English}
\Title[fi]{Otsikko suomeksi}
\begin{document}
\selectlanguage{english}
\begin{abstract}
Abstract environment in English.
\end{abstract}
\begin{abstract}[fi]
Abstract environment in Finnish.
\end{abstract}
\end{document}