Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DndMonsterAttack spanish #324

Open
tenllado opened this issue Jun 20, 2021 · 10 comments
Open

DndMonsterAttack spanish #324

tenllado opened this issue Jun 20, 2021 · 10 comments

Comments

@tenllado
Copy link

I am using this package to translate an adventure to spanish. Everithing is working flawlessly except the damage type of the \DndMonsterAttack. While in english you would write posion damage, in spanish it would be daño de veneno (damage poison).

I looked at the implementation of the macro, and I think that the piece of code that generates that part is:

    \str_if_empty:NF {\l__dmg_tl} % Don't show any damage if `dmg' is not set.
        {
          \l__dmg_tl\ \l__dmg_type_tl\ \damagename
          \__dnd_if_or_dmg:
          \__dnd_if_plus_dmg:
        }

The thing is that in spanish the first line between the curly braces should be

          \l__dmg_tl\ \damagename\ \l__dmg_type_tl

I do not know how to express this language-dependent change. I am writing this in the hope that it could be an easy change for somebody that knows latex/tex and this library better than me.

Thank you.

@BrianCriswell
Copy link
Member

BrianCriswell commented Jun 20, 2021

It looks like the official translations use "de daño veneno". Properly fixing requires that line you highlighted to be tokenized. In other words

\renewcommand\damageentryname{|1| \damagename |2|}

Where |1| is \l__damage_tl (the damage passed to the function) and |2| is \l__dmg_type_tl (the damage type: veneno in this case).

In the meantime, you can probably do the following as a workaround. Set \damagename to an empty string in your preamble:

 \renewcommand\damagename{}

Then pass the entire damage description into the attack function (de daño veneno). The spacing might be slightly off, but it may work at the moment. Another option would be to rewrite the attack macro in the preamble, swapping the order of the \damagename and the damage type parameter. You would need to turn the latex3 syntax on and off. This would probably work in the preamble of your document. This is off the top of my head, so no guarantees that it works (and sorry for the messy formatting.

\ExplSyntaxOn % Use tilde (~) for spaces.

\renewcommand\damagename{de~daño}

\cs_renew_protected:Npn \__dnd_if_plus_dmg:  {
    \tl_if_empty:NF {\l__plus_dmg_tl}
    { ~ \plusname\ \l__plus_dmg_tl\ \damagename\ \l__plus_dmg_type_tl }  }

\cs_renew_protected_nopar:Npn \__dnd_if_or_dmg:  {
    \tl_if_empty:NF {\l__or_dmg_tl}    {
      , ~ \orname\ \l__or_dmg_tl\ \damagename\ \l__dmg_type_tl\ \l__or_dmg_when_tl
      \tl_if_empty:NF {\l__plus_dmg_tl}        {,}    }  }

\cs_renew_protected:Npn \__dnd_monster_attack:  {    \__dnd_check_for_key:Nnn \l__name_tl {\DndMonsterAttack} {name}    \__dnd_check_for_key:Nnn \l__mod_tl {\DndMonsterAttack} {mod}
    \begin{DndMonsterAction} {\l__name_tl}~
      \str_case_e:nnF {\l__dnd_attack_distance_tl}        {          { melee }            {              \textit{ \__dnd_caption:nn {\meleeattackname} {\l__dnd_attack_type_tl} : } ~ \__dnd_caption:nn {\tohitname} {\l__mod_tl}, ~ \__dnd_monster_reach:            }          { ranged }            {              \textit{ \__dnd_caption:nn {\rangedattackname} {\l__dnd_attack_type_tl} : } ~ \__dnd_caption:nn {\tohitname} {\l__mod_tl}, ~ \__dnd_monster_range:            }        }        {% Melee and Ranged is the default          \textit{ \__dnd_caption:nn {\meleeorrangedattackname} {\l__dnd_attack_type_tl} : } ~ \__dnd_caption:nn {\tohitname} {\l__mod_tl}, ~ \__dnd_monster_reach:\ \orname\ \__dnd_monster_range:        }      , ~ \l__targets_tl. ~      \textit { \hitname : } ~
      \str_if_empty:NF {\l__dmg_tl} % Don't show any damage if `dmg' is not set.        {          \l__dmg_tl\ \damagename\ \l__dmg_type_tl          \__dnd_if_or_dmg:          \__dnd_if_plus_dmg:        }
      % `extra' is any special text that goes after the final damage; do not      % include the final full stop.      \l__extra_tl .    \end{DndMonsterAction}  }

\ExplSyntaxOff

@tenllado
Copy link
Author

tenllado commented Jun 21, 2021

Brian, thank you for your help. Apparently this is not working. For some reason that I do not understand changing the definition of \damagename in the preamble is not working and when I try to redefine the protected macros the compiler gives me an error. I will try to further investigate this problem later when I have some time for it. I might have to learn a bit of latex3.

I will let you know if I find some solution and keep an eye on the project in case you manage to solve this internationalization issue.

@tenllado
Copy link
Author

The problem in my case is that the pdflatex compiler complains about undefined sequence:

! Undefined control sequence.
l.117 \cs_renew_protected:Npn
__dnd_monster_attack:
? H
The control sequence at the end of the top line
of your error message was never \def'ed. If you have
misspelled it (e.g., \hobx'), type I' and the correct
spelling (e.g., `I\hbox'). Otherwise just continue,
and I'll forget about whatever was undefined.

Is like I cannot change a private function of the dnd library. Is it possible to change the private function from outside the library?

@tenllado
Copy link
Author

tenllado commented Jun 22, 2021

Hello, I could not manage to change the private functions, if anyone can help me with that I would appreciate it.

I found an alternative solution that might not be ideal, but works for me. I created a new cls file dndes.cls to include a new definition of the DocumentCommands: DndMonsterAttack and siblings. This gave me no problems at all. The redefinition of the \damagename did not work either, so I included the modification inside the new private function __dnd_monster_attackes (and siblings). The full content of this file is:

\ProvidesClass{dndes}
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{dndbook}} 
\ProcessOptions\relax
\LoadClass[]{dndbook}
\RequirePackage{expl3}

\ExplSyntaxOn

\cs_new_protected:Npn \__dnd_if_plus_dmges:
  {
    \tl_if_empty:NF {\l__plus_dmg_tl}
    { ~ \plusname\ \l__plus_dmg_tl\ de\ \damagename\ \l__plus_dmg_type_tl}
  }

\cs_new_protected_nopar:Npn \__dnd_if_or_dmges:
  {
    \tl_if_empty:NF {\l__or_dmg_tl}
    {
      , ~ \orname\ \l__or_dmg_tl\ de\ \damagename\ \l__dmg_type_tl\ \l__or_dmg_when_tl

      \tl_if_empty:NF {\l__plus_dmg_tl}
        {,}
    }
  }

\cs_new_protected:Npn \__dnd_monster_attackes:
  {
    \__dnd_check_for_key:Nnn \l__name_tl {\DndMonsterAttack} {name}
    \__dnd_check_for_key:Nnn \l__mod_tl {\DndMonsterAttack} {mod}

    \begin{DndMonsterAction} {\l__name_tl}~

      \str_case_e:nnF {\l__dnd_attack_distance_tl}
        {
          { melee }
            {
              \textit{ \__dnd_caption:nn {\meleeattackname} {\l__dnd_attack_type_tl} : } ~ \__dnd_caption:nn {\tohitname} {\l__mod_tl}, ~ \__dnd_monster_reach:
            }
          { ranged }
            {
              \textit{ \__dnd_caption:nn {\rangedattackname} {\l__dnd_attack_type_tl} : } ~ \__dnd_caption:nn {\tohitname} {\l__mod_tl}, ~ \__dnd_monster_range:
            }
        }
        {% Melee and Ranged is the default
          \textit{ \__dnd_caption:nn {\meleeorrangedattackname} {\l__dnd_attack_type_tl} : } ~ \__dnd_caption:nn {\tohitname} {\l__mod_tl}, ~ \__dnd_monster_reach:\ \orname\ \__dnd_monster_range:
        }
      , ~ \l__targets_tl. ~
      \textit { \hitname : } ~

      \str_if_empty:NF {\l__dmg_tl} % Don't show any damage if `dmg' is not set.
        {
          \l__dmg_tl\ de\ \damagename\ \l__dmg_type_tl
          \__dnd_if_or_dmges:
          \__dnd_if_plus_dmges:
        }

      % `extra' is any special text that goes after the final damage; do not
      % include the final full stop.
      \l__extra_tl .
    \end{DndMonsterAction}
  }

\RenewDocumentCommand {\DndMonsterAttack} {o}
  {
    \group_begin:
      \keys_set:nn { dnd / monster / attack } {#1}
      \__dnd_monster_attackes:
    \group_end:
  }

\RenewDocumentCommand {\DndMonsterMelee} {o}
  {
    \group_begin:
      \keys_set:nn { dnd / monster / attack } { #1, distance = melee }
      \__dnd_monster_attackes:
    \group_end:
  }

\RenewDocumentCommand {\DndMonsterRanged} {o}
  {
    \group_begin:
      \keys_set:nn { dnd / monster / attack } { #1, distance = ranged }
      \__dnd_monster_attackes:
    \group_end:
  }

\ExplSyntaxOff

@BrianCriswell
Copy link
Member

That should work for now until we can add a bit more flexibility into the class functions.

The "undefined control sequence" means that I gave you the wrong name for renewing a LaTeX3 function, and I don't have the time to look up the correct one.

As for the localization text, try wrapping the renewcommand line in addtocaptions block. See the lib/langages/espanol.def for an example.

@vonBarbarosa
Copy link

Hi @tenllado, I also have the same problem with damage types in Portuguese, I'm following this thread and also trying to solve this on my side, I'll let you know if I get any further than you did.

Feel free to reach me if you want :)

@vonBarbarosa
Copy link

I added this to my lib/languages/Portuguese.sty and it seems to work fine (not the best but still), check if it works for you too @tenllado:

\ExplSyntaxOn % Use tilde (~) for spaces.

\addto\captionsportuguese
  {

    ... % The translated commands e.g. \renewcommand\armorclassname{Classe~de~Armadura}, etc

    % Workaround for changing from "<damage_type> \damagename" to "de \damagename <damage_type>"
    \renewcommand\__dnd_if_plus_dmg:
      {
        \tl_if_empty:NF {\l__plus_dmg_tl}
        { ~ \plusname\ \l__plus_dmg_tl\ de\ \damagename\ \l__plus_dmg_type_tl }
      }

    \renewcommand\__dnd_if_or_dmg:
      {
        \tl_if_empty:NF {\l__or_dmg_tl}
        {
          , ~ \orname\ \l__or_dmg_tl\ de\ \damagename\ \l__dmg_type_tl\ \l__or_dmg_when_tl

          \tl_if_empty:NF {\l__plus_dmg_tl}
            {,}
        }
      }

    \renewcommand\__dnd_monster_attack:
      {
        \__dnd_check_for_key:Nnn \l__name_tl {\DndMonsterAttack} {name}
        \__dnd_check_for_key:Nnn \l__mod_tl {\DndMonsterAttack} {mod}

        \begin{DndMonsterAction} {\l__name_tl}~

          \str_case_e:nnF {\l__dnd_attack_distance_tl}
            {
              { melee }
                {
                  \textit{ \__dnd_caption:nn {\meleeattackname} {\l__dnd_attack_type_tl} : } ~ \__dnd_caption:nn {\tohitname} {\l__mod_tl}, ~ \__dnd_monster_reach:
                }
              { ranged }
                {
                  \textit{ \__dnd_caption:nn {\rangedattackname} {\l__dnd_attack_type_tl} : } ~ \__dnd_caption:nn {\tohitname} {\l__mod_tl}, ~ \__dnd_monster_range:
                }
            }
            {% Melee and Ranged is the default
              \textit{ \__dnd_caption:nn {\meleeorrangedattackname} {\l__dnd_attack_type_tl} : } ~ \__dnd_caption:nn {\tohitname} {\l__mod_tl}, ~ \__dnd_monster_reach:\ \orname\ \__dnd_monster_range:
            }
          , ~ \l__targets_tl. ~
          \textit { \hitname : } ~

          \str_if_empty:NF {\l__dmg_tl} % Don't show any damage if `dmg' is not set.
            {
              \l__dmg_tl\ de\ \damagename\ \l__dmg_type_tl
              \__dnd_if_or_dmg:
              \__dnd_if_plus_dmg:
            }

          % `extra' is any special text that goes after the final damage; do not
          % include the final full stop.
          \l__extra_tl .
        \end{DndMonsterAction}
      }
  }

@JordyProvost
Copy link

JordyProvost commented Aug 6, 2022

@vonBarbarosa it works for me for french, thanks.

i have just updated this (in \renewcommand__dnd_if_plus_dmg) :

{ ~ \plusname\ \l__plus_dmg_tl\ de\ \damagename\ \l__plus_dmg_type_tl

into this :

{ ~ \plusname\ \l__plus_dmg_tl\ \damagename\ \l__plus_dmg_type_tl }

and this (in \renewcommand__dnd_if_or_dmg:):

, ~ \orname\ \l__or_dmg_tl\ de\ \damagename\ \l__dmg_type_tl\ \l__or_dmg_when_tl

into this

, ~ \orname\ \l__or_dmg_tl\ \damagename\ \l__dmg_type_tl\ \l__or_dmg_when_tl

As in french we have not always "de" before damage type

  • fire damage : dégâts de feu
  • lightning damage : dégâts de foudre
  • acid damage: dégâts d'acide

as you see "de" is not correct for acid type

So i just tweak dmg-type/plus-dmg-type accordingly to have the correct syntax, but its works:
dmg-type=de feu,
dmg-type=de foudre,
dmg-type=d'acide,

And also, i have updated this (in \renewcommand__dnd_monster_attack:):

\l__dmg_tl\ de\ \damagename\ \l__dmg_type_tl

into this:

\l__dmg_tl\ \damagename\ \l__dmg_type_tl

To replace "X de dégâts perforants" by "X dégâts perforants", which is more correct.

Full modified french.sty (renammed in .txt) in attachement.

Thanks !

french.sty.txt

@JordyProvost
Copy link

Maybe to make this more cleaner, french.sty must call frenchtweaks.sty via \includepackage.
But i dont know how to do that without braking everything.

@BrianCriswell
Copy link
Member

Maybe to make this more cleaner, french.sty must call frenchtweaks.sty via \includepackage. But i dont know how to do that without braking everything.

You can just include your customizations in your own .sty file that loads after the class.

This issue is going off-topic. If you want to propose changes to french.sty, please open a new issue, and you can reference this issue for examples.

Long term, the plan is to update the line in question to use a parametrized string similar to how \meleeattackname is handled.

\renewcommand\meleeattackname{Attaque~|1|~au~corps~à~corps}

This will allow each translation to use a different word order.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants