I wish to assign a \crefname with dynamical strings. With \exp_args_generate:n { xVV }, I ended up with something like:

\exp_args:NxVV \crefname {\__my_countername: }
                         {\csname my@cref@\__my_countername:\csname\languagename ABBR\endcsname @name\endcsname}
                         {\csname my@cref@\__my_countername:\csname\languagename ABBR\endcsname @name@plural\endcsname}

Here \__my_countername: is the counter's name, such as theorem. \csname\languagename ABBR\endcsname is a conversion from string like english to EN.

However, this expands the arguments too deeply that the strings are no longer dynamic with respect to the context. To be clear, I wish the arguments to be expanded to:

\crefname {theorem }
          {\csname my@cref@theorem\csname\languagename ABBR\endcsname @name\endcsname}
          {\csname my@cref@theorem\csname\languagename ABBR\endcsname @name@plural\endcsname}

That is, to make \__my_countername: expanded while keeping \csname\languagename ABBR\endcsname untouched, since it should receive \languagename from the context. Would that be possible?

I tried to use \noexpand, but probably misused, which leads to an error with no warning text.

(Please forgive my terrible mixture of expl3 and LaTeX2e code, I'm not familiar with expl3 and it would be much easier for me to use a little LaTeX2e code for some tasks)

  • Like that you can't. When you expand \csname once, it expands and collects everything up to the (matching) \endcsname, so all macros (including \languagename) are expanded. There is not much you can do here, because both the inside and outside \csnames vary with \languagename, so you should probably leave that unexpanded. Oct 26, 2021 at 18:50
  • P.S.: The V expansion works on a single token/variable. Feeding it multiple tokens (\csname...\endcsname) is wrong and works by pure chance. The correct form here would be with v (but then it expands the \csname, which you don't want): \exp_args:Nxvv \crefname {\__my_countername: } { my@cref@\__my_countername:\csname\languagename ABBR\endcsname @name } { my@cref@\__my_countername:\csname\languagename ABBR\endcsname @name@plural }. The v expansion is short for c then V. Oct 26, 2021 at 18:53
  • @PhelypeOleinik Is there any way to expand only \__my_countername:? If it is not expanded, an error would occur, though I don't know the exact reason.
    – Jinwen
    Oct 26, 2021 at 18:54
  • Hard to say without seeing the whole code, but if you only want to x-expand \__my_countername:, then \exp_args:Nx \crefname { \__my_countername: } { ... Oct 26, 2021 at 18:55
  • @PhelypeOleinik Yes, actually this was my original code. But I want also the \__my_countername: in the last two arguments get expanded (and leave everything else untouched). Would that be possible?
    – Jinwen
    Oct 26, 2021 at 18:57

1 Answer 1


Became too long for a comment:

If you want to expand \__my_countername: and keep everything else unexpanded, then you can use x expansion in all arguments, and keep other tokens from being expanded with \exp_not:N:

\exp_args:Nxxx \crefname { \__my_countername: }
  { \exp_not:N \use:c { my@cref@ \__my_countername: \exp_not:N \use:c { \exp_not:N \languagename ABBR } @name } }
  { \exp_not:N \use:c { my@cref@ \__my_countername: \exp_not:N \use:c { \exp_not:N \languagename ABBR } @name@plural } }

(I replaced \csname ... \endcsname with the more expl3-y \use:c { ... }).

The above would expand only the three \__my_countername: (which sounds like it's misnamed). But that's doing the same work three times, so you can instead define an auxiliary macro and expand \__my_countername: just once, making the code a bit faster, and a lot easier to understand:

\cs_new_protected:Npn \__my_crefname_aux:n #1
    % In this macro, #1 is \__my_countername: expanded
    \crefname {#1}
      { \use:c { my@cref@#1 \use:c { \languagename ABBR } @name } }
      { \use:c { my@cref@#1 \use:c { \languagename ABBR } @name@plural } }
% then use it as:
\exp_args:Nx \__my_crefname_aux:n { \__my_countername: }

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .