달력

1

« 2025/1 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
2016. 11. 5. 14:17

Globalization and Localization 프로그래밍/WPF2016. 11. 5. 14:17

Globalization and Localization



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 How to: 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 .

    • Use SizeToContent; and keep widths and heights set to Auto.

    • Avoid using Canvas to lay out UIs.

    • Use Grid and its size-sharing feature.

  • Provide extra space in margins because localized text often requires more space. Extra space allows for possible overhanging characters.

  • Enable TextWrapping on TextBlock to avoid clipping .

  • Set the xml:langattribute . 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 theFlowDirection 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 aNavigationWindow 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 local ization comments to provide extra context for localizers.

  • Use localization attributes to control localization instead of selectively omitting Uid properties on elements. See Localization Attributes and Comments for more information.

  • 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).

    • Set the UltimateResourceFallback location 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 theUltimateResourceFallback location 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.exe and the culturally dependent (English)  MyDialog.resources.dll files are released to the English-speaking customer.

Localization Workflow

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 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.

Localization workflow
Unlocalized work flow

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.

English:

Run dialog box

German:

German Run dialog box

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:

Automatic Layout

In Window1.xaml:

<Window SizeToContent="WidthAndHeight">

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.

<Grid x:Uid="Grid_1">

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 sameSharedSizeGroup. 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.

Xml:lang

Xml:lang="en-US"

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

In .csproj:

<UICulture>en-US</UICulture>

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.

<Resource Include="RunIcon.JPG">

<Localizable>False</Localizable>

</Resource>

The 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 true.

Localizing the Run Dialog

Parse

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.

Localize

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

Button_1:System.Windows.Controls.Button.$Content

Button

OK

Button_2:System.Windows.Controls.Button.$Content

Button

Cancel

Button_3:System.Windows.Controls.Button.$Content

Button

Browse...

ComboBox_1:System.Windows.Controls.ComboBox.$Content

ComboBox

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.

TextBlock_2:System.Windows.Controls.TextBlock.$Content

Text

Open:

Window_1:System.Windows.Window.Title

Title

Run

Localizing the application to German would require the following translations:

Resource Key

Localization Category

Value

Button_1:System.Windows.Controls.Button.$Content

Button

OK

Button_2:System.Windows.Controls.Button.$Content

Button

Abbrechen

Button_3:System.Windows.Controls.Button.$Content

Button

Durchsuchen…

ComboBox_1:System.Windows.Controls.ComboBox.$Content

ComboBox

TextBlock_1:System.Windows.Controls.TextBlock.$Content

Text

Geben Sie den Namen eines Programms, Ordners, Dokuments oder einer Internetresource an.

TextBlock_2:System.Windows.Controls.TextBlock.$Content

Text

Öffnen:

Window_1:System.Windows.Window.Title

Title

Run

Generate

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

MyDialog.exe

en-US\MyDialog.resources.dll

de-DE\MyDialog.resources.dll

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’sThread.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.

English:

English page

Arabic:

Arabic page

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.

FlowDirection

Homepage.xaml:

<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:

FlowDirection="LeftToRight"

Flow from left to right

FlowDirection="RightToLeft"

Flow from right to left

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.

Localization Comments

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 How to: Localize an Application), it can be seen in the 6th column of the TextBlock_1 row in the output .csv file:

Resource Key

Category

Readable

Modifiable

Comment

Value

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>

Localization Attributes

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 theGlobalization Homepage Sample.




Globalization for WPF


This topic introduces issues that you should be aware of when writing Windows Presentation Foundation (WPF) applications for the global market. The globalization programming elements are defined in Microsoft .NET in System.Globalization.

XAML Globalization

Extensible Application Markup Language (XAML) is based on XML and takes advantage of the globalization support defined in the XML specification. The following sections describe some XAML features that you should be aware of.

Character References

A character reference gives the number of the particular Unicode character it represents, in either decimal or hexadecimal. The following example shows a decimal character reference.

&#1000;

This example shows a hexadecimal character reference. Notice that it has an x in front of the hexadecimal number.

&#x3E8;

Encoding

The encoding supported by XAML are ASCII, Unicode UTF-16, and UTF-8. The encoding statement is at the beginning of XAML document. If no encoding attribute exists and there is no byte-order, the parser defaults to UTF-8. UTF-8 and UTF-16 are the preferred encodings. UTF-7 is not supported. The following example demonstrates how to specify a UTF-8 encoding in a XAML file.

?xml encoding="UTF-8"?

Language Attribute

XAML uses xml:lang to represent the language attribute of an element.  To take advantage of the CultureInfo class, the language attribute value needs to be one of the culture names predefined by CultureInfoxml:lang is inheritable in the element tree (by XML rules, not necessarily because of dependency property inheritance) and its default value is an empty string if it is not assigned explicitly.

The language attribute is very useful for specifying dialects. For example, French has different spelling, vocabulary, and pronunciation in France, Quebec, Belgium, and Switzerland. Also Chinese, Japanese, and Korean share code points in Unicode, but the ideographic shapes are different and they use totally different fonts.

The following Extensible Application Markup Language (XAML) example uses the fr-CA language attribute to specify Canadian French.

<TextBlock xml:lang="fr-CA">Découvrir la France</TextBlock>

Unicode

XAML supports all Unicode features including surrogates. As long as the character set can be mapped to Unicode, it is supported. For example, GB18030 introduces some characters that are mapped to the Chinese, Japanese, and Korean (CFK) extension A and B and surrogate pairs, therefore it is fully supported. A WPF application can use StringInfo to manipulate strings without understanding whether they have surrogate pairs or combining characters.

Designing an International User Interface with XAML

This section describes user interface (UI) features that you should consider when writing an application.

International Text

WPF includes built-in processing for all Microsoft .NET Framework supported writing systems.

The following scripts are currently supported:

  • Arabic

  • Bengali

  • Devanagari

  • Cyrillic

  • Greek

  • Gujarati

  • Gurmukhi

  • Hebrew

  • Ideographic scripts

  • Kannada

  • Lao

  • Latin

  • Malayalam

  • Mongolian

  • Odia

  • Syriac

  • Tamil

  • Telugu

  • Thaana

  • Thai*

  • Tibetan

*In this release the display and editing of Thai text is supported; word breaking is not.

The following scripts are not currently supported:

  • Khmer

  • Korean Old Hangul

  • Myanmar

  • Sinhala

All the writing system engines support OpenType fonts. OpenType fonts can include the OpenType layout tables that enable font creators to design better international and high-end typographic fonts. The OpenType font layout tables contain information about glyph substitutions, glyph positioning, justification, and baseline positioning, enabling text-processing applications to improve text layout.

OpenType fonts allow the handling of large glyph sets using Unicode encoding. Such encoding enables broad international support as well as for typographic glyph variants.

WPF text rendering is powered by Microsoft ClearType sub-pixel technology that supports resolution independence. This significantly improves legibility and provides the ability to support high quality magazine style documents for all scripts.

International Layout

WPF provides a very convenient way to support horizontal, bidirectional, and vertical layouts. In presentation framework the FlowDirectionproperty can be used to define layout. The flow direction patterns are:

  • LeftToRight - horizontal layout for Latin, East Asian and so forth.

  • RightToLeft - bidirectional for Arabic, Hebrew and so forth.

Developing Localizable Applications

When you write an application for global consumption you should keep in mind that the application must be localizable. The following topics point out things to consider.

Multilingual User Interface

