Variável de string com vários valores

Variável de string com vários valores

Estou atrás de uma definição de um comando que possa ter vários valores para usar em diferentes contextos. O caso de uso para isso seria em uma classe customizada que usa duas linguagens simultaneamente, ou acho que qualquer situação em que uma variável possa ter valores diferentes dependendo do ambiente. Depois de pesquisar informações \newcommande coisas relacionadas a isso, ainda estou um pouco confuso sobre as coisas.

Pelo que entendi, uma implementação simples seria:

\newcommand\varname{text value}

No entanto, ter comandos diferentes para as mesmas coisas fica feio aos meus olhos. Por exemplo, tenho diante de mim uma classe antiga com comandos como Doctypee Doctypefinpara a versão finlandesa. Em vez disso, gostaria de usar o comando assim:

% Definitions
\title{en}{Title Of The Document}
\title{fi}{Dokumentin otsikko}

% Use in class environments or tex files
\title{en} % -> "Title Of The Document"
\title{fi} % -> "Dokumentin otsikko"

Existe alguma maneira de construir tal macro ou definição?

Idealmente, especificar categorias não vistas (aqui idiomas) não seria um problema, mas posso ver que seria razoável exigir a especificação dos valores aceitos no arquivo de classe. Além disso, como no exemplo abaixo, acho que seria aceitável ter um comando separado para gerar a variável, se isso for um problema.


Tentei observar a maneira como outros comandos de classe são construídos. Existe um MakeStringVarcomando útil que constrói uma variável e, se não for definido, exibe um texto padrão. Essa funcionalidade de texto padrão seria muito útil para o novo comando, porque muitos ambientes na classe usam as definições para enviar texto para páginas de título, etc.

