How to localize a managed VS Package

Background:

Historically

, localized resources for Visual Studio packages were located in native satellite resource DLLs, located in a codepage subdirectory. For example, if you had installed both the English and Japanese versions of Visual Studio on the same system, you would find some of these native satellite DLLs under C:\Program Files\Microsoft\Visual Studio 9.0\Common7\Packages\1033 and C:\Program Files\Microsoft\Visual Studio 9.0\Common7\Packages\1041.

However, you may have also noticed the presence of managed resource assemblies in subdirectories like "en", "ja", "es", etc. This is how managed code typically supports localization. This article will detail how you can implement localized resources for your managed package, in managed .NET assemblies.

Setting up the environment:

Currently, Visual Studio does not support the concept of language packs. If you want to run Visual Studio with different languages, you need to install the localized versions of Visual Studio for the languages you wish to use. MSDN subscribers can download the localized versions through the MSDN downloads. If you do not happen to have a current MSDN subscription, you can download and install one or more of the localized versions of Visual Studio Integrated Shell alongside your existing installation.

After you install the localized versions of the IDE, you can switch between languages using the Tools.Options dialog. Select the Environment\International Settings category, and then select the desired language from the dropdown combo. Alternatively, you can invoke DevEnv.exe with the /lcid switch, specifying the codepage of the language you wish to use. For example, the following command line will invoke Visual Studio using the Spanish language resources.

   devenv.exe /lcid 3083

BUG ALERT: There is a known bug with the Visual Studio "Isolated Shell" installation that prevents the installation of localized resources after installing the isolated shell redist. Attempting to install other isolated shell redists, will fail to install the expected localized resources.

Localizing the .CTO Resource

A Visual Studio Package can contain any number of localized resources. See "Resources in Managed VSPackages" for details. However, the most important is the embedded .CTO resource, which defines the menus and commands for the package.

The easiest way to build a localized .CTO resource is to leverage the "language" attribute in the package's .VSCT file, in conjunction with the VSCT Compilers' -L switch. For example:

<Button guid="guidLocPackageCmdSet" id="cmdidMyLocCommand" priority="0x0100" type="Button">

   <Parent guid="guidLocPackageCmdSet" id="MyMenuGroup" />

   <Icon guid="guidImages" id="bmpPic1" />

   <Strings langauge = "en">

   <CommandName>cmdidMyLocCommand</CommandName>

      <ButtonText>Howdy</ButtonText>

   </Strings>

   <Strings langauge = "ja" >

      <CommandName>cmdidMyLocCommand</CommandName>

      <ButtonText>Konichiwa</ButtonText>

   </Strings>

</Button>

 

BUG ALERT: There is a known bug where the VSCT compiler recognizes "langauge" instead of "language". This bug has since been fixed with the Dev10 Beta1 SDK. If you are using the VSCT.EXE compiler from one of the VS 2008 SDK drops, you will need to rename the "language" attributes to "langauge".

The Visual Studio SDK currently has no support for passing the /L switch to the VSCT compiler via the MSBuild rules. Therefore, you will need to prebuild the .CTO files before compiling your package. The LocPackage sample does this through the supplied BuildCommandTables.bat file, generating the localized .CTO binaries such as LocPackage.ja.cto, LocPackage.it.cto, etc.

Once the localized .CTO binaries have been built, you can then include them into your localized .RESX files with an entry similar to the following:

  <data name="VSPackage.ctmenu" type="System.Resources.ResXFileRef, System.Windows.Forms">

    <value>.\Resources\LocPackage.es.cto;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>

  </data>

The name attribute has to be "VSPackage.ctmenu" in order for the IDE to find the resource. You must also change the ProvideMenuResource attribute on your package object to reference the resource with this name. For example:

    [ProvideMenuResource("VSPackage.ctmenu", 1)]

Additionally, you will need to manually edit the project file and modify the VSCTCompile tag as follows:

    <VSCTCompile Include="LocPackage.vsct">

      <ResourceName>VSPackage.ctmenu</ResourceName>

    </VSCTCompile>

As a side note, do not attempt to remove the default .CTO resource from the package assembly by modifying or removing the above VSCTCompile operation. For managed packages, the IDE requires the default language resources to be located in the package assembly.

Sample Code:

Sample code illustrating this concept can be found at code.msdn.microsoft.com/locpackage.