Multilingual User Interfaces (MUI) is a Microsoft support for switching UIs from one language to another. A WPF application uses the assembly model to support MUI. One application contains language-neutral assemblies as well as language-dependent satellite resource assemblies. The entry point is a managed .EXE in the main assembly. WPF resource loader takes advantage of the Framework's resource manager to support resource lookup and fallback. Multiple language satellite assemblies work with the same main assembly. The resource assembly that is loaded depends on the CurrentUICulture of the current thread.

Localizable User Interface

WPF applications use XAML to define their UI. XAML allows developers to specify a hierarchy of objects with a set of properties and logic. The primary use of XAML is to develop WPF applications but it can be used to specify a hierarchy of any common language runtime (CLR) objects. Most developers use XAML to specify their application's UI and use a programming language such as C# to react to user interaction.

From a resource point of view, a XAML file designed to describe a language-dependent UI is a resource element and therefore its final distribution format must be localizable to support international languages. Because XAML cannot handle events many XAML applications contain blocks of code to do this. For more information, see XAML Overview (WPF). Code is stripped out and compiled into different binaries when a XAML file is tokenized into the BAML form of XAML. The BAML form of XAML files, images, and other types of managed resource objects are embedded in the satellite resource assembly, which can be localized into other languages, or the main assembly when localization is not required.

System_CAPS_noteNote

WPF applications support all the FrameworkCLR resources including string tables, images, and so forth.

Building Localizable Applications

Localization means to adapt a UI to different cultures. To make a WPF application localizable, developers need to build all the localizable resources into a resource assembly. The resource assembly is localized into different languages, and the code-behind uses resource management API to load. One of the files required for a WPF application is a project file (.proj). All resources that you use in your application should be included in the project file. The following example from a .csproj file shows how to do this.

<Resource Include="data\picture1.jpg"/>
<EmbeddedResource Include="data\stringtable.en-US.restext"/>

To use a resource in your application instantiate a ResourceManager and load the resource you want to use. The following example demonstrates how to do this.

void OnClick(object sender, RoutedEventArgs e)
{
  ResourceManager rm = new ResourceManager ("MySampleApp.data.stringtable",
       Assembly.GetExecutingAssembly());
  Text1.Text = rm.GetString("Message");
}

Using ClickOnce with Localized Applications

ClickOnce is a new Windows Forms deployment technology that will ship with Microsoft Visual Studio 2005. It enables application installation and upgrading of Web applications. When an application that was deployed with ClickOnce is localized it can only be viewed on the localized culture. For example, if a deployed application is localized to Japanese it can only be viewed on Japanese Microsoft Windows not on English Windows. This presents a problem because it is a common scenario for Japanese users to run an English version of Windows.

The solution to this problem is setting the neutral language fallback attribute. An application developer can optionally remove resources from the main assembly and specify that the resources can be found in a satellite assembly corresponding to a specific culture. To control this process use theNeutralResourcesLanguageAttribute. The constructor of the NeutralResourcesLanguageAttribute class has two signatures, one that takes anUltimateResourceFallbackLocation parameter to specify the location where the ResourceManager should extract the fallback resources: main assembly or satellite assembly. The following example shows how to use the attribute. For the ultimate fallback location, the code causes theResourceManager to look for the resources in the "de" subdirectory of the directory of the currently executing assembly.

[assembly: NeutralResourcesLanguageAttribute(
    "de" , UltimateResourceFallbackLocation.Satellite)]




Use Automatic Layout Overview


This topic introduces guidelines for developers on how to write Windows Presentation Foundation (WPF) applications with localizable user interfaces (UIs). In the past, localization of a UI was a time consuming process. Each language that the UI was adapted for required a pixel by pixel adjustment. Today with the right design and right coding standards, UIs can be constructed so that localizers have less resizing and repositioning to do. The approach to writing applications that can be more easily resized and repositioned is called automatic layout, and can be achieved by using WPF application design.

This topic contains the following sections.

Advantages of Using Automatic Layout

Because the WPF presentation system is powerful and flexible, it provides the ability to layout elements in an application that can be adjusted to fit the requirements of different languages. The following list points out some of the advantages of automatic layout.

  • UI displays well in any language.

  • Reduces the need to readjust position and size of controls after text is translated.

  • Reduces the need to readjust window size.

  • UI layout renders properly in any language.

  • Localization can be reduced to the point that it is little more than string translation.

Automatic Layout and Controls

Automatic layout enables an application to adjust the size of a control automatically. For example, a control can change to accommodate the length of a string. This capability enables localizers to translate the string; they no longer need to resize the control to fit the translated text. The following example creates a button with English content.

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="ButtonLoc.Pane1"
    Name="myWindow"
    SizeToContent="WidthAndHeight"
    >

<DockPanel> 
    <Button FontSize="28" Height="50">My name is Hope.</Button>
</DockPanel>
</Window>

In the example, all you have to do to make a Spanish button is change the text. For example,

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="ButtonLoc.Pane1"
    Name="myWindow"
    SizeToContent="WidthAndHeight"
    >

 <DockPanel> 
    <Button FontSize="28" Height="50">Me llamo Esperanza.</Button>
  </DockPanel>
</Window>

The following graphic shows the output of the code samples.

The same button with text in different languages

Auto Resizable Button

Automatic Layout and Coding Standards

Using the automatic layout approach requires a set of coding and design standards and rules to produce a fully localizable UI. The following guidelines will aid your automatic layout coding.

Coding Standards

Description

Do not use absolute positions.

Do not set a fixed size for a window.

<StackPanel
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="GridLoc.Pane1"
>

Add a FlowDirection.

  • Add a FlowDirection to the root element of your application.

  • WPF provides a convenient way to support horizontal, bidirectional, and vertical layouts. In presentation framework, the FlowDirection property can be used to define layout. The flow-direction patterns are:

    • LeftToRight (LrTb) — horizontal layout for Latin, East Asian, and so forth.

    • RightToLeft (RlTb) — bidirectional for Arabic, Hebrew, and so forth.

Use composite fonts instead of physical fonts.

  • With composite fonts, the FontFamily property does not need to be localized.

  • Developers can use one of the following fonts or create their own.

    • Global User Interface

    • Global San Serif

    • Global Serif

Add xml:lang.

  • Add the xml:lang attribute in the root element of your UI, such as xml:lang="en-US" for an English application.

  • Because composite fonts use xml:lang to determine what font to use, set this property to support multilingual scenarios.

Automatic Layout and Grids

The Grid element, is useful for automatic layout because it enables a developer to position elements. A Grid control is capable of distributing the available space among its child elements, using a column and row arrangement. The UI elements can span multiple cells, and it is possible to have grids within grids. Grids are useful because they enable you to create and position complex UI. The following example demonstrates using a grid to position some buttons and text. Notice that the height and width of the cells are set to Auto; therefore, the cell that contains the button with an image adjusts to fit the image.

<Grid Name="grid" ShowGridLines ="false">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>

<TextBlock Margin="10, 10, 5, 5" Grid.Column="0" Grid.Row="0" FontSize="24">Grid
</TextBlock>
<TextBlock Margin="10, 10, 5, 5" Grid.Column="0" Grid.Row="1" FontSize="12"  
    Grid.ColumnSpan="2">The following buttons and text are positioned using a Grid.
</TextBlock>  
<Button Margin="10, 10, 5, 5" Grid.Column="0" Grid.Row="2" Background="Pink" 
    BorderBrush="Black" BorderThickness="10">Button 1
