Tuesday, August 10, 2010

WPF Localization - Using RESX

English has become a global language. People communicate using this language if they are in different parts of the world. The problem is that it has not yet become the only language of the world. There are many languages spoken in the nooks and corners of the world. People like to communicate, read poetry and do many other wonderful things because they can't or don't want to use a foreign language. As engineers, we still need to get scientific solutions to them. To consider this need softwares are localized for different cultures and sub-cultures. WPF also supports that. In this discussion, we will be discussing how we can use RESX files to localize our applications.

Let's create three resource files (*.resx) as follows:

1. WindowStaticText.resx (Culture Neutral)
2. WindowStaticText.es-ES.resx (Spanish - es-ES)
3. WindowStaticText.ur-PK.resx (Urdu - ur-PK)

Basically the .net framework will use any of the resource file by comparing the culture between the name of resource file and the culture of current UI thread. If no culture is matched, it would use the culture neutral file (WindowStaticText.resx in this case). I have used google/translate to translate the text in these languages.

http://translate.google.com/

I create two resource strings in all these resource files as follows:

Culture Neutral:



Spanish - es-ES


Urdu - ur-PK



Urdu is written from Right To Left unlike English and Spanish. If you could understand the language then you could realize that the letters are flowing from left to right in the resource file. But there is no need to worry because the runtime would load them just fine in the application (Right to Left).

UI Culture:
The application should be reading the culture information seamlessly from regional settings of the machine. We can also change the culture of UIThread as follows:
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("es-ES");
If you are planning to change the culture through code then you must realize that for reading each item from the resource file, the runtime makes culture check to decide about source resource file (resx). So if you have to get a few items from the resource file and you set culture information after some items are already loaded then the runtime would not go back and update the already loaded information and would apply the new culture (and hence use the new culture specific resource file) only for the items loaded afterwards. In this example, similarly, since we are setting the contents of labels in XAML, we need to set the UI culture before initializeComponent() of the Window gets called.

WPF Window using RESX file:

<Window x:Class="WPFLocalization.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFLocalization"
Title="Window1" Height="300" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="42*" />
<RowDefinition Height="220*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="88*" />
<ColumnDefinition Width="190*" />
</Grid.ColumnDefinitions>
<Label Margin="12,12,3,5" Name="label1" Content="{x:Static local:WindowStaticText.NameLabel}" Grid.Row="0" Grid.Column="0"/>
<TextBox Margin="4,12,8,5" Name="textBox1" Grid.Column="1" />
<Label Height="24" Margin="5,1,0,0" Name="label2"
VerticalAlignment="Top" Content="{x:Static local:WindowStaticText.FatherNameLabel}" Grid.Row="1" />
<TextBox Grid.Column="1" Grid.Row="1" Height="22" Margin="4,3,8,0" Name="textBox2" VerticalAlignment="Top" />
</Grid>
</Window>

When you run the application, it should appear as follows:

Urdu (ur-PK)


Spanish (es-ES)


Neutral:


The world is not a very simple place to live. We are used to writing languages from left to right. There are languages which are written from right to left, there are others which are written from top to bottom. We can check if any language is written from right to left by checking IsRightToLeft property of TextInfo available in CurrentUICulture. We can use it define flow direction of window.


if (Thread.CurrentThread.CurrentUICulture.TextInfo.IsRightToLeft == true)
{
this.FlowDirection = System.Windows.FlowDirection.RightToLeft;
}




Note:
If you want to learn more about how .net framework package and deploy resources, you can read the following msdn article. This discusses how .net framework uses hub and spoke model for resources.

http://msdn.microsoft.com/en-us/library/sb6a8618%28v=VS.71%29.aspx

1 comment:

Anonymous said...

Unfortunately, MSFT doesn't make it easy to translate ".resx" files. I just released a new program that does (shameless plug): http://www.hexadigm.com.