\newcommand\MakeStringVar[2][\relax]{%
  \ifx#1\relax%
    \expandafter\newcommand\csname Emit#2\endcsname{%
      {\scriptsize (Use {\tt\textbackslash #2} to replace this text.)}}%
  \else%
    \expandafter\newcommand\csname Emit#2\endcsname{#1}%
  \fi%
  \expandafter\newcommand\csname #2\endcsname[1]{%
     \expandafter\renewcommand\csname Emit#2\endcsname{##1}%
  }%
}

É usado assim:

\MakeStringVar{Major} % Definition in class
\Major{Major subject name} % Set value in pre-document
\EmitMajor % Used in environments in class -> "Major subject name"

Mas sou um novato quando se trata de LaTeX, então não sei por onde começar. Tenho a sensação de que o comando acima poderia ser expandido de alguma maneira, mas realmente não conheço as limitações das macros LaTeX.

Responder1

Você pode considerar esta abordagem que usa \@namedef:

\documentclass{article}

\makeatletter
\newcommand\deftitle[2][en]{%
    \global\@namedef{title:#1}{#2}%
}
\newcommand\usetitle[1][en]{\@nameuse{title:#1}}
\makeatother

\begin{document}

\deftitle{Default Language (English) Title} % same as \deftitle[en]{...}
\deftitle[it]{Italian Title}
\deftitle[fr]{French Title}

\usetitle[it]
\usetitle % same as \usetitle[en]
\usetitle[fr]

\end{document}

Quando o usuário chama \deftitle[en]{<content>}, uma nova macro title:ené definida e se expande para <content>quando chamada via \@nameuse.

EDIT: Aqui está uma maneira geral de construir essas macros:

\makeatletter
\newcommand\newconstructor[1]{%
    \expandafter\newcommand\csname def#1\endcsname[2][en]{%
        \global\@namedef{#1:##1}{##2}%
    }%
    \expandafter\newcommand\csname use#1\endcsname[1][en]{\@nameuse{#1:##1}}%
}
\makeatother

Agora, por exemplo, \newconstructor{title}define \deftitlee \usetitle, como antes.

Responder2

Nesta implementação, as várias versões são inseridas com uma interface útil de valor-chave (coloque o valor entre chaves se ele contiver uma vírgula).

Também podem ser definidos aliases para chaves. Para idiomas, acho preferível usar chaves longas com o nome completo do idioma, para que \languagenamepossam ser usadas para obter a string relacionada. No entanto, aliases para chaves também podem ser usados ​​no documento, desde que sejam definidos previamente.

Você não é obrigado a adicionar todas as versões no momento da definição de uma variável, pois poderá usar \addtovarstringposteriormente.

\documentclass{article}
\usepackage[english,finnish]{babel}

\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\definevarstring}{mO{}}
 {
  \prop_new:c { g_felix_varstring_#1_prop }
  \felix_varstring_add:nn { #1 } { #2 }
 }
\NewDocumentCommand{\addtovarstring}{mm}
 {
  \felix_varstring_add:nn { #1 } { #2 }
 }
\NewDocumentCommand{\definealias}{m}
 {
  \prop_gset_from_keyval:Nn \g_felix_varstring_alias_prop { #1 }
 }
\NewExpandableDocumentCommand{\getvarstring}{mm}
 {
  \prop_if_in:cfTF { g_felix_varstring_#1_prop } { #2 }
   {
    \prop_item:cf { g_felix_varstring_#1_prop } { #2 }
   }
   {
    \prop_if_in:NnT \g_felix_varstring_alias_prop { #2 }
     {
      \prop_item:cf { g_felix_varstring_#1_prop }
       {
        \prop_item:Nn \g_felix_varstring_alias_prop { #2 }
       }
     }
   }
 }

\cs_generate_variant:Nn \prop_item:Nn { cf }
\prg_generate_conditional_variant:Nnn \prop_if_in:Nn { cf } { T,F,TF,p }
\prop_new:N \g_felix_varstring_alias_prop

\cs_new_protected:Nn \felix_varstring_add:nn
 {
  \prop_gset_from_keyval:cn { g_felix_varstring_#1_prop } { #2 }
 }

\ExplSyntaxOff

\definealias{fi=finnish,en=english}

\definevarstring{title}[% long versions for languages
  english=Title of the document,
  finnish=Dokumentin otsikko,
]

\begin{document}

\author{A. Uthor}
\title{\getvarstring{title}{\languagename}}
\maketitle

\selectlanguage{english}

\getvarstring{title}{\languagename}

\getvarstring{title}{en}---\getvarstring{title}{english}

\getvarstring{title}{fi}---\getvarstring{title}{finnish}

\end{document}

insira a descrição da imagem aqui

Responder3

Há algum tempo eu escrevi uma \SetProperty- \GetProperty-interface.

Provavelmente é útil para você.

%% This coding example was written by Ulrich Diez in November 16, 2018.
%% It was modified by Ulrich Diez in February 28, 2019.
%%
%% Copyright 2018, 2019 Ulrich Diez (e-mail: [email protected])
%%
%% This work may be distributed and/or modified under the conditions of
%% the LaTeX Project Public License, either version 1.3c of this license
%% or (at your option) any later version.
%%
%% The latest version of this license is in
%%
%%   <http://www.latex-project.org/lppl.txt>
%%
%% and version 1.3x or later is part of all distributions of LaTeX
%% version 2005/12/01 or later.
%%
%% This work has the LPPL maintenance status `unmaintained'.
%%
%% This work consists of this coding example.
%%
\errorcontextlines=10000
\documentclass[landscape]{article}

\makeatletter
%%==== Begin of code for the \SetProperty-\GetProperty-Interface =======
\RequirePackage{ifluatex, ifxetex}
%%======================================================================
%% Paraphernalia:
%%    \UD@firstoftwo, \UD@secondoftwo, \UD@PassFirstToSecond,
%%    \UD@exchange, \UD@removespace, \UD@name, \UD@CheckWhetherNull,
%%    \UD@loopcall,
%%......................................................................
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\newcommand\UD@exchange[2]{#2#1}%
\newcommand\UD@removespace{}\UD@firstoftwo{\def\UD@removespace}{} {}%
%%----------------------------------------------------------------------
%% Put a control sequence token in place instead of the string denoting
%% its name.
%%......................................................................
%%  \UD@name<emptiness or tokens other than braces>{<Name of
%%                                                   Control Sequence>}
%%
%% yields:
%%
%%  <emptiness or tokens other than braces>\Controlsequence
%%
%% E.g.,
%%
%%   \UD@name foo{bar} -> foo\bar
%%   \UD@name{bar} -> \bar
%%   \UD@name\newcommand*{wEirdName}[1]{Arg 1: (#1)}
%%       -> \newcommand*\wEirdName[1]{Arg 1: (#1)}
%%
\newcommand\UD@name{}\long\def\UD@name#1#{\romannumeral\UD@@name{#1}}%
\newcommand\UD@@name[2]{%
  \expandafter\UD@exchange\expandafter{\csname#2\endcsname}{0 #1}%
}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
%% (\romannumeral expansion was introduced in order to overcome the
%%  concerns and worries about improperly balanced
%%  \if..\else..\fi constructs.)
%%
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
  \UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%----------------------------------------------------------------------
%% Expandable Loop:
%% \UD@loopcall{<action>}%
%%          {<action if list empty>}%
%%          {<preset>}%
%%          {{<e_k>}{<e_(k+1)>}..{e_n}}% <- this is the list
%%
%% If list is empty: <action if list empty>
%% Else:
%% <action>{<e_k>}<preset> \UD@loopcall{<action>}%
%%                                  {<action if list empty>}%
%%                                  {<preset>}{{<e_(k+1)>}..{e_n}}
%%
%% <action> can be defined to mesh into the iteration-process, e.g.,
%% (ex)changing arguments like the <action if list empty>-argument for
%% the next \UD@loopcall-iteration, e.g., terminating iteration
%% prematurely under some circumstances.
%%......................................................................
\newcommand\UD@RemoveTillUD@nil{}%
\long\def\UD@RemoveTillUD@nil#1#2\UD@nil{{#1}}%
\newcommand\UD@Extractfirstloop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
  {\UD@exchange{#1}}%
  {%
    \expandafter\UD@Extractfirstloop
    \expandafter{\UD@RemoveTillUD@nil#1}%
  }%
}%
\newcommand\UD@loopcall[4]{%
  \UD@CheckWhetherNull{#4}{#2}{%
    \expandafter\UD@exchange
    \expandafter{\expandafter{\UD@firstoftwo{}#4}}%
    {\UD@Extractfirstloop{#4\UD@nil}{#1}#3\UD@loopcall{#1}{#2}{#3}}%
  }%
}%
%%======================================================================
%% Expandable comparison of two strings:
%%
%% Derived from David Kastrup's \ifstrequal-test from the
%% TeX Pearl Diving Site;
%% Pearls of 2005;
%% Title: David Kastrup - Comparing two strings known to consist
%% only of characters ;
%% Url: <http://www.gust.org.pl/projects/pearls/2005p/david-kastrup/bachotex2005-david-kastrup-pearl1.pdf>
%%......................................................................
%% \UD@ifstrequal{<String 1>}{<String 2>}%
%%               {%
%%                  <Tokens to be delivered in case strings are equal>
%%               }%
%%               {%
%%                  <Tokens to be delivered in case strings are
%%                   not equal>
%%               }%
%%
%% (<String 1> gets expanded during comparison.
%%  <String 2> gets not expanded during comparison.
%%
%% I bloated this thing up for ensuring it also takes spaces into
%% account.
%%
\@ifdefinable\UD@strchksp{%
  \long\def\UD@strchksp#1#2#3#4 #5\relax{%
    #1{\if\UD@strequal\UD@secondoftwo{}{#4}%
       \expandafter\UD@firstoftwo\else\expandafter\UD@secondoftwo\fi
       {\if\UD@strequal\UD@secondoftwo{}{#5}%
        \expandafter\UD@firstoftwo\else\expandafter\UD@secondoftwo\fi
        {\UD@strequalstart#1{#2}{#3} \relax}%
        {\UD@strequalstart#1{#2}{#3}{ }#5\relax}}}%
    {\UD@strequalstart#1{#2}{#3}#4 #5\relax}%
  }%
}
\newcommand\UD@strequal[2]{\number\UD@strchksp#1{}{}#2 \relax}
\newcommand\UD@strequalstart[4]{%
  \if#4\relax\UD@strequalstop\fi
  \UD@strchksp#1{\if#4#2}{#3\fi}%
}%
\@ifdefinable\UD@strequalstop{%
  \long\def\UD@strequalstop\fi\UD@strchksp#1#2#3#4{\fi#2#4\relax'#313 }%
}
\newcommand\UD@ifstrequal[2]{%
  \romannumeral0%
  \if\UD@strequal\@firstofone{#2.}{#1.}%
  \expandafter\UD@firstoftwo\else\expandafter\UD@secondoftwo\fi
  {\UD@exchange{ \UD@firstoftwo}}{\UD@exchange{ \UD@secondoftwo}}%
  {\expandafter\expandafter\expandafter}%
}%
%%======================================================================
%% Total expansion and stringification of argument:
%%......................................................................
%% \UD@stringify{<argument that expands to character tokens>}
%%
%% Does \csname..\endcsname with the argument, then \string,
%% then removal of \escapechar if that was added.
%%
\newcommand\UD@stringify[1]{%
  \romannumeral0%
  \expandafter\expandafter\expandafter\UD@exchange
  \expandafter\expandafter\expandafter{%
  \expandafter\string\csname#1\endcsname}%
  {%
    \ifnum\the\escapechar<0 %
    \expandafter\UD@secondoftwo\else\expandafter\UD@firstoftwo\fi
    {%
      \ifnum\the\escapechar>\ifxetex 1114111 %
      \else\ifluatex 1114111 \else 255 \fi\fi
      \expandafter\UD@secondoftwo\else\expandafter\UD@firstoftwo\fi
      {%
        \ifnum\the\escapechar=32 %
        \expandafter\UD@secondoftwo\else\expandafter\UD@firstoftwo\fi
        {\UD@firstoftwo{ }}{}%
      }{ }%
    }{ }%
  }%
}%
%%======================================================================
%% Property-Management:
%%......................................................................
%%
%% The concept is about maintaining macros that expand to lists of
%% 2-tuple-arguments.
%% The first component of the tuple holds the name of a property.
%% The second component holds the value of the property.
%%
%% E.g., the macro \macro could be defined to expand to:
%%
%%   {{property name 1}{property value 1}}%
%%   {{property name 2}{property value 2}}%
%%   ...
%%   {{property name K}{property value K}}%
%%
%%
%% \SetProperty{\macro}%
%%             {<name of property>}%
%%             {<new value of property>}
%%
%%   In case \macro is undefined, \macro will be defined empty.
%%
%%   In case a property <name of property> does not exist within the
%%   macro \macro, it will be added to the macro and it will get the
%%   value <new value of property>.
%%
%%   In case a property <name of property> does exist within the macro
%%   \macro, its value will get replaced by <new value of property>.
%%
%%   Before further evaluation <name of property> will be expanded via
%%   \csname..\endcsname-expansion and afterwards "stringified" by
%%   applying \string and removing a leading escapechar if one was
%%   added.
%%
%%   Example:
%%
%%     \SetProperty{\macro}{property name 2}{changed property value 2}
%%
%%        would make \macro to expand to
%%
%%     {{property name 1}{property value 1}}%
%%     {{property name 2}{changed property value 2}}%
%%     ...
%%     {{property name K}{property value K}}%
%%
%%       and
%%
%%     \SetProperty{\macro}{property name (K+1)}{property value (K+1)}
%%
%%        would make \macro to expand to
%%
%%     {{property name 1}{property value 1}}%
%%     {{property name 2}{changed property value 2}}%
%%     ...
%%     {{property name K}{property value K}}%
%%     {{property name (K+1)}{property value (K+1)}}%
%%
%%
%% \GetProperty{\macro}%
%%             {<name of property>}%
%%             {%
%%               <tokens to be delivered in case
%%                property is not available>
%%             }
%%
%%   In case \macro is undefined or property <name of property> does not
%%   exist within the macro \macro,
%%   <tokens to be delivered in case property is not available>
%%   will be delivered.
%%
%%   In case a property <name of property> does exist within the macro
%%   \macro, its value will be delivered.
%%
%%   Before further evaluation <name of property> will be expanded via
%%   \csname..\endcsname-expansion and afterwards "stringified" by
%%   applying \string and removing a leading escapechar if one was
%%   added.
%%
%%   \GetProperty is expandable and delivers the result after two
%%   expansion steps / after being hit "twice" by \expandafter.
%%
%%   E.g., with the macro \macro being defined to expand to
%%
%%     {{property name 1}{property value 1}}%
%%     {{property name 2}{property value 2}}%
%%     ...
%%     {{property name K}{property value K}}%
%%
%%   , the sequence
%%
%%     \GetProperty{\macro}{property name 2}{Huh?}
%%
%%   will expand to:
%%
%%     property value 2
%%
\newcommand\UD@ExpandProperties[3]{%
  \expandafter\UD@PassFirstToSecond\expandafter{#1}%
  {\expandafter\expandafter\expandafter\UD@PassFirstToSecond
  \expandafter\expandafter\expandafter{%
  \UD@stringify{#2}}{#3}}%
}%
\newcommand\UD@AtIfPropertyListUndefined[1]{%
  \@ifundefined{%
    \expandafter\UD@exchange\expandafter{\string#1}%
    {%
      \ifnum\the\escapechar<0 %
      \expandafter\UD@secondoftwo\else\expandafter\UD@firstoftwo\fi
      {%
        \ifnum\the\escapechar>\ifxetex 1114111 %
        \else\ifluatex 1114111 \else 255 \fi\fi
        \expandafter\UD@secondoftwo\else\expandafter\UD@firstoftwo\fi
        {%
          \ifnum\the\escapechar=32 %
          \expandafter\UD@secondoftwo\else\expandafter\UD@firstoftwo\fi
          {\UD@firstoftwo{}}{\UD@removespace}%
        }{}%
      }{}%
    }%
  }%
}%
\newcommand\SetProperty[2]{%
  \@bsphack
  \UD@AtIfPropertyListUndefined{#1}{\newcommand*#1{}}{}%
  \romannumeral0%
  \UD@ExpandProperties{#1}{#2}{\UD@@setproperty}{#1}%
}%
\newcommand\UD@@setproperty[4]{%
  \UD@loopcall{\UD@@@setproperty}%
              { \global\def#3{{{#1}{#4}}}\@esphack}%
              {{#1}{#4}{ \global\def#3}{}}%
              {#2}%
}%
\newcommand\UD@@@setproperty{}%
\long\def\UD@@@setproperty#1#2#3#4#5\UD@loopcall#6#7#8#9{%
  \UD@ifstrequal{\UD@firstoftwo#1}{#2}%
  {%
    #4{#5{{#2}{#3}}#9}\@esphack
  }{%
    \UD@loopcall{#6}%
                {#4{#5{#1}{{#2}{#3}}}\@esphack}%
                {{#2}{#3}{#4}{#5{#1}}}%
                {#9}%
  }%
}%
\newcommand\GetProperty[3]{%
  \romannumeral0%
  \UD@AtIfPropertyListUndefined{#1}{ #3}{%
    \UD@ExpandProperties{#1}{#2}{\UD@@getproperty}{ #3}%
  }%
}%
\newcommand\UD@@getproperty[3]{%
  \UD@loopcall{\UD@@@getproperty}%
              {#3}%
              {{#1}}%
              {#2}%
}%
\newcommand\UD@@@getproperty{}%
\long\def\UD@@@getproperty#1#2\UD@loopcall#3#4#5#6{%
  \UD@ifstrequal{\UD@firstoftwo#1}{#2}%
    {\UD@exchange{ }\expandafter\UD@secondoftwo#1}%
    {%
      \UD@loopcall{#3}%
                  {#4}%
                  {#5}%
                  {#6}%
    }%
}%
%%==== End of code for the \SetProperty-\GetProperty-Interface =========


%%==== Layout of this example ==========================================
%   - No headers / no footers
\pagestyle{empty}
%   - paragraph-breaking:
\parindent=0ex
\parskip=\medskipamount
%   - horizontal margins:
\setlength\textwidth{\paperwidth}
\addtolength\textwidth{-3cm}
\setlength\oddsidemargin{1.5cm}%
\addtolength\oddsidemargin{-1in}%
\addtolength\oddsidemargin{-\hoffset}%
\setlength\evensidemargin{\oddsidemargin}%
\setlength\marginparwidth{1.5cm}%
\addtolength\marginparwidth{-2\marginparsep}%
%   - vertical margins:
\setlength\topmargin{1.5cm}
\addtolength\topmargin{-1in}
\addtolength\topmargin{-\voffset}
%   - no headheight/headsep etc as there are no headers as
%     pagestyle=empty:
\setlength\headsep{0pt}
\setlength\headheight{0pt}
\setlength\footskip{0pt}
\setlength\textheight{\paperheight}
\addtolength\textheight{-3cm}%
\addtolength\textheight{-\footskip}%
\addtolength\textheight{-\headsep}%
\addtolength\textheight{-\headheight}%
%   - allow linebreaks after closing braces in typewriter font:
\DeclareFontFamily{\encodingdefault}{\ttdefault}{\hyphenchar\font=`\}}
%   - in case of pdftex also adjust the underlying paper
\@ifundefined{pdfpagewidth}{}{\pdfpagewidth=\paperwidth}%
\@ifundefined{pdfpageheight}{}{\pdfpageheight=\paperheight}%
\@ifundefined{pagewidth}{}{\pagewidth=\paperwidth}%
\@ifundefined{pageheight}{}{\pageheight=\paperheight}%
%%==== Layout-changes etc done.=========================================

\newcommand\Errortext[3]{%
  \nfss@text{\reset@font\bfseries#3}%
  \GenericError{\space\@spaces\@spaces}%
               {Error: \string#1: Translation into language #2 not available}%
               {Source for further information on this error is neither available nor needed.}%
               {You can use \string\SetProperty for specifying a translation.}%
}%

\SetProperty{\mymacro}{English}{This is a sentence in English.}
\SetProperty{\mymacro}{Francais}{Ceci est une phrase en fran\c cais.}
\SetProperty{\mymacro}{Italiano}{Questa \`e una frase in italiano.}
\SetProperty{\mymacro}{Deutsch}{Dies ist ein Satz in deutscher Sprache.}

\makeatother

\begin{document}
\verb|\SetProperty{\mymacro}{English}{This is a sentence in English.}|\\
\verb|\SetProperty{\mymacro}{Francais}{Ceci est une phrase en fran\c cais.}|\\
\verb|\SetProperty{\mymacro}{Italiano}{Questa \`e una frase in italiano.}|\\
\verb|\SetProperty{\mymacro}{Deutsch}{Dies ist ein Satz in deutscher Sprache.}|
\\\null\hrulefill\null

\verb|\GetProperty{\mymacro}{English}{\Errortext{\mymacro}{English}{No translation available.}}|\\
\GetProperty{\mymacro}{English}{\Errortext{\mymacro}{English}{No translation available.}}

\verb|\GetProperty{\mymacro}{Francais}{\Errortext{\mymacro}{Francais}{Aucune traduction disponible.}}|\\
\GetProperty{\mymacro}{Francais}{\Errortext{\mymacro}{Francais}{Aucune traduction disponible.}}

\verb|\GetProperty{\mymacro}{Italiano}{\Errortext{\mymacro}{Italiano}{Nessuna traduzione disponibile.}}|\\
\GetProperty{\mymacro}{Italiano}{\Errortext{\mymacro}{Italiano}{Nessuna traduzione disponibile.}}

\verb|\GetProperty{\mymacro}{Deutsch}{\Errortext{\mymacro}{Deutsch}{Keine Übersetzung vorhanden.}}|\\
\GetProperty{\mymacro}{Deutsch}{\Errortext{\mymacro}{Deutsch}{Keine Übersetzung vorhanden.}}

\verb|% This will raise an error:|\\    
\verb|\GetProperty{\mymacro}{Esperanto}{\Errortext{\mymacro}{Esperanto}{Neniu traduko havebla.}}|\\
% This will raise an error:
\GetProperty{\mymacro}{Esperanto}{\Errortext{\mymacro}{Esperanto}{Neniu traduko havebla.}}

\end{document}

insira a descrição da imagem aqui

informação relacionada