</Button>
<TextBlock Margin="10, 10, 5, 5" Grid.Column="1" Grid.Row="2" FontSize="12" 
   VerticalAlignment="Center" TextWrapping="WrapWithOverflow">Sets the background 
   color.
</TextBlock>  
<Button Margin="10, 10, 5, 5" Grid.Column="0" Grid.Row="3" Foreground="Red">
   Button 2
</Button>
<TextBlock Margin="10, 10, 5, 5" Grid.Column="1" Grid.Row="3" FontSize="12" 
   VerticalAlignment="Center" TextWrapping="WrapWithOverflow">Sets the foreground 
   color.
</TextBlock>  
<Button Margin="10, 10, 5, 5" Grid.Column="0" Grid.Row="4">
   <Image Source="data\flower.jpg"></Image>
</Button>
<TextBlock Margin="10, 10, 5, 5" Grid.Column="1" Grid.Row="4" FontSize="12" 
   VerticalAlignment="Center" TextWrapping="WrapWithOverflow">Adds an image as 
   the button's content.
</TextBlock>
</Grid>

The following graphic shows the grid produced by the previous code.

Grid example

Grid

Automatic Layout and Grids Using the IsSharedSizeScope Property

Grid element is useful in localizable applications to create controls that adjust to fit content. However, at times you want controls to maintain a particular size regardless of content. For example, if you have "OK", "Cancel" and "Browse" buttons you probably do not want the buttons sized to fit the content. In this case the Grid.IsSharedSizeScope attached property is useful for sharing the same sizing among multiple grid elements. The following example demonstrates how to share column and row sizing data between multiple Grid elements.

<StackPanel Orientation="Horizontal" DockPanel.Dock="Top">  
    <Button Click="setTrue" Margin="0,0,10,10">Set IsSharedSizeScope="True"</Button>
    <Button Click="setFalse" Margin="0,0,10,10">Set IsSharedSizeScope="False"</Button>
</StackPanel> 

<StackPanel Orientation="Horizontal" DockPanel.Dock="Top">

<Grid ShowGridLines="True" Margin="0,0,10,0">
  <Grid.ColumnDefinitions>
    <ColumnDefinition SharedSizeGroup="FirstColumn"/>
    <ColumnDefinition SharedSizeGroup="SecondColumn"/>
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" SharedSizeGroup="FirstRow"/>
  </Grid.RowDefinitions>

    <Rectangle Fill="Silver" Grid.Column="0" Grid.Row="0" Width="200" Height="100"/>
    <Rectangle Fill="Blue" Grid.Column="1" Grid.Row="0" Width="150" Height="100"/>

    <TextBlock Grid.Column="0" Grid.Row="0" FontWeight="Bold">First Column</TextBlock>
    <TextBlock Grid.Column="1" Grid.Row="0" FontWeight="Bold">Second Column</TextBlock>
</Grid>

<Grid ShowGridLines="True">
  <Grid.ColumnDefinitions>
    <ColumnDefinition SharedSizeGroup="FirstColumn"/>
    <ColumnDefinition SharedSizeGroup="SecondColumn"/>
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>        
    <RowDefinition Height="Auto" SharedSizeGroup="FirstRow"/>
  </Grid.RowDefinitions>

    <Rectangle Fill="Silver" Grid.Column="0" Grid.Row="0"/>
    <Rectangle Fill="Blue" Grid.Column="1" Grid.Row="0"/>

    <TextBlock Grid.Column="0" Grid.Row="0" FontWeight="Bold">First Column</TextBlock>
    <TextBlock Grid.Column="1" Grid.Row="0" FontWeight="Bold">Second Column</TextBlock>
</Grid>

</StackPanel>

<TextBlock Margin="10" DockPanel.Dock="Top" Name="txt1"/>

Note   For the complete code sample, see How to: Share Sizing Properties Between Grids




Localization Attributes and Comments


Windows Presentation Foundation (WPF) localization comments are properties, inside XAML source code, supplied by developers to provide rules and hints for localization. Windows Presentation Foundation (WPF) localization comments contain two sets of information: localizability attributes and free-form localization comments. Localizability attributes are used by the WPF Localization API to indicate which resources are to be localized. Free-form comments are any information that the application author wants to include.

Localization Comments

If markup application authors have requirements for specific elements in XAML, such as constraints on text length, font family, or font size, they can convey this information to localizers with comments in the XAML code. The process for adding comments to source code is as follows:

  1. Application developer adds localization comments to XAML source code.

  2. During the build process, you can specify in the .proj file whether to leave the free-form localization comments in the assembly, strip out part of the comments, or strip out all the comments. The stripped-out comments are placed in a separate file. You specify your option using a LocalizationDirectivesToLocFile tag, eg:

    <LocalizationDirectivesToLocFile>value</LocalizationDirectivesToLocFile>

  3. The values that can be assigned are:

    • None - Both comments and attributes stay inside the assembly and no separate file is generated.

    • CommentsOnly - Strips only the comments from the assembly and places them in the separate LocFile.

    • All - Strips both the comments and the attributes from the assembly and places them both in a separate LocFile.

  4. When localizable resources are extracted from BAML, the localizability attributes are respected by the BAML Localization API.

  5. Localization comment files, containing only free-form comments, are incorporated into the localization process at a later time.

The following example shows how to add localization comments to a XAML file.

<TextBlock x:Id = "text01"

FontFamily = "Microsoft Sans Serif"

FontSize = "12"

Localization.Attributes = "$Content (Unmodifiable Readable Text)

FontFamily (Unmodifiable Readable)"

Localization.Comments = "$Content (Trademark)

FontSize (Trademark font size)" >

Microsoft

</TextBlock>

In the previous sample the Localization.Attributes section contains the localization attributes and the Localization.Comments section the free-form comments. The following tables show the attributes and comments and their meaning to the localizer.

Localization attributes

Meaning

$Content (Unmodifiable Readable Text)

Contents of the TextBlock element cannot be modified. Localizers cannot change the word "Microsoft". The content is visible (Readable) to the localizer. The category of the content is text.

FontFamily (Unmodifiable Readable)

The font family property of the TextBlock element cannot be changed but it is visible to the localizer.

Localization free-form comments

Meaning

$Content (Trademark)

The application author tells the localizer that the content in the TextBlock element is a trademark.

FontSize (Trademark font size)

The application author indicates that the font size property should follow the standard trademark size.

Localizability Attributes

The information in Localization.Attributes contains a list of pairs: the targeted value name and the associated localizability values. The target name can be a property name or the special $Content name. If it is a property name, the targeted value is the value of the property. If it is $Content, the target value is the content of the element.

There are three types of attributes:

  • Category. This specifies whether a value should be modifiable from a localizer tool. See Category.

  • Readability. This specifies whether a localizer tool should read (and display) a value. See Readability.

  • Modifiability. This specifies whether a localizer tool allows a value to be modified. See Modifiability.

These attributes can be specified in any order delimited by a space. In case duplicate attributes are specified, the last attribute will override former ones. For example, Localization.Attributes = "Unmodifiable Modifiable" sets Modifiability to Modifiable because it is the last value.

Modifiability and Readability are self-explanatory. The Category attribute provides predefined categories that help the localizer when translating text. Categories, such as, Text, Label, and Title give the localizer information about how to translate the text. There are also special categories: None, Inherit, Ignore, and NeverLocalize.

The following table shows the meaning of the special categories.

Category

Meaning

None

Targeted value has no defined category.

Inherit

Targeted value inherits its category from its parent.

Ignore

