Skip to content

Basic localization

Jecho Jekov edited this page Nov 26, 2017 · 9 revisions

Text & images

The simplest form of localization is to be automatically update text/images/size/colors/fonts/etc. when the culture changes. To do that simply add text and images to the default resource file of the project created by Visual Studio:

  • Solution Explorer - Project -> Properties -> Resources
  • OR open Properties/Resources.resx (C#), My Project/Resources.resx (VB.NET)

and then refer to the resource key in XAML. For example:

<Window ...>
  ...
  <TextBlock Text="{Loc Text_HelloWorld}"/>
  ...
  <Image Source="{Loc Image_CapitalPhoto}"/>
  ...
  <Image Source="{Loc Icon_NationalFlag}"/>
</Window>

In the example above Text_HelloWorld, Image_CapitalPhoto and Icon_NationalFlag are resource names.

The Loc extension automatically loads the resource (e.g. text or image) from the resource file and sets the value of the property. It also automatically updates the value whenever the culture changes (see Setting the current culture).

The Loc extension supports localization of both dependency and non-dependency properties of any dependency object.

Missing resources

If the specified resource name is not found in the resource file then the extension displays [Resource name] instead of the text value. For other data types (e.g. images) the extension sets the property to its default value (DependencyProperty.DefaultMetadata.DefaultValue is used for dependency properties and the type's default value for non-dependency properties).

Data types

The Loc extension automatically inspects the type of the property and converts the resource value if necessary. Text, images, icons, fonts, brushes, numbers, enums, margins, padding, etc. are supported out of the box as well as any type for which there is a TypeConverter. For other types it is possible to specify an IValueConverter or alternatively create and register a TypeConverter.

<controls:MyControl CustomProperty="{Loc SomeResource, Converter={...}}"/>
TypeDescriptor.AddAttributes(typeof(CustomType), new TypeConverterAttribute(typeof(CustomTypeConverter)));

Bindings

Localizing a binding is as trivial as specifying the binding in the extension:

<TextBlock Text="{Loc Text_HelloUser, Binding={Binding UserName}}"/>

In the example above the extension uses the Text_HelloUser resource value to format the binding's value in the same way Binding.StringFormat works. For example, if Text_HelloUser="Hello {0}!" and UserName="John" the result will be "Hello John!".

Multi-bindings are supported as well. For example,

  <TextBlock>
    <TextBlock.Text>
      <Loc Key="Text_HelloPersonalName">
        <Binding Path="FirstName"/>
        <Binding Path="LastName"/>
      </Loc>
    </TextBlock.Text>
  </TextBlock>

If Text_HelloPersonalName="Hello {0} {1}!", FirstName="John", LastName="Smith" then the result will be "Hello John Smith!".

It is also possible to simply format a date or a number without any localized text. For example,

<TextBlock Text="{Loc Binding={Binding TimeLastChange}}"/>
<TextBlock Text="{Loc StringFormat='{}{0:d}', Binding={Binding BirthDate}}"/>

The formatting of the value will be updated automatically whenever the culture changes.

CAUTION Bindings are supported for dependency properties only - same as in WPF.

Setting the current culture

The extension uses Thread.CurrentUICulture when loading resources and Thread.CurrentCulture when formatting dates and numbers.

It is possible to change the culture in two ways:

  • Set LocalizationManager.CurrentUICulture and/or LocalizationManager.CurrentCulture. In this case all localized properties will be updated automatically.
  • Set Thread.CurrentUICulture and/or Thread.CurrentCulture and then call LocalizationManager.RefreshValues() to update the localized values.

Unless there is a specific reason for setting Thread.CurrentUICulture / Thread.CurrentCulture directly it is recommended to use LocalizationManager.CurrentUICulture / LocalizationManager.CurrentCulture for simplicity.

LocalizationManager.CurrentUICulture = CultureInfo.GetCulture("en-US");

Binding to culture properties in XAML

It is possible to bind to the CurrentUICulture and the CurrentCulture properties directly in XAML. To do this simply use the LocalizationManager.Cultures property:

<ComboBox ... IsReadOnly="True" DisplayMemberPath="NativeName" SelectedValue="{Binding Path=CurrentCulture, Source={x:Static LocalizationManager.Cultures}}">
  <CultureInfo Name="en-US"/>
  <CultureInfo Name="fr-FR"/>
  <CultureInfo Name="ru-Ru"/>
  <CultureInfo Name="bg-BG"/>
</ComboBox>

The CultureInfo extension (CultureInfoExtension type) can be used to obtain a reference to a CultureInfo instance in XAML (e.g. {CultureInfo en-US} or <CultureInfo Name="en-US"/>).

*CultureChanged events

The LocalizationManager.CurrentUICultureChanged and the LocalizationManager.CurrentCultureChanged events can be used in code-behind to get a notification when the culture changes. Note that events are raised only when the culture is set by using the LocalizationManager properties.

LocalizationManager.CurrentUICulture += ...;

CAUTION LocalizationManager keeps strong references to event handlers. Therefore, if a window or a user control subscribe to an event it should unsubscribe from it before the it is closed/disposed in order to avoid memory leaks.

Next: Advanced localization

Clone this wiki locally