是否可以使用占位符作为 \crefname 中的计数器名称?

是否可以使用占位符作为 \crefname 中的计数器名称?

\cref一个定理时,为了显示与其上下文中原来出现相对应的引用名称(即,如果你在英文上下文中写了一条定理,后来在法文上下文中引用它,那么就Theorem应该显示英文名称),我定义了单独的计数器theorem-english和,theorem-french然后将它们别名为theorem,并\crefname给这些计数器定义了单独的。

问题在于它\crefname很慢,所以随着语言和类定理环境的数量增加,这种方法很快就会变得难以忍受的慢。

一个想法是减少使用\crefname,只为计数器定义一次theorem-\languagename(这里\languagename用作占位符)。但是我不知道这是否真的可行——我尝试将其设置为计数器theorem- \exp_not:N \languagename,但最终出现了几个错误。

下面是 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}

下面是一个复杂的版本,包含应该是构建projlib-theorem模块的一部分的代码。如果取消注释该To slow部分,这是上述 MWE 的行为,但具有更完整的配置。

\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}

答案1

自从这个问题提出半年多以来寻求更快的 \CreateTheorem 实现,我想我终于意识到是什么在“originalref”模式中真正耗费了这么多时间。

内部调用,尽管创建了名称宏和,但仍将当前计数器名称添加到。从那时起,确实花费了大量时间。在中\crefname,可以找到以下代码来处理中每个项目的名称、格式等:\@crefname\cref@...@name\cref@...@name@plural\cref@label@typescleveref.dtx\cref@label@types