Targeted value is ignored in the localization process. Ignore affects only the current value. It will not affect child nodes.

NeverLocalize

Current value cannot be localized. This category is inherited by the children of an element.

Localization.Comments contains free-form strings concerning the targeted value. Application developers can add information to give localizers hints about how the applications text should be translated. The format of the comments can be any string surrounded by "()". Use '\' to escape characters.




Bidirectional Features in WPF Overview


Unlike any other development platform, WPF has many features that support rapid development of bidirectional content, for example, mixed left to right and right to left data in the same document. At the same time, WPF creates an excellent experience for users who require bidirectional features such as Arabic and Hebrew speaking users.

The following sections explain many bidirectional features together with examples illustrating how to achieve the best display of bidirectional content. Most of the samples use XAML, though you can easily apply the concepts to C# or Microsoft Visual Basic code.

FlowDirection

The basic property that defines the content flow direction in a WPF application is FlowDirection. This property can be set to one of two enumeration values, LeftToRight or RightToLeft. The property is available to all WPF elements that inherit from FrameworkElement.

The following examples set the flow direction of a TextBox element.

Left-to-right flow direction

<TextBlock Background="DarkBlue" Foreground="LightBlue" 
   FontSize="20" FlowDirection="LeftToRight">
        This is a left-to-right TextBlock
</TextBlock>

Right-to-left flow direction

<TextBlock Background="LightBlue" Foreground="DarkBlue"
   FontSize="20" FlowDirection="RightToLeft">
        This is a right-to-left TextBlock
</TextBlock>

The following graphic shows how the previous code renders.

Graphic That Illustrates FlowDirection

TextBlock alignment

An element within a user interface (UI) tree will inherit the FlowDirection from its container. In the following example, the TextBlock is inside a Grid, which resides in a Window. Setting the FlowDirection for the Window implies setting it for the Grid and TextBlock as well.

The following example demonstrates setting FlowDirection.

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="FlowDirectionApp.Window1"
    Title="BidiFeatures" Height="200" Width="700" 
    FlowDirection="RightToLeft">

    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
      </Grid.ColumnDefinitions>
      <TextBlock Grid.Column="0" >
          This is a right-to-left TextBlock
      </TextBlock>

      <TextBlock Grid.Column="1" FlowDirection="LeftToRight">
          This is a left-to-right TextBlock
      </TextBlock>
    </Grid>
</Window>

The top level Window has a RightToLeftFlowDirection, so all elements contained within it also inherit the same FlowDirection. For an element to override a specified FlowDirection it must add an explicit direction change such as the second TextBlock in the previous example which changes toLeftToRight. When no FlowDirection is defined, the default LeftToRight applies.

The following graphic shows the output of the previous example.

Graphic That Illustrates Explicitly Assigned FlowDirection

Flow direction illustration

FlowDocument

Many development platforms such as HTML, Win32 and Java provide special support for bidirectional content development. Markup languages such as HTML give content writers the necessary markup to display text in any required direction, for example the HTML 4.0 tag, "dir" that takes "rtl" or "ltr" as values. This tag is similar to the FlowDirection property, but the FlowDirection property works in a more advanced way to layout textual content and can be used for content other than text.

In WPF, a FlowDocument is a versatile UI element that can host a combination of text, tables, images and other elements. The samples in the following sections use this element.

Adding text to a FlowDocument can be done in more that one way. A simple way to do so is through a Paragraph which is a block-level element used to group content such as text. To add text to inline-level elements the samples use Span and RunSpan is an inline-level flow content element used for grouping other inline elements, while a Run is an inline-level flow content element intended to contain a run of unformatted text. A Spancan contain multiple Run elements.

The first document example contains a document that has a number of network share names; for example \\server1\folder\file.ext. Whether you have this network link in an Arabic or English document, you always want it to appear in the same way. The following graphic shows the link in an Arabic RightToLeft document.

Graphic That Illustrates Using the Span Element

Document that flows from right to left

Because the text is RightToLeft, all special characters, such as the "\", separate the text in a right to left order. That results in the link not being shown in the correct order, therefore to solve the problem, the text must be embedded to preserve a separate Run flowing LeftToRight. Instead of having a separate Run for each language, a better way to solve the problem is to embed the less frequently used English text into a larger Arabic Span.

The following graphic illustrates this.

Graphic That Illustrates Using the Run Element Embedded in a Span Element

XamlPad screen shot

The following example demonstrates using Run and Span elements in documents.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    FlowDirection="RightToLeft">

  <FlowDocument>
    <Paragraph>
      <Span FlowDirection="RightToLeft" >
        ستجد الملف هنا:
        <Run FlowDirection="LeftToRight">
           \\server1\filename\filename1.txt</Run>
        ثم باقى النص!
      </Span>
    </Paragraph>
  </FlowDocument>
</Page>

Span Elements

The Span element works as a boundary separator between texts with different flow directions. Even Span elements with the same flow direction are considered to have different bidirectional scopes which means that the Span elements are ordered in the container’s FlowDirection, only the content within the Span element follows the FlowDirection of the Span.

The following graphic shows the flow direction of several TextBlock elements.

Graphic That Illustrates FlowDirection in Several TextBlock Elements

Text blocks with different flow directions

The following example shows how to use the Span and Run elements to produce the results shown in the previous graphic.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <StackPanel >

    <TextBlock FontSize="20" FlowDirection="RightToLeft">
      <Run FlowDirection="LeftToRight">العالم</Run>
      <Run FlowDirection="LeftToRight" Foreground="Red" >فى سلام</Run>
    </TextBlock>

    <TextBlock FontSize="20" FlowDirection="LeftToRight">
      <Run FlowDirection="RightToLeft">العالم</Run>
      <Run FlowDirection="RightToLeft" Foreground="Red" >فى سلام</Run>
    </TextBlock>

    <TextBlock FontSize="20" Foreground="Blue">العالم فى سلام</TextBlock>

    <Separator/>

    <TextBlock FontSize="20" FlowDirection="RightToLeft">
      <Span Foreground="Red" FlowDirection="LeftToRight">Hello</Span>
      <Span FlowDirection="LeftToRight">World</Span>
    </TextBlock>

    <TextBlock FontSize="20" FlowDirection="LeftToRight">
      <Span Foreground="Red" FlowDirection="RightToLeft">Hello</Span>
      <Span FlowDirection="RightToLeft">World</Span>
    </TextBlock>

    <TextBlock FontSize="20" Foreground="Blue">Hello World</TextBlock>

  </StackPanel>

</Page>

In the TextBlock elements in the sample, the Span elements are laid out according to the FlowDirection of their parents, but the text within each Spanelement flows according to its own FlowDirection. This is applicable to Latin and Arabic – or any other language.

Adding xml:lang

The following graphic shows another example that uses numbers and arithmetic expressions, such as "200.0+21.4=221.4". Notice that only theFlowDirection is set.

Graphic That Displays Numbers Using Only FlowDirection

Numbers that flow from right to left

Users of this application will be disappointed by the output, even though the FlowDirection is correct the numbers are not shaped as Arabic numbers should be shaped.

XAML elements can include an XML attribute ( xml:lang) that defines the language of each element. XAML also supports a XML language principle whereby xml:lang values applied to parent elements in the tree are used by child elements. In the previous example, because a language was not defined for the Run element or any of its top level elements, the default xml:lang was used, which is en-US for XAML. The internal number shaping algorithm of Windows Presentation Foundation (WPF) selects numbers in the corresponding language – in this case English. To make the Arabic numbers render correctly xml:lang needs to be set.

The following graphic shows the example with xml:lang added.

Graphic That Illustrates Using the xml:lang Attribute

Arabic numbers that flow from right to left

The following example adds xml:lang to the application.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    FlowDirection="RightToLeft">
      <FlowDocument>
         <Paragraph>
            <Span FlowDirection="RightToLeft" Language="ar-SA">
              العملية الحسابية: "200.0+21.4=221.4"
            </Span>
         </Paragraph>
      </FlowDocument>
</Page>

Be aware that many languages have different xml:lang values depending on the targeted region, for example, "ar-SA" and "ar-EG" represent two variations of Arabic. The previous examples illustrate that you need to define both the xml:lang and FlowDirection values.

FlowDirection with Non-text Elements

FlowDirection defines not only how text flows in a textual element but also the flow direction of almost every other UI element. The following graphic shows a ToolBar that uses a horizontal LinearGradientBrush to draw its background.

Graphic That Shows a ToolBar with a Left to Right Gradient

Gradient screen shot

After setting the FlowDirection to RightToLeft, not only the ToolBar buttons are arranged from right to left, but even the LinearGradientBrush realigns its offsets to flow from right to left.

The following graphic shows the realignment of the LinearGradientBrush.

Graphic That Shows a ToolBar with a Right to Left Gradient

A gradient that flows from right to left

