In your original question "Help on a macro \CreateTheorem(*)" I found the following preliminaries:
- The
\CreateTheorem
-mechanism is to work also when package(s) amsthm and/or cleveref are/is loaded.
- The underlying macros, whose arguments need to be arranged properly, are
\newtheorem
, \crefname
, \Crefname
, etc.
The problem with my current approach is that
\newtheorem
is slow and is carried out often.
- cleveref's macros
\Crefname
and \crefname
are slow and are carried out often.
- loading the package cleveref takes some time
You can see the slowness of \newtheorem
etc by deriving a damaged/crippled variant of PJLthm.sty
where
- instances of
\Crefname
and \crefname
and \newtheorem
are replaced by instances of argument-gobbling-macros.
- the loading of cleveref is removed.
- package-name and version is changed.
When using the crippled/damaged variant of the package for benchmarking, make sure that no attempts take place at using the environments that should be defined as with the crippled/damaged variant defining in terms of underlying \newtheorem
/\Crefname
/\crefname
does not take place and therefore with the crippled/damaged variant of the package environments that should be defined are not available.
I just downloaded ProjLib [2021/08/07a] from CTAN and compiled the .ins-files for obtaining the .sty-files.
When I save the example
\documentclass{article}
\makeatletter
\def\@gobblethree#1#2#3{}%
\def\@gobbleMandOptMand#1[#2]#3{}%
\makeatother
\usepackage[originalref]{PJLthm}
\UseLanguage{French}
% For some reason the package defines the theorem-environment
% via \AtEndPreamble.
% Therefore theorems based on that cannot be defined within the preamble
% unless via \AtEndPreamble or \AtBeginDocument or the like.
\AtEndPreamble{%
\def\ideanameFR{Idée}%
\CreateTheorem{idea}[theorem]%
}%
\begin{document}
%%%\begin{theorem}\label{thm}
%%% Un théorème en français.
%%%\end{theorem}
%%%\begin{idea}\label{idea}
%%% Une idée en français.
%%%\end{idea}
%%%\cref{thm,idea}
\end{document}
as test.tex and on Debian Linux do
time pdflatex test.tex
, then I get:
real 1m0,548s
user 1m0,284s
sys 0m0,134s
When I derive PJLthmDamaged.sty from PJLthm.sty by
- replacing instances of
\Crefname
and \crefname
and \newtheorem
by instances of argument-gobbling-macros,
- removing the loading of cleveref,
- changing package-name and version,
so that the diff-file Patch.diff
looks like this:
--- PJLthm.sty
+++ PJLthmDamaged.sty
@@ -1,23 +1,17 @@
%%
-%% This is file `PJLthm.sty',
-%% generated with the docstrip utility.
-
-%% Copyright (C) 2021 by Jinwen XU
-%%
-%% This is part of the ProjLib Toolkit.
-%%
-%% 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.3c or later is part of all distributions of LaTeX version
-%% 2005/12/01 or later.
+%% This is file `PJLthmDamaged.sty',
+%% generated by Ulrich Diez via manually editing
+%%
+%% `PJLthm.sty',
+%% Copyright (C) 2021 by Jinwen XU
%%
+%% in August 10, 2021, 18:24:37(UTC)
+%% in order to create a crippled/damaged variant which does not
+%% perform all the \Crefname/\crefname/\newtheorem.
+%%
\NeedsTeXFormat{LaTeX2e}[2020-10-01]
-\ProvidesPackage{PJLthm}
- [2021/08/07a Theorem setup and configuration]
+\ProvidesPackage{PJLthmDamaged}
+ [2021/08/10 Damaged!!!! theorem setup and configuration]
\RequirePackage{kvoptions}
\RequirePackage{etoolbox}
\SetupKeyvalOptions{%
@@ -45,8 +39,8 @@
\RequirePackage{PJLlang}
\RequirePackage{amsmath,amsthm}
\RequirePackage{aliascnt}
-\PassOptionsToPackage{nameinlink}{cleveref}
-\RequirePackage{cleveref}
+%%\PassOptionsToPackage{nameinlink}{cleveref}
+%%\RequirePackage{cleveref}
\NewDocumentCommand{\NameTheorem}{omm}{%
\protected@edef\PJLthm@temp{#2}%
@@ -176,8 +170,8 @@
{\IfValueTF{#5}{\@firstoftwo}{\@secondoftwo}}%
}{%
\IfValueTF{#4}
- {\IfValueTF{#5}{\@firstoftwo}{\@secondoftwo}}{
- \@secondoftwo}
+ {\IfValueTF{#5}{\@firstoftwo}{\@secondoftwo}}{%%%%
+ \@secondoftwo}%%%%
}%
{%
\GenericError{}%
@@ -205,17 +199,17 @@
}
}{%
\IfBooleanTF{#1}{%
- \if@PJLlang@enable@EN\expandafter\PassFirstToSecond\expandafter{\csname#2nameEN\endcsname}{\newtheorem*{#2EN#3}}\fi%
- \if@PJLlang@enable@FR\expandafter\PassFirstToSecond\expandafter{\csname#2nameFR\endcsname}{\newtheorem*{#2FR#3}}\fi%
- \if@PJLlang@enable@DE\expandafter\PassFirstToSecond\expandafter{\csname#2nameDE\endcsname}{\newtheorem*{#2DE#3}}\fi%
- \if@PJLlang@enable@IT\expandafter\PassFirstToSecond\expandafter{\csname#2nameIT\endcsname}{\newtheorem*{#2IT#3}}\fi%
- \if@PJLlang@enable@PT\expandafter\PassFirstToSecond\expandafter{\csname#2namePT\endcsname}{\newtheorem*{#2PT#3}}\fi%
- \if@PJLlang@enable@BR\expandafter\PassFirstToSecond\expandafter{\csname#2nameBR\endcsname}{\newtheorem*{#2BR#3}}\fi%
- \if@PJLlang@enable@ES\expandafter\PassFirstToSecond\expandafter{\csname#2nameES\endcsname}{\newtheorem*{#2ES#3}}\fi%
- \if@PJLlang@enable@CN\expandafter\PassFirstToSecond\expandafter{\csname#2nameCN\endcsname}{\newtheorem*{#2CN#3}}\fi%
- \if@PJLlang@enable@TC\expandafter\PassFirstToSecond\expandafter{\csname#2nameTC\endcsname}{\newtheorem*{#2TC#3}}\fi%
- \if@PJLlang@enable@JP\expandafter\PassFirstToSecond\expandafter{\csname#2nameJP\endcsname}{\newtheorem*{#2JP#3}}\fi%
- \if@PJLlang@enable@RU\expandafter\PassFirstToSecond\expandafter{\csname#2nameRU\endcsname}{\newtheorem*{#2RU#3}}\fi%
+ \if@PJLlang@enable@EN\expandafter\PassFirstToSecond\expandafter{\csname#2nameEN\endcsname}{\@gobbletwo{#2EN#3}}\fi
+ \if@PJLlang@enable@FR\expandafter\PassFirstToSecond\expandafter{\csname#2nameFR\endcsname}{\@gobbletwo{#2FR#3}}\fi
+ \if@PJLlang@enable@DE\expandafter\PassFirstToSecond\expandafter{\csname#2nameDE\endcsname}{\@gobbletwo{#2DE#3}}\fi
+ \if@PJLlang@enable@IT\expandafter\PassFirstToSecond\expandafter{\csname#2nameIT\endcsname}{\@gobbletwo{#2IT#3}}\fi
+ \if@PJLlang@enable@PT\expandafter\PassFirstToSecond\expandafter{\csname#2namePT\endcsname}{\@gobbletwo{#2PT#3}}\fi
+ \if@PJLlang@enable@BR\expandafter\PassFirstToSecond\expandafter{\csname#2nameBR\endcsname}{\@gobbletwo{#2BR#3}}\fi
+ \if@PJLlang@enable@ES\expandafter\PassFirstToSecond\expandafter{\csname#2nameES\endcsname}{\@gobbletwo{#2ES#3}}\fi
+ \if@PJLlang@enable@CN\expandafter\PassFirstToSecond\expandafter{\csname#2nameCN\endcsname}{\@gobbletwo{#2CN#3}}\fi
+ \if@PJLlang@enable@TC\expandafter\PassFirstToSecond\expandafter{\csname#2nameTC\endcsname}{\@gobbletwo{#2TC#3}}\fi
+ \if@PJLlang@enable@JP\expandafter\PassFirstToSecond\expandafter{\csname#2nameJP\endcsname}{\@gobbletwo{#2JP#3}}\fi
+ \if@PJLlang@enable@RU\expandafter\PassFirstToSecond\expandafter{\csname#2nameRU\endcsname}{\@gobbletwo{#2RU#3}}\fi
}{%
\IfValueTF{#5}{%
\newcounter{#2#3}[{#5}]%
@@ -241,7 +235,7 @@
\if@PJLlang@enable@RU\CreateTheoremNumberedLikeAliasCounter{#2}{RU}{#3}\fi%
%---------------------------------------------------------------
}%
- \NewDocumentEnvironment{#2#3}{}
+ \NewDocumentEnvironment{#2#3}{}%%%
{\csname#2\csname\languagename ABBR\endcsname#3\endcsname}%
{\csname end#2\csname\languagename ABBR\endcsname#3\endcsname}%
}%
@@ -249,17 +243,17 @@
}%
\NewDocumentCommand{\CreateTheoremNumberedLikeAliasCounter}{mmm}{%
\newaliascnt{#1#2#3}{#1#3}%
- \expandafter\PassFirstToSecond\expandafter{\csname#1name#2\endcsname}{\newtheorem{#1#2#3}[{#1#2#3}]}%
+ \expandafter\PassFirstToSecond\expandafter{\csname#1name#2\endcsname}{\@gobbleMandOptMand{#1#2#3}[{#1#2#3}]}%
\aliascntresetthe{#1#2#3}%
\expandafter\PassFirstToSecond\expandafter{\csname#1name#2\endcsname}%
{%
\expandafter\PassFirstToSecond\expandafter{\csname#1name#2\endcsname}%
- {\crefname{#1#2#3}}%
+ {\@gobblethree{#1#2#3}}%
}%
\expandafter\PassFirstToSecond\expandafter{\csname#1name#2\endcsname}%
{%
\expandafter\PassFirstToSecond\expandafter{\csname#1name#2\endcsname}%
- {\Crefname{#1#2#3}}%
+ {\@gobblethree{#1#2#3}}%
}%
}%
\fi
@@ -702,4 +696,4 @@
\endinput
%%
-%% End of file `PJLthm.sty'.
+%% End of file `PJLthmDamaged.sty'.
and save the example
\documentclass{article}
\makeatletter
\def\@gobblethree#1#2#3{}%
\def\@gobbleMandOptMand#1[#2]#3{}%
\makeatother
\usepackage[originalref]{PJLthmDamaged}
\UseLanguage{French}
% For some reason the package defines the theorem-environment
% via \AtEndPreamble.
% Therefore theorems based on that cannot be defined within the preamble
% unless via \AtEndPreamble or \AtBeginDocument or the like.
\AtEndPreamble{%
\def\ideanameFR{Idée}%
\CreateTheorem{idea}[theorem]%
}%
\begin{document}
%%%\begin{theorem}\label{thm}
%%% Un théorème en français.
%%%\end{theorem}
%%%\begin{idea}\label{idea}
%%% Une idée en français.
%%%\end{idea}
%%%\cref{thm,idea}
\end{document}
as test.tex (same example as above, the only fifference is, that PJLthmDamaged.sty is loaded instead of PJLthm.sty) and on Debian Linux do
time pdflatex test.tex
, then I get:
real 0m1,614s
user 0m1,522s
sys 0m0,084s
The ratio
⟨compilation-time without disabling \newtheorem
, \crefname
, \Crefname
⟩ : ⟨compilation-time with disabling \newtheorem
, \crefname
, \Crefname
⟩
on my machine is about 38 : 1 !
You can see that with my current approach the slowness is not that much due to the code I wrote around the calls to \newtheorem
etc for properly arranging the arguments of \newtheorem
etc, but is more due to the frequency with which \newtheorem
etc actually are carried out.
Thus I don't see ways of getting things compiled considerably faster other than reducing the amount of \newtheorem
etc to carry out.
In this context, however, the requirement of \CreateTheorem
also working while amsthm is in use is a problem—remembering the "joyful" comments about ams-things in the commented source code of previous hyperref package releases: When does a problem not have to do with ams-math-stuff? (-:
amsthm redefines internals of \newtheorem
so that you cannot use a placeholder for the counter to use with the theorem to be defined.
Otherwise you could, e.g.,
have a macro \languagename
which is to hold the name of the language currently in use
via \newcountr
define a counter counter
temporarily define \languagename
to be empty
do something like
\newtheorem{theorem}[counter\languagename]{\csname theorem\languagename heading\endcsname}
restore \languagename
and for each ⟨languagename⟩ maintain an alias-counter whose name is of pattern counter⟨languagename⟩
and which is an alias of the "underlying" real counter counter
and define macros whose names are of pattern \theorem⟨languagename⟩heading
.
(\languagename
must temporarily be defined to be empty in order to prevent \newtheorem
from delivering an error-message in case currently a language is in use where no language-specific alias-counter for the environment's real counter is defined yet.)
Without amsthm you can do this because without amsthm the tokens counter\languagename
go into the definition of the environment in question unevaluated/unexpanded and are evaluated at the time of carrying out instances of the environment in question.
With amsthm, however, you can't do this because amsthm redefines things in a way where not the the tokens counter\languagename
go into the definition of the environment in question but the control-word-token resulting from evaluating \csname thecounter\languagename\endcsname
goes into the definition of the environment in question.
I.e., with amsthm the token \languagename
is evaluated at the time of defining the environment in question and therefore doesn't make it into the definition of the environment in question.
When patching amsthm's redefinitions of the internals of \newtheorem
so that—as is the case without amsthm—the tokens forming the name of the counter in use go into the definition of the environment in question unexpanded/unevaluated, then you would not need to define an internal theorem-environment theorem⟨languagename⟩
for each kind of theorem in each language, but one call to \newtheorem
per group of theorems of same kind but differing in language would be sufficient.
If you don't mind patching the internal macro \@ynthm
in case amsthm/cleveref is loaded—the patch could be arranged to be valid only during carrying out \CreateTheorem
—, a solution according to the approach just outlined might be possible.
So far I have been reluctant to patch an internal macro, which, by the way, is also patched by other packages, for the following reasons:
- E.g., the packages cleveref and hyperref in turn also patch the amsthm-code of
\@ynthm
. I did not yet delve into the code of cleveref deep enough to find out about all the details.
- I don't know about the ways in which such patching would affect other packages about cross-referencing or theorems, e.g., the packages varioref or theorem.
- Patching code of other packages implies the need of keeping track of changes to the code which your package is patching. This doesn't make maintenance of the package more easy.
- Patching code of other packages implies the need of ensuring that your package in any case is loaded after those packages whose code it needs to patch. This doesn't make usage of the package more easy.
In case you are interested in such an approach despite its drawbacks, let me know and I might delve into the code of cleveref etc and edit this answer when I am done.
An initial experimental start, but one that needs intensive revision, debugging, adjusting, rectifying and thought, might be something like the following:
\documentclass[french,english,ngerman]{article}
\usepackage{babel}
\usepackage{xcolor}
\definecolor{paper}{RGB}{255,255,255}
\PassOptionsToPackage{nameinlink}{cleveref}
\usepackage{hyperref}
\usepackage{mathtools}
\usepackage{amsthm}
\makeatletter
\RequirePackage{aliascnt}
\RequirePackage{cleveref}
\crefdefaultlabelformat{#2#1#3}
\RequirePackage{etoolbox}
\@ifdefinable\@ynthmcopyA{\let\@ynthmcopyA\@ynthm}
\@ifdefinable\@ynthmcopyB{\let\@ynthmcopyB\@ynthm}
\newcommand\languagenamecopy{}
\@ifpackageloaded{amsthm}{\iftrue}{\csname iffalse\endcsname}%
\patchcmd{\@ynthmcopyA}%
{\@xp\xdef\csname the#1\endcsname{\@xp\@nx\csname the#2\endcsname}}%
{\@xp\gdef\csname the#1\endcsname{\csname the#2\endcsname}}%
{\message{!!! Patching successful !!!}}%
{\message{!!! Patching failed !!!}}%
\patchcmd{\@ynthmcopyA}%
{{#2}{\the\toks@}}%
{{\unexpanded{#2}}{\the\toks@}}%
{\message{!!! Patching successful !!!}}%
{\message{!!! Patching failed !!!}}%
\@ifpackageloaded{cleveref}{\iftrue}{\csname iffalse\endcsname}%
% !!! Probably some more things need to be done.
% !!! E.g., I did not yet grasp what all this preamble-stuff in
% !!! cleveref's redefinition of \@ynthm is about.
\patchcmd{\@ynthmcopyA}%
{\@thm[#1]}%
{\@thm[#1\@nx\languagename]}%
{\message{!!! Patching successful !!!}}%
{\message{!!! Patching failed !!!}}%
\fi
\fi
\makeatother
\makeatletter
\newtheoremstyle{simple}%
{}{}%
{\normalfont}{}%
{\normalfont}{}%
{0pt}%
{%
\thmname{\MakeUppercase{#1}}%
\thmnumber{ #2}%
\hspace{.4em}%
\textcolor{gray!55!paper}{$|$}%
\hspace{.4em}
\color{gray}%
\thmnote{\ensuremath{(\text{#3})}~~}\pushQED{\qed}%
}
% One needs to see if something can be done about this:
\def\@endtheorem{\popQED\endtrivlist\@endpefalse}%
% because the redifinition applies to all theorem-environments, not just
% those defined with theoremstyle "simple". Probably the new
% environment-hook-management of up-to-date LaTeX-kernels can be used.
\renewcommand{\qedsymbol}{\makebox[1em]{\color{gray!55!paper}\rule[-0.1em]{.95em}{.95em}}}%
\makeatother
\newcounter{theorem}
\newaliascnt{theoremenglish}{theorem}%
\aliascntresetthe{theoremenglish}%
\newcommand\theoremenglishheading{Theorem}%
\newcommand\theoremenglishname{Theorem}%
\crefname{theoremenglish}{theorem}{Theorem}%
\newaliascnt{theoremfrench}{theorem}%
\aliascntresetthe{theoremfrench}%
\newcommand\theoremfrenchheading{Théorème}%
\newcommand\theoremfrenchname{Théorème}%
\crefname{theoremfrench}{théorème}{Théorème}%
\newaliascnt{theoremngerman}{theorem}%
\aliascntresetthe{theoremngerman}%
\newcommand\theoremngermanheading{GTheorem}%
\newcommand\theoremngermanname{GTheorem}%
\crefname{theoremngerman}{gtheorem}{GTheorem}%
\theoremstyle{simple}
\makeatletter
\let\@ynthm\@ynthmcopyA
\let\languagenamecopy\languagename
\let\languagename\empty
\newtheorem{theorem}[theorem\languagename]{\csname theorem\languagename heading\endcsname}
\let\@ynthm\@ynthmcopyB
\let\languagename\languagenamecopy
\makeatother
\begin{document}
\begin{theorem}\label{theoremA}%
bla bla
\end{theorem}
\selectlanguage{french}
\begin{theorem}\label{theoremB}%
blu blu
\end{theorem}
\ref{theoremA}\\
\pageref{theoremA}\\
\autoref{theoremA}\\
% \nameref{theoremA}\\
\cref{theoremA,theoremB}
\ref{theoremB}\\
\pageref{theoremB}\\
\autoref{theoremB}\\
% \nameref{theoremB}\\
\cref{theoremA,theoremB}
\end{document}

I have some questions regarding the "user interface":
How about following the convention of naming languages as they are named in the babel package? Then you could get the name of the language currently in use from the macro \languagename
. And you could simply use babel's infrastructure (\selectlanguage
, \foreignlanguage
etc) to change the language. babel's infrastructure would automatically set/adjust \languagename
. Language specific defined structures would have names that can be obtained using the expansion of the macro \languagename
. E.g. not "counterFR" but "counterfrench or "counterenglish", so that one could also say "counter\languagename" in general.
What about using expl3 for adding an argument with comma-list/key=value-syntax for those cases where \CreateTheorem
is used for creating numbered theorems? Something like
\CreateTheorem{MyTheorem}[superordinate counter]{%
EN={%
crefname={bla}{bla}{bla}, %<- for cleveref's \crefname with aliascounter MyTheoremEN
Crefname={bla}{bla}{bla} %<- for cleveref's \Crefname with aliascounter MyTheoremEN
name=bla, %<- for the macro \MyTheoremENname
autoref=bla,%<- for the macro \MyTheoremENautorefname with aliascounter MyTheoremEN
heading=Theorem heading in English %<- for the macro \MyTheoremENheading
},
FR={%
crefname={bla}{bla}{bla}, %<- for cleveref's \crefname with aliascounter MyTheoremFR
Crefname={bla}{bla}{bla} %<- for cleveref's \Crefname with aliascounter MyTheoremFR
name=bla, %<- for the macro \MyTheoremFRname
autoref=bla,%<- for the macro \MyTheoremFRautorefname with aliascounter MyTheoremFR
heading=Titre du théorème en français %<- for the macro \MyTheoremFRheading
},
%...
}%
An initial experimental start, but one that needs intensive revision, debugging, adjusting, rectifying and thought :-) , might be something like the following:
\documentclass{article}
\RequirePackage{xparse}
\RequirePackage{aliascnt}
\RequirePackage{cleveref}
\ExplSyntaxOn
% Helper-macros/scratch-macros
%-----------------------------
\cs_new:Nn \MYMODULE_exchange_i_iii_ii:nnn { #1 {#3} {#2} }
\cs_new:Nn \__MYMODULE_languageprefix: {}
\cs_new:Nn \__MYMODULE_countername: {}
% Message-management:
%--------------------
\msg_new:nnnn {MYMODULE}
{Undefined Language Dependent Specification Class}
{\token_to_str:N \CreateTheorem :\ Value\ `\tl_to_str:n{#2}'\ for\ invalid\ key\ `#1'.}
{Providing\ Language-dependent\ specifications\ for\ element\ `#1'\ is\ currently\ not\ implemented.}
% As long as MYMODULE is not a real package but just some preamble-code redirect
% MYMODULE-related messages to denote to the preamble instead of a package/module:
\prop_gput:Nnn \g_msg_module_type_prop { MYMODULE } {}
\prop_gput:Nnn \g_msg_module_name_prop { MYMODULE } {Preamble-Code}
% Nested key=value-interface by means of package l3keys:
%-------------------------------------------------------
% (l3keys is similar to pgfkeys.)
% The outer level of key=value-specifications, i.e., <language-ID>={...},
% is processed via \keyval_parse:nnn which was added tpo expl3 in 2020/12/19.
% The inner level of key=value-specifications,
% i.e., the single keys whose values are to be specified dependant on the language,
% i.e., the "..."-content of the outer lever's {...},
% is processed via \keys_set:nn .
% The keys for the inner level are defined via \keys_define:nn .
\NewDocumentCommand \CreateTheoremSetKeys { mm } {
% #1 = name of counter
% #2 = keyval-list of language-specifications
\cs_set:Nn \__MYMODULE_countername: {#1}
\keyval_parse:nnn { \MYMODULE_exchange_i_iii_ii:nnn { \MYMODULE_setlanguagespecificparameters:nn } {} }
{ \MYMODULE_setlanguagespecificparameters:nn }
{ #2 }
}
\cs_new_protected:Nn \MYMODULE_setlanguagespecificparameters:nn {
% #1 = language-prefix
% #2 = key-val-list for language whose prefix is language-prefix
\cs_set:Nn \__MYMODULE_languageprefix: {#1}
\newaliascnt {\__MYMODULE_countername: \__MYMODULE_languageprefix:} {\__MYMODULE_countername:}%
\aliascntresetthe {\__MYMODULE_countername: \__MYMODULE_languageprefix:}%
\keys_set:nn { MYMODULE } { #2 }
}%
\keys_define:nn { MYMODULE } {
crefname.code:n = \cs_if_exist:NTF \crefname {
\exp_args:Nx \crefname {\__MYMODULE_countername: \__MYMODULE_languageprefix: }#1
}{},
crefname.value_required:n = true,
Crefname.code:n = \cs_if_exist:NTF \Crefname {
\exp_args:Nx \Crefname {\__MYMODULE_countername: \__MYMODULE_languageprefix: }#1
}{},
Crefname.value_required:n = true,
name.code:n = \exp_args:Nx \cs_set:cpn {\__MYMODULE_countername: \__MYMODULE_languageprefix: name} {#1},
name.value_required:n = true,
autorefname.code:n = \exp_args:Nx \cs_set:cpn {\__MYMODULE_countername: \__MYMODULE_languageprefix: autorefname} {#1},
autorefname.value_required:n = true,
theoremheading.code:n= \exp_args:Nx \cs_set:cpn {\__MYMODULE_countername: \__MYMODULE_languageprefix: heading} {#1},
theoremheading.value_required:n = true,
the.code:n= \exp_args:Nx \cs_set:cpn {the \__MYMODULE_countername: \__MYMODULE_languageprefix: } {#1},
the.value_required:n = true,
%
% Define keys for more Language Dependent Specification Classes.
%
unknown.code:n = \msg_error:nnxx {MYMODULE}
{Undefined Language Dependent Specification Class}
{\exp_args:No \exp_not:n \l_keys_key_str}
{\exp_not:n{#1}},
}
\ExplSyntaxOff
\newcounter{oddity}%
% By default \theoddity is now s.th. like \arabic{oddity}.
%
% Assume a \CreateTheorem-command is in progesss and has already defined
% - a theroem-like environment "oddity", using the "oddity\languageplaceholder"-counter,
% and where the heading is to come from the macro \oddity<languageplaceholder>heading .
% - a real counter "oddity" which is to be aliased to counters "oddity<languageplaceholder>"
% for language-specific output related to that counter.
% - a macro "\theoddity".
%
% For defining language-specific alias-counter-related supplementary macros
% which do not get defined by \newaliascnt, the macro \CreateTheorem could
% now internally do:
%
\CreateTheoremSetKeys{oddity}{%
FR={%
crefname={folie}{folies},
Crefname={Folie}{Folies},
name=folie,
autorefname=folie,
theoremheading=Folie,
},
EN={%
crefname={oddity}{oddities},
Crefname={Oddity}{Oddities},
name=oddity,
autorefname=oddity,
theoremheading=Oddity,
the=\roman{oddity}
},
DE={%
crefname={Seltsamkeit}{Seltsamkeiten},
Crefname={Seltsamkeit}{Seltsamkeiten},
name=Seltsamkeit,
autorefname=Seltsamkeit,
theoremheading=Seltsamkeit,
the=\alph{oddity},
},
}%
\begin{document}
\ttfamily
\def\printmeaning#1{\string#1 = \meaning#1}
\def\printmeanings#1#2{%
\par{%
\parskip=0ex \frenchspacing
\hrule\hfill\par
\noindent\strut Counter: #1\\
\noindent Language: #2\\
supplementary macros for alias-counter #1#2:\strut\par
\hrule\hfill\par
\noindent%
\expandafter\printmeaning\csname cref@#1#2@name\endcsname \\
\expandafter\printmeaning\csname Cref@#1#2@name\endcsname \\
\expandafter\printmeaning\csname cref@#1#2@name@plural\endcsname \\
\expandafter\printmeaning\csname Cref@#1#2@name@plural\endcsname \\
\expandafter\printmeaning\csname #1#2name\endcsname \\
\expandafter\printmeaning\csname #1#2autorefname\endcsname \\
\expandafter\printmeaning\csname #1#2heading\endcsname \\
\expandafter\printmeaning\csname the#1#2\endcsname\strut\par
\hrule\hfill\par
}%
}%
\printmeanings{oddity}{FR}
\vfill
\printmeanings{oddity}{EN}
\vfill
\printmeanings{oddity}{DE}
\vfill\vfill
\end{document}

Pitfalls I am currently aware of:
With the keys of crefname
and Crefname
currently it is not checked whether the values consist of exactly two non-optional arguments and thus fit the syntax of \crefname
/\Crefname
.
When you have PJLthm.sty ([2021/08/07a]) and Patch.diff in the same directory, then in Debian Linux you can obtain the crippled/damaged PJLthmDamaged.sty, where
- instances of
\Crefname
and \crefname
and \newtheorem
are replaced by instances of argument-gobbling-macros,
- the loading of cleveref is removed,
- package-name and version is changed,
by opening a shell, changing to that directory and performing the command
patch -o PJLthmDamaged.sty PJLthm.sty Patch.diff
(I could not insert PJLthmDamaged.sty into this answer directly as by doing so this answer would have exceeded the 30000-character limit.)