Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StringFormat Localization issues in wpf

// Ensure the current culture passed into bindings is the OS culture.
// By default, WPF uses en-US as the culture, regardless of the system settings.
FrameworkElement.LanguageProperty.OverrideMetadata(
      typeof(FrameworkElement),
      new FrameworkPropertyMetadata(
          XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));

From Creating an Internationalized Wizard in WPF


Define the following xml namespace:

xmlns:gl="clr-namespace:System.Globalization;assembly=mscorlib"

Now behold this fantastic fix:

<TextBlock Text="{Binding Path=Model.SelectedNoteBook.OriginalDate, StringFormat='f', ConverterCulture={x:Static gl:CultureInfo.CurrentCulture}" FontSize="20"TextTrimming="CharacterEllipsis" />

I'm well aware this isn't a global fix and you will require it on each of your Bindings but surely that is just good XAML? As far as I'm aware, the next time the binding updates it will use the correct CultureInfo.CurrentCulture or whatever you have supplied.

This solution will immediately update your Bindings with the correct values but it seems like a lot of code for something so rare and innocuous.


I just wanted to add that loraderon's answer works great in most cases. When I put the following line of code in my App.xaml.cs, the dates in my TextBlocks are formatted in the correct culture.

FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(System.Windows.Markup.XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));

I say 'most cases'.For example, this will work out of the box:

<TextBlock Text="{Binding Path=Date, StringFormat={}{0:d MMMM yyyy}}" />
--> "16 mei 2013" (this is in Dutch)

...but when using Run's in a TextBlock, the DateTime is formatted in the default culture.

<TextBlock>
  <Run Text="Datum: " />
  <Run Text="{Binding Path=Date, StringFormat={}{0:d MMMM yyyy}, Mode=OneWay}" />
</TextBlock>
--> "Datum: 16 may 2013" (this is in English, notice the
    name of the month "may" vs. "mei")

For this to work, I needed Gusdor's answer, namely adding ConverterCulture={x:Static gl:CultureInfo.CurrentCulture} to the Binding.

<TextBlock>
  <Run Text="Datum: " />
  <Run Text="{Binding Path=Date, StringFormat={}{0:d MMMM yyyy}, ConverterCulture={x:Static gl:CultureInfo.CurrentCulture}, Mode=OneWay}" />
</TextBlock>
--> "Datum: 16 mei 2013" (=Dutch)

I hope this additional answer will be of use to someone.


Just insert the culture shortcut to the top-level tag:

xml:lang="de-DE"

e.g.:

<Window x:Class="MyApp"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xml:lang="de-DE"
    Title="MyApp" Height="309" Width="497" Loaded="Window_Loaded">....</Window>

As already stated, XAML defaults to the invariant culture (en-US), and you can use

FrameworkElement.LanguageProperty.OverrideMetadata(
  typeof(FrameworkElement),
  new FrameworkPropertyMetadata(
      XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));

to set the culture to the default culture for the language of the current culture. But the comment is wrong; this does not use the current culture, as you will not see any customizations the user might have made, it will always be the default for the language.

To actually use the current culture with customizations, you will need to set the ConverterCulture together with the StringFormat, as in

Text="{Binding Day, StringFormat='d', ConverterCulture={x:Static gl:CultureInfo.CurrentCulture}}"

with the gldefined as a global namespace in your root element

xmlns:gl="clr-namespace:System.Globalization;assembly=mscorlib"