Click here to Skip to main content
Click here to Skip to main content
Go to top

Creating a Localized Windows Installer & Bootstrapper: Part 3

, 25 Feb 2013
Rate this:
Please Sign up or sign in to vote.
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:

<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:

<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)

Share

About the Author

TheCodeKing
Architect
United Kingdom United Kingdom
Mike Carlisle - Technical Architect with over 15 years experience in a wide range of technologies.
 
@TheCodeKing
Follow on   Twitter

Comments and Discussions

 
QuestionAuto-language detection doesn't work PinmemberAKlaus29-Jan-14 19:36 
AnswerRe: Auto-language detection doesn't work PinmemberAKlaus30-Jan-14 18:53 
QuestionDemo files not available PinmemberMember 986252525-Feb-13 2:11 
When I try to download the demo files I get always a "files not available" error.
 
Can you verify that the files are still present?
AnswerRe: Demo files not available PinmemberTheCodeKing25-Feb-13 2:32 
GeneralAdditional note PinmemberStefan Repas4-Oct-10 21:35 
GeneralRe: Additional note PinmemberTheCodeKing4-Oct-10 22:27 
GeneralWindows 7 Mobile Localization Pinmembermadhukaudantha30-Aug-10 0:50 

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

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

| Advertise | Privacy | Mobile
Web02 | 2.8.140926.1 | Last Updated 25 Feb 2013
Article Copyright 2010 by TheCodeKing
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid