#1,134 – Localization XV – Localizing Other Content

You’ll sometimes have content in an application that needs to be localized but is not already present in a XAML file.  Below, a MessageBox uses a hard-coded string.

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            string message = "Apples are crunchy, portable and taste great!";
            MessageBox.Show(message, "Apples");
        }

One approach to this is to move the string into a XAML file as a resource and then localize the string when localizing all of the other content in the XAML file.

We start by including an XML namespace that defines an alias for the System namespace.

        xmlns:sys="clr-namespace:System;assembly=mscorlib"

We can now add the string as a resource (e.g. within a <Window> element).

    <Window.Resources>
        <sys:String x:Uid="sys:String_1" x:Key="AppleMessage">Apples are crunchy, portable and taste great!</sys:String>
    </Window.Resources>

At run-time, we can load the resource rather than a hard-coded string.

            string message = (string)this.Resources["AppleMessage"];
            MessageBox.Show(message, "Apples");

#1,133 – Localization XIV – Add Content to Already Localized Application

After localizing your application for multiple languages, you have a main executable and a satellite assembly for each language that you’ve localized for.

If you then make changes to content in your application that is represented as XAML, the changes will show up in the satellite assembly for the neutral language, but not in the other satellite assemblies.  The changes will only be present when running under the neutral language.

After changing XAML content in a localized application, you need to take the following steps:

  • Make changes in Visual Studio, fully test under neutral language
  • Update UIDs using msbuild tool: msbuild /t:updateuid appname.csproj
  • Save and rebuild application
  • Re-extract localizable content using LocBaml tool: locbaml.exe /parse .\en-US\appname.resources.dll
  • Localize new content, integrating changes into existing language-specific .csv files
  • Re-generate satellite DLLs using LocBaml: locbaml.exe /generate .\en-US\appname.resources.dll /trans:.\appname.resources.fr-FR.csv /out:.\fr-FR /cul:fr-FR
  • Run application and test changes

#1,132 – Localization XIII – Verifying Localized Content

Once you integrate localized content back into your application, you’ll want to verify that the new content looks correct.  You could verify the content by running your application on a system having the target culture (e.g. French).  You can also just override the local culture information at run-time, setting it to the target culture for testing purposes.

To override the culture at run-time, you set the CurrentUICulture property of the current thread.  Below, we change the current UI culture at app startup so that we can test localization for the fr-FR (French/France) culture.  We also override metadata for the Language property to force user interface controls to pick up the current culture (rather than UI culture).

    public partial class App : Application
    {
        public App()
        {
            Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("fr-FR");
            FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(
                        XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
        }
    }

1132-001

#1,131 – Localization XII – Set NeutralLanguageResources Attribute

When you set the UICulture tag in your project, signifying that you want to store resources in a satellite assembly, you also need to set the NeutralResourcesLanguage attribute to indicate the default language to be used when trying to load resources to match the current culture.

Below is a fragment from AssemblyInfo.cs, showing use of the NeutralResourcesLanguage attribute, as well as the comments provided by the New Project wizard.

//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>.  For example, if you are using US english
//in your source files, set the <UICulture> to en-US.  Then uncomment
//the NeutralResourceLanguage attribute below.  Update the "en-US" in
//the line below to match the UICulture setting in the project file.
[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]

#1,130 – Localization XI – Satellite Assemblies

After localizing an application, you’ll have a directory structure that looks something like what’s shown below.

\bin – contains AppName.exe

\bin\fr-FR – contains AppName.resources.dll

\bin\en-US – contains AppName.resources.dll

We started by setting the UICulture tag to en-US.  This resulted in the \en-US\AppName.resources.dll file being generated.  This assembly is the satellite assembly containing English/US resources.

We then extracted resources using the LocBaml tool, translated content to French, and then generated a new satellite assembly for the fr-FR culture, again using the LocBaml tool.

At run-time, the current user interface culture (CurrentUICulture property) is read to determine the desired culture to use when loading resources.  This is typically the language used by the version of Windows that is installed.  (Rather than the current regional setting).

If there is a sub-directory whose name matches CurrentUICulture, then the corresponding satellite assembly is loaded.  If none is found, a neutral language assembly is used.

#1,129 – Localization X – Integrating Translations Back into Application

Once you get localized resources back from the translation team, you need to integrate these localized resources back into your application.

To integrate localized changes, once you have the new .csv file containing localized resources, do the following:

  • Open a Visual Studio command prompt
  • Change directory to be directory containing main application .exe file (e.g. \bin\Release)
  • Copy .csv file containing translations into this directory (e.g. WpfApplication1.resources.fr-FR.csv)
  • Create a sub-directory matching the desired culture name  (e.g. fr-FR)
  • Ensure that locbaml.exe is also present in this directory
  • Execute this command: locbaml.exe /generate .\en-US\WpfApplication1.resources.dll /trans:.\WpfApplication1.resources.fr-FR.csv /out:.\fr-FR /cul:fr-FR

You should see a new WpfApplication1.resources.dll file in the fr-FR sub-directory.

#1,128 – Localization IX – Localizing Content

After you’ve created .csv files containing the English-based property values, including text, the next step is to have the content actually localized.  This most often consists of translating the English text into another language.

The steps taken for actual localization of content are typically something like:

  • You hand off neutral (e.g. English) .CSV file to translators  (e.g. WpfApplication1.resources.csv)
  • Translators make a copy of the file, typically naming it to indicate culture  (e.g. WpfApplication1.resources.fr-FR.csv)
  • Translators translate all textual content
  • Translators send the file back to development team for integration into the application

Below is an example, show the .csv file before and after translation from English to French.  Note that three different strings have been translated.

English:

1128-001

French:

1128-002