Поиск на сайте: Расширенный поиск


Новые программы oszone.net Читать ленту новостей RSS
CheckBootSpeed - это диагностический пакет на основе скриптов PowerShell, создающий отчет о скорости загрузки Windows 7 ...
Вы когда-нибудь хотели создать установочный диск Windows, который бы автоматически установил систему, не задавая вопросо...
Если после установки Windows XP у вас перестала загружаться Windows Vista или Windows 7, вам необходимо восстановить заг...
Программа подготовки документов и ведения учетных и отчетных данных по командировкам. Используются формы, утвержденные п...
Red Button – это мощная утилита для оптимизации и очистки всех актуальных клиентских версий операционной системы Windows...
OSzone.net Microsoft Разработка приложений Windows (до Windows 10) Разработка многоязыковых приложений на XAML (часть 2) RSS

Разработка многоязыковых приложений на XAML (часть 2)

Текущий рейтинг: 1 (проголосовало 1)
 Посетителей: 839 | Просмотров: 1032 (сегодня 0)  Шрифт: - +

Это вторая часть статьи о создании многоязыковых приложений с помощью XAML. В первой части мы говорили о выборе шрифтов и поддержке двунаправленного текста. Здесь мы рассмотрим, как использовать ресурсный механизм для поиска локализованных версий строк и ресурсов, а также для управления ими. Кроме того, мы поговорим об API для форматирования, позволяющих представить даты и числа в подходящем для пользователей вашего приложения формате.

Словари ресурсов

В XAML существует понятие словарей ресурсов, которые используются для определения стилей и других ресурсов. В Windows 8 шаблоны включали словарь ресурсов в Common/StandardStyles.xaml. В предварительной версии Windows 8.1 эти стили интегрированы в платформу и теперь являются частью generic.xaml. Для поддержки пользовательской настройки ресурсов мы добавили новый механизм поиска ресурсов ThemeResource, который пересматривается, когда тема операционной системы переключается в контрастный режим.

Например, generic.xaml определяет ресурс для шрифта по умолчанию, используемого в других стилях, следующим образом:

<FontFamily x:Key="ContentControlThemeFontFamily">Segoe UI</FontFamily>

На что затем ссылаются другие стили:

<!-- Default style for Windows.UI.Xaml.Controls.Button -->
<Style TargetType="Button">
  <Setter Property="Background" Value="{ThemeResource ButtonBackgroundThemeBrush}" />
  <Setter Property="Foreground" Value="{ThemeResource ButtonForegroundThemeBrush}"/>
  <Setter Property="BorderBrush" Value="{ThemeResource ButtonBorderThemeBrush}" />
  <Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}" />
  <Setter Property="Padding" Value="12,4,12,4" />
  <Setter Property="HorizontalAlignment" Value="Left" />
  <Setter Property="VerticalAlignment" Value="Center" />
  <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
  <Setter Property="FontWeight" Value="SemiBold" />
  <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
  <Setter Property="Template">...</Setter>
</Style>

Ресурсы темы могут быть заменены при запуске приложения с помощью:

  • переопределения их в App.xaml, например:
<Application
  x:Class="MyTestApp.App"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="using:MyTestApp">

  <Application.Resources>
    <FontFamily x:Key="ContentControlThemeFontFamily">Times New Roman</FontFamily>
  </Application.Resources>

</Application>
  • переопределения их в коде в App.xaml.cs, например:
protected override void OnWindowCreated(WindowCreatedEventArgs args)
{
  base.OnWindowCreated(args);
  SetResource("ContentControlThemeFontFamily", new FontFamily("Papyrus"));
}

void SetResource(object key, object value)
{
  if (this.Resources.ContainsKey(key))
    this.Resources[key] = value;
  else
    this.Resources.Add(key, value);
}
  • загрузки словаря ресурсов из App.xaml.cs, например:
