Adding Language strings as resources

From NSIS Wiki

Author: CancerFace (talk, contrib)

NSIS forum thread


This is a small tutorial that will help you add to an NSIS installer a Message Table resource with text strings that can be called and displayed from within the installer. Message Tables can contain multiple languages and can be edited using tools such as Resource Hacker without the need to recompile the installer. The advantage is that the end user can choose to alter the language table according to their own preferences/needs and add the strings they want in their own language.


The easiest way to achieve this is by first adding a Message Table to an existing version of the installer. A handy tool for that purpose is XN Resource Editor. Note that the installer will not be usable once you add the new resource so it is a good idea/practice to have a backup.

Step 1

Open the installer EXE file and from the Resource menu select Add Resource and then Message Table. Populate the table with as many strings as you like and then save the changes to the installer. Open the new installer file that contains the Message Table with Resource Hacker, select the newly created message table and from the Action menu select Save resource as a *res file. RES files are binary and cannot be easily edited, however once they are imported into an EXE using Resource hacker they can be readily manipulated.

Step 2

Assuming that the RES file is called 'Lang_EN.res' and is located in a subfolder called 'Lang' inside your project's directory, add the following code to you NSIS script in order to add the Message table to the NSIS header when compiling your script:

CRCCheck off
!packhdr "$%TEMP%\exehead.dat" 'header.cmd'

Step 3

Now generate the file header.cmd and place it inside your project directory. It should contain the following:

echo Adding Message Table resources
@echo off
"%ProgramFiles%\Resource Hacker\ResHacker.exe" -add "%TEMP%\exehead.dat", "%TEMP%\exehead.dat", "%~dps0Lang\Lang_EN.res" , MESSAGETABLE,,
echo Compressing the header with UPX (optional)
upx --best --compress-icons=0 "%TEMP%\exehead.dat"

I am using upx to compress the header but this optional (ignore the upx line).

Step 4

Create a macro that will get the strings out of the Message Table and will store them in a string for immediate use:

!macro GetMessage MESSAGE_ID VAR
   System::Call 'kernel32::GetModuleHandleA(i n)i .R1'
   System::Call 'kernel32::GetSystemDefaultLangID()i .R2'
   System::Call 'kernel32::FormatMessageW(i 2559,i R1,i "${MESSAGE_ID}",i R2,*w .R3, \
i 0,i n) i .R4'
   StrCpy ${VAR} $R3

Call the macro when needed using the String ID that you want to extract from the Message table and use the string:

!insertmacro GetMessage 2 $R9

Step 5

Compile your installer :o)

Adding New Language Tables

The main advantage of the above method is that you can add new language tables to your installer without having to recompile it. Simply open the installer with Resource Hacker, change the language ID of the Message Table to anything then use the Action/Add a new Resource option of Resource Hacker to add another RES file. Edit the resulting Message table changing the language ID of the new entry and adjust the included strings accordingly (screenshot)


  • It is a good idea to add an entry to your Message Table using 0 as the language (the equivalent of {LANG_NEUTRAL,SUBLANG_NEUTRAL}). This will ensure that if the language ID of a system is not found in the Message Table then the default strings will be used (those stored in the table with ID 0 as shown on this screenshot)
  • If you don't add the 'CRCCheck off' directive in your script the installer will fail to run once you manually edit the Message Tables after compiling it

Resources and Links

The above macro is using API calls to

Personal tools