When \cref a theorem, in order to show the referencing name corresponding to the original appearance in its context (i.e., if you write a theorem in English context, and later refer to it in French context, then the English name Theorem shall be shown), I defined separate counters theorem-english and theorem-french and then alias them to theorem, and defined separate \crefname to these counters.
The problem is that \crefname is slow, so as the number of languages and theorem-like environments increase, this approach quite soon becomes unbearably slow.
An idea is to reduce the use of \crefname, only define it once for the counter theorem-\languagename (here \languagename is used as a place holder). However I don't know if this can actually work -- I tried to set it to the counter theorem- \exp_not:N \languagename, but this ended up with several errors.
Below is a MWE.
\documentclass{article}
\usepackage[french,english]{babel}
\usepackage{amsthm}
\usepackage{aliascnt}
\usepackage[french,english]{cleveref}
\makeatletter
\ExplSyntaxOn
\newtheorem{theorem}{ \tl_use:c { c_projlib_theorem_name_theorem_ \languagename tl } }
\newtheorem{definition}[theorem]{ \tl_use:c { c_projlib_theorem_name_definition \languagename _tl } }
\newaliascnt{theorem-english}{theorem}
\newaliascnt{theorem-french}{theorem}
%% Too many crefnames thus too slow
\crefname{theorem-english}{\c_projlib_theorem_name_theorem_english_tl}{\c_projlib_theorem_name_theorem_plural_english_tl}
\crefname{theorem-french}{\c_projlib_theorem_name_theorem_french_tl}{\c_projlib_theorem_name_theorem_plural_french_tl}
%% Does not work
% \crefname{theorem- \exp_not:N \languagename}
% { \tl_use:c { c_projlib_theorem_name_theorem_\languagename_tl } }
% { \tl_use:c { c_projlib_theorem_name_theorem_plural_\languagename_tl } }
% Temporary names
\tl_set:Nn \c_projlib_theorem_name_theorem_english_tl { Theorem }
\tl_set:Nn \c_projlib_theorem_name_theorem_plural_english_tl { Theorems }
\tl_set:Nn \c_projlib_theorem_name_theorem_french_tl { Théorème }
\tl_set:Nn \c_projlib_theorem_name_theorem_plural_french_tl { Théorèmes }
\tl_set:Nn \c_projlib_theorem_name_definition_english_tl { Definition }
\tl_set:Nn \c_projlib_theorem_name_definition_plural_english_tl { Definitions }
\tl_set:Nn \c_projlib_theorem_name_definition_french_tl { Définition }
\tl_set:Nn \c_projlib_theorem_name_definition_plural_french_tl { Définitions }
\ExplSyntaxOff
\makeatother
\begin{document}
\begin{theorem}
\addtocounter{theorem-english}{-1}
\refstepcounter{theorem-english}
\label{thm1}
In english.
\end{theorem}
\begin{definition}\label{def1}
In english.
\end{definition}
\cref{thm1,thm2,def1,def2}
\selectlanguage{french}
\begin{theorem}
\addtocounter{theorem-french}{-1}
\refstepcounter{theorem-french}
\label{thm2}
En français.
\end{theorem}
\begin{definition}\label{def2}
En français.
\end{definition}
\cref{thm1,thm2,def1,def2}
% \makeatletter
% \meaning\cref@old@refstepcounter
% \meaning\refstepcounter@noarg
\end{document}
Below is a sophisticated version, contains the code that is supposed to be part of the in building projlib-theorem module. If you uncomment the To slow part, this is the behavior of the above MWE, but with a more complete configuration.
\begin{filecontents*}[overwrite]{projlib-language.sty}
\NeedsTeXFormat{LaTeX2e}[2020-10-01]
\RequirePackage{l3keys2e}
\ProvidesExplPackage
{projlib-language}
{2022/02/10} {}
{Multi-language configuration}
\clist_new:N \c__projlib_language_supported_clist
\clist_new:N \g__projlib_language_babel_option_clist
\clist_set:Nn \c__projlib_language_supported_clist
{
english ,
french ,
ngerman ,
italian ,
portuguese ,
brazilian ,
spanish ,
schinese ,
tchinese ,
japanese ,
russian ,
}
\str_new:N \g__projlib_language_main_str
\bool_new:N \g__projlib_language_enabled_all_bool
\bool_gset_true:N \g__projlib_language_enabled_all_bool
\clist_map_inline:Nn \c__projlib_language_supported_clist
{
\bool_new:c { g__projlib_language_enabled_ #1 bool }
\bool_gset_false:c { g__projlib_language_enabled #1 _bool }
}
\cs_new:Nn \projlib_language_set_option_no_babel:n
{
\bool_gset_false:N \g__projlib_language_enabled_all_bool
\bool_gset_true:c { g__projlib_language_enabled_ #1 _bool }
\str_if_empty:NT \g__projlib_language_main_str
{
\str_gset:Nn \g__projlib_language_main_str { #1 }
}
}
\cs_new:Nn \projlib_language_set_option:n
{
\projlib_language_set_option_no_babel:n { #1 }
\clist_gput_left:Nn \g__projlib_language_babel_option_clist { #1 }
}
\keys_define:nn { projlib-language }
{
, EN .code:n = { \projlib_language_set_option:n { english } }
, english .code:n = { \projlib_language_set_option:n { english } }
, English .code:n = { \projlib_language_set_option:n { english } }
, FR .code:n = { \projlib_language_set_option:n { french } }
, french .code:n = { \projlib_language_set_option:n { french } }
, French .code:n = { \projlib_language_set_option:n { french } }
, DE .code:n = { \projlib_language_set_option:n { ngerman } }
, german .code:n = { \projlib_language_set_option:n { ngerman } }
, ngerman .code:n = { \projlib_language_set_option:n { ngerman } }
, German .code:n = { \projlib_language_set_option:n { ngerman } }
, IT .code:n = { \projlib_language_set_option:n { italian } }
, italian .code:n = { \projlib_language_set_option:n { italian } }
, Italian .code:n = { \projlib_language_set_option:n { italian } }
, PT .code:n = { \projlib_language_set_option:n { portuguese } }
, portuguese .code:n = { \projlib_language_set_option:n { portuguese } }
, Portuguese .code:n = { \projlib_language_set_option:n { portuguese } }
, BR .code:n = { \projlib_language_set_option:n { brazilian } }
, brazilian .code:n = { \projlib_language_set_option:n { brazilian } }
, Brazilian .code:n = { \projlib_language_set_option:n { brazilian } }
, ES .code:n = { \clist_gput_left:Nn \g__projlib_language_babel_option_clist { es-notilde, es-noquoting } \projlib_language_set_option:n { spanish } }
, spanish .code:n = { \clist_gput_left:Nn \g__projlib_language_babel_option_clist { es-notilde, es-noquoting } \projlib_language_set_option:n { spanish } }
, Spanish .code:n = { \clist_gput_left:Nn \g__projlib_language_babel_option_clist { es-notilde, es-noquoting } \projlib_language_set_option:n { spanish } }
, CN .code:n = { \projlib_language_set_option_no_babel:n { schinese } }
, chinese .code:n = { \projlib_language_set_option_no_babel:n { schinese } }
, schinese .code:n = { \projlib_language_set_option_no_babel:n { schinese } }
, simplifiedchinese .code:n = { \projlib_language_set_option_no_babel:n { schinese } }
, Chinese .code:n = { \projlib_language_set_option_no_babel:n { schinese } }
, SChinese .code:n = { \projlib_language_set_option_no_babel:n { schinese } }
, SimplifiedChinese .code:n = { \projlib_language_set_option_no_babel:n { schinese } }
, TC .code:n = { \projlib_language_set_option_no_babel:n { tchinese } }
, tchinese .code:n = { \projlib_language_set_option_no_babel:n { tchinese } }
, traditionalchinese .code:n = { \projlib_language_set_option_no_babel:n { tchinese } }
, TChinese .code:n = { \projlib_language_set_option_no_babel:n { tchinese } }
, TraditionalChinese .code:n = { \projlib_language_set_option_no_babel:n { tchinese } }
, JP .code:n = { \projlib_language_set_option:n { japanese } }
, japanese .code:n = { \projlib_language_set_option:n { japanese } }
, Japanese .code:n = { \projlib_language_set_option:n { japanese } }
, RU .code:n = { \projlib_language_set_option:n { russian } }
, russian .code:n = { \projlib_language_set_option:n { russian } }
, Russian .code:n = { \projlib_language_set_option:n { russian } }
, unknown .code:n = {}
}
\ProcessKeysOptions { projlib-language }
\cs_new_protected:Nn \projlib_language_clear_global_option:n
{
\clist_remove_all:cn { @classoptionslist } { #1 }
}
\projlib_language_clear_global_option:n { chinese }
\projlib_language_clear_global_option:n { Chinese }
\clist_gput_right:Nn \g__projlib_language_babel_option_clist { shorthands = off }
\str_if_empty:NT \g__projlib_language_main_str
{
\str_gset:Nn \g__projlib_language_main_str { english }
}
\bool_if:NT \g__projlib_language_enabled_all_bool
{
\clist_map_inline:Nn \c__projlib_language_supported_clist
{
\bool_gset_true:c { g__projlib_language_enabled_ #1 _bool }
}
}
\cs_new:Nn \projlib_language_str_to_languagename:n
{
\str_case_e:nnF { \str_foldcase:n { #1 } }
{
{all} {common}
{common} {common}
{cn} {schinese}
{chinese} {schinese}
{schinese} {schinese}
{simplifiedchinese} {schinese}
{tc} {tchinese}
{tchinese} {tchinese}
{traditionalchinese} {tchinese}
{jp} {japanese}
{japanese} {japanese}
{en} {english}
{english} {english}
{fr} {french}
{french} {french}
{de} {ngerman}
{german} {ngerman}
{ngerman} {ngerman}
{it} {italian}
{italian} {italian}
{pt} {portuguese}
{portuguese} {portuguese}
{br} {brazilian}
{brazilian} {brazilian}
{es} {spanish}
{spanish} {spanish}
{ru} {russian}
{russian} {russian}
}
{ #1 }
}
\cs_new:Nn \projlib_language_str_to_languagetype:n
{
\str_case_e:nn { \str_foldcase:n { #1 } }
{
{cn} {cjk}
{chinese} {cjk}
{schinese} {cjk}
{simplifiedchinese} {cjk}
{tc} {cjk}
{tchinese} {cjk}
{traditionalchinese} {cjk}
{jp} {cjk}
{japanese} {cjk}
{en} {latin}
{english} {latin}
{fr} {latin}
{french} {latin}
{de} {latin}
{german} {latin}
{ngerman} {latin}
{it} {latin}
{italian} {latin}
{pt} {latin}
{portuguese} {latin}
{br} {latin}
{brazilian} {latin}
{es} {latin}
{spanish} {latin}
{ru} {latin}
{russian} {latin}
}
}
\sys_if_engine_pdftex:T
{
\RequirePackage [T1] { fontenc }
\RequirePackage { inputenc }
}
\bool_if:NTF \g__projlib_language_enabled_all_bool
{
\sys_if_engine_pdftex:F
{
\PassOptionsToPackage { japanese, russian } { babel }
}
\PassOptionsToPackage { italian, portuguese, brazilian, spanish, es-notilde, es-noquoting, ngerman, french, english, shorthands = off } { babel }
}
{
\PassOptionsToPackage { \g__projlib_language_babel_option_clist } { babel }
}
\PassOptionsToPackage { italian, brazilian, spanish, ngerman, french, english } { cleveref }
\RequirePackage { babel }
\bool_if:NT \g__projlib_language_enabled_french_bool
{
\frenchsetup { PartNameFull = false }
}
\bool_if:NT \g__projlib_language_enabled_portuguese_bool
{
\cs_set_eq:NN __projlib_language_babel_ord: \ord
\cs_undefine:N \ord
\hook_gput_code:nnn { begindocument } { projlib-language }
{
\cs_if_exist:NT \ord
{
\cs_set_eq:NN __projlib_language_user_ord: \ord
\cs_set_protected:Npn \ord
{
\mode_if_math:TF
{ __projlib_language_user_ord: }
{ __projlib_language_babel_ord: }
}
}
}
}
\babelprovide { schinese }
\babelprovide { tchinese }
\NewCommandCopy \projlib_language_backup_today:n \today
\tl_new:N \g_projlib_language_settings_common_tl
\clist_map_inline:Nn \c__projlib_language_supported_clist
{
\tl_new:c { g_projlib_language_settings_ #1 _tl }
}
\tl_gput_right:Nn \g_projlib_language_settings_common_tl
{
\cs_if_exist:NT \ProjLibToday
{
\RenewCommandCopy \today \ProjLibToday
}
}
\tl_gput_right:Nn \g_projlib_language_settings_schinese_tl
{
\g_projlib_language_settings_common_tl
\tl_gset:Nn \languagename { schinese }
\tl_gset:cn { abstractname } { 摘要 }
\tl_gset:cn { proofname } { 证明 }
\tl_gset:cn { contentsname } { 目录 }
\tl_gset:cn { listfigurename } { 插图 }
\tl_gset:cn { listtablename } { 表格 }
\tl_gset:cn { figurename } { 图 }
\tl_gset:cn { tablename } { 表 }
\tl_gset:cn { indexname } { 索引 }
\tl_gset:cn { appendixname } { 附录 }
\tl_gset:cn { refname } { 参考文献 }
\tl_gset:cn { bibname } { 参考文献 }
}
\tl_gput_right:Nn \g_projlib_language_settings_tchinese_tl
{
\g_projlib_language_settings_common_tl
\tl_gset:Nn \languagename { tchinese }
\tl_gset:cn { abstractname } { 摘要 }
\tl_gset:cn { proofname } { 證明 }
\tl_gset:cn { contentsname } { 目錄 }
\tl_gset:cn { listfigurename } { 插圖 }
\tl_gset:cn { listtablename } { 表格 }
\tl_gset:cn { figurename } { 圖 }
\tl_gset:cn { tablename } { 表 }
\tl_gset:cn { indexname } { 索引 }
\tl_gset:cn { appendixname } { 附錄 }
\tl_gset:cn { refname } { 參考文獻 }
\tl_gset:cn { bibname } { 參考文獻 }
}
\tl_gput_right:Nn \g_projlib_language_settings_japanese_tl
{
\selectlanguage { japanese }
\g_projlib_language_settings_common_tl
}
\tl_gput_right:Nn \g_projlib_language_settings_english_tl
{
\selectlanguage { english }
\g_projlib_language_settings_common_tl
}
\tl_gput_right:Nn \g_projlib_language_settings_french_tl
{
\selectlanguage { french }
\g_projlib_language_settings_common_tl
\tl_gset:cn { frenchpartname } { Partie }
}
\tl_gput_right:Nn \g_projlib_language_settings_ngerman_tl
{
\selectlanguage { ngerman }
\g_projlib_language_settings_common_tl
}
\tl_gput_right:Nn \g_projlib_language_settings_italian_tl
{
\selectlanguage { italian }
\g_projlib_language_settings_common_tl
}
\tl_gput_right:Nn \g_projlib_language_settings_portuguese_tl
{
\selectlanguage { portuguese }
\g_projlib_language_settings_common_tl
}
\tl_gput_right:Nn \g_projlib_language_settings_brazilian_tl
{
\selectlanguage { brazilian }
\g_projlib_language_settings_common_tl
}
\tl_gput_right:Nn \g_projlib_language_settings_spanish_tl
{
\selectlanguage { spanish }
\g_projlib_language_settings_common_tl
}
\tl_gput_right:Nn \g_projlib_language_settings_russian_tl
{
\selectlanguage { russian }
\g_projlib_language_settings_common_tl
}
\NewDocumentCommand \AddLanguageSetting { O{} m }
{
\IfNoValueTF { #1 }
{
\tl_gput_right:Nn \g_projlib_language_settings_common_tl { #2 }
}
{
\tl_gput_right:cn { g_projlib_language_settings_ \projlib_language_str_to_languagename:n { #1 } _tl } { #2 }
}
}
\RequirePackage { setspace }
\tl_new:N \g_projlib_language_linespacing_latin_tl
\tl_new:N \g_projlib_language_linespacing_cjk_tl
\tl_gset:Nn \g_projlib_language_linespacing_latin_tl
{
\setstretch { 1.00 }
}
\tl_gset:Nn \g_projlib_language_linespacing_cjk_tl
{
\onehalfspacing
}
\cs_new:Nn \projlib_language_set_linespacing_latin:n
{
\tl_gset:Nn \g_projlib_language_linespacing_latin_tl { #1 }
}
\cs_new:Nn \projlib_language_set_linespacing_cjk:n
{
\tl_gset:Nn \g_projlib_language_linespacing_cjk_tl { #1 }
}
\tl_new:N \g_projlib_language_parindent_latin_tl
\tl_new:N \g_projlib_language_parindent_cjk_tl
@ifclassloaded{beamer}
{
\tl_gset:Nn \g_projlib_language_parindent_latin_tl
{
\dim_set:Nn \parindent { 0em }
}
\tl_gset:Nn \g_projlib_language_parindent_cjk_tl
{
\dim_set:Nn \parindent { 0em }
}
}
{
\tl_gset:Nn \g_projlib_language_parindent_latin_tl
{
\dim_set:Nn \parindent { 1.5em }
}
\tl_gset:Nn \g_projlib_language_parindent_cjk_tl
{
\dim_set:Nn \parindent { 2em }
}
}
\cs_new:Nn \projlib_language_set_parindent_latin:n
{
\tl_gset:Nn \g_projlib_language_parindent_latin_tl { #1 }
}
\cs_new:Nn \projlib_language_set_parindent_cjk:n
{
\tl_gset:Nn \g_projlib_language_parindent_cjk_tl { #1 }
}
\cs_new:Nn \projlib_language_use_language_pure:n
{
\tl_use:c { g_projlib_language_settings_ \projlib_language_str_to_languagename:n { #1 } _tl }
}
\cs_new:Nn \projlib_language_use_language:n
{
\projlib_language_use_language_pure:n { #1 }
\tl_use:c { g_projlib_language_linespacing_ \projlib_language_str_to_languagetype:n { #1 } tl }
\tl_use:c { g_projlib_language_parindent \projlib_language_str_to_languagetype:n { #1 } _tl }
}
\cs_generate_variant:Nn \projlib_language_use_language:n { e }
\NewDocumentCommand \UseLanguage { m }
{
\hook_gput_code:nnn { begindocument } { projlib-language }
{
\projlib_language_use_language:e { #1 }
}
}
\NewDocumentCommand \UseOtherLanguage { m m }
{
\group_begin: \group_begin:
\projlib_language_use_language_pure:e { #1 }
#2
\group_end: \group_end:
}
\UseLanguage { \g__projlib_language_main_str }
\cs_new:Nn \projlib_langauge_define_multilingual_text:Nn
{ % #1 = command name
% #2 = key-value name configuration
\keyval_parse:nnn
{}
{
__projlib_langauge_define_multilingual_text_do:nnn
{ \cs_to_str:N #1 }
}
{ #2 }
\tl_gset:Nn #1
{
\tl_use:c { \cs_to_str:N #1 projlib_language_text \languagename }
}
}
\cs_generate_variant:Nn \projlib_langauge_define_multilingual_text:Nn { cn }
\cs_new:Nn __projlib_langauge_define_multilingual_text_do:nnn
{ % #1 = command name
% #2 = language name
% #3 = the text
\exp_args:Ne \tl_gset:cn { #1 projlib_language_text \projlib_language_str_to_languagename:n { #2 } } { #3 }
}
\endinput
%%
%% End of file `projlib-language.sty'.
\end{filecontents*}
\documentclass{article}
\usepackage{projlib-language}
\usepackage{amsthm}
\usepackage{aliascnt}
\usepackage{cleveref}
\makeatletter
\ExplSyntaxOn
\bool_new:N \l__projlib_theorem_regionalref_bool
\bool_new:N \l__projlib_theorem_originalref_bool
\bool_set_true:N \l__projlib_theorem_originalref_bool
% \bool_set_false:N \l__projlib_theorem_originalref_bool
\clist_set:Nn \c__projlib_theorem_supported_clist
{
theorem ,
lemma ,
proposition ,
corollary ,
property ,
fact ,
conjecture ,
definition ,
axiom ,
assumption ,
convention ,
hypothesis ,
notation ,
exemple ,
problem ,
question ,
exercise ,
remark ,
observation ,
definition-proposition ,
definition-theorem ,
}
\clist_map_inline:Nn \c__projlib_theorem_supported_clist
{
\clist_map_inline:Nn \c__projlib_language_supported_clist
{
\tl_new:c { c_projlib_theorem_name_ #1 _ ##1 tl }
\tl_new:c { c_projlib_theorem_name #1 plural ##1 tl }
\tl_new:c { c_projlib_theorem_name_uppercase #1 _ ##1 tl }
\tl_new:c { c_projlib_theorem_name_uppercase #1 plural ##1 _tl }
}
}
\clist_map_inline:Nn \c__projlib_theorem_supported_clist
{
\newtheorem { #1 projlib_regional } { \tl_use:c { c_projlib_theorem_name #1 _ \languagename tl } }
\NewDocumentEnvironment { #1 } { O{} }
{
\begin{ #1 _projlib_regional }[##1]
\bool_if:NT \l__projlib_theorem_originalref_bool
{
\addtocounter { #1 _projlib_original\languagename } { -1 }
\refstepcounter { #1 projlib_original\languagename }
}
}
{
\end{ #1 _projlib_regional }
}
}
\bool_if:NTF \l__projlib_theorem_originalref_bool
{% "originalref" mode
\clist_map_inline:Nn \c__projlib_theorem_supported_clist
{
\clist_map_inline:Nn \c__projlib_language_supported_clist
{
\newaliascnt { #1 projlib_original ##1 } { #1 projlib_regional }
%% Too slow
% \crefname { #1 _projlib_original ##1 }
% { \tl_use:c { c_projlib_theorem_name_ #1 _ ##1 tl } }
% { \tl_use:c { c_projlib_theorem_name #1 plural ##1 tl } }
% \Crefname { #1 _projlib_original ##1 }
% { \tl_use:c { c_projlib_theorem_name_uppercase_ #1 _ ##1 tl } }
% { \tl_use:c { c_projlib_theorem_name_uppercase #1 plural ##1 tl } }
}
%% Does not work
% \crefname { #1 _projlib_original \exp_not:N \languagename }
% { \tl_use:c { c_projlib_theorem_name_ #1 _ \languagename tl } }
% { \tl_use:c { c_projlib_theorem_name #1 plural \languagename tl } }
}
}
{% "regionalref" mode
\clist_map_inline:Nn \c__projlib_theorem_supported_clist
{
\crefname { #1 _projlib_regional }
{ \tl_use:c { c_projlib_theorem_name #1 _ \languagename tl } }
{ \tl_use:c { c_projlib_theorem_name #1 plural \languagename tl } }
\Crefname { #1 _projlib_regional }
{ \tl_use:c { c_projlib_theorem_name_uppercase #1 _ \languagename tl } }
{ \tl_use:c { c_projlib_theorem_name_uppercase #1 plural \languagename _tl } }
}
}
% Temporary names
\tl_set:Nn \c_projlib_theorem_name_theorem_english_tl { Theorem }
\tl_set:Nn \c_projlib_theorem_name_theorem_plural_english_tl { Theorems }
\tl_set:Nn \c_projlib_theorem_name_theorem_french_tl { Théorème }
\tl_set:Nn \c_projlib_theorem_name_theorem_plural_french_tl { Théorèmes }
\tl_set:Nn \c_projlib_theorem_name_definition_english_tl { Definition }
\tl_set:Nn \c_projlib_theorem_name_definition_plural_english_tl { Definitions }
\tl_set:Nn \c_projlib_theorem_name_definition_french_tl { Définition }
\tl_set:Nn \c_projlib_theorem_name_definition_plural_french_tl { Définitions }
\ExplSyntaxOff
\makeatother
\begin{document}
\UseLanguage{English}
\begin{theorem}\label{thm1}
In english.
\end{theorem}
\begin{definition}\label{def1}
In english.
\end{definition}
\cref{thm1,thm2,def1,def2}
\UseLanguage{French}
\begin{theorem}\label{thm2}
En français.
\end{theorem}
\begin{definition}\label{def2}
En français.
\end{definition}
\cref{thm1,thm2,def1,def2}
\end{document}


\crefname/\Crefnameinternally use\csname..\endcsnamefor defining some macros. In the course of defining the\csname..\endcsname-expressions are evaluated fully to yield the corresponding control-word-token. Seems basically you ask whether the name of a control-word-token can have a place-holder. This is not possible. You can use place-holders with\csname..\endcsname-expressions but you cannot have place-holders in the names of already created control-word-tokens. ... – Ulrich Diez Feb 11 '22 at 10:33c_projlib_theorem_name_theorem_\languagename_tland the like you could use macro-names that match the naming-pattern of the macros defined via\crefname/\Crefname, then you would be done without needing to use\crefname/\Crefname. But I think this is not an option for you. – Ulrich Diez Feb 11 '22 at 10:35cleveref. Clearly\crefnamedoes much more that just set some name macros, otherwise it won't take so much time. That said, I'm not sure which macros should be set if not using\crefnameto accomplish the goal. – Jinwen Feb 11 '22 at 10:39\crefname. Definitions can be found in lines 4164 ff. Basically both\crefnameand\Crefnamreinternally use\@crefname(defined in line 4245) for doing some\csname..\endcsname-trickery. Seems the time-consuming part with\crefnameand\Crefnameis the attempts of defining the other case-variants as well. – Ulrich Diez Feb 11 '22 at 10:45\newtheoremis reduced to only once per theorem-like environment, and is instead using only counters for recording the language name in the context, so the code is more compact. The sad thing is\newtheoremis not the most time-consuming item, so one still has to deal with the\crefname/\Crefnameissue. – Jinwen Feb 11 '22 at 10:53cleverefat all, but just now while following the code I found something. Since the detail is a bit long, I put them in an answer below. I shall put the code into\CreateTheoremin the newprojlib-theorem, taking this chance to rewrite this macro completely withexpl3. I would like to express my gratitude to you again for building the early version of this macro, without which I wouldn't have the slightest idea where to begin with ;-) – Jinwen Feb 11 '22 at 12:22