Andrew Truckle
Andrew Truckle

Reputation: 19107

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.

Upvotes: 2

Views: 209

Answers (2)

Martin Prikryl
Martin Prikryl

Reputation: 202272

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

Upvotes: 2

Andrew Truckle
Andrew Truckle

Reputation: 19107

I am adding this answer just so that users are aware of a better approach to my situation.

I was recently told this (quite by chance as my question was a different one) on the Inno Setup Support channel:

It loads the MessageFiles in order, followed by the messages in the script. Last one wins.

And prefixed values win over un-prefixed values within the script as well.

So you should put all your English defaults into an .isl file that is listed before the language-specific .isl file. Anything not specified in the real language file will use the defaults from the previous files.

Or alternatively if you do not want to use .isl files for your custom messages, then you can specify your English defaults without prefix and your actual translations with the appropriate prefix directly in your script, omitting anything not yet translated. Again, anything that's missing a language-specific-prefixed value will default back to the un-prefixed value.

If you do both things, then anything in the script (prefixed or not) will always override anything in the .isl files.

So I simplified my custom messages file:

[CustomMessages]
; ==================================================================
; These are the default custom messages.
; They are used by:

; - Amharic
; - Aukan
; - Cebuano
; - English
; - Filipino
; - Gujarati
; - Gun
; - HaitianCreole
; - Lingala
; - Malagasy
; - Maltese
; - Punjabi
; - Saramaccan
; - Sesotho
; - Setswana
; - Sranantongo
; - Swahili
; - Tamil
; - Tsonga
; - Twi
; - Vietnamese
; - Zulu

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

All language prefixed translations follow in the same file. Using this approach I don't actually need to use the #sub / #endsub mechanism after-all.

Upvotes: 1

Related Questions