Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Silverlight and Application Globalization – The Converter Approach

0.00/5 (No votes)
3 Sep 2009 1  
Silverlight and Application Globalization – The Converter approach

Introduction

It is often required to customize a software application to support multiple cultures and regions. This helps clients in different geographical locations use the same application, but with some information customized to support that culture or region. A date, for example, may be displayed very differently in different regions or countries. In this article, we will explore some possibilities to globalize parts of our Silverlight application using converters.

Regional Settings - Where and Why?

Language, Date and Number formatting depend on how we have configured our Operating System. Generally, in Windows, this setting can be achieved by going to Control Panel Settings and then choosing Regional and Language Options. Any user can change the regional settings (provided the network administrators allow them to do so) to suit their own needs.

So, now, what happens, when your application is downloaded and run in two different countries? A German user may like to view Dates and Numbers (by numbers I mean any numerical amount displayed in the application) type properties very differently from a French user.

Converter Approach

To do this, a simple approach would be to design your application in such a way that every Date (or Number) field is passed through a method that formats this Date (or Number) to that system’s locale (basically what you set in the Control Panel). A simpler (oh well – a neater) approach from a Silverlight point of view is to design your XAML in such a way that when we are doing the binding for any Date and Number property, we also pass this value through a converter. This converter is responsible for localizing our attribute to the particular system locale.

Let us quickly look at some code, after which I shall discuss some interesting issues I faced with this implementation.

In my example, I bind a text block to the current date and time. This displays the original value. I then bind another text block to the same attribute that was used for the earlier text block. This time, however, I pass this value through a converter (in my sample, called the DateConverter). This converter gets the current system culture, and then displays the ‘converted’ value in the text block. There are four command buttons that change the culture of the current thread by using locale codes (like en-US, de-DE) that the operating system understands.

This is what the XAML looks like:

<TextBlock Text="Date" Grid.Row="1" Grid.Column="0" FontWeight="Bold"/>
<TextBlock x:Name="CurrentDate" Text="{Binding Path=DateText}" Grid.Row="1" 
Grid.Column="1" HorizontalAlignment="Left"/>
<TextBlock Text="Converted Date" Grid.Row="1" Grid.Column="2" FontWeight="Bold"/>
<TextBlock x:Name="ParsedDate" Text="{Binding DateText,
Converter={StaticResource DateConverter}}" Grid.Row="1" Grid.Column="3"/>
<Button x:Name="French" Content="French" Grid.Row="2" Grid.Column="0" 
Height="25" Width="120" HorizontalAlignment="Left" Click="French_Click"/>
<Button x:Name="German" Content="German" Grid.Row="2" Grid.Column="1" 
Height="25" Width="120" HorizontalAlignment="Left" Click="German_Click"/>
<Button x:Name="EnglishUS" Content="English - US" Grid.Row="2" Grid.Column="2" 
Height="25" Width="120" HorizontalAlignment="Left" Click="EnglishUS_Click"/>
<Button x:Name="EnglishUK" Content="English - UK" Grid.Row="2" Grid.Column="3" 
Height="25" Width="120" HorizontalAlignment="Left" Click="EnglishUK_Click"/>

This is what the display looks like in the browser: 

The buttons are only used to simulate what we would do from the control panel's regional settings screen.

//This is to be done by changing regional system settings.
//But for the sample here, a command click makes this change.
private void EnglishUK_Click(object sender, System.Windows.RoutedEventArgs e) {
    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");
    LoadDate();
}

private void EnglishUS_Click(object sender, System.Windows.RoutedEventArgs e) {
    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
    LoadDate();
}

private void German_Click(object sender, System.Windows.RoutedEventArgs e) {
    Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
    LoadDate();
}

private void French_Click(object sender, System.Windows.RoutedEventArgs e) {
    Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
    LoadDate();
}

This is what the convert method in the converter looks like:

public object Convert(object value,
    Type targetType,
    object parameter,
    System.Globalization.CultureInfo culture) {
        DateTime date;
        culture = System.Globalization.CultureInfo.CurrentCulture;
        if (value != null && DateTime.TryParse(value.ToString(), out date)) {
            string strDate = string.Empty;
            strDate = date.ToString(culture.DateTimeFormat.ShortDatePattern.ToString());
            return strDate;
        }
        else {
            return string.Empty;}
        }
}

We have an if–else condition to make sure that the value passed into the converter is actually a DateTime value, or else we would get some nasty errors. Next, we need to note the date format type we are using i.e. we need to know whether we are going to show the short or long date format in our application. In this example, I've used the short date format. But, the parameter object provided in the Converter’s constructor can easily be used to make this more customizable. The DateTime’s ToString() does the core of the conversion work for us.

Let me also quickly discuss how the date approach can be used for numbers, First I would convert the number to a decimal (an integer could have been passed into the converter), and then format that decimal using a decimal’s ToString() method and the culture. This is what my converter code would look like:

Decimal decNumber = System.Convert.ToDecimal(value);
strNum = decNumber.ToString("N", culture);

Here again, the Converter parameter object provides further customization opportunities to pass in some additional formatting values, like additional instructions to round values to the nearest decimal, etc.

Currency converters could also be created using similar principles.

Implementation Issues With This Approach

Right, let us now look at some potential issues that could arise from such implementations.

First, if you look at the DateConverter above, you will see an additional line of code that sets the local culture variable to the CultureInfo.CurrentCulture. Why is this required? Well, the user could potentially (and I use the word potentially) change the regional settings after the application is launched. For some reason, the culture parameter in the converter does not get updated when a regional setting changes after the application is running. We then need to force the date to be converted to the new culture by using this approach. My guess to why the culture does not get updated in the converter once the application is running is that the converter is loaded into the memory just once and then not really updated when the culture changes (after all a converter is shared by the entire Silverlight application, so why load it in memory again and again?). I have not found any formal documentation that states this, so this is just pure guess work.

Another issue with this implementation is what if you need to pass the bound value through another converter for some other processing (let's call this new converter SomeOtherConverter). Well, in this case, you can create an instance of your DateConverter in SomeOtherConverter and then pass your date into it. At least, this keeps your globalization / localization processing in one place, making maintainability easier.

Whenever we pass a date or number through these locale converters, we must remember that these values lose their original type. A DateTime or a Decimal value is converted to a String. This does not help if you want to plot a graph of “Loan Amount” versus say, “name of the client” in your application, and you want to display your “Loan Amount” in the current locale. The graph control may need actual numbers as “Loan Amounts” and converting those values to string before plotting may throw errors when the graph is finally constructed.

Can this approach be used for language globalization? Well, theoretically, for a small application, you could. Imagine your XAML has a lot of “hard-coded” captions displayed in text blocks or list boxes or some other control. Instead of hard coding, we could bind to the language converter and return the locale language equivalent using the culture. The name of the control can be sent to the converter using the converter parameter, just to allow us to keep a single language converter. However, as you've guessed by now, this may not be a good approach. We should probably stick to resource files to support multiple languages in Silverlight.

This article explored ways to use a Silverlight Converter to provide locale support for dates and numbers. Additionally, some implementation issues were discussed here.

History

  • Initial revision - 3rd September 2009

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here