% Define any undefined formats listed in \cmd{\cref@label@types} using
% the components.
%    \begin{macrocode}
  \let\@tempstack\cref@label@types%
  \cref@isstackfull{\@tempstack}%
  \@whilesw\if@cref@stackfull\fi{%
    \edef\@tempa{\cref@stack@top{\@tempstack}}%
    \@ifundefined{cref@\@tempa @name}{%
      \expandafter\def\expandafter\@tempb\expandafter{%
        \csname cref@\@tempa @name\endcsname}%
      \expandafter\def\expandafter\@tempc\expandafter{%
        \csname cref@\@tempa @name@preamble\endcsname}%
      \expandafter\expandafter\expandafter%
        \let\expandafter\@tempb\@tempc%
      \expandafter\def\expandafter\@tempb\expandafter{%
        \csname cref@\@tempa @name@plural\endcsname}%
      \expandafter\def\expandafter\@tempc\expandafter{%
        \csname cref@\@tempa @name@plural@preamble\endcsname}%
      \expandafter\expandafter\expandafter%
        \let\expandafter\@tempb\@tempc%
    }{%
      \edef\@tempb{%
        \expandafter\noexpand\csname extras\cref@language\endcsname}%
      \expandafter\def\expandafter\@tempc\expandafter{%
        \expandafter\crefname\expandafter{\@tempa}}%
      \expandafter\expandafter\expandafter\cref@addto%
      \expandafter\expandafter\expandafter\@tempc%
      \expandafter\expandafter\expandafter{%
        \expandafter\expandafter\expandafter{%
          \csname cref@\@tempa @name\endcsname}}%
      \expandafter\expandafter\expandafter\cref@addto%
      \expandafter\expandafter\expandafter\@tempc%
      \expandafter\expandafter\expandafter{%
        \expandafter\expandafter\expandafter{%
          \csname cref@\@tempa @name@plural\endcsname}}%
      \expandafter\expandafter\expandafter\cref@addto%
        \expandafter\@tempb\expandafter{\@tempc}%
    }%
    \@ifundefined{Cref@\@tempa @name}{%
      \expandafter\def\expandafter\@tempb\expandafter{%
        \csname Cref@\@tempa @name\endcsname}%
      \expandafter\def\expandafter\@tempc\expandafter{%
        \csname Cref@\@tempa @name@preamble\endcsname}%
      \expandafter\expandafter\expandafter%
        \let\expandafter\@tempb\@tempc%
      \expandafter\def\expandafter\@tempb\expandafter{%
        \csname Cref@\@tempa @name@plural\endcsname}%
      \expandafter\def\expandafter\@tempc\expandafter{%
        \csname Cref@\@tempa @name@plural@preamble\endcsname}%
      \expandafter\expandafter\expandafter%
        \let\expandafter\@tempb\@tempc%
    }{%
      \edef\@tempb{%
        \expandafter\noexpand\csname extras\cref@language\endcsname}%
      \expandafter\def\expandafter\@tempc\expandafter{%
        \expandafter\Crefname\expandafter{\@tempa}}%
      \expandafter\expandafter\expandafter\cref@addto%
      \expandafter\expandafter\expandafter\@tempc%
      \expandafter\expandafter\expandafter{%
        \expandafter\expandafter\expandafter{%
          \csname Cref@\@tempa @name\endcsname}}%
      \expandafter\expandafter\expandafter\cref@addto%
      \expandafter\expandafter\expandafter\@tempc%
      \expandafter\expandafter\expandafter{%
        \expandafter\expandafter\expandafter{%
          \csname Cref@\@tempa @name@plural\endcsname}}%
      \expandafter\expandafter\expandafter\cref@addto%
        \expandafter\@tempb\expandafter{\@tempc}%
    }%
%    \end{macrocode}
% We only define the reference-range and multi-reference formats if the
% plural form of the name is defined in the corresponding
% \cmd{\cref\meta{type}@name@plural}. Though \cmd{\crefname} and
% \cmd{\Crefname} always define both the singular and plural forms
% together, cross-reference names can also be defined automatically by
% \cmd{\newtheorem}, which can only define the singular form. For
% symmetry, we apply the same logic to the normal cross-reference format
% definition (only defining it if the singular form of the name is
% defined in \cmd{\cref\meta{type}@name}), though this should always be
% the case.
%    \begin{macrocode}
    \@ifundefined{cref@\@tempa @format}{%
      \@ifundefined{cref@\@tempa @name}{}{%
        \expandafter\@crefdefineformat\expandafter{\@tempa}}}{}%
    \@ifundefined{crefrange@\@tempa @format}{%
      \@ifundefined{cref@\@tempa @name@plural}{}{%
        \expandafter\@crefrangedefineformat\expandafter{\@tempa}}}{}%
    \@ifundefined{cref@\@tempa @format@first}{%
      \@ifundefined{cref@\@tempa @name@plural}{}{%
        \expandafter\@crefdefinemultiformat\expandafter{\@tempa}}}{}%
    \@ifundefined{crefrange@\@tempa @format@first}{%
      \@ifundefined{cref@\@tempa @name@plural}{}{%
        \expandafter\@crefrangedefinemultiformat%
        \expandafter{\@tempa}}}{}%
    \cref@stack@pop{\@tempstack}%
    \cref@isstackfull{\@tempstack}}%
%    \end{macrocode}
%
% If formats for subsections are undefined, define them to be identical
% to the formats for sections. Similarly for subsections within
% appendices, subfigures, subtables, subequations and enums.
%    \begin{macrocode}
  \@crefcopyformats{section}{subsection}%
  \@crefcopyformats{subsection}{subsubsection}%
  \@crefcopyformats{appendix}{subappendix}%
  \@crefcopyformats{subappendix}{subsubappendix}%
  \@crefcopyformats{figure}{subfigure}%
  \@crefcopyformats{table}{subtable}%
  \@crefcopyformats{equation}{subequation}%
%
  \@crefcopyformats{enumi}{enumii}%
  \@crefcopyformats{enumii}{enumiii}%
  \@crefcopyformats{enumiii}{enumiv}%
  \@crefcopyformats{enumiv}{enumv}%
%    \end{macrocode}

