Localizzare un applicazione WPF rappresenta sotto certi aspetti un salto nel passato. Dopo esserci abituati a Visual Studio e alla possibilità di localizzare un form semplicemente cambiando la proprietà Language, ora il gioco si fa decisamente più "duro".
Innanzitutto bisogna procurarsi i ferri del mestiere quindi oltre a Visual Studio 2008 bisogna scaricarsi l'esempio LocBaml (per la serie "fatelo da voi"...) e compilarselo.
A questo punto immaginiamo di avere un applicazione come quella in fig1 composta da una finestra con all'interno un semplice pulsante che quando premuto visualizza una MessageBox
fig.1
Il punto di partenza è modificare il file .csproj (o vbproj) inserendo la cultura predefinita della vostra applicazione attaraverso il tag UICulture.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<UICulture>en-US<UICulture>
...
</PropertyGroup>
successivamente scommentate l'attributo NeutralResourceAssembly nel file AssemblyInfo allineandolo alla cultura definita nel file di progetto:
[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
Fatto questo, compiliamo il progetto ottenendo sotto la directory bin, una nuova directory en-US con all'interno l'assembly satellite contenente le risorse della default culture.
Preparare per la localizzazione
Per una migliore localizzazione è consigliabile racchiudere le varie risorse in opportuni ResourceDictionaries e renderli visibili all'applicazione usando
l'opzione MergeDictionaries. Creaiamo quindi un ResourceDictionary StringTables che conterrà tutti i testi da localizzare.
StringTable.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib" >
<sys:String x:Key="buttonText">Hello</sys:String>
<sys:String x:Key="messageText">Welcome to WPF</sys:String>
<sys:String x:Key="windowTitleText">Localization Demo</sys:String>
</ResourceDictionary>
App.xaml
<Application x:Class="LocalizeWPF.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="StringTables.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
e utilizziamo quando definito in StringTables usando la markup extension DynamicResource.
Window1.xaml
<Window x:Class="LocalizeWPF.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{DynamicResource windowTitleText}" Height="143" Width="360">
<Grid>
<Button
Content="{DynamicResource buttonText}"
Margin="14,17,12,0"
Name="button1" FontSize="24" Height="59" VerticalAlignment="Top" Click="button1_Click" />
</Grid>
</Window>
Window1.xaml.cs
public partial class Window1 : Window
{
public Window1 ()
{
InitializeComponent();
}
private void button1_Click (object sender, RoutedEventArgs e)
{
string msg = this.FindResource("messageText") as string;
MessageBox.Show(msg);
}
}
Ora la nostra applicazione è pronta per essere localizzata.
Esportare i dati da localizzare
Il primo passo è quello di aggiungere gli identificativi di localizzazione utilizzando msbuild /t:updateuid $(ProjectFileName)
(personalmente mi sono creato una nuova voce nel menu External Tools di Visual Studio) il risultato è che files xaml vengono modificati aggiungendo ai vari elementi un nuovo attributo x:Uid.
Ecco come appare dopo l'operazione il file Window1.xaml
<Grid x:Uid="Grid_1">
<Button
x:Uid="button1" Content="{DynamicResource buttonText}"
Margin="14,17,12,0"
Name="button1" FontSize="24" Height="59" VerticalAlignment="Top" Click="button1_Click" />
</Grid>
A questo punto compiliamo e copiamo LocBaml.exe creato in precedenza e l'eseguibile principale, nella cartella en-US dopodichè dalla cartella en-US eseguiamo:
locbaml /parse nomeprogetto.resources.dll /out:nomefile.csv (es: locbaml /parse LocalizationWPF.resources.dll /out:output.csv)
In nomefiles.csv ora avrete le varie stringhe che potete localizzare, aprendo il file in Excel (fig.2)
fig.2
le varie colonne rappresentano informazioni di localizzazione (impostabili attraverso l'attached property Localization) dirette al traduttore, come ad esempio se un testo deve essere tradotto oppure no.
Completata la localizzazione, salviamo il risultato in un file italian.csv e creiamo una cartella it-IT sotto la dir bin del progetto.
A questo punto generiamo l'assembly satellite per la localizzazione italiana all'interno della cartella it-IT lanciando, sempre dalla cartella en-US, il comando:
locbaml /generate /trans:italian.csv /out:..\it-IT /cul:it-IT nomeprogetto.resources.dll
Se tutto è andato a buon fine, nella dir it-IT troverete la dll satellite per la cultura it-IT.
Verificare la localizzazione
Testare la localizzazione comporta la forzatura della cultura allo startup che in WPF si traduce nell'aggiungere questo codice nel costruttore di App.xaml.cs
public partial class App : Application
{
public App ()
{
CultureInfo itCulture = new CultureInfo("it-IT");
Thread.CurrentThread.CurrentCulture = itCulture;
Thread.CurrentThread.CurrentUICulture = itCulture;
}
}
Il risultato finale è quello in fig.3
Q: E', o non è, un gioco da ragazzi?
A: Non lo è, non lo è... (da leggere alla Ezio Greggio)