Home .NET Easy localization of Windows Phone app names

Easy localization of Windows Phone app names

by admin

Easy localization of Windows Phone app names
As a developer of Windows Phone applications I have realized for a long time that the market of mobile applications is global and in order to successfully promote a mobile application it needs to be localized for as many languages as possible.The localization of Windows Phone applications is described in detail in app development documentation However, The process of localizing the headers and headers of the application tiles is different from the localization of the application itself, and often causes difficulties because it requires preparing a separate resource file for each language.
To solve this problem, I created several resource projects which, after a successful build, copied the result to the application directory. This solution suited me fine as long as my applications supported no more than three languages. Once the need to localize applications into more languages became necessary, this approach became cumbersome.
Search showed that many people are looking for a convenient solution to this problem. But I haven’t found any convenient way, so I decided to write a utility that will allow me to create and manage resource files. For me the most convenient way is header description in XML file and automatic generation of necessary files on its basis.
The following format would be chosen for the application header description file :

<Localization><Application><Name /><Description /></Application><Languages><Default inactive="false"><Title /><TileTitle /></Default><Albanian inactive="true"><Title /><TileTitle /></Albanian>…</Languages></Localization>

I decided to create this utility as a Custom Tool for Visual Studio
Easy localization of Windows Phone app names
To implement an object that can be used as a Custom Tool, you need to implement the interface IVsSingleFileGenerator

interface IVsSingleFileGenerator{int DefaultExtension(out string);int Generate(string, string, string, IntPtr[], out uint, IVsGeneratorProgress);}

As you can see from the name and the description of the interface, it can only generate one file, which is not enough for the task at hand. However, research has shown that during generation the utility is available Visual Studio context , through which you can modify projects arbitrarily.
To manage the project, we need to get a reference to the object ProjectItem which has an XML file associated with it which describes the source data

var dte = (EnvDTE.DTE)Package.GetGlobalService(typeof(EnvDTE.DTE));var sourceControl = dte.SourceControl;var projectItem = dte.Solution.FindProjectItem(sourceFilePath);if (projectItem == null){throw new ApplicationException("Unable to locate a ProjectItem associated to the file");}

After that, we can add and remove child files from the ProjectItems collection of this item.

private static void UpdateNestedProjectItems(ProjectItem projectItem, HashSet<string> generatedFiles){foreach (ProjectItem item in projectItem.ProjectItems){if (item.Properties != null){var property = item.Properties.Item("FullPath");if (property != null){var value = property.Value as string;if (value != null){if (generatedFiles.Contains(value)){item.Properties.Item("BuildAction").Value = 2;generatedFiles.Remove(value);}else{if(value.EndsWith("txt", StringComparison.CurrentCultureIgnoreCase)){item.Properties.Item("BuildAction").Value = 0;}else{item.Remove();}}}}}}foreach (var file in generatedFiles){var item = projectItem.ProjectItems.AddFromFile(file);item.Properties.Item("BuildAction").Value = 2;}}

The second important part of the created utility is the creation of resource files, to solve this, an empty dll file was created and embedded into the utility resources. This file is copied and renamed while working according to the resource file naming requirements. After that the resources are added to this file using the WIN API functions: BeginUpdateResource , UpdateResource , EndUpdateResource

internal static class APIHelper{public const int RT_STRING = 6;[DllImport("kernel32.dll", SetLastError = true)]public static extern IntPtr BeginUpdateResource(string pFileName, bool bDeleteExistingResources);[DllImport("kernel32.dll", SetLastError = true)]public static extern bool UpdateResource(IntPtr hUpdate, int lpType, int lpName, ushort wLanguage, IntPtr lpData, uint cbData);[DllImport("kernel32.dll", SetLastError = true)]public static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);}

There is a little trick when creating string resources, the thing is that strings in resources are stored in blocks of 16 strings each, which is done for optimization purposes. To change a string it is necessary to overwrite the whole block of strings it is included in. For our task we don’t need to change the data, so we can just write the data we want and not worry about saving the other lines of the block.
The line block number can be calculated using the following algorithm :
N = STRID / 16 + 1
where N is string block number, STRID is resource string ID (the localization documentation accepts 100 for application header, 200 for tile header)
You need to register the tool in the GAC, and add an entry in the registry to register it as a Custom Tool, and then you can use it in your projects.
The output of the utility looks like this
Easy localization of Windows Phone app names
For more convenient usage of the utility, we also created an item template for Visual Studio and created the installer for automatic registration of the utility.
Source codes are available : http://wptitlelocalizationtool.codeplex.com/
Installation package available : http://visualstudiogallery.msdn.microsoft.com/527c7d79-55f7-4ff2-9ab8-d6122bf6e75d

You may also like