#1,115 – Internationalization I – Obey CurrentCulture for Output

The first step in internationalizing an application is to ensure that your application honors the user’s current regional settings, as reflected by the CurrentCulture property of the application’s main thread.

Current culture impacts the display of the following:

  • Numeric data
  • Date/time values
  • Currency values

All of these values are typically stored internally as numeric (e.g. double, int) or DateTime values.  These values exist in memory in a culture-agnostic form.  You only need to worry about regional settings when you display a value to the user.

In .NET, if you use the ToString method on a numeric or date/time object, with or without formatting strings, the resulting string will correctly reflect the current regional settings.

If you’re using data binding to convert numeric or date/time data to strings, you need to manually set the Language property on each window or page to force data binding to use the culture correctly.

Advertisements

#765 – WPF Data Binding Ignores CurrentCulture

Using the ToString method on numeric and date-based types from within your code, the output will reflect the current culture, as stored in the CurrentCulture property of the current thread.

When the data binding mechanism in WPF converts numeric or date-based data to a string, however, it doesn’t automatically use the current culture.  Instead, you must set the Language property of the FrameworkElement where the binding is occurring.  You typically set this property based on the CurrentCulture property of the current thread.  You can set the Language property of the topmost user-interface element, so that all of the other elements inherit the value.

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;

            this.Language = XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag);
        }

We can now do binding as follows (where BoundDate property is of type DateTime):

        <TextBlock Text="{Binding BoundDate, StringFormat=d}"/>

Now if we run with the region set to French (France), we see:
765-001

#764 – Current Culture Is Used When Converting Data to A String

The CurrentCulture property of a Thread object indicates a user’s current locale, as set in the Region applet.  This value can normally be thought of as indicating the user’s location.

If you convert either numeric or date data to a string, the formatting used will depend on the current locale, as set in the Region applet and reported by the CurrentCulture property.

For example:

            double d1 = 123.456;
            DateTime date1 = DateTime.Now;

            string output = string.Format("123.456 => {0}\nNow => {1}",
                d1.ToString(),
                date1.ToString());

            MessageBox.Show(output);

If we run this code when our region is set to English (United States), we get:

764-001

But now if we switch our region to French (France) and re-run the application, we get:

764-002

Notice that the decimal point is now displayed as a comma (,) and the date format is dd/mm, rather than mm/dd.

#763 – The Difference Between CurrentCulture and CurrentUICulture

In a WPF application, you have access to two properties that give you information about the user’s culture and language.  They are both properties of a Thread object, which you can access via Thread.CurrentThread.

  • CurrentCulture – Tells you the user’s current locale, as set in the Region applet.  I.e.: Where is the user located?
  • CurrentUICulture – Tells you the native language of the version of Windows that is installed.  I.e.: What language does the user speak?

The user can change CurrentCulture using the Region applet.  It’s used to determine formatting for numeric and date/time strings.

763-001

The user normally can’t change CurrentUICulture without re-installing Windows.  It’s used to know what language to use when displaying text in your application.  (I.e. Which resource files to load).

            CultureInfo ci = Thread.CurrentThread.CurrentCulture;
            lblCurrentCulture.Content = string.Format("CurrentCulture = {0} - {1}", ci.Name, ci.DisplayName);

            ci = Thread.CurrentThread.CurrentUICulture;
            lblCurrentUICulture.Content = string.Format("CurrentUICulture = {0} - {1}", ci.Name, ci.DisplayName);

For example, someone in England might see:
763-002