четверг, 9 июня 2011 г.

Технология локализации WPF приложений

При использовании материала
ссылка на источник обязательна.
Интернет пестрит разнообразными методами локализации WPF приложений. Я даже не буду приводить здесь ссылки, любой заинтересованный в этом вопросе найдет их за несколько секунд. В этой статье я хочу рассказать о технологии локализации, которая практически применялась при разработке в моем последнем проекте (программа ProjectsProfiler), и, как мне кажется, может оказаться полезной другим разработчикам. В отличие от любого метода, который лишь обозначает способ, которым теоретически можно создавать приложение, говорящего на разных языках, технология описывает производственный процесс создания такого приложения и дает ответ на многие вопросы типа "А как сделать...".

Выбор метода
Публикуемые методы локализации WPF приложений можно разделить на две категории:
  1. Использование locbaml для локализации свойств элементов, объявленных в XAML
  2. Размещение локализуемых строк (и других ресурсов) в соответствующих языку resx файлах и размещение в XAML ссылок на них (через связывание данных или расширения разметки)
В качестве основы для  рассматриваемой технологии был выбран метод от Microsoft с использованием инструмента locbaml. Использование метода в чистом виде сопряжено с рядом проблем:
  1. Полученный файл .csv крайне сложен для обработки переводчиком, так как содержит массу служебных свойств, необходимых для корректного создания сателлитной сборки.
  2. Крайне затруднительно одновременно выполнять перевод и разработку программы, так как .csv не является исходным файлом для генерации программы и его нельзя сохранять для повторного использования.
Но даже при наличии этих недостатков этот метод  обладает и достоинствами:
  1. Данные для перевода находятся в отдельном файле, который можно отдать стороннему переводчику и потом влить результаты его работы.
  2. LocBaml сам извлекает все строковые значения из XAML, что существенно упрощает работу разработчиков - нет нужды думать о необходимости вставления заклинаний в значения свойств.
Взвесив эти достоинства и недостатки было принято решение, что в общем метод локализации с использованием locbaml нам подходит, но требует небольшой "доработки напильником".

Подготовка к локализации
Для подготовки приложения к локализации нужно сделать следующее:
  1. Проектный файл дорабатывается таким образом, как это описано в исходной статье от Microsoft
  2. В  Pre-build event вставляется строка call updateUID.bat "$(DevEnvDir)..\..\vc\vcvarsall.bat", где updateUID.bat содержит следующие команды:
    call %1
    for %%i in (*.csproj) DO msbuild /t:UpdateUID %%i
    Это необходимо для расстановки атрибутов Uid для всех элементов в XAML
  3. После сборки приложения с помощью locbaml генерируется файл .csv, содержащий ресурсы, извлеченные из сателлитной сборки и подлежащие переводу
  4. Этот .csv размножается в соответствии с тем, на сколько языков требуется переводить программу и помещается в исходный код.
    Добавлять файлы в проект не обязательно, но обязательно поместить их в систему хранения версиями. Эти файлы удобно именовать в соответствии с локализацией, для которой они предназначены, например ru-ru.csv, en-us.csv и т.д.
После выполнения этих действий переводчик может приступать к работе, переводя тексты в полученных файлах и сдавая изменения в систему хранения версий. А разработчики могут спокойно продолжать работать и даже создавать новые элементы в XAML! А чтобы узнать как свести результаты их работы воедино и донести до переводчика информацию о том, что есть строки, которые нуждаются в локализации - читайте следующий раздел.

Сборка локализованной версии программы
Для того чтобы собрать локализованные сателлитные сборки используется следующий алгоритм:
  1. Первая сателлитная сборка образуется при сборке программы из исходных файлов.
  2. Из первой сателлитной сборки с помощью locbaml формируется temp.csv
  3. Выполняется слияние temp.csv с файлом, содержащими перевод ( см. выше).
    В
    результате слияния образуется новый .csv файл, который содержит как переведенные значения свойств (для которых был выполнен перевод), так и новые значения из temp.csv, которых раньше не было в файле с переводом. Строки, которые были в переводе, но которых нет в temp.csv (т.е. соответствующие удаленным элементам) в итоговый файл не попадают. Новые строки (которые до слияния отсутствовали в файле перевода) помечаются специальным маркером в колонке комментария, чтобы их можно было идентифицировать.
  4. Полученный в результате слияния файл заменяет файл с переводом и сдается в систему управления версиями.
Данный алгоритм достаточно сложен, чтобы выполнять его вручную на каждом рабочем месте разработчика, но это, как правило, и не требуется. Оформленный в виде сценария командной оболочки, этот алгоритм выполняется в процессе автоматической сборки программы. Изредка (при отладке отображения и работы программы в различных локализациях) требовалось прогнать данный сценарий непосредственно разработчику. Это выполнялось запуском соответствующего .bat файла.
Для слияния .csv файлов была написана маленькая программка CsvMerge, которая по определенному алгоритму выполняет слияние .csv файлов, генерируемых locbaml.


Оптимизация технологии
Поработав по данной технологии некоторое время, мы пришли к выводу, что это, конечно, гораздо лучше, чем просто locbaml, но, все-таки, недостаточно удобно для переводчика. CsvMerge был дополнен новой функцией, которая на основе всех файлов, содержащих переводы, генерирует один файл (мы назвали его translation.csv), содержащий переводы сразу на все требуемые языки - в отдельных колонках. Это дает возможность видеть в одной строке представления одного текста сразу на всех языках. Кроме этого, в этом файле отфильтровываются только те строки из исходных файлов, которые действительно требуют перевода (в нашем случае это 8% от всех строк). Переводчик (в нашем случае языков было немного, поэтому это был один переводчик) работает с этим файлом и вносит в него необходимые изменения. В процессе ночной сборки этот файл распадается на отдельные файлы с переводом для каждого языка и сливается с фактическими ресурсами программы. По результатам слияния генерируются сателлитные сборки и обновленный translation.csv. При этом новые строки (т.е. те, которые были добавлены разработчиками со времени начала работа переводчика) помечаются в нем специальным маркером в столбце комментария. Таким образом переводчик всегда может найти те строки, которые еще не были переведены.
Вот так выглядят строки из translation.csv в Microsoft Excel:

Заключение

Описанная технология была успешно применена при разработке ProjectsProfiler и после внедрения (в итоге на внедрение ушло порядка 2-х недель, с учетом разработки необходимых инструментов) дала возможность конструировать сателлитные сборки в процессе автоматической сборки программы, при этом разработчики и переводчик могли работать независимо, не мешая друг другу.
В нашем проекте удалось все локализуемые ресурсы поместить в одну сборку, но ничего не мешает находиться им в разных сборках, правда в этой ситуации файлов с переводами будет несколько - под одному на каждую сборку.

По моим оценкам внедрение этой технологии на живом проекте потребует около 1 дня + некоторое время на оформление XAML в соответствии с определенными правилами.

Исходные тексты CsvMerge и сценария командной оболочки доступны здесь.

Если Вас заинтересовала эта технология или же, напротив, Вы считаете её ущербной - пожалуйста, оставьте комментарий. Я открыт для общения и готов к критике :-).

Связанные материалы:

Комментариев нет:

Отправить комментарий