protected override void OnWindowCreated(WindowCreatedEventArgs args)
{
base.OnWindowCreated(args);

ResourceDictionary d = new ResourceDictionary();
d.Source = new Uri(“ms-appx:///Resources/Dictionary1.xaml”);
this.Resources.MergedDictionaries.Add(d);
}

Примечание. Если ваше приложение использует несколько окон, у каждого из них есть свои ресурсы и поток интерфейса. Поэтому ресурсы нужно загружать в OnWindowCreated, чтобы их можно было инициализировать для каждого окна.

Примечание. Копия generic.xaml включена в состав Windows SDK, по умолчанию она расположена в C:\Program Files (x86)\Windows Kits\8.1\Include\winrt\xaml\design\.

Таблицы строк (.resw)

XAML-проекты для Магазина Windows используют файлы resw, чтобы определять строки ресурсов в коллекции ресурсов для дальнейшей локализации. Их можно использовать для локализации разметки xaml, к ним можно также отправлять запросы через программный код.

Таблицы строк задаются в resw-файлах под названием Resources.resw, которые можно располагать в любом месте проекта (чаще всего их помещают в папку strings). Вы можете использовать шаблоны имен квалификаторов (мы поговорим о них чуть ниже), чтобы создавать версии для разных языков, регионов и т. д.

Локализация XAML-разметки

Рекомендуемый (и самый простой) способ локализации XAML –– добавление атрибутов x:Uid к элементам, значения которых нужно локализовать. Рассмотрим это на примере из MainPage.xaml:

<Page
  x:Class="MyTestApp.MainPage"
  xmlns="http://schemas.microsoft.com/winfx/2006/XAML/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/XAML"
  xmlns:local="using:MyTestApp"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="d"
  xml:lang="en-us">

  <Grid>
    <StackPanel Margin="20">
      <TextBlock x:Uid="mp_tb1" x:Name="TextBlock1" Text="Hello World" />
    </StackPanel>
  </Grid>
</Page>

При запуске вы увидите TextBlock с надписью «Hello World» внутри. Если я добавлю файл Resources.resw в мой проект, содержащий:

*

Редактор ресурсов в Visual Studio

и заново запущу приложение, то отобразится «Welcome!» Это происходит вот почему: если элементы имеют атрибут x:Uid, то при загрузке XAML программа сопоставит значение Uid с имеющимися строками в таблице строк, названными согласно шаблону «uid.property», и добавит или переопределит свойства в XAML. Так что если я добавлю:

ИмяЗначениеКомментарий
mp_tb1.FontSize40

в файл ресурсов, то будет установлен FontSize (Размер шрифта) 40 пт, хотя этот атрибут не задан в XAML.

Данный метод можно использовать для замены любого атрибута в XAML, включая определения стиля и ресурсов, как показано в следующем примере из MainPage.xaml:

<Page.Resources>
  <SolidColorBrush x:Key="TextBoxBrush" x:Uid="test1" Color="Blue" />
  <Style TargetType="TextBox">
    <Setter Property="Background" Value="{StaticResource TextBoxBrush}" />
    <Setter Property="FontSize" Value="20" x:Uid="test2" />
  </Style>
</Page.Resources>
ИмяЗначениеКомментарий
test1.ColorGreen
test2.Value40

Значения для атрибута x:Uid не зависят от названия элемента (x:Name). Значения x:Uid не проверяются на глобальную уникальность по всему проекту. Однако механизм ограничения области здесь отсутствует, поэтому одни и те же значения будут присвоены всем элементам с одинаковым x:Uid.

Поиск строк с помощью программного кода

Значения в таблице строк можно запрашивать из кода, как показано в следующем примере из MainPage.xaml.cs:

using Windows.UI.Xaml.Controls;
using Windows.ApplicationModel.Resources;

namespace MyTestApp
{
  /// <summary>
  /// Пустая страница может быть использована отдельно либо на нее можно перейти внутри Frame
  /// </summary>
  public sealed partial class MainPage : Page
  {
    public MainPage()
    {
      this.InitializeComponent();

      ResourceLoader loader = ResourceLoader.GetForCurrentView();
      string s = loader.GetString("String1");
    }
  }
}

Это очень полезно для локализации программно-генерируемого содержимого, особенно в комбинации с string.Format() в .NET (или семейством API wsprintf()в C++) для подстановки строк на основе строки форматирования. Не полагайтесь на конкатенацию при создании строк, поскольку в других языках порядок подстановки может отличаться.

Средства локализации

Я просто обязан упомянуть набор средств для многоязычных приложений. Один раз подключив их, вы сможете создавать XLIFF-файлы для отправки на локализацию и выполнять автоматический перевод на несколько языков с помощью переводческого сервиса Bing.

*

Диалоговое окно «Языки» в наборе средств для многоязычных приложений

Затем программа создает файлы для каждого языка, и вы можете воспользоваться диалоговым окном «Перевод» для локализации каждого ресурса:

*

Многоязычный редактор в наборе средств для многоязычных приложений

Псевдолокализация

Отправка файлов на локализацию иногда занимает много времени. Вам лучше подождать и сделать локализацию тогда, когда практически завершите работу над пользовательским интерфейсом и он будет более-менее стабильным и доступным для изменения. Псевдолокализация — это методика, в рамках которой используется машинный алгоритм для локализации строк, увеличения их размера и смены кодировки; она позволяет проверить локализацию. Инструмент псевдолокализации берет строки по умолчанию и затем:

  • Создает идентификатор, позволяющий увидеть строки в интерфейсе.
  • Изменяет текст, благодаря чему вы понимаете, что он локализован, но все равно можете его прочитать.
  • Удлиняет текст, поскольку длина предложений отличается в разных языках, например, немецкий язык гораздо многословнее английского.

Вы можете добавить qps-ploc в качестве языка Windows (вам нужно поискать его), назначить ему высший приоритет, а затем запустить свое приложение, чтобы посмотреть результат локализации. Возьмем в качестве примера проект Hub Template (Шаблон концентратора), использующий ресурсы-строки. После локализации он будет выглядеть следующим образом:

*

Локализованный шаблон концентратора

Квалификаторы наименований файлов

В средстве управления ресурсами для приложений Магазина Windows есть очень полезная функция, позволяющая выбрать для загрузки один из нескольких файлов на основе набора квалификаторов в названии файла или пути.

К примеру, если у вас есть ресурс Strings/Resources.resw, он загрузит другие файлы на основе квалификаторов, включающих:

  • Язык и языковые стандарты
  • DPI
  • Ориентацию справа налево
  • Высокую контрастность

Другие файловые ресурсы, которые возвратятся:

*
Увеличить

Данный механизм используется для сопоставления с несколькими версиями любых ресурсов, загруженных из проекта, например, с изображениями, resw, xml, html и даже XAML-файлами.

Примечание. В отличие от ресурсов .Net, неподходящие ресурсы не становятся резервными ресурсами по умолчанию для языков. Так что если вы зададите ресурс для одного языка /fr-fr/MyIcon.jpg и установите язык по умолчанию en-us, то неподходящий файл, например /MyIcon.jpg, не будет сопоставлен с этим языком. Вам нужно будет специально создать резервный ресурс для языка, например /en-us/MyIcon.jpg.

Предоставляйте одинаковые наборы ресурсов для каждого поддерживаемого языка. Если вы предоставляете набор ресурсов для французского и немецкого языков, каждый набор должен содержать идентичные единообразные ключи ресурсов (файлы и названия элементов таблиц строк).

Файловые ресурсы XAML

Рекомендуемый механизм для локализации XAML-файлов –– использование x:Uid и таблицы строк, как описано выше. Однако при необходимости можно загрузить альтернативные версии с помощью механизма квалификаторов ресурсов:

  • Сохраняйте оригинальный XAML-файл для компиляции и (или) генерации кода вместе с файлом с выделенным кодом (*.xaml.cs).
  • Добавляйте локализованные варианты только для XAML, идентифицируя их с помощью квалификаторов имен.
    • Оставьте значение типа компиляции Page.
    • Удалите x:Class из объявления XAML в заголовке файла, чтобы предотвратить генерацию кода и ошибки компиляции.

Например:

*

Solution Explorer демонстрирует проект с локализованными версиями App.xaml для английского,
французского и испанского языков

Пакеты ресурсов

Пакеты ресурсов –– это новая функция упаковки в Windows 8.1. Ресурсы для различных языков и DPI упаковываются в отдельные appx-файлы, за счет чего сокращается объем загрузки и место, занимаемое на диске.

Опция для создания пакетов ресурсов находится под Generate app bundle (Создать набор приложений) мастера Create App Packages (Создание пакетов приложения) в Visual Studio.

*

Если приложение содержит несколько ресурсов, то после выбора этого пункта будет создан appxbundle, а не пакетный файл appx. Если вы смените его расширение на .zip, то содержимое будет выглядеть примерно так:

*

Файл appx bundle, содержащий ресурсы для французского и испанского языков

API для форматирования

Форматы даты, времени, чисел и валюты различаются в зависимости от страны. XAML и WinRT содержат элементы управления и API, позволяющие отображать и вводить эти значения в подходящем для конечного пользователя формате.

Дата и время

В США и Европе используется григорианскийкалендарь. В других регионах применяются собственные календари, например корейский и  еврейский. Количество и длительность месяцев в этих календарях отличается от григорианского, а начало года приходится на разные даты.

Даты, вводимые из различных типов календарей, обрабатывает элемент управления DatePicker, например:

<DatePicker CalendarIdentifier="JapaneseCalendar" x:Name="date1" />

Для их отображения используется DateTimeFormatter API из WinRT или DateTime.ToString из .Net.

К примеру, этот код:

public void ShowDates()
{
  string[] languages = { "en-us", "en-gb", "fr-fr", "ar-sa", "zh-hans-cn", "hi-in", "ja-jp", "ko-kr", "ru-ru" };
  StringBuilder sb = new StringBuilder();

  DateTime now = DateTime.Now;

  foreach (string lang in languages)
  {
    sb.AppendLine(string.Format("Language: {0}", lang));
    DateTimeFormatter df = new DateTimeFormatter("longdate",new string[] {lang} );
    sb.AppendLine(df.Format(now));
    df = new DateTimeFormatter("shortdate", new string[] { lang });
    sb.AppendLine(df.Format(now));
    df = new DateTimeFormatter("longtime", new string[] { lang });
    sb.AppendLine(df.Format(now));
  }
  Reb1.Document.SetText(TextSetOptions.UnicodeBidi, sb.ToString());
}

возвратит следующие результаты:

*

Будьте осторожны при синтаксическом анализе дат из строк, поскольку разные страны могут использовать свой собственный формат даты. Например, в США дата в сокращенном виде обычно записывается как месяц/день/год, а в Великобритании — день/месяц/год. Метод .Net DateTime.Parse учитывает культурные различия при анализе дат из строк.

При работе с временем важно учитывать часовые пояса. Пользователи обычно ожидают отображения времени с учетом их часового пояса.

Числа и валюты

Имеются региональные отличия в форматировании чисел, например, в качестве десятичного разделителя служит точка или запятая, разряды (тысячи, миллионы и т. д.) могут отделяться друг от друга. Не во всех языковых стандартах применяется десятичная система счисления с арабскими цифрами (0–9), в отдельных регионах используются другие системы счисления. Для форматирования чисел служит DecimalFormatter API из WinRT, поддерживающий подобные сценарии.

При работе с валютами необходимо учитывать, какой символ использовать для обозначения валюты и где его разместить по отношению к числу. Для форматирования валют служит CurrencyFormatter API.

Примечание. Средство форматирования не выполняет конвертацию валют, так что вы должны помнить об этом при сопоставлении валют разных стран.

Данный код форматирует числа:

public void ShowNumbers()
{
  string[] languages = { "en-US", "en-GB", "fr-FR", "ar-SA", "zh-CN", "hi-IN", "ja-JP", "ko-KR", "ru-RU" };
  StringBuilder sb = new StringBuilder();
  double d = 1234567.89;

  foreach (string l in languages)
  {
    string[] t = l.Split('-');
    GeographicRegion region = new GeographicRegion(t[1]);

    sb.AppendLine(string.Format("Language: {0}", l));
    DecimalFormatter df = new DecimalFormatter(new string[] { l }, region.CodeTwoLetter);
    df.IsGrouped = true;
    sb.AppendLine(df.Format(d));

    CurrencyFormatter cf = new CurrencyFormatter(region.CurrenciesInUse[0], new string[] { l }, region.CodeTwoLetter);
    cf.IsGrouped = true;
    sb.AppendLine(cf.FormatDouble(d));
  }
  Reb1.Document.SetText(TextSetOptions.UnicodeBidi, sb.ToString());
}

В результате получается:

*

Подведем итоги

Платформы XAML и WinRT содержат множество функций, которые будут очень полезны при разработке многоязыковых приложений. Надеюсь, данная статья станет хорошим руководством при создании приложений, которыми смогут пользоваться жители самых разных стран.

Автор: Сэм Спенсер  •  Иcточник: MSDN  •  Опубликована: 19.08.2014
Нашли ошибку в тексте? Сообщите о ней автору: выделите мышкой и нажмите CTRL + ENTER
Теги:   XAML.


Оценить статью:
Вверх
Комментарии посетителей
Комментарии отключены. С вопросами по статьям обращайтесь в форум.