The following example draws a RightToLeftToolBar. (To draw it left to right, remove the FlowDirection attribute on the ToolBar.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

  <ToolBar FlowDirection="RightToLeft" Height="50" DockPanel.Dock="Top">
    <ToolBar.Background>
      <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,1">
        <LinearGradientBrush.GradientStops>
          <GradientStop Color="DarkRed" Offset="0" />
          <GradientStop Color="DarkBlue" Offset="0.3" />
          <GradientStop Color="LightBlue" Offset="0.6" />
          <GradientStop Color="White" Offset="1" />
        </LinearGradientBrush.GradientStops>
      </LinearGradientBrush>
    </ToolBar.Background>

    <Button FontSize="12" Foreground="White">Button1</Button>
    <Rectangle Width="20"/>
    <Button FontSize="12" Foreground="White">Button2</Button>
    <Rectangle Width="20"/>
    <Button FontSize="12" Foreground="White">Button3</Button>
    <Rectangle Width="20"/>
    <Button FontSize="12" Foreground="White">Button4</Button>
    <Rectangle Width="20"/>
  </ToolBar>
</Page>

FlowDirection Exceptions

There are a few cases where FlowDirection does not behave as expected. This section covers two of these exceptions.

Image

An Image represents a control that displays an image. In XAML it can be used with a Source property that defines the uniform resource identifier (URI) of the Image to display.

Unlike other UI elements, an Image does not inherit the FlowDirection from the container. However, if the FlowDirection is set explicitly toRightToLeft, an Image is displayed flipped horizontally. This is implemented as a convenient feature for developers of bidirectional content; because in some cases, horizontally flipping the image produces the desired effect.

The following graphic shows a flipped Image.

Graphic That Illustrates a Flipped Image

XamlPad screen shot

The following example demonstrates that the Image fails to inherit the FlowDirection from the StackPanel that contains it. Note   You must have a file named ms_logo.jpg on your C:\ drive to run this example.

<StackPanel 
  xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' 
  FlowDirection="RightToLeft">

  <Image Source="file://c:/ms_logo.jpg" 
         Width="147" Height="50"/>
  <Separator Height="10"/>
  <Image Source="file://c:/ms_logo.jpg" 
         Width="147" Height="50" FlowDirection="LeftToRight" />
  <Separator Height="10"/>
  <Image Source="file://c:/ms_logo.jpg" 
         Width="147" Height="50" FlowDirection="RightToLeft"/>
</StackPanel>

Note   Included in the download files is an ms_logo.jpg file. The code assumes that the .jpg file is not inside your project but somewhere on the C:\ drive. You must copy the .jpg from the project files to your C:\ drive or change the code to look for the file inside the project. To do this changeSource="file://c:/ms_logo.jpg" to Source="ms_logo.jpg".

Paths

In addition to an Image, another interesting element is Path. A Path is an object that can draw a series of connected lines and curves. It behaves in a manner similar to an Image regarding its FlowDirection; for example its RightToLeftFlowDirection is a horizontal mirror of its LeftToRight one. However, unlike an ImagePath inherits its FlowDirection from the container and one does not need to specify it explicitly.

The following example draws a simple arrow using 3 lines. The first arrow inherits the RightToLeft flow direction from the StackPanel so that its start and end points are measured from a root on the right side. The second arrow which has an explicit RightToLeftFlowDirection also starts on the right side. However, the third arrow has its starting root on the left side. For more information on drawing see LineGeometry andGeometryGroup.

<StackPanel 
  xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' 
  FlowDirection="RightToLeft">

  <Path Stroke="Blue" StrokeThickness="4">
    <Path.Data>
      <GeometryGroup >
        <LineGeometry StartPoint="300,10" EndPoint="350,30" />
        <LineGeometry StartPoint="10,30" EndPoint="352,30" />
        <LineGeometry StartPoint="300,50" EndPoint="350,30" />
      </GeometryGroup>
    </Path.Data>
  </Path>

  <Path Stroke="Red" StrokeThickness="4" FlowDirection="RightToLeft">
    <Path.Data>
      <GeometryGroup >
        <LineGeometry StartPoint="300,10" EndPoint="350,30" />
        <LineGeometry StartPoint="10,30" EndPoint="352,30" />
        <LineGeometry StartPoint="300,50" EndPoint="350,30" />
      </GeometryGroup>
    </Path.Data>
  </Path>

  <Path Stroke="Green" StrokeThickness="4" FlowDirection="LeftToRight">
    <Path.Data>
      <GeometryGroup >
        <LineGeometry StartPoint="300,10" EndPoint="350,30" />
        <LineGeometry StartPoint="10,30" EndPoint="352,30" />
        <LineGeometry StartPoint="300,50" EndPoint="350,30" />
      </GeometryGroup>
    </Path.Data>
  </Path>
</StackPanel>

The following graphic shows the output of the previous example.

Graphic That Illustrates Arrows Drawn Using the Path Element

Paths

The Image and Path are two examples of a how Windows Presentation Foundation (WPF) uses FlowDirection. Beside laying out UI elements in a specific direction within a container, FlowDirection can be used with elements such as InkPresenter which renders ink on a surface,LinearGradientBrushRadialGradientBrush. Whenever you need a right to left behavior for your content that mimics a left to right behavior, or vice versa, Windows Presentation Foundation (WPF) provides that capability.

Number Substitution

Historically, Windows has supported number substitution by allowing the representation of different cultural shapes for the same digits while keeping the internal storage of these digits unified among different locales, for example numbers are stored in their well known hexadecimal values, 0x40, 0x41, but displayed according to the selected language.

This has allowed applications to process numerical values without the need to convert them from one language to another, for example a user can open an Microsoft Excel spreadsheet in a localized Arabic Windows and see the numbers shaped in Arabic, but open it in a European version of Windows and see European representation of the same numbers. This is also necessary for other symbols such as comma separators and percentage symbol because they usually accompany numbers in the same document.

Windows Presentation Foundation (WPF) continues the same tradition, and adds further support for this feature that allows more user control over when and how substitution is used. While this feature is designed for any language, it is particularly useful in bidirectional content where shaping digits for a specific language is usually a challenge for application developers because of the various cultures an application might run on.

The core property controlling how number substitution works in Windows Presentation Foundation (WPF) is the Substitution dependency property. The NumberSubstitution class specifies how numbers in text are to be displayed. It has three public properties that define its behavior. Following is a summary of each of the properties.

CultureSource:

This property specifies how the culture for numbers is determined. It takes one of three NumberCultureSource enumeration values.

CultureOverride:

The CultureOverride property is used only if the CultureSource property is set to Override and is ignored otherwise. It specifies the number culture. A value of null, the default value, is interpreted as en-US.

Substitution:

This property specifies the type of number substitution to perform. It takes one of the following NumberSubstitutionMethod enumeration values.

  • AsCulture: The substitution method is determined based on the number culture's NumberFormatInfo.DigitSubstitution property. This is the default.

  • Context: If the number culture is an Arabic or Farsi culture, it specifies that the digits depend on the context.

  • European: Numbers are always rendered as European digits.

  • NativeNational: Numbers are rendered using the national digits for the number culture, as specified by the culture's NumberFormat.

  • Traditional: Numbers are rendered using the traditional digits for the number culture. For most cultures, this is the same as NativeNational. However, NativeNational results in Latin digits for some Arabic cultures, whereas this value results in Arabic digits for all Arabic cultures.

What do those values mean for a bidirectional content developer? In most cases, the developer might need only to define FlowDirection and the language of each textual UI element, for example Language="ar-SA" and the NumberSubstitution logic takes care of displaying the numbers according to the correct UI. The following example demonstrates using Arabic and English numbers in a Windows Presentation Foundation (WPF) application running in an Arabic version of Windows.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
  <StackPanel>
   <TextBlock Background="LightGreen" FontSize="32" 
      Language="ar-SA" FlowDirection="RightToLeft">1+2=3</TextBlock>
   <TextBox Background="LightGreen" FontSize="32" 
      Language="ar-SA" FlowDirection="RightToLeft">1+2=3</TextBox>
   <TextBlock Background="LightBlue" FontSize="32">1+2=3</TextBlock>
   <TextBox Background="LightBlue" FontSize="32">1+2=3</TextBox>
 </StackPanel>
</Page>

The following graphic shows the output of the previous sample if you are running in an Arabic version of Windows.

Graphic That Shows Arabic and English Numbers Displayed

XamlPad screen shot with numbers

The FlowDirection was important in this case because setting the FlowDirection to LeftToRight instead would have yielded European digits. The following sections discuss how to have a unified display of digits throughout your document. If this example is not running on Arabic Windows, all the digits display as European digits.

Defining Substitution Rules

In a real application you might need to set the Language programmatically. For example, you want to set the xml:lang attribute to be the same as the one used by the system’s UI, or maybe change the language depending on the application state.

If you want to make changes based on the application's state, make use of other features provided by Windows Presentation Foundation (WPF).

First, set the application component’s NumberSubstitution.CultureSource="Text". Using this setting makes sure that the settings do not come from the UI for text elements that have "User" as the default, such as TextBlock.

For example:

<TextBlock

Name="text1" NumberSubstitution.CultureSource="Text">

1234+5679=6913

</TextBlock>

In the corresponding C# code, set the Language property for example, to "ar-SA".

text1.Language =

System.Windows.Markup.XmlLanguage.GetLanguage("ar-SA");

If you need to set the Language property to the current user’s UI language use the following code.

text1.Language =

System.Windows.Markup.XmlLanguage.GetLanguage(

System.Globalization.CultureInfo.CurrentUICulture.IetfLanguageTag);

CurrentCulture represents the current culture used by the current thread at run time.

Your final XAML example should be similar to the following example.

<Page x:Class="WindowsApplication.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Code Sample" Height="300" Width="300"
>
    <StackPanel>
      <TextBlock Language="ar-SA" 
         FlowDirection="RightToLeft">عربى: 1+2=3
      </TextBlock>
      <TextBlock Language="ar-SA" 
         FlowDirection="RightToLeft" 
         NumberSubstitution.Substitution="European">عربى: 1+2=3 
      </TextBlock>
    </StackPanel>
</Page>

Your final C# example should be similar to the following.

namespace BidiTest
{
    public partial class Window1 : Window
    {

        public Window1()
        {
            InitializeComponent();

            string currentLanguage = 
                System.Globalization.CultureInfo.CurrentCulture.IetfLanguageTag;

            text1.Language = System.Windows.Markup.XmlLanguage.GetLanguage(currentLanguage);

            if (currentLanguage.ToLower().StartsWith("ar"))
            {
                text1.FlowDirection = FlowDirection.RightToLeft;
            }
            else
            {
                text1.FlowDirection = FlowDirection.LeftToRight;
            }
        }
    }
}

The following graphic shows what the window looks like for either programming language.

Graphic That Displays Arabic Numbers

Arabic numbers

Using the Substitution Property

The way number substitution works in Windows Presentation Foundation (WPF) depends on both the Language of the text element and itsFlowDirection. If the FlowDirection is left to right, then European digits are rendered. However if it is preceded by Arabic text, or has the language set to "ar" and the FlowDirection is RightToLeft, Arabic digits are rendered instead.

In some cases, however, you might want to create a unified application, for example European digits for all users. Or Arabic digits in Table cells with a specific Style. One easy way to do that is using the Substitution property.

In the following example, the first TextBlock does not have the Substitution property set, so the algorithm displays Arabic digits as expected. However in the second TextBlock, the substitution is set to European overriding the default substitution for Arabic numbers, and European digits are displayed.

<Page x:Class="WindowsApplication.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Code Sample" Height="300" Width="300"
>
    <StackPanel>
      <TextBlock Language="ar-SA" 
         FlowDirection="RightToLeft">عربى: 1+2=3
      </TextBlock>
      <TextBlock Language="ar-SA" 
         FlowDirection="RightToLeft" 
         NumberSubstitution.Substitution="European">عربى: 1+2=3 
      </TextBlock>
    </StackPanel>
</Page>




Globalization and Localization How-to Topics


How to: Localize an Application


This tutorial explains how to create a localized application by using the LocBaml tool.

System_CAPS_noteNote

The LocBaml tool is not a production-ready application. It is presented as a sample that uses some of the localization APIs and illustrates how you might write a localization tool.

Overview

This discussion gives you a step-by-step approach to localizing an application. First, you will prepare your application so that the text that will be translated can be extracted. After the text is translated, you will merge the translated text into a new copy of the original application.

Requirements

Over the course of this discussion, you will use Microsoft build engine (MSBuild), which is a compiler that runs from the command line.

Also, you will be instructed to use a project file. For instructions on how to use MSBuild and project files, see Building and Deploying WPF Applications.

All the examples in this discussion use en-US (English-US) as the culture. This enables you to work through the steps of the examples without installing a different language.

Create a Sample Application

In this step, you will prepare your application for localization. In the Windows Presentation Foundation (WPF) samples, a HelloApp sample is supplied that will be used for the code examples in this discussion. If you would like to use this sample, download the Extensible Application Markup Language (XAML) files from the LocBaml Tool Sample.

  1. Develop your application to the point where you want to start localization.

  2. Specify the development language in the project file so that MSBuild generates a main assembly and a satellite assembly (a file with the .resources.dll extension) to contain the neutral language resources. The project file in the HelloApp sample is HelloApp.csproj. In that file, you will find the development language identified as follows:

    <UICulture>en-US</UICulture>

  3. Add Uids to your XAML files. Uids are used to keep track of changes to files and to identify items that must be translated. To add Uids to your files, run updateuid on your project file: 

    msbuild /t:updateuid helloapp.csproj

    To verify that you have no missing or duplicate Uids, run checkuid:

    msbuild /t:checkuid helloapp.csproj

    After running updateuid, your files should contain Uids. For example, in the Pane1.xaml file of HelloApp, you should find the following:

    <StackPanel x:Uid="StackPanel_1">

      <TextBlock x:Uid="TextBlock_1">Hello World</TextBlock>

      <TextBlock x:Uid="TextBlock_2">Goodbye World</TextBlock>

    </StackPanel>

Create the Neutral Language Resources Satellite Assembly

After the application is configured to generate a neutral language resources satellite assembly, you build the application. This generates the main application assembly, as well as the neutral language resources satellite assembly that is required by LocBaml for localization. To build the application:

  1. Compile HelloApp to create a dynamic-link library (DLL):

    msbuild helloapp.csproj

  2. The newly created main application assembly, HelloApp.exe, is created in the following folder:

    C:\HelloApp\Bin\Debug\

  3. The newly created neutral language resources satellite assembly, HelloApp.resources.dll, is created in the following folder:

    C:\HelloApp\Bin\Debug\en-US\

Build the LocBaml Tool

  1. All the files necessary to build LocBaml are located in the WPF samples. Download the C# files from the LocBaml Tool Sample.

  2. From the command line, run the project file (locbaml.csproj) to build the tool:

    msbuild locbaml.csproj

  3. Go to the Bin\Release directory to find the newly created executable file (locbaml.exe). Example:C:\LocBaml\Bin\Release\locbaml.exe.

  4. The options that you can specify when you run LocBaml are as follows:

    • parse or -p: Parses Baml, resources, or DLL files to generate a .csv or .txt file.

    • generate or -g: Generates a localized binary file by using a translated file.

    • out or -o [ filedirectory: Output file name.

    • culture or -cul [ culture: Locale of output assemblies.

    • translation or -trans [ translation.csv: Translated or localized file.

    • asmpath or -asmpath: [ filedirectory: If your XAML code contains custom controls, you must supply the asmpath to the custom control assembly.

    • nologo: Displays no logo or copyright information.

    • verbose: Displays verbose mode information.

    System_CAPS_noteNote

    If you need a list of the options when you are running the tool, type LocBaml.exe and press ENTER.

Use LocBaml to Parse a File

Now that you have created the LocBaml tool, you are ready to use it to parse HelloApp.resources.dll to extract the text content that will be localized.

  1. Copy LocBaml.exe to your application's bin\debug folder, where the main application assembly was created.

  2. To parse the satellite assembly file and store the output as a .csv file, use the following command:

    LocBaml.exe /parse HelloApp.resources.dll /out:Hello.csv

    System_CAPS_noteNote

    If the input file, HelloApp.resources.dll, is not in the same directory as LocBaml.exe move one of the files so that both files are in the same directory.

  3. When you run LocBaml to parse files, the output consists of seven fields delimited by commas (.csv files) or tabs (.txt files). The following shows the parsed .csv file for the HelloApp.resources.dll:

    HelloApp.g.en-US.resources:window1.baml,Stack1:System.Windows.Controls.StackPanel.$Content,Ignore,FALSE, FALSE,,#Text1;#Text2;

    HelloApp.g.en-US.resources:window1.baml,Text1:System.Windows.Controls.TextBlock.$Content,None,TRUE, TRUE,,Hello World

    HelloApp.g.en-US.resources:window1.baml,Text2:System.Windows.Controls.TextBlock.$Content,None,TRUE, TRUE,,Goodbye World

    The seven fields are:

    1. BAML Name. The name of the BAML resource with respect to the source language satellite assembly.

    2. Resource Key. The localized resource identifier.

    3. Category. The value type. See Localization Attributes and Comments.

    4. Readability. Whether the value can be read by a localizer. See Localization Attributes and Comments.

    5. Modifiability. Whether the value can be modified by a localizer. See Localization Attributes and Comments.

    6. Comments. Additional description of the value to help determine how a value is localized. See Localization Attributes and Comments.

    7. Value. The text value to translate to the desired culture.

    The following table shows how these fields map to the delimited values of the .csv file:

    BAML name

    Resource key

    Category

    Readability

    Modifiability

    Comments

    Value

    HelloApp.g.en-US.resources:window1.baml

    Stack1:System.Windows.Controls.StackPanel.$Content

    Ignore

    FALSE

    FALSE

    #Text1;#Text2

    HelloApp.g.en-US.resources:window1.baml

    Text1:System.Windows.Controls.TextBlock.$Content

    None

    TRUE

    TRUE

    Hello World

    HelloApp.g.en-US.resources:window1.baml

    Text2:System.Windows.Controls.TextBlock.$Content

    None

    TRUE

    TRUE

    Goodbye World

    Notice that all the values for the Comments field contain no values; if a field doesn't have a value, it is empty. Also notice that the item in the first row is neither readable nor modifiable, and has "Ignore" as its Category value, all of which indicates that the value is not localizable.

  4. To facilitate discovery of localizable items in parsed files, particularly in large files, you can sort or filter the items by CategoryReadability, and Modifiability. For example, you can filter out unreadable and unmodifiable values.

Translate the Localizable Content

Use any tool that you have available to translate the extracted content. A good way to do this is to write the resources to a .csv file and view them in Microsoft Excel, making translation changes to the last column (value).

Use LocBaml to Generate a New .resources.dll File

The content that was identified by parsing HelloApp.resources.dll with LocBaml has been translated and must be merged back into the original application. Use the generate or -g option to generate a new .resources.dll file.

  1. Use the following syntax to generate a new HelloApp.resources.dll file. Mark the culture as en-US (/cul:en-US).

    LocBaml.exe /generate HelloApp.resources.dll /trans:Hello.csv /out:c:\ /cul:en-US

    System_CAPS_noteNote

    If the input file, Hello.csv, is not in the same directory as the executable, LocBaml.exe, move one of the files so that both files are in the same directory.

  2. Replace the old HelloApp.resources.dll file in the C:\HelloApp\Bin\Debug\en-US\HelloApp.resources.dll directory with your newly created HelloApp.resources.dll file.

  3. "Hello World" and "Goodbye World" should now be translated in your application.

  4. To translate to a different culture, use the culture of the language that you are translating to. The following example shows how to translate to French-Canadian:

    LocBaml.exe /generate HelloApp.resources.dll /trans:Hellofr-CA.csv /out:c:\ /cul:fr-CA

  5. In the same assembly as the main application assembly, create a new culture-specific folder to house the new satellite assembly. For French-Canadian, the folder would be fr-CA.

  6. Copy the generated satellite assembly to the new folder.

  7. To test the new satellite assembly, you need to change the culture under which your application will run. You can do this in one of two ways:

    • Change your operating system's regional settings ( Start | Control Panel | Regional and Language Options).

    • In your application, add the following code to App.xaml.cs:

      <Application
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          x:Class="SDKSample.App"
          x:Uid="Application_1"
          StartupUri="Window1.xaml">
      </Application>
      
      using System.Windows; // Application
      using System.Globalization; // CultureInfo
      using System.Threading; // Thread
      
      namespace SDKSample
      {
          public partial class App : Application
          {
              public App()
              {
                  // Change culture under which this application runs
                  CultureInfo ci = new CultureInfo("fr-CA");
                  Thread.CurrentThread.CurrentCulture = ci;
                  Thread.CurrentThread.CurrentUICulture = ci;
              }
          }
      }
      

Some Tips for Using LocBaml

  • All dependent assemblies that define custom controls must be copied into the local directory of LocBaml or installed into the GAC. This is necessary because the localization API must have access to the dependent assemblies when it reads the binary XAML (BAML).

  • If the main assembly is signed, the generated resource DLL must also be signed in order for it to be loaded.

  • The version of the localized resource DLL needs to be synchronized with the main assembly.

You should now have a basic understanding of how to use the LocBaml tool. You should be able to make a file that contains Uids. By using the LocBaml tool, you should be able to parse a file to extract the localizable content, and after the content is translated, you should be able to generate a .resources.dll file that merges the translated content. This topic does not include every possible detail, but you now have the knowledge necessary to use LocBaml for localizing your applications.




How to: Use Automatic Layout to Create a Button


This example describes how to use the automatic layout approach to create a button in a localizable application.

Localization of a user interface (UI) can be a time consuming process. Often localizers need to resize and reposition elements in addition to translating text. In the past each language that a UI was adapted for required adjustment. Now with the capabilities of Windows Presentation Foundation (WPF) you can design elements that reduce the need for adjustment. The approach to writing applications that can be more easily resized and repositioned is called automatic layout.

The following two Extensible Application Markup Language (XAML) examples create applications that instantiate a button; one with English text and one with Spanish text. Notice that the code is the same except for the text; the button adjusts to fit the text.

Example

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="ButtonLoc.Pane1"
    Name="myWindow"
    SizeToContent="WidthAndHeight"
    >

<DockPanel> 
    <Button FontSize="28" Height="50">My name is Hope.</Button>
</DockPanel>
</Window>
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="ButtonLoc.Pane1"
    Name="myWindow"
    SizeToContent="WidthAndHeight"
    >

 <DockPanel> 
    <Button FontSize="28" Height="50">Me llamo Esperanza.</Button>
  </DockPanel>
</Window>

The following graphic shows the output of the code samples.

The same button with text in different languages

Auto Resizable Button




How to: Use a Grid for Automatic Layout


This example describes how to use a grid in the automatic layout approach to creating a localizable application.

Localization of a user interface (UI) can be a time consuming process. Often localizers need to re-size and reposition elements in addition to translating text. In the past each language that a UI was adapted for required adjustment. Now with the capabilities of Windows Presentation Foundation (WPF) you can design elements that reduce the need for adjustment. The approach to writing applications that can be more easily re-sized and repositioned is called auto layout.

The following Extensible Application Markup Language (XAML) example demonstrates using a grid to position some buttons and text. Notice that the height and width of the cells are set to Auto; therefore the cell that contains the button with an image adjusts to fit the image. Because the Gridelement can adjust to its content it can be useful when taking the automatic layout approach to designing applications that can be localized.

Example

The following example shows how to use a grid.

<Grid Name="grid" ShowGridLines ="false">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>

<TextBlock Margin="10, 10, 5, 5" Grid.Column="0" Grid.Row="0" FontSize="24">Grid
</TextBlock>
<TextBlock Margin="10, 10, 5, 5" Grid.Column="0" Grid.Row="1" FontSize="12"  
    Grid.ColumnSpan="2">The following buttons and text are positioned using a Grid.
</TextBlock>  
<Button Margin="10, 10, 5, 5" Grid.Column="0" Grid.Row="2" Background="Pink" 
    BorderBrush="Black" BorderThickness="10">Button 1
</Button>
<TextBlock Margin="10, 10, 5, 5" Grid.Column="1" Grid.Row="2" FontSize="12" 
   VerticalAlignment="Center" TextWrapping="WrapWithOverflow">Sets the background 
   color.
</TextBlock>  
<Button Margin="10, 10, 5, 5" Grid.Column="0" Grid.Row="3" Foreground="Red">
   Button 2
</Button>
<TextBlock Margin="10, 10, 5, 5" Grid.Column="1" Grid.Row="3" FontSize="12" 
   VerticalAlignment="Center" TextWrapping="WrapWithOverflow">Sets the foreground 
   color.
</TextBlock>  
<Button Margin="10, 10, 5, 5" Grid.Column="0" Grid.Row="4">
   <Image Source="data\flower.jpg"></Image>
</Button>
<TextBlock Margin="10, 10, 5, 5" Grid.Column="1" Grid.Row="4" FontSize="12" 
   VerticalAlignment="Center" TextWrapping="WrapWithOverflow">Adds an image as 
   the button's content.
</TextBlock>
</Grid>

The following graphic shows the output of the code sample.

Grid example

Grid





How to: Use a ResourceDictionary to Manage Localizable String Resources


This example shows how to use a ResourceDictionary to package localizable string resources for Windows Presentation Foundation (WPF) applications.

To use a ResourceDictionary to manage localizable string resources

  1. Create a ResourceDictionary that contains the strings you would like to localize. The following code shows an example.

    <ResourceDictionary 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:system="clr-namespace:System;assembly=mscorlib">
    
      <!-- String resource that can be localized -->
      <system:String x:Key="localizedMessage">en-US Message</system:String>
    
    </ResourceDictionary>
    

    This code defines a string resource, localizedMessage, of type String, from the System namespace in mscorlib.dll.

  2. Add the ResourceDictionary to your application, using the following code.

    <Application.Resources>
      <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
          <ResourceDictionary Source="StringResources.xaml" />
        </ResourceDictionary.MergedDictionaries>
      </ResourceDictionary>
    </Application.Resources>
    
  3. Use the string resource from markup, using Extensible Application Markup Language (XAML) like the following.

    <!-- Declarative use of string resource from StringResources.xaml resource dictionary -->
    <TextBox DockPanel.Dock="Top" Text="{StaticResource localizedMessage}" />
    
  4. Use the string resource from code-behind, using code like the following.

    // Programmatic use of string resource from StringResources.xaml resource dictionary
    string localizedMessage = (string)Application.Current.FindResource("localizedMessage");
    MessageBox.Show(localizedMessage);
    
  5. Localize the application. For more information, see How to: Localize an Application.




How to: Use Resources in Localizable Applications


Localization means to adapt a UI to different cultures. To do this, text such as titles, captions, list box items and so forth have to be translated. To make translation easier the items to be translated are collected into resource files. See How to: Localize an Application for information on how to create a resource file for localization. To make a WPF application localizable, developers need to build all the localizable resources into a resource assembly. The resource assembly is localized into different languages, and the code-behind uses resource management API to load. One of the files required for a WPF application is a project file (.proj). All resources that you use in your application should be included in the project file. The following code example shows this.

Example

XAML

<Resource Include="data\picture1.jpg"/>

<EmbeddedResource Include="data\stringtable.en-US.restext"/>

To use a resource in your application, you instantiate ResourceManager and load the resource you want to use. The following demonstrates how to do this.

void OnClick(object sender, RoutedEventArgs e)
{
  ResourceManager rm = new ResourceManager ("MySampleApp.data.stringtable",
       Assembly.GetExecutingAssembly());
  Text1.Text = rm.GetString("Message");
}






'프로그래밍 > WPF' 카테고리의 다른 글

Migration and Interoperability  (0) 2016.11.05
Layout  (0) 2016.11.05
Documents  (0) 2016.11.05
Resources  (0) 2016.11.01
Events  (0) 2016.11.01
:
Posted by 지훈2