由于所有这些单独的定理计数器都具有相同的格式,因此可以简单地使用\@crefcopyformats。也就是说,除了\crefname,还可以这样做:

\tl_gset:cn { cref@ ... @name } { ... }
\tl_gset:cn { cref@ ... @name@plural } { ... }
\@crefcopyformats { <the main counter> } { <the separate counter> }

对于originalref模式,这将节省大量时间,使其几乎与regionalref模式一样快(最终)。

完整的例子是:

\documentclass{article}

\usepackage{projlib-language}

\usepackage{amsthm}
\usepackage{aliascnt}
\usepackage{hyperref}
\usepackage[nameinlink]{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_const:Nn \c__projlib_theorem_supported_clist
  {
    theorem                   ,
    lemma                     ,
    proposition               ,
    corollary                 ,
    property                  ,
    fact                      ,
    conjecture                ,
    definition                ,
    axiom                     ,
    assumption                ,
    convention                ,
    hypothesis                ,
    notation                  ,
    example                   ,
    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_plural_ #1 _ ##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_plural_uppercase_ #1 _ ##1 _tl } }
            \tl_gset:cn { cref@ #1 _projlib_original_ ##1 @name } { \tl_use:c { c_projlib_theorem_name_ #1 _ ##1 _tl } }
            \tl_gset:cn { cref@ #1 _projlib_original_ ##1 @name@plural } { \tl_use:c { c_projlib_theorem_name_plural_ #1 _ ##1 _tl } }
            % Two ways to add items in \cref@label@types, just for testing
            % \cref@stack@push{ #1 _projlib_original_ ##1 }{\cref@label@types}
            % \regex_replace_once:nnN { \c{@nil} } { #1 _projlib_original_ ##1 , \c{@nil} } \cref@label@types
            \@crefcopyformats { #1_projlib_regional } { #1 _projlib_original_ ##1 }
          }
      }
  }
  {% "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_plural_ #1 _ \languagename _tl } }
        \Crefname { #1 _projlib_regional }
          { \tl_use:c { c_projlib_theorem_name_uppercase_ #1 _ \languagename _tl } }
          { \tl_use:c { c_projlib_theorem_name_plural_uppercase_ #1 _ \languagename _tl } }
      }
  }


% Temporary names
\tl_set:Nn \c_projlib_theorem_name_theorem_english_tl { Theorem }
\tl_set:Nn \c_projlib_theorem_name_plural_theorem_english_tl { Theorems }
\tl_set:Nn \c_projlib_theorem_name_theorem_french_tl { Théorème }
\tl_set:Nn \c_projlib_theorem_name_plural_theorem_french_tl { Théorèmes }

\tl_set:Nn \c_projlib_theorem_name_definition_english_tl { Definition }
\tl_set:Nn \c_projlib_theorem_name_plural_definition_english_tl { Definitions }
\tl_set:Nn \c_projlib_theorem_name_definition_french_tl { Définition }
\tl_set:Nn \c_projlib_theorem_name_plural_definition_french_tl { Définitions }

\ExplSyntaxOff

\makeatother


\begin{document}

\UseLanguage{English}

Current language: \languagename

\begin{theorem}\label{thm1}
  In english.
\end{theorem}
\begin{theorem}\label{thm2}
  In english.
\end{theorem}
\begin{definition}\label{def1}
  In english.
\end{definition}

\cref{thm1,thm2,thm3,def1,def2}


\vspace{1cm}

\UseLanguage{French}

Current language: \languagename

\begin{theorem}\label{thm3}
  En français.
\end{theorem}
\begin{definition}\label{def2}
  En français.
\end{definition}

\cref{thm1,thm2,thm3,def1,def2}

\end{document}

在此处输入图片描述

如果取消注释\bool_set_false:N \l__projlib_theorem_originalref_bool以启用该regionalref模式,结果将是:

在此处输入图片描述

相关内容