Click here to Skip to main content
15,867,704 members
Articles / Windows Installer

Creating a Localized Windows Installer & Bootstrapper: Part 3

Rate me:
Please Sign up or sign in to vote.
4.60/5 (3 votes)
25 Feb 2013CPOL5 min read 55.5K   537   17   8
This series of articles is a complete end-to-end solution for building a localizable Windows Installer & Bootstrapper using some real-world requirements.

Introduction

In Parts 1 & 2, we created a Windows Installer using Wix in the form of an MSI file. In the real-world, installers often require localization, and in this part we'll look at a solution for localizing the installer into a second language; in this example Italian.

Strictly speaking, Windows Installer doesn't support multiple languages and can only store one set of strings at any point in time. However it does provide a mechanism which allows for localization via an implementation of transforms. A transform is a delta MST file which can sit inside or outside of the main MSI package. By supplying the transform to Windows Installer, the MSI content is replaced by matching content in the MST file at runtime before installation begins, which is ideal for localization.

Our localization solution involves the following steps:

  • Make the Wix source localizable
  • Generate an Italian version of the MSI file
  • Create an MST transform file
  • Embed the transform file into the original MSI

Localizing Wix

Wix contains all of the tools required for localization, and the WixUI library we are using already comes with stock translations for the UI dialogs provided. The localization authoring features allow us to move localizable strings into separate Wix translation files, which can then be swapped out by LIGHT when generating an MSI. This will ultimately make it easier to generate transforms later on in the process.

In the solution provided, all of the custom strings have been moved into external localization files and named with the relevant culture code. These are then referenced in the main source files using the syntax !(loc.VariableName). The WixLocalization element in the localization file must contain correct values for Culture and Codepage attributes for the localized version to function correctly with different character sets. We also add the language LCID as a translation string so that we can reference the language code as a variable in the main project and override the product language attribute.

The final localization file looks something like this:

XML
<WixLocalization Culture="en-GB" 
	xmlns="http://schemas.microsoft.com/wix/2006/localization" Codepage='1252'>
  <String Id='LANG' Overridable="yes">1033</String>
  <String Id="Windows7Required" Overridable="yes">
	This application only runs on Windows 7.</String>
   ...  
</WixLocalization>

The main source code references these localization strings as follows:

XML
<Condition Message='!(loc.Windows7Required)'>
   <![CDATA[VersionNT = 601 AND WindowsBuild > 7100]]>
</Condition>

Once the strings are re-factored into the localization files, we can go ahead and get these translated into multiple languages. A set of localization files are created for each new language and the culture specific attributes set up accordingly.

Create Localized MSI

LIGHT provides some handy features that allow us to create a localized version of the MSI. Firstly, the utility takes multiple translation files that can contain a mixture of cultures. The output file however will only contain a single set of translation strings. So how does this work?

The trick is the cultures argument that takes a list of cultures in order of precedence. From left to right, LIGHT will look through the supplied translations looking for the first matching culture for each string. This allows us to build fall-backs into our translation set.

Please note that WixVariables cannot reference localized translation variables, and therefore to swap out the path to the T&Cs agreement, we must change our solution so that this is passed through on the command line. We can then pass in references to different agreement files for each localized installer.

So implementing this technique, we can create an Italian version of the Installer as follows:

light.exe -o bin\Release\Setup.msi
     -ext WixNetFxExtension.dll
     -ext WixUIExtension.dll
     -cultures:"it-IT,en-GB"
     -dWixUILicenseRtf=Binary\EULA_it-IT.rtf
     Main.wixobj 
     Component.wixobj
     -loc it-IT.wxl
     -loc en-GB.wxl

The example above will look for Italian translations, and for any strings not found, it will fall back to English. Note, the naming of the WXL files is irrelevant to the linker.

Creating a Transform

Now that we have an English and Italian version of the MSI, we can generate a transform file. The transform will contain a set of differences between the two files. In this case, it will contain just the Italian translations and a new agreement file.

The Wix TORCH tool is used to create the transform MST file as follows:

torch.exe setup.msi it-IT\setup.msi -o it-IT.mst

The resultant it-IT.mst file is smaller than the original and contains the transforms which can be applied to the original MSI file in order to localize the installer. It could be deployed alongside the MSI file, but in our case we want to embed the transform and create a single MSI for ease of deployment.

This is where we can leverage an undocumented and unsupported feature of Windows Installer which allows us to auto-detect the language of the installer from the user's region settings. By naming the transform with the corresponding LCID, Windows Installer will automatically apply the transform at runtime.

The tool used to embed the MST with a specific name is a script taken from the Microsoft Windows Software Development Kit. This is used as follows, where 1040 is the Italian LCID:

cscript.exe WiSubStg.vbs setup.msi it-IT.mst 1040

Once embedded, the transform can be applied explicitly through the command line to launch the Italian version of the installer.

msiexec /i setup.msi TRANSFORMS=":1040"

Note the TRANSFORMS=":1040" syntax (with colon) applies embedded transforms, whereas TRANSFORMS="it-IT.mst" (without colon) will apply an external transform file.

To test the auto-language detection functionality, change the regional settings by opening control panel and navigating to regional settings. On the first dialog which defines date and time Formats, select Italy from the language selector. Apply the settings and launch the MSI with no parameters. You should then see the Italian version of the installer.

Summary

In this part of the series, we talked through localizing the installer by leveraging some of the Wix tools and by taking advantage of some undocumented features of Windows Installer. Our installer is almost complete. In part 4, I'll show how to create bootstrapper for the installer that will detect and install any prerequisites.

History

  • 22nd August, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
United Kingdom United Kingdom
Mike Carlisle - Technical Architect with over 20 years experience in a wide range of technologies.

@TheCodeKing

Comments and Discussions

 
QuestionOne or two MSI? Pin
Member 1466515722-Nov-19 8:02
Member 1466515722-Nov-19 8:02 
QuestionAuto-language detection doesn't work Pin
AKlaus29-Jan-14 19:36
AKlaus29-Jan-14 19:36 
AnswerRe: Auto-language detection doesn't work Pin
AKlaus30-Jan-14 18:53
AKlaus30-Jan-14 18:53 
QuestionDemo files not available Pin
Member 986252525-Feb-13 2:11
Member 986252525-Feb-13 2:11 
AnswerRe: Demo files not available Pin
TheCodeKing25-Feb-13 2:32
TheCodeKing25-Feb-13 2:32 
GeneralAdditional note Pin
Stefan Repas4-Oct-10 21:35
Stefan Repas4-Oct-10 21:35 
GeneralRe: Additional note Pin
TheCodeKing4-Oct-10 22:27
TheCodeKing4-Oct-10 22:27 
GeneralWindows 7 Mobile Localization Pin
madhukaudantha30-Aug-10 0:50
madhukaudantha30-Aug-10 0:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.