#1,126 – Localization VII – Preventing Translator from Modifying Certain Elements

By default, when a .csv file is created using the LocBaml tool, the fifth parameter on each line is set to True.  This parameter indicates whether a particular property should be modifiable by the translator.

You can change the value of this modifiable field by setting the Localization.Attributes property for an element.  This property is set to a string of the form “propname(locvalue1 locvalue2) propname(locvalue1 locvalue2)”.

One of the localizability values that you can set is Unmodifiable, to indicate that the specified property should not be modified by the translator.

Below, we set Unmodifiable for various property values.

<Window x:Uid="Window_1" x:Class="WpfApplication1.MainWindow"
        Localization.Attributes="$Content(Unmodifiable) SizeToContent(Unmodifiable)"
        Title="The App" SizeToContent="WidthAndHeight">

    <StackPanel x:Uid="StackPanel_1" Margin="15"
        <Label x:Uid="Label_1" Content="Hello, I like apples."
        <Button x:Uid="Button_1" Content="Learn More" Margin="5"
                Localization.Attributes="$Content(Unmodifiable) Margin(Unmodifiable)"/>

After running the LocBaml tool, we see that the modifiable field is now false for these properties.


#1,125 – Localization VI – Interpreting CSV File That Is Output by LocBaml Tool

As part of the localization process, you can use the LocBaml tool to extract localizable content into a text-based .csv file.

Below is a snapshot of a sample .csv file containing localizable content.


Each line in the .csv file represents a single property of some user interface element.  The line contains the following elements (separated by commas):

  • The name of the BAML resource containing the property
    • (e.g. WpfApplication1.g.en-US.resources:mainwindow.baml)
  • Fully qualified property name, including the element’s UID
    • (e.g. Label_1:System.Windows.Controls.ContentControl.Content)
  • Localization category  (e.g. Button, Label, Text, etc).
  • Whether property is visible to user (T/F).
  • Whether property can or should be modified by translator (T/F)  (defaults to true for all elements)
  • Comments provided for translator  (defaults to blank)
  • Property value  (the thing that should be localized)

#1,124 – Localization V – Extracting Localizable Content Using LocBaml

Once you’ve generated UIDs for user interface elements and obtained the LocBaml tool, the next step in the localization process is to extract localizable content from the BAML data in your compiled DLL.

The steps are as follows:

  • Copy the locbaml.exe into the same directory as your application’s .exe file
  • Open a Visual Studio 2013 command prompt
  • Navigate to directory containing your .exe (e.g. \bin\Release, with \en-US sub-directory containing satellite assembly)
  • Enter: locbaml.exe /parse .\en-US\[application].resources.dll  (where en-US is the default culture)

After running this command, you’ll see a .csv file show up in the same directory (e.g. WpfApplication1.resources.csv).  The CSV file will contain a list of localizable content.


#1,123 – Localization IV – Download and Build the LocBaml Tool

After generating UIDs for all user interface elements in your project, the next step is to extract elements that need to be localized (i.e. given values for a specific language) into an external file.  This file can be passed to people doing the localization.

To extract localizable data, you need a tool called LocBaml.  This tool is made available by Microsoft, but not distributed with Visual Studio.

To get a copy of the LocBaml tool:

  • Download LocBaml project (for .NET 4) from here
  • Open LocBaml project and rebuild using Release|x86 configuration, targeting a .NET Framework version that matches your main project

#1,122 – Localization III – Updating UIDs after Initial Creation

In order to localize your application, you must assign unique UIDs to all elements.  This is done with the msbuild command and the /t:updateuid parameter.  You normally do this before you start localizing your application.

If you later add user interface elements to your application, you’ll have some elements that don’t have the x:Uid attribute.  You can check to see if there are elements that are missing this attribute using the /t:checkuid parameter on the msbuild command.


At this point, you can use the /t:updateuid parameter with the msbuild command again to add the x:Uid attribute to any elements that are missing it.  This command will also fix any duplicated UIDs.

You can use the /t:updateuid parameter as often as you like.  Each time you run msbuild with this parameter, you’ll update UIDs for all user interface elements.


#1,121 – Localization II – Assigning UIDs to All Localizable Elements

After adding a UICulture tag, the next step in localizing a WPF is to assign a UID (unique identifier) to each element in each of your XAML files.  These UIDs will later be used to localize/translate the XAML.

To start, press the Windows key, type Visual Studio, and click on the Visual Studio Tools icon.


Double-click the Developer Command Prompt for VS2013 shortcut.


In the command prompt, navigate to the directory containing your project (.csproj) file.  Enter the command:

msbuild /t:updateuid [yourapplication].csproj


Open your project and then open one of your .xaml files.  You’ll see that each element now has a x:Uid attribute that wasn’t there before.  Each element will have a unique value for this attribute.

Before running msbuild:


After running msbuild:


#1,120 – Getting a List of All Supported Cultures

You can get a full list of all cultures supported by .NET using the CultureInfo.GetCultures static method.  (In System.Globalization namespace).

Below is a code sample that dumps out a little bit of information about all known cultures.

            CultureInfo[] cultureList = CultureInfo.GetCultures(CultureTypes.AllCultures);
            foreach (CultureInfo ci in cultureList.OrderBy(cult => cult.Name))
                if (ci.IsNeutralCulture)
                    Console.WriteLine("{0} (neutral) - {1}", ci.Name, ci.EnglishName);
                    Console.WriteLine("{0} - {1}", ci.Name, ci.EnglishName);