Click here to Skip to main content
15,896,063 members
Articles / Desktop Programming / WPF

Advanced WPF Localization

Rate me:
Please Sign up or sign in to vote.
4.85/5 (27 votes)
1 Oct 2017Public Domain6 min read 275.2K   7.1K   74  
Provides a solution for localization of WPF application both in XAML and in code-behind
<Window x:Class="Demo.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:resources="clr-namespace:Demo.Properties;assembly=Demo"
    xmlns:res="clr-namespace:Demo.Properties"
    xmlns:controls="clr-namespace:Demo.Controls"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    Title="Window1" Width="640" ResizeMode="NoResize" Loaded="Window_Loaded" SnapsToDevicePixels="True" Closing="Window_Closing" WindowStartupLocation="CenterScreen" SizeToContent="Height">
    <Window.Resources>
        <Style TargetType="TextBlock" x:Key="Label">
            <Setter Property="Margin" Value="5"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="HorizontalAlignment" Value="Left"/>
        </Style>
        <Style TargetType="FrameworkElement" x:Key="Field">
            <Setter Property="Margin" Value="5"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="HorizontalAlignment" Value="Left"/>
        </Style>
        <LocalizationCallbackReference x:Key="Callback" Callback="Callback"/>
        <LocalizationCallbackReference x:Key="Multilingual_Callback" Callback="Multilingual_Callback"/>
    </Window.Resources>
    <Grid Margin="10">
        <StackPanel HorizontalAlignment="Right" VerticalAlignment="Top" Orientation="Horizontal">
            <TextBlock Text="{Loc Label_Language}" Style="{StaticResource Label}"/>
            <ComboBox Name="comboBoxLanguage" SelectionChanged="comboBoxLanguage_SelectionChanged" Width="100" Margin="5">
                <ComboBoxItem Content="English (US)" Tag="en-US" IsSelected="True"/>
                <ComboBoxItem Content="Française" Tag="fr-FR"/>
                <ComboBoxItem Content="Български" Tag="bg-BG"/>
            </ComboBox>
        </StackPanel>
        <StackPanel VerticalAlignment="Top">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Row="0" Grid.Column="0" Text="{Loc Label_SelectedLanguage}" Style="{StaticResource Label}"/>
                <TextBlock Grid.Row="0" Grid.Column="1" Text="{Loc LanguageName}" Style="{StaticResource Field}"/>
                <TextBlock Grid.Row="1" Grid.Column="0" Text="{Loc Label_Flag}" Style="{StaticResource Label}"/>
                <Border Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" BorderBrush="Gray" BorderThickness="1" Style="{StaticResource Field}">
                    <Image Source="{Loc Image_Flag}" Stretch="None"/>
                </Border>
            </Grid>
            <GroupBox Margin="0,10,0,0">
                <GroupBox.Header>
                    <TextBlock Text="{Loc Title_CodeBehind}" FontWeight="Bold"/>
                </GroupBox.Header>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Row="0" Grid.Column="0" Text="{Loc Label_CodeBehind_Callback}" Style="{StaticResource Label}"/>
                    <TextBlock Grid.Row="1" Grid.Column="0" Text="{Loc Label_CodeBehind_Resource}" Style="{StaticResource Label}"/>
                    <TextBlock Grid.Row="2" Grid.Column="0" Text="{Loc Label_CodeBehind_Format}" Style="{StaticResource Label}"/>
                    <TextBlock Grid.Row="3" Grid.Column="0" Text="{Loc Label_CodeBehind_ResourceFormat}" Style="{StaticResource Label}"/>
                    <TextBlock Grid.Row="0" Grid.Column="1" Text="{Loc Callback={StaticResource Callback}}" Style="{StaticResource Field}"/>
                    <TextBlock Grid.Row="1" Grid.Column="1" Name="labelCodeBehind_Resource" Style="{StaticResource Field}"/>
                    <TextBlock Grid.Row="2" Grid.Column="1" Name="labelCodeBehind_Format" Style="{StaticResource Field}"/>
                    <TextBlock Grid.Row="3" Grid.Column="1" Name="labelCodeBehind_ResourceFormat" Style="{StaticResource Field}"/>
                </Grid>
            </GroupBox>
            <GroupBox Margin="0,10,0,0">
                <GroupBox.Header>
                    <TextBlock Text="{Loc Title_ResourceFiles}" FontWeight="Bold"/>
                </GroupBox.Header>
                <StackPanel>
                    <Grid LocalizationScope.ResourceManager="{ResourceManager res:LocalResources}">
                        <TextBlock Text="{Loc Title}" TextWrapping="Wrap"/>
                    </Grid>
                    <Grid LocalizationScope.ResourceManager="{ResourceManager AssemblyName=Demo, BaseName=Demo.Properties.LocalResourcesByName}" Margin="0,10,0,0">
                        <TextBlock Text="{Loc Explanation}" TextWrapping="Wrap"/>
                    </Grid>
                </StackPanel>
            </GroupBox>
            <GroupBox Margin="0,10,0,0">
                <GroupBox.Header>
                    <TextBlock Text="{Loc Title_Templates}" FontWeight="Bold"/>
                </GroupBox.Header>
                <StackPanel>
                    <StackPanel.Resources>
                        <Style TargetType="Label" x:Key="ComplexTemplate">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="Label">
                                        <TextBlock Text="{Loc Text_ComplexTemplate}" />
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </StackPanel.Resources>
                    <controls:TestControl StringContent="{Loc Text_NonDependencyProperty}"/>
                    <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                        <ListBox Width="200">
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Loc Text_SimpleTemplate}" />
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                            <ListItem />
                            <ListItem />
                        </ListBox>
                        <ListBox Width="200" Margin="20,0,0,0">
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <Label Style="{StaticResource ComplexTemplate}" />
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                            <ListItem />
                            <ListItem />
                        </ListBox>
                    </StackPanel>
                </StackPanel>
            </GroupBox>
            <GroupBox Margin="0,10,0,0">
                <GroupBox.Header>
                    <TextBlock Text="{Loc Title_Bindings}" FontWeight="Bold"/>
                </GroupBox.Header>
                <StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBox Name="textBoxBindings_Data" Width="150" Text="Enter text here"/>
                        <TextBlock Style="{StaticResource Field}" Width="250">
                            <TextBlock.Text>
                                <LocBinding ResourceKey="Textl_Bindings_FormattedData">
                                    <Binding ElementName="textBoxBindings_Data" Path="Text"/>
                                </LocBinding>
                            </TextBlock.Text>
                        </TextBlock>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Loc Label_Bindings_Date}" Style="{StaticResource Label}"/>
                        <TextBlock Style="{StaticResource Field}">
                            <TextBlock.Text>
                                <!-- This demonstrates that dates and numbers are formatted according to the selected language -->
                                <LocBinding StringFormat="{}{0:d} | {1:C}">
                                    <Binding Source="{x:Static sys:DateTime.Now}" Path="."/>
                                    <Binding Path=".">
                                        <Binding.Source>
                                            <sys:Int32>1000000</sys:Int32>
                                        </Binding.Source>
                                    </Binding>
                                </LocBinding>
                            </TextBlock.Text>
                        </TextBlock>
                    </StackPanel>
                </StackPanel>
            </GroupBox>
            <GroupBox Margin="0,10,0,0" Name="panelMultilingual">
                <GroupBox.Header>
                    <TextBlock Text="{Loc Title_Multilingual}" FontWeight="Bold"/>
                </GroupBox.Header>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Row="0" Grid.Column="0" Text="{Loc Label_Multilingual_Language}" Style="{StaticResource Label}"/>
                    <ComboBox Grid.Row="0" Grid.Column="1" Name="comboBoxMultilingual_Language" SelectionChanged="comboBoxMultilingual_Language_SelectionChanged" Width="100" Style="{StaticResource Field}">
                        <ComboBoxItem Content="Parent" Tag="" IsSelected="True"/>
                        <ComboBoxItem Content="English (US)" Tag="en-US"/>
                        <ComboBoxItem Content="Française" Tag="fr-FR"/>
                        <ComboBoxItem Content="Български" Tag="bg-BG"/>
                    </ComboBox>
                    <TextBlock Grid.Row="2" Grid.Column="0" Text="{Loc Label_CodeBehind_Callback}" Style="{StaticResource Label}"/>
                    <TextBlock Grid.Row="3" Grid.Column="0" Text="{Loc Label_CodeBehind_Resource}" Style="{StaticResource Label}"/>
                    <TextBlock Grid.Row="4" Grid.Column="0" Text="{Loc Label_CodeBehind_Format}" Style="{StaticResource Label}"/>
                    <TextBlock Grid.Row="5" Grid.Column="0" Text="{Loc Label_CodeBehind_ResourceFormat}" Style="{StaticResource Label}"/>
                    <TextBlock Grid.Row="2" Grid.Column="1" Text="{Loc Callback={StaticResource Multilingual_Callback}}" Style="{StaticResource Field}"/>
                    <TextBlock Grid.Row="3" Grid.Column="1" Name="labelMultilingual_CodeBehind_Resource" Style="{StaticResource Field}"/>
                    <TextBlock Grid.Row="4" Grid.Column="1" Name="labelMultilingual_CodeBehind_Format" Style="{StaticResource Field}"/>
                    <TextBlock Grid.Row="5" Grid.Column="1" Name="labelMultilingual_CodeBehind_ResourceFormat" Style="{StaticResource Field}"/>
                </Grid>
            </GroupBox>
            <GroupBox Margin="0,10,0,0">
                <GroupBox.Header>
                    <TextBlock Text="{Loc Title_Multithreading}" FontWeight="Bold"/>
                </GroupBox.Header>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Row="0" Grid.Column="0" Text="{Loc Label_Multithreading_NonUIThread}" Style="{StaticResource Label}"/>
                    <TextBlock Grid.Row="0" Grid.Column="1" Name="labelMultithreading_CurrentTime" Style="{StaticResource Field}"/>
                </Grid>
            </GroupBox>
            <GroupBox Margin="0,10,0,0">
                <GroupBox.Header>
                    <TextBlock Text="{Loc Title_Style}" FontWeight="Bold"/>
                </GroupBox.Header>
                <Grid>
                    <TextBlock 
                        Text="{Loc Text_StyleMessage}" 
                        Style="{StaticResource Label}" 
                        Foreground="{Loc Brush_Style_Foreground}"
                        FontSize="{Loc Font_Style_Size}"
                        FontFamily="{Loc Font_Style_Family}"
                        FontStyle="{Loc Font_Style_Style}"
                        Margin="{Loc Margin_Style}"
                        />
                </Grid>
            </GroupBox>
        </StackPanel>
    </Grid>
</Window>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication


Written By
Software Developer (Senior)
Bulgaria Bulgaria
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions