poniedziałek, 13 czerwca 2011

70-511: Enhancing Usability: Implementacja „Globalizacji” i „Lokalizacji” (praktyka, kod + LocBaml) [PL]

W ramach kontynuacji tematu rozpoczętego we wpisie „70-511: Enhancing Usability: Implementacja „Globalizacji” i „Lokalizacji” (teoria)”, zapraszam do zapoznania się z przykładem kodu źródłowego, który będzie ilustracją do przedstawionej teorii (przykład kodu źródłowego dotyczy implementacji „globalizacji” i „lokalizacji”, ze szczególnym naciskiem na to, jak jest to rozwiązane w lokalizacji dla WPF). W ramach przykładu zostanie pokazane wykorzystanie narzędzia LocBaml.
W przykładzie tym lokalizowane jest proste okno aplikacji WPF. W oknie znajdują się dwie etykiety z napisami i dwa przyciski zmieniające lokalizację:
<Window x:Class="SampleApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBlock x:Uid="loc1">Hello World</TextBlock>
        <TextBlock x:Uid="loc2">Goodbye World</TextBlock>
        <Button x:Uid="but_PL" Content="PL" Height="23" Name="button_pl" Width="75" Click="button_pl_Click" />
        <Button x:Uid="but_EN" Content="EN" Height="23" Name="button_en" Width="75" Click="button_en_Click" />
    </StackPanel>
</Window>

Oczywiście pierwszym krokiem jest ustawienie (zgodnie z opisem w poprzednim wpisie) kultury dla projektu (<UICulture>en-US</UICulture>). Powoduje to, że po wykonaniu build'u pojawi się nowy plik, np.: \SampleApp_Localisation\bin\Debug\en-US\SampleApp.resources.dll. Dodano również [assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)], w AssemblyInfo.
Do solution zostało dodane narzędzie LocBaml, którego kod źródłowy został pobrany ze strony: http://msdn.microsoft.com/en-us/library/ms771568%28v=VS.90%29.aspx. Zwróćmy tutaj uwagę, pobrana została wersja dla .NET 3.5 (tylko taka jest w chwili pisania artykułu dostępna), dla której zmieniono docelową platformę na .NET 4.0.
Do projektu zostały dodane dwa skrypty, które generują plik CSV (generateCSV.cmd) lub assembly (generateAssembly.cmd) potrzebne do lokalizacji:
skrypt generateCSV.cmd:
locbaml /parse en-US\SampleApp.resources.dll  

skrypt generateAssembly.cmd:
md pl-PL
locbaml /generate en-US\SampleApp.resources.dll /trans:SampleApp.resources.pl-PL.csv /cul:pl-PL /out:pl-PL
Pierwszy z nich generuje plik trzeba uruchomić raz po pierwszym buildzie, by wygenerować plik CSV, który przetłumaczymy, może on wyglądać tak:
plik SampleApp.resources.pl-PL.csv:
SampleApp.g.en-US.resources:mainwindow.baml,loc1:System.Windows.Controls.TextBlock.$Content,Text,True,True,,Witaj świecie
SampleApp.g.en-US.resources:mainwindow.baml,loc2:System.Windows.Controls.TextBlock.$Content,Text,True,True,,Żegnaj świecie
SampleApp.g.en-US.resources:mainwindow.baml,but_PL:System.Windows.Controls.Button.$Content,Button,True,True,,
SampleApp.g.en-US.resources:mainwindow.baml,but_PL:System.Windows.Controls.ContentControl.Content,Button,True,True,,PL
SampleApp.g.en-US.resources:mainwindow.baml,but_PL:System.Windows.FrameworkElement.Height,None,False,True,,23
SampleApp.g.en-US.resources:mainwindow.baml,but_PL:System.Windows.FrameworkElement.Width,None,False,True,,75
SampleApp.g.en-US.resources:mainwindow.baml,but_EN:System.Windows.Controls.Button.$Content,Button,True,True,,
SampleApp.g.en-US.resources:mainwindow.baml,but_EN:System.Windows.Controls.ContentControl.Content,Button,True,True,,EN
SampleApp.g.en-US.resources:mainwindow.baml,but_EN:System.Windows.FrameworkElement.Height,None,False,True,,23
SampleApp.g.en-US.resources:mainwindow.baml,but_EN:System.Windows.FrameworkElement.Width,None,False,True,,75
Drugi ze skryptów wykonywany jest automatycznie w kroku „post-build step”.
Warto jeszcze zwrócić uwagę na kod obsługi przycisków i funkcję CloseAllWindowsReloadMain zaczerpniętą z przykładów dostępnych w projekcie „WPF Localization Guidance” (codeplex).
   private void button_pl_Click( object sender, RoutedEventArgs e )
    {
     CultureInfo ci = new CultureInfo( "pl-PL" );
     System.Threading.Thread.CurrentThread.CurrentCulture = ci;
     System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
     CloseAllWindowsReloadMain();
    }

    private void button_en_Click( object sender, RoutedEventArgs e )
    {
      CultureInfo ci = new CultureInfo( "en-US" );
      System.Threading.Thread.CurrentThread.CurrentCulture = ci;
      System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
      CloseAllWindowsReloadMain();
    }
    private void CloseAllWindowsReloadMain()
    {
      Window oldForm = App.Current.Windows[ 0 ];
      Type mainWinType = App.Current.Windows[ 0 ].GetType();
      Window mainForm = Assembly.GetExecutingAssembly().CreateInstance( mainWinType.FullName ) as Window;
      mainForm.Top = oldForm.Top;
      mainForm.Left = oldForm.Left;
      mainForm.Show();

      // close all windows and reload the startup form
      foreach ( Window win in App.Current.Windows )
      {
        if ( mainForm == win ) // skip our newly loaded form
          continue;
        win.Close();
      }
    }
Zapraszam do pobrania całego kodu źródłowego dla tego przykładu:
Promuj

Brak komentarzy:

Prześlij komentarz

Posty powiązane / Related posts