Локалізація WPF сторінок

Сьогодні існує багато способів локалізації WPF проектів в основному заснованих на биндинге.
У цьому підході є свої плюси і мінуси. Мене не влаштовує в цьому підході це величезна кількість біндінгів в розмітки xaml, додаткова затримка при завантаженні сторінки. Так само додатковий час для пошуку рядка у вихідному коді тобто коли я бачу рядок в запущеній програмі, спочатку я повинен знайти цю сходинку в .resx ресурсах, а після тільки xaml містить цей ключ.

Нещодавно ми підключили Elas для локалізації нашого проекту. Elas витягує з розмітки xaml всі значення атрибутів позначеного елемента x:Uid і поміщає їх в xlf файл для подальшого перекладу. Розповім на простому прикладі, як це робиться.

Windows 8, Visual Studio 2013

І так створимо новий WPF проект.



І кілька елементів на головному вікні.



MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="525"
Height="350">
<Grid>

<Menu Height="22" VerticalAlignment="Top">
<MenuItem Header="File">
<MenuItem Header="New" />
<MenuItem Header="Open" />
<Separator />
<MenuItem Header="Exit" />
</MenuItem>
<MenuItem Header="Help">
<MenuItem Header="About" />
</MenuItem>
</Menu>
<TabControl Margin="10,40,10,10">
<TabItem Header="File">
<Grid>
<Button Width="97"
Height="21"
Margin="11,26,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Content="Add" />
<Button Width="97"
Height="21"
Margin="11,53,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Content="Remove" />
<ListBox Margin="122,28,13,38" />
<TextBlock Height="26"
Margin="6,0,6,6"
VerticalAlignment="Bottom">
<TextBlock>
Selected Item:<Run Text="{Binding SelectedItem}" />
</TextBlock>
</TextBlock>
</Grid>
</TabItem>
<TabItem Header="Fs">
<Grid>
<TextBox Height="21"
Margin="14,16,24,0"
VerticalAlignment="Top" />
</Grid>
</TabItem>
</TabControl>
</Grid>
</Window>



Додамо Elas Core Nuget пакет.



Зверніть увагу солюшене з'явився новий файл ".elas\ElasConfiguration.props"



Це конфігураційний файл Elas де ви можете задати мови на які бажаєте отримати переказ.

Далі запускаємо білд.

І після білду у нас тепер є xliff файл для «MainWindow.xaml»:



Але він не має жодного trans-unit оскільки ми не задали жодного x:Uid елементів.

Додамо x:Uid для кожного елемента.
MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="525"
Height="350">
<Grid>

<Menu x:Uid="Menu"
Height="22"
VerticalAlignment="Top">
<MenuItem x:Uid="Menu.File" Header="File">
<MenuItem x:Uid="Menu.File.New" Header="New" />
<MenuItem x:Uid="Menu.File.Open" Header="Open" />
<Separator x:Uid="Menu.File.Separator" />
<MenuItem x:Uid="Menu.File.Exit" Header="Exit" />
</MenuItem>
<MenuItem x:Uid="Menu.Help" Header="Help">
<MenuItem x:Uid="Menu.Help.About" Header="About" />
</MenuItem>
</Menu>
<TabControl x:Uid="TabControl" Margin="10,40,10,10">
<TabItem x:Uid="TabControl.File" Header="File">
<Grid x:Uid="TabControl.File.Grid">
<Button x:Uid="TabControl.File.Add"
Width="97"
Height="21"
Margin="11,26,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Content="Add" />
<Button x:Uid="TabControl.File.Remove"
Width="97"
Height="21"
Margin="11,53,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Content="Remove" />
<ListBox Margin="122,28,13,38" />
<TextBlock x:Uid="TabControl.File.Bottom"
Height="26"
Margin="6,0,6,6"
VerticalAlignment="Bottom">
<TextBlock x:Uid="TabControl.File.Bottom.SelectedItem">
Selected Item:<Run x:Uid="TabControl.File.Bottom.SelectedItem.Run" Text="{Binding SelectedItem}" />
</TextBlock>
</TextBlock>
</Grid>
</TabItem>
<TabItem x:Uid="TabControl.Directory" Header="Fs">
<Grid x:Uid="TabControl.Directory.Grid">
<TextBox x:Uid="TabControl.Directory.TextBox"
Height="21"
Margin="14,16,24,0"
VerticalAlignment="Top" />
</Grid>
</TabItem>
</TabControl>
</Grid>
</Window>





Знову білд. І тепер ми можемо приступити до локалізації.

Перед локалізацієюЯкщо ви збираєтеся працювати з «MainWindow.xaml.xlf» файлом самостійно в Visual Studio, то для цього буде зручніше додати xml-схему «xliff-core-1.2-transitional.xsd» в Visual Studio. Цей файл можна знайти в "%SolutionDir%\packages\DevUtils.Elas.Core.X.X.X\schemas\xliff-core-1.2-transitional.xsd" і додати його в Visual Studio.



Розглянемо файл «MainWindow.xaml.xlf».



Цей файл містить ключі (1) (x:Uid) і початкове значення (2) який необхідно перекласти. Переклад додається до елемента target і state змінюється на «translated». Елементи для яких ви не бажаєте робити переклад встановіть translate «no» і state «final»

Ось що вийшло у мене.

MainWindow.xaml.xlf

<xliff version="1.2" xmlns:elas="urn:devutils:names:tc:xliff:document:1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file original="MainWindow.xaml" source-language="en-US" target-language="ru-UA" datatype="xml">
<header>
<tool tool-version="0.0.8.0" tool-name="ELAS" tool-company="DevUtils.Net" tool-id="DevUtils.Elas.Tasks.Core Version=0.0.8.0, Culture=neutral, PublicKeyToken=3cae0f4d0d366709" />
</header>
<body>
<group id="Menu">
<trans-unit id="Menu.$Content" translate="ні">
<source xml:space="preserve">#Menu.File;#Menu.Help;</source>
<target xml:space="preserve" state="final"></target>
</trans-unit>
<group id="File">
<trans-unit id="Menu.File.$Content" translate="ні">
<source xml:space="preserve">#Menu.File.New;#Menu.File.Open;#Menu.File.Separator;#Menu.File.Exit;</source>
<target xml:space="preserve" state="final"> </target>
</trans-unit>
<trans-unit id="Menu.File.Header" translate="так">
<source xml:space="preserve">File</source>
<target xml:space="preserve" state="translated">Файл</target>
</trans-unit>
<group id="New">
<trans-unit id="Menu.File.New.Header" translate="так">
<source xml:space="preserve">New</source>
<target xml:space="preserve" state="translated">Новий</target>
</trans-unit>
</group>
<group id="Open">
<trans-unit id="Menu.File.Open.Header" translate="так">
<source xml:space="preserve">Open</source>
<target xml:space="preserve" state="translated">Відкрити</target>
</trans-unit>
</group>
<group id="Exit">
<trans-unit id="Menu.File.Exit.Header" translate="так">
<source xml:space="preserve">Exit</source>
<target xml:space="preserve" state="translated">Вихід</target>
</trans-unit>
</group>
</group>
<group id="Help">
<trans-unit id="Menu.Help.$Content" translate="ні">
<source xml:space="preserve">#Menu.Help.About;</source>
<target xml:space="preserve" state="final"></target>
</trans-unit>
<trans-unit id="Menu.Help.Header" translate="так">
<source xml:space="preserve">Help</source>
<target xml:space="preserve" state="translated">Допомога</target>
</trans-unit>
<group id="About">
<trans-unit id="Menu.Help.About.Header" translate="так">
<source xml:space="preserve">About</source>
<target xml:space="preserve" state="translated">Про програму</target>
</trans-unit>
</group>
</group>
</group>
<group id="TabControl">
<group id="File">
<trans-unit id="TabControl.File.$Content" translate="ні">
<source xml:space="preserve">#TabControl.File.Grid;</source>
<target xml:space="preserve" state="final"></target>
</trans-unit>
<trans-unit id="TabControl.File.Header" translate="так">
<source xml:space="preserve">File</source>
<target xml:space="preserve" state="translated">Файл</target>
</trans-unit>
<group id="Add">
<trans-unit id="TabControl.File.Add.Content" translate="так">
<source xml:space="preserve">Add</source>
<target xml:space="preserve" state="translated">&Додати lt;/target>
</trans-unit>
</group>
<group id="Remove">
<trans-unit id="TabControl.File.Remove.Content" translate="так">
<source xml:space="preserve">Remove</source>
<target xml:space="preserve" state="translated">Видалити</target>
</trans-unit>
</group>
<group id="Bottom">
<trans-unit id="TabControl.File.Bottom.$Content" translate="ні">
<source xml:space="preserve">#TabControl.File.Bottom.SelectedItem;</source>
<target xml:space="preserve" state="final"></target>
</trans-unit>
<group id="SelectedItem">
<trans-unit id="TabControl.File.Bottom.SelectedItem.$Content" translate="так">
<source xml:space="preserve">Selected Item:#TabControl.File.Bottom.SelectedItem.Run;</source>
<target xml:space="preserve" state="translated">Вибраний елемент:#TabControl.File.Bottom.SelectedItem.Run;</target>
</trans-unit>
</group>
</group>
</group>
<group id="Fs">
<trans-unit id="TabControl.Directory.$Content" translate="ні">
<source xml:space="preserve">#TabControl.Directory.Grid;</source>
<target xml:space="preserve" state="final"></target>
</trans-unit>
<trans-unit id="TabControl.Directory.Header" translate="так">
<source xml:space="preserve">Fs</source>
<target xml:space="preserve" state="translated">Директорія</target>
</trans-unit>
</group>
</group>
</body>
</file>
</xliff>



Знову білд. Перевіряємо немає попереджень або помилок.

Далі перемикаємо локаль на російську Windows або у програмі (Я додав в конструктор класу «App»

CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("ru-UA");
).

І отримуємо локалізоване додаток на російську.


P. S. наступного разу я розповім, як за допомогою Elas локалізувати C++ (Windows resources) додатка.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.