Когда я учился разрабатывать приложения на основе MVVM мне жутко не понравилось, что во многих статьях показано как ApplicationBar создается во ViewModel. Там же кнопки и элементы меню заполняется локализованными строками. Я долго искал решение, и оно было найдено.
Внимание! Статья описывает только решение проблемы локализации панели приложения и подразумевает что читатели знакомы с основами XAML, MVVM, связыванием данных и локализацией приложений.
Встречайте бибилиотеку для локализации панели приложения: http://appbarutils.codeplex.com/
Что бы попробовать ее в работе создадим страницу приложения и добавим в ней обычную панель приложения, с кнопками и, если необходимо, пунктами меню. Например, такую:
<shell:ApplicationBar>
<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem IsEnabled="True" Text="lookscreen"/>
</shell:ApplicationBar.MenuItems>
<shell:ApplicationBarIconButton IconUri="/Assets/AppBar/save.png" IsEnabled="True" Text="save"/>
</shell:ApplicationBar>
Обратите внимание: свойство Text должно быть без пробелов. Работоспособность при наличии кириллицы не проверял.
Добавляем пакет AppBarUtils в приложение командой Install-Package AppBarUtils или через диспетчер пакетов. Добавляем в разметку страницы ссылку на сборку этого пакета:
xmlns:AppBarUtils="clr-namespace:AppBarUtils;assembly=AppBarUtils"
И нам еще понадобится сборка для задания поведений:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
После этих приготовлений задаем поведения для страницы на которой находится панель приложения. У меня получилось вот так:
<i:Interaction.Behaviors>
<AppBarUtils:AppBarItemCommand Id="save" Type="Button" Command="{Binding SaveCommand}" Text="{Binding LocalizedResources.SaveButton, Mode=OneWay, Source={StaticResource LocalizedStrings}}"/>
<AppBarUtils:AppBarItemCommand Id="lookscreen" Type="MenuItem" Command="{Binding LookScreenCommand}" Text="{Binding LocalizedResources.ScreenItem, Mode=OneWay, Source={StaticResource LocalizedStrings}}"/>
</i:Interaction.Behaviors>
Связывание поведения с элементом, которому он назначен, происходит по ID со значением равным свойству Text пункта меню или кнопки. Кроме того, задается тип элемента меню, которому задается поведение: для кнопки – Button, для пункта меню – MenuItem. Значение остальных свойств пояснять думаю не нужно.
После всех манипуляций у меня получилась страница в реальном приложении, которое опубликовано в windows phone store:
<phone:PhoneApplicationPage
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:Command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP8"
xmlns:AppBarUtils="clr-namespace:AppBarUtils;assembly=AppBarUtils"
x:Class="CatDay.MainPage"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations ="PortraitOrLandscape"
shell:SystemTray.IsVisible="True"
DataContext="{Binding Main, Mode=OneWay, Source={StaticResource Locator}}">
<shell:SystemTray.ProgressIndicator>
<shell:ProgressIndicator IsIndeterminate="true" IsVisible="{Binding ProgressBarValue}" Text="{Binding ProgressBarText}" />
</shell:SystemTray.ProgressIndicator>
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar>
<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem IsEnabled="True" Text="donate"/>
<shell:ApplicationBarMenuItem IsEnabled="True" Text="lookscreen"/>
<shell:ApplicationBarMenuItem IsEnabled="True" Text="skydrive"/>
<shell:ApplicationBarMenuItem IsEnabled="True" Text="feedback"/>
</shell:ApplicationBar.MenuItems>
<shell:ApplicationBarIconButton IconUri="/Assets/AppBar/transport.rew.png" IsEnabled="True" Text="previus"/>
<shell:ApplicationBarIconButton IconUri="/Assets/AppBar/save.png" IsEnabled="True" Text="save"/>
<shell:ApplicationBarIconButton IconUri="/Assets/AppBar/share.png" IsEnabled="True" Text="share"/>
<shell:ApplicationBarIconButton IconUri="/Assets/AppBar/transport.ff.png" IsEnabled="True" Text="next"/>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
<i:Interaction.Behaviors>
<AppBarUtils:AppBarItemCommand Id="next" Type="Button" Text="{Binding LocalizedResources.NextButton, Mode=OneWay, Source={StaticResource LocalizedStrings}}" Command="{Binding NextImageCommand}"/>
<AppBarUtils:AppBarItemCommand Id="share" Type="Button" Command="{Binding ShareCommand}" Text="{Binding LocalizedResources.ShareButton, Mode=OneWay, Source={StaticResource LocalizedStrings}}"/>
<AppBarUtils:AppBarItemCommand Id="previus" Type="Button" Command="{Binding PreviusImageCommand}" Text="{Binding LocalizedResources.PreviusButton, Mode=OneWay, Source={StaticResource LocalizedStrings}}"/>
<AppBarUtils:AppBarItemCommand Id="save" Type="Button" Command="{Binding SaveCommand}" Text="{Binding LocalizedResources.SaveButton, Mode=OneWay, Source={StaticResource LocalizedStrings}}"/>
<AppBarUtils:AppBarItemCommand Id="lookscreen" Type="MenuItem" Command="{Binding LookScreenCommand}" Text="{Binding LocalizedResources.ScreenItem, Mode=OneWay, Source={StaticResource LocalizedStrings}}"/>
<AppBarUtils:AppBarItemCommand Id="skydrive" Type="MenuItem" Command="{Binding SkyDriveCommand}" Text="{Binding LocalizedResources.SkydriveItem, Mode=OneWay, Source={StaticResource LocalizedStrings}}" />
<AppBarUtils:AppBarItemCommand Id="donate" Type="MenuItem" Text="{Binding LocalizedResources.DonateMenuItem, Mode=OneWay, Source={StaticResource LocalizedStrings}}" Command="{Binding DonateCommand }"/>
<AppBarUtils:AppBarItemCommand Id="feedback" Type="MenuItem" Text="{Binding LocalizedResources.FeedbackAppBarButton, Mode=OneWay, Source={StaticResource LocalizedStrings}}" Command="{Binding FeedbackCommand}"/>
</i:Interaction.Behaviors>
<!--LayoutRoot представляет корневую сетку, где размещается все содержимое страницы-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="{Binding LocalizedResources.ApplicationTitle, Mode=OneWay, Source={StaticResource LocalizedStrings}}" Style="{StaticResource PhoneTextGroupHeaderStyle}" Margin="12,0"/>
</StackPanel>
</Grid>
</phone:PhoneApplicationPage>
В конце статьи еще раз укажу ссылку на страницу проекта AppBarUtils, там же много ссылок на примеры использования этой библиотеки, исходники не выложены.
Надеюсь, что эта маленькая статья поможет начинающим разработчикам в локализации приложений, а опытных разработчиков избавит от распространенного заблуждения что панель приложения нельзя локализовать с помощью связывания данных.
Автор: SZolotov
Добрый день! Если Вы заинтересованы в локализации web-ПО, ПО для персональных компьютеров, ПО для мобильных устройств либо иного вида программного обеспечения, я рекомендую Вам использовать этот инструмент на базе web: https://poeditor.com/ POEditor является интуитивным, хорошо проработанным инструментом, обладающим рядом полезных свойств, которые помогают организовать процесс управления переводом. Он поддерживает множество популярных форматов файлов и обладает собственным API, что обеспечивает лучшую автоматизацию. Желаю Вам больших успехов в Ваших проектах!