inno-setup

Can Inno Setup Preprocessor be used to build a duplicated set of custom messages?


My installer caters for 20 partial translations. Partial translations have the bulk of the GUI in English and just certain parts in the respective languages. To acheive this with the installer I physically duplicate the default English isl file and rename the language name property to each of the twenty languages. Then Iuse those files in the installer script to add these languages to the drop-down list for the user to choose from.

What this means is that for my custom message I have to replicate them for each of the 20 languages. At the moment I am doing it manually but I wondered if this can be managed from now on using ISPP?

So we start with these custom messages:

; Automatic Backup Settings Wizard Page
English.pageAutoBackupTitle=Automatic Backup
English.pageAutoBackupDescription=Configure automatic backup settings.
English.lblBackupWhat=What to backup:
English.radBackupWhatNone=Don't perform any backup when the program shuts down
English.radBackupWhatComplete=Make a complete backup when the program shuts down
English.radBackupWhatEssential=Only make an essential backup when the program shuts down
English.lblBackupMode=How to backup:
English.radBackupModeAuto=Perform automatically when the program is shut down
English.radBackupModeManual=Prompt the user when the program is shut down
English.lblPromptMode=Also prompt to backup at the following intervals while the application is running:
English.cmbPromptModeItemNever=Never prompt to backup
English.cmbPromptModeItemDaily=Prompt to backup everyday
English.cmbPromptModeItemWeekly=Prompt to backup once a week
English.cmbPromptModeItemMonthly=Prompt to backup once a month
English.lblBackupFolder=Where to backup:
English.btnButtonBrowse=Browse ...

And we want to replicate them for the following languages identifiers:

I know I don't need to add the custom messages because the installer would default to English, but then I get the barage of compiler warnings about missing message definitions.


Solution

  • The preprocessor has two mechanisms how to repeat some code, both having advantages and disadvantages.


    User defined procedures

    With the User defined procedures, the code that you want to repeat is a way more readable – you basically use the same syntax as if you write a normal script (even syntax highlighting will work in editors), you just use {#Var} syntax to inject the variable parts.

    There's virtually no limit to how long the repeated code can be long.

    But the code to cause the code to repeat is clumsier, as the procedures cannot take arguments, so you have to pass the variable parts via "global variables". But in your case, with a single parameter and no recursion, it's not a big limitation.

    #sub DefaultMessages
    {#Lang}.pageAutoBackupTitle=Automatic Backup
    {#Lang}.pageAutoBackupDescription=Configure automatic backup settings.
    {#Lang}.lblBackupWhat=What to backup:
    ; ...
    #endsub
    
    #define Lang
    #expr Lang = "German"
    #expr DefaultMessages
    #expr Lang = "French"
    #expr DefaultMessages
    ; ...
    

    If you prefer, you can put the variable assignment and procedure call to the same line using a sequential evaluation operator (a comma):

    #define Lang
    #expr Lang = "German", DefaultMessages
    #expr Lang = "French", DefaultMessages
    ; ...
    

    The #expr directive has to be placed where you would otherwise explicitly put the code it generates. The #sub has to be placed anywhere above.


    User defined functions

    User defined functions can take parameters, so from a programming perspective, they are cleaner – and allow a recursion (not relevant in this case).

    But the code is not very readable. And there's an internal preprocessor stack limit, which makes the solution not scalable.

    #define DefaultMessages(Lang) \
        Lang + ".pageAutoBackupTitle=Automatic Backup" + NewLine + \
        Lang + ".pageAutoBackupDescription=Configure automatic backup settings." + NewLine + \
        Lang + ".lblBackupWhat=What to backup:" + NewLine \
        ; ...
    
    #emit DefaultMessages("German")
    #emit DefaultMessages("French")
    ; ...
    

    Again, the #emit directive has to be placed where you would otherwise explicitly put the code it generates. The #define has to be placed anywhere above.


    For another example, that shows implementing the same functionality using both these approaches, see:
    Recurse sub directories without creating those same sub directories in Inno Setup