%20und%20ihrer%20Setter.png)
Ich möchte einige Makros definieren, um Texte in verschiedenen Sprachen zu erstellen. Der Befehl lautet: , \newlang
der ein unsichtbares Makro oder eine Variable zum Speichern des Textes in der jeweiligen Sprache und einen Setter zum Festlegen dieser Variable erstellt.
Beispielsweise: \newlang{ar}
würde erstellen \@artxt
, um den Text zu speichern und \setartext{text}
festzulegen \@artxt
.
Wenn ich den Inhalt dieser Variablen anzeigen möchte (nehmen wir an, wir haben sie \newlang
dreimal aufgerufen), \csname
zeigt nur die letzte Variable ihren Inhalt an. Dies ist der Code:
\documentclass{article}
\makeatletter
\newcommand\newlang[1]{ %
\ifdefined\@langs %
\expandafter\def\expandafter\@langs\expandafter{\@langs{},#1} %
\else %
\def\@langs{#1} %
\fi
\@namedef{@#1txt}{}%
%
\expandafter\newcommand\csname set#1text\endcsname[1]{ %
%
\expandafter\def\csname @#1txt\endcsname{##1} %
} %
}
\newcommand{\@processTexts}[1]{ %
-----#1----\\
\ifcsname @#1txt\endcsname
\csname @#1txt\endcsname
\else
No #1 csname here
\fi\\
******\\
\@artxt \\
\@frtxt \\
}
\newcommand\@splitcomma[1]{\@for\tmp:=#1\do{\@processTexts{\tmp}}}
\newcommand{\print}{ %
\ifdefined\@langs %
\@splitcomma{\@langs}%
\fi %
}
\makeatother
\begin{document}
\newlang{ar}
\newlang{fr}
\newlang{en}
\setartext{arabic}
\setfrtext{french}
\setentext{english}
\setartext{arabic2}
\print{}
Another text
\end{document}
Es sollte Folgendes gedruckt werden:
—–ar—-
arabic2
*****
arabic2
french
—–fr—-
french
*****
arabic2
french
—–en—-
english
*****
arabic2
french
Another text
Stattdessen wird Folgendes gedruckt:
—–ar—-
No ar csname here
*****
arabic2
french
—–fr—-
No fr csname here
*****
arabic2
french
—–en—-
english
*****
arabic2
french
Another text
Antwort1
Der Fehler liegt darin \@langs{}
, dass für jeden Eintrag ein explizites {}
Token zur Sprachenliste hinzugefügt wird ar{}
und nicht das erwartete übrig bleibt ar
usw.
Auf diese Weise muss der \ifcsname ....
Test fehlschlagen, d. h. er gibt den falschen Zweig zurück, da @ar{}text
er nicht definiert ist.
\documentclass{article}
\makeatletter
\newcommand\newlang[1]{%
\ifdefined\@langs%
\expandafter\def\expandafter\@langs\expandafter{\@langs,#1} %
\else %
\def\@langs{#1} %
\fi
\global\expandafter\newcommand\csname @#1txt\endcsname{foo}%
\expandafter\newcommand\csname set#1text\endcsname[1]{ %
%
\expandafter\gdef\csname @#1txt\endcsname{##1} %
}%
}
\newcommand{\@processTexts}[1]{ %
-----#1----\\
\@ifundefined{@#1txt}{%
No #1 csname here -- sorry%
}{%
\csname @#1txt\endcsname%
}
\\
******\\
}
\newcommand\@splitcomma[1]{\@for\tmp:=#1\do{\@processTexts{\tmp}}}
\newcommand{\print}{ %
\ifdefined\@langs %
\@splitcomma{\@langs}%
\fi %
}
\makeatother
\begin{document}
\newlang{ar}
\newlang{fr}
\newlang{en}
\setartext{arabic}
\setfrtext{french}
\setentext{english}
\setartext{arabic2}
\print{}
Another text
\end{document}
Antwort2
Der Fehler liegt hier:
\expandafter\def\expandafter\@langs\expandafter{\@langs{},#1} %
denn wenn Sie anrufen \@splitcomma
, ist die Liste
ar{},fr{},en
\tmp
wird also ar{}
und \csname @ar{}txt\endcsname
ist sehr verschieden von \csname @artxt\endcsname
.
Eine aufpolierte Version mit Korrekturen %
am Zeilenende:
\documentclass{article}
\makeatletter
\newcommand\newlang[1]{%
\ifdefined\@langs
\expandafter\def\expandafter\@langs\expandafter{\@langs,#1}%
\else
\def\@langs{#1}%
\fi
\@namedef{@#1txt}{}%
\expandafter\newcommand\csname set#1text\endcsname[1]{%
\expandafter\def\csname @#1txt\endcsname{##1}%
}%
}
\newcommand{\@processTexts}[1]{%
-----#1----\\
\ifcsname @#1txt\endcsname
\csname @#1txt\endcsname
\else
No #1 csname here%
\fi
\\
******\\
\@artxt \\
\@frtxt \\
}
\newcommand\@splitcomma[1]{\@for\tmp:=#1\do{\@processTexts{\tmp}}}
\newcommand{\print}{%
\ifdefined\@langs
\@splitcomma{\@langs}%
\fi
}
\makeatother
\begin{document}
\newlang{ar}
\newlang{fr}
\newlang{en}
\setartext{arabic}
\setfrtext{french}
\setentext{english}
\setartext{arabic2}
\noindent\print{}
Another text
\end{document}
Eine andere Implementierung mit expl3
:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
% User level commands
\NewDocumentCommand{\newlang}{m}
{
\karim_lang_newlang:n { #1 }
}
\DeclareExpandableDocumentCommand{\gettext}{m}
{
\karim_lang_gettext:n { #1 }
}
\NewDocumentCommand{\print}{}
{
\karim_lang_print:
}
% Variables
\seq_new:N \g_karim_lang_langs_seq
\prop_new:N \g_karim_lang_texts_prop
% Internal functions
\cs_new_protected:Nn \karim_lang_newlang:n
{
\seq_gput_right:Nn \g_karim_lang_langs_seq { #1 }
\cs_new:cpn { set#1text } ##1
{
\prop_gput:Nnn \g_karim_lang_texts_prop { #1 } { ##1 }
}
}
\cs_new:Nn \karim_lang_gettext:n
{
\prop_if_in:NnTF \g_karim_lang_texts_prop { #1 }
{
\prop_item:Nn \g_karim_lang_texts_prop { #1 }
}
{
No~text~for~#1~here
}
}
\cs_new_protected:Nn \karim_lang_print:
{
\seq_map_inline:Nn \g_karim_lang_langs_seq
{
\noindent
---##1---\\
\karim_lang_gettext:n { ##1 } \\
*****\par
}
}
\ExplSyntaxOff
\begin{document}
\newlang{ar}
\newlang{fr}
\newlang{en}
\setartext{arabic}
\setfrtext{french}
\setentext{english}
\setartext{arabic2}
\print
This is the text for French: \gettext{fr}
\end{document}
Eine einfachere Version Ihrer Makros:
\documentclass{article}
\makeatletter
\let\karim@langs\@gobble
\newcommand\newlang[1]{%
\expandafter\def\expandafter\karim@langs\expandafter{\karim@langs,#1}%
\expandafter\newcommand\csname set#1text\endcsname[1]{%
\@namedef{karim@#1@text}{##1}%
}%
}
\newcommand{\gettext}[1]{%
\ifcsname karim@#1@text\endcsname
\@nameuse{karim@#1@text}%
\else
No text for #1!%
\fi
}
\newcommand{\print}{%
\ifx\karim@langs\@gobble
\else
\@for\next:=\karim@langs\do{%
\noindent
---\next---\\
\gettext{\next}\\
******\par
}%
\fi
}
\makeatother
\begin{document}
\newlang{ar}
\newlang{fr}
\newlang{en}
\setartext{arabic}
\setfrtext{french}
\setentext{english}
\setartext{arabic2}
\print
\end{document}
Antwort3
Der folgende Code ist etwas angenehmer für die Augen:
\documentclass{article}
\usepackage{etoolbox}
\makeatletter
\newcommand{\@langs}{}
\newcommand\newlang[1]{%
\xdef\@langs{\@langs,#1}%
\@namedef{set#1text}##1{\@namedef{@#1txt}{##1}}%
}
\newcommand{\printlangs}{%
\renewcommand{\do}[1]{%
\if$##1$\else
\par\noindent
\begin{tabular}{c}
\hline
-- ##1 -- \\
\hline
\ifcsname @##1txt\endcsname
\@nameuse{@##1txt}%
\else
No text specified%
\fi
\\
\hline
\end{tabular}
\par\bigskip
\fi
}
\expandafter\docsvlist\expandafter{\@langs}
}
\makeatother
\begin{document}
\newlang{ar}
\newlang{fr}
\newlang{en}
\setartext{arabic}
\setfrtext{french}
\setartext{arabic2}
\printlangs
Another text
\end{document}
Die Sprachen werden in einer Liste gespeichert und mitetoolbox
(sehenWie iteriert man über eine durch Kommas getrennte Liste?für mehr Details).