WPF Globalization and Localization Overview
When you limit your product's availability to only one language, you limit your potential customer base to a fraction of our world’s 6.5 billion population. If you want your applications to reach a global audience, cost-effective localization of your product is one of the best and most economical ways to reach more customers.
This overview introduces globalization and localization in Windows Presentation Foundation (WPF). Globalization is the design and development of applications that perform in multiple locations. For example, globalization supports localized user interfaces and regional data for users in different cultures. WPF provides globalized design features, including automatic layout, satellite assemblies, and localized attributes and commenting.
Localization is the translation of application resources into localized versions for the specific cultures that the application supports. When you localize in WPF, you use the APIs in the System.Windows.Markup.Localizer namespace. These APIs power the LocBaml Tool Sample command-line tool. For information about how to build and use LocBaml, see Localize an Application.
Best Practices for Globalization and Localization in WPF
You can make the most of the globalization and localization functionality that is built into WPF by following the UI design and localization-related tips that this section provides.
Best Practices for WPF UI Design
When you design a WPF–based UI, consider implementing these best practices:
Write your UI in XAML; avoid creating UI in code. When you create your UI by using XAML, you expose it through built-in localization APIs.
Avoid using absolute positions and fixed sizes to lay out content; instead, use relative or automatic sizing.
Provide extra space in margins because localized text often requires more space. Extra space allows for possible overhanging characters.
Set the xml:lang attribute. This attribute describes the culture of a specific element and its child elements. The value of this property changes the behavior of several features in WPF. For example, it changes the behavior of hyphenation, spell checking, number substitution, complex script shaping, and font fallback. See Globalization for WPF for more information about setting the xml:lang Handling in XAML.
Create a customized composite font to obtain better control of fonts that are used for different languages. By default, WPF uses the GlobalUserInterface.composite font in your Windows\Fonts directory.
When you create navigation applications that may be localized in a culture that presents text in a right-to-left format, explicitly set the FlowDirection of every page to ensure the page does not inherit FlowDirection from the NavigationWindow.
When you create stand-alone navigation applications that are hosted outside a browser, set the StartupUri for your initial application to a NavigationWindow instead of to a page (for example,
<Application StartupUri="NavigationWindow.xaml">). This design enables you to change the FlowDirection of the Window and the navigation bar. For more information and an example, see Globalization Homepage Sample.
Best Practices for WPF Localization
When you localize WPF–based applications, consider implementing these best practices:
Use localization comments to provide extra context for localizers.
Use msbuild /t:updateuid and /t:checkuid to add and check Uid properties in your XAML. Use Uid properties to track changes between development and localization. Uid properties help you localize new development changes. If you manually add Uid properties to a UI, the task is typically tedious and less accurate.
Do not edit or change Uid properties after you begin localization.
Do not use duplicate Uid properties (remember this tip when you use the copy-and-paste command).
UltimateResourceFallbacklocation in AssemblyInfo.* to specify the appropriate language for fallback (for example,
[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]).
If you decide to include your source language in the main assembly by omitting the
<UICulture>tag in your project file, set the
UltimateResourceFallbacklocation as the main assembly instead of the satellite (for example,
[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.MainAssembly)]).
Localize a WPF Application
When you localize a WPF application, you have several options. For example, you can bind the localizable resources in your application to an XML file, store localizable text in resx tables, or have your localizer use Extensible Application Markup Language (XAML) files. This section describes a localization workflow that uses the BAML form of XAML, which provides several benefits:
You can localize after you build .
You can update to a newer version of the BAML form of XAMLwith localizations from an older version of the BAML form of XAML so that you can localize at the same time that you develop.
You can validate original source elements and semantics at compile time because the BAML form of XAML is the compiled form of XAML.
Localization Build Process
When you develop a WPF application, the build process for localization is as follows:
The developer creates and globalizes the WPF application. In the project file the developer sets
<UICulture>en-US</UICulture>so that when the application is compiled, a language-neutral main assembly is generated. This assembly has a satellite .resources.dll file that contains all the localizable resources. Optionally, you can keep the source language in the main assembly because our localization APIs support extraction from the main assembly.
When the file is compiled into the build, the XAML is converted to the BAML form of XAML. The culturally neutral
MyDialog.exeand the culturally dependent (English)
MyDialog.resources.dllfiles are released to the English-speaking customer.
The localization process begins after the unlocalized
MyDialog.resources.dll file is built. The UI elements and properties in your original XAML are extracted from the BAML form of XAML into key-value pairs by using the APIs under System.Windows.Markup.Localizer. Localizers use the key-value pairs to localize the application. You can generate a new .resource.dll from the new values after localization is complete.
The keys of the key-value pairs are
x:Uid values that are placed by the developer in the original XAML. These
x:Uid values enable the API to track and merge changes that happen between the developer and the localizer during localization. For example, if the developer changes the UI after the localizer begins localizing, you can merge the development change with the already completed localization work so that minimal translation work is lost.
The following graphic shows a typical localization workflow that is based on the BAML form of XAML. This diagram assumes the developer writes the application in English. The developer creates and globalizes the WPF application. In the project file the developer sets
<UICulture>en-US</UICulture> so that on build, a language neutral main assembly gets generated with a satellite .resources.dll containing all localizable resources. Alternately, one could keep the source language in the main assembly because WPF localization APIs support extraction from the main assembly. After the build process, the XAML get compiled into BAML. The culturally neutral MyDialog.exe.resources.dll get shipped to the English speaking customer.
Examples of WPF Localization
This section contains examples of localized applications to help you understand how to build and localize WPF applications.
Run Dialog Box Example
The following graphics show the output of the Run dialog box sample.
Designing a Global Run Dialog Box
This example produces a Run dialog box by using WPF and XAML. This dialog box is equivalent to the Run dialog box that is available from the Microsoft Windows Start menu.
Some highlights for making global dialog boxes are:
The previous Window property automatically resizes the window according to the size of the content. This property prevents the window from cutting off content that increases in size after localization; it also removes unneeded space when content decreases in size after localization.
Uid properties are needed in order for WPF localization APIs to work correctly.
They are used by WPF localization APIs to track changes between the development and localization of the user interface (UI). Uid properties enable you to merge a newer version of the UI with an older localization of the UI. You add a Uid property by running msbuild /t:updateuid RunDialog.csproj in a command shell. This is the recommended method of adding Uid properties because manually adding them is typically time-consuming and less accurate. You can check that Uid properties are correctly set by running msbuild /t:checkuid RunDialog.csproj.
The UI is structured by using the Grid control, which is a useful control for taking advantage of the automatic layout in WPF. Note that the dialog box is split into three rows and five columns. Not one of the row and column definitions has a fixed size; hence, the UI elements that are positioned in each cell can adapt to increases and decreases in size during localization.
<Grid.ColumnDefinitions> <ColumnDefinition x:Uid="ColumnDefinition_1" /> <ColumnDefinition x:Uid="ColumnDefinition_2" />
The first two columns where the Open: label and ComboBox are placed use 10 percent of the UI total width.
<ColumnDefinition x:Uid="ColumnDefinition_3" SharedSizeGroup="Buttons" /> <ColumnDefinition x:Uid="ColumnDefinition_4" SharedSizeGroup="Buttons" /> <ColumnDefinition x:Uid="ColumnDefinition_5" SharedSizeGroup="Buttons" /> </Grid.ColumnDefinitions>
Note that of the example uses the shared-sizing feature of Grid. The last three columns take advantage of this by placing themselves in the same SharedSizeGroup. As one would expect from the name of the property, this allows the columns to share the same size. So when the "Browse…" gets localized to the longer string "Durchsuchen…", all buttons grow in width instead of having a small "OK" button and a disproportionately large "Durchsuchen…" button.
Notice the xml:lang Handling in XAML placed at the root element of the UI. This property describes the culture of a given element and its children. This value is used by several features in WPF and should be changed appropriately during localization. This value changes what language dictionary is use to hyphenate and spell check words. It also affects the display of digits and how the font fallback system selects which font to use. Finally, the property affects the way numbers are displayed and the way texts written in complex scripts are shaped. The default value is "en-US".
Building a Satellite Resource Assembly
Notice the addition of a
UICulture value. When this is set to a valid CultureInfo value such as en-US, building the project will generate a satellite assembly with all localizable resources in it.
RunIcon.JPG does not need to be localized because it should appear the same for all cultures.
Localizable is set to
false so that it remains in the language neutral main assembly instead of the satellite assembly. The default value of all noncompilable resources is
Localizable set to
Localizing the Run Dialog
After building the application, the first step in localizing it is parsing the localizable resources out of the satellite assembly. For the purposes of this topic, use the sample LocBaml tool which can be found at LocBaml Tool Sample. Note that LocBaml is only a sample tool meant to help you get started in building a localization tool that fits into your localization process. Using LocBaml, run the following to parse: LocBaml /parse RunDialog.resources.dll /out: to generate a "RunDialog.resources.dll.CSV" file.
Use your favorite CSV editor that supports Unicode to edit this file. Filter out all entries with a localization category of "None". You should see the following entries:
|Resource Key||Localization Category||Value|
|TextBlock_1:System.Windows.Controls.TextBlock.$Content||Text||Type the name of a program, folder, document, or Internet resource, and Windows will open it for you.|
Localizing the application to German would require the following translations:
|Resource Key||Localization Category||Value|
|TextBlock_1:System.Windows.Controls.TextBlock.$Content||Text||Geben Sie den Namen eines Programms, Ordners, Dokuments oder einer Internetresource an.|
The last step of localization involves creating the newly localized satellite assembly. This can be accomplished with the following LocBaml command:
LocBaml.exe /generate RunDialog.resources.dll /trans:RunDialog.resources.dll.CSV /out: . /cul:de-DE
On German Windows, if this resources.dll is placed in a de-DE folder next to the main assembly, this resource will automatically load instead of the one in the en-US folder. If you do not have a German version of Windows to test this, set the culture to whatever culture of Windows you are using (i.e. en-US), and replace the original resources.dll.
Satellite Resource Loading
|Code||Original English BAML||Localized BAML|
|Culturally neutral resources||Other resources in English||Other resources localized to German|
The .NET framework automatically chooses which satellite resources assembly to load based on the application’s
Thread.CurrentThread.CurrentUICulture. This defaults to the culture of your Windows OS. So if you are using German Windows, the de-DE\MyDialog.resources.dll loads, if you are using English Windows, the en-US\MyDialog.resources.dll loads. You can set the ultimate fallback resource for your application by specifying the NeutralResourcesLanguage in your project’s AssemblyInfo.*. For example if you specify:
[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
then the en-US\MyDialog.resources.dll will be used with German Windows if a de-DE\MyDialog.resources.dll or de\MyDialog.resources.dll are both unavailable.
Microsoft Saudi Arabia Homepage
The following graphics show an English and Arabic Homepage. For the complete sample that produces these graphics see Globalization Homepage Sample.
Designing a Global Microsoft Homepage
This mock up of the Microsoft Saudi Arabia web site illustrates the globalization features provided for RightToLeft languages. Languages such as Hebrew and Arabic have a right-to-left reading order so the layout of UI must often be laid out quite differently than it would be in left-to-right languages such as English. Localizing from a left-to-right language to a right-to-left language or vice versa can be quite challenging. WPF has been designed to make such localizations much easier.
<Page x:Uid="Page_1" x:Class="MicrosoftSaudiArabiaHomepage.Homepage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" FlowDirection="LeftToRight" Localization.Comments="FlowDirection(This FlowDirection controls the actual content of the homepage)" xml:lang="en-US">
Notice the FlowDirection property on Page. Changing this property to RightToLeft will change the FlowDirection of the Page and its children elements so that the layout of this UI is flipped to become right-to-left as an Arabic user would expect. One can override the inheritance behavior by specifying an explicit FlowDirection on any element. The FlowDirection property is available on any FrameworkElement or document related element and has an implicit value of LeftToRight.
Observe that even the background gradient brushes are flipped correctly when the root FlowDirection is changed:
Avoid Using Fixed Dimensions for Panels and Controls
Take a look through Homepage.xaml, notice that aside from the fixed width and height specified for the entire UI on the top DockPanel, there are no other fixed dimensions. Avoid using fixed dimensions to prevent clipping localized text that may be longer than the source text. WPF panels and controls will automatically resize based on the content that they contain. Most controls also have minimum and maximum dimensions that you can set for more control (i.e. MinWidth= "20"). With Grid, you can also set relative widths and heights by using ‘*’ (i.e. Width= "0.25*") or use its cell size sharing feature.
There are many cases where content may be ambiguous and difficult to translate. The developer or designer has the ability to provide extra context and comments to localizers through localization comments. For example the Localization.Comments below clarifies the usage of the character ‘|’.
<TextBlock x:Uid="TextBlock_2" DockPanel.Dock="Right" Foreground="White" Margin="5,0,5,0" Localization.Comments="$Content(This character is used as a decorative rule.)"> | </TextBlock>
This comment becomes associated with TextBlock_1’s content and in the case of the LocBaml Tool, ( see Localize an Application), it can be seen in the 6th column of the TextBlock_1 row in the output .csv file:
|TextBlock_1:System.Windows.Controls.TextBlock.$Content||Text||TRUE||TRUE||This character is used as a decorative rule.||||
Comments can be placed on the content or property of any element using the following syntax:
<TextBlock x:Uid="TextBlock_1" DockPanel.Dock="Right" Foreground="White" Margin="5,0,5,0" Localization.Comments="$Content(This is a comment on the TextBlock's content.) Margin(This is a comment on the TextBlock's Margin property.)"> | </TextBlock>
Often the developer or localization manager needs control of what localizers can read and modify. For example, you might not want the localizer to translate the name of your company or legal wording. WPF provides attributes that enable you to set the readability, modifiability, and category of an element’s content or property which your localization tool can use to lock, hide, or sort elements. For more information, see Attributes. For the purposes of this sample, the LocBaml Tool just outputs the values of these attributes. WPF controls all have default values for these attributes, but you the can override them. For example, the following example overrides the default localization attributes for
TextBlock_1 and sets the content to be readable but unmodifiable for localizers.
<TextBlock x:Uid="TextBlock_1" Localization.Attributes= "$Content(Readable Unmodifiable)"> Microsoft Corporation </TextBlock>
In addition to the readability and modifiability attributes, WPF provides an enumeration of common UI categories (LocalizationCategory) that can be used to give localizers more context. The WPF default categories for platform controls can be overridden in XAML as well:
<TextBlock x:Uid="TextBlock_2"> <TextBlock.ToolTip> <TextBlock x:Uid="TextBlock_3" Localization.Attributes= "$Content(ToolTip Readable Unmodifiable)"> Microsoft Corporation </TextBlock> </TextBlock.ToolTip> Windows Vista </TextBlock>
The default localization attributes that WPF provides can also be overridden through code, so you can correctly set the right default values for custom controls. For example:
[Localizability(Readability = Readability.Readable, Modifiability=Modifiability.Unmodifiable, LocalizationCategory.None)]
public class CorporateLogo: TextBlock
The per instance attributes set in XAML will take precedence over the values set in code on custom controls. For more information on attributes and comments, see Localization Attributes and Comments.
Font Fallback and Composite Fonts
If you specify a font that does not support a given codepoint range, WPF will automatically fallback to one that does by using the Global User Interface.compositefont that is located in your Windows\Fonts directory. Composite fonts work just as any other font and can be used explicitly by setting an element’s FontFamily (i.e. FontFamily= "Global User Interface"). You can specify your own font fallback preference by creating your own composite font and specifying what font to use for specific codepoint ranges and languages.
For more information on composite fonts see FontFamily.
Localizing the Microsoft Homepage
You can follow the same steps as the Run Dialog example to localize this application. The localized .csv file for Arabic is available for you in the Globalization Homepage Sample.