I'd like to generate an environment that changes a bit according to an argument given for it. The reason is having different locales in the document. I have defined a command, EmitLanguageStr that determines the argument to otherlanguage according to the argument that was passed. For example, \EmitLanguageStr[en] -> english. See these questions for further context: [ 1, 2 ]. Here's the environment stripped down.
\renewenvironment{abstract}[1][en]{%
\section*{\EmitAbstractStr[#1]}
\begin{otherlanguage}{\EmitLanguageStr[#1]}
\@author\par
\textbf{\EmitTitle[#1]}\par
}{%
\end{otherlanguage}
}
Turns out other people have had the same problem (Q), but the solution did not quite work for me. The answer suggests that wrapping the environment in one of two ways would allow the argument to be expanded:
% 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}
First, without these wrappers, babel gives an error message that the language EmitLanguageStr[en] is not defined. That was addressed in the linked question. However, the solutions presented produce another kind of error: Use of \EmitLanguageStr doesn't match its definition.
How can the command be properly expanded?
Here's a complete example of the situation. This works, but by switching the argument of Otherlanguage to the one in the comment the described error is thrown.
\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}
\EmitLanguageStrprocesses an optional argument. LaTeX-macros that process optional arguments usually are not fully expandable. This means\EmitLanguageStrwon't expand to tokens only that form the name of a language but it also delivers assignment-tokens like\@ifnextchar/\futureletwhich are used for "looking ahead" at the next token for finding out whether that is a left-bracket. Such assignment-tokens won't vanish during expansion. Besides this for debugging a compilable example is needed which lets you reproduce the erroneous/problematic behavior exactly. – Ulrich Diez Mar 04 '19 at 12:39