Сообщений 11    Оценка 25        Оценить  
Система Orphus

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

Использование языковых библиотек

Авторы: Таратин Михаил
Марков Сергей

Источник: RSDN Magazine #2-2006
Опубликовано: 07.10.2006
Версия текста: 1.0
Введение
Механизм хранения переводов
Языковые библиотеки
Создание языковых библиотек
Ручное создание
Автоматическое создание
Подключение языковых библиотек
Библиотека Multilingual
Подключение библиотеки
Механизм работы
Заключение

Файлы к статье - sample_bin.zip, sample_src.zip, multiLang.zip

Введение

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

В данной статье рассматривается один из подходов к созданию многоязычных приложений - использование отдельных языковых библиотек (resource-only/satellite dll). Описаны способы их создания и подключения к основному приложению. Кроме этого, предложена миниатюрная библиотека для выбора языка прямо из пользовательского интерфейса. Решение ориентировано на Microsoft Visual C++/MFC, но может быть также адаптировано и для других конфигураций.

Механизм хранения переводов

При решении задачи поддержки приложением нескольких языков, прежде всего, встает вопрос о том, какой механизм лучше выбрать для хранения переводов. Зачастую для этого используют текстовые файлы, в которых задают соответствие между исходным текстом и его переводом. На первый взгляд, это решение кажется простым и изящным, однако его использование и поддержка порождают множество проблем. Для перехода на этот механизм необходимо заменить обращение к ресурсам во всей программе, начиная со строк и заканчивая диалогами, что в большинстве случаев требует огромных затрат времени. Кроме того, данное решение не предоставляет возможности настройки размеров элементов диалогов под перевод. Зачастую при выходе очередной версии возникает рассинхронизация переводов, что заметно лишь на этапе выполнения. Возможность использования разных переводов для одинаковых выражений требует дополнительного усложнения механизма соответствия между переводами. С учетом этих нюансов использование текстовых файлов является неудачным решением.

Рассмотрим, каким требованиям должен удовлетворять идеальный механизм хранения переводов. Желательно, чтобы он обеспечивал хранение как текстовых значений, так и координат элементов диалогов. Затраты времени, необходимые для перехода со стандартного способа хранения ресурсов на новый, должны быть минимальны. В идеале для разработчика не должно быть заметно, является данное приложение обычным или же многоязычным. Иными словами, код, отвечающий за поддержку приложением нескольких языков, должен быть хорошо изолирован. Желательно сохранить возможность использования стандартных мастеров и редакторов ресурсов Visual C++. Кроме того, в большинстве случаев требуется возможность поставлять приложение пользователю как со всеми языками, так и с заданным набором.

Языковые библиотеки

Стандартным способом хранения ресурсов пользовательского интерфейса для приложений Windows является использование специализированной секции формата PE (Portable Executable). В отличие от текстовых файлов, данный подход предоставляет возможности хранения не только строк, но и других видов ресурсов. Ресурсы данного формата поддерживаются мастерами и редакторами Microsoft Visual C++, а также большинством библиотек пользовательского интерфейса, например, MFC.

Просмотрев спецификацию PE формата, вы обнаружите, что он позволяет хранить в одном файле ресурсы на нескольких языках. Однако не все так безупречно, как может показаться на первый взгляд. При таком способе хранения все языки равнозначны, и операционная система по некоторым признакам сама выбирает язык пользовательского интерфейса. Проблема кроется в механизме выбора языка. Microsoft Windows использует сложный алгоритм, который анализирует список содержащихся в файле языков и осуществляет выбор, учитывая несколько параметров, таких как: язык пользовательского интерфейса Windows, региональные настройки, базовую часть идентификатора языка. Кроме того, этот алгоритм меняется в каждой версии Windows. Поэтому, чтобы избежать шквала звонков в центры поддержки с вопросами в стиле «Почему моё приложение запускается на китайском языке», Microsoft не рекомендует одновременное хранение нескольких языков ресурсов в одном файле. Вместо этого предлагается использовать отдельные языковые библиотеки.

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


Рисунок 1 Схема использования языковых библиотек.

Для перехода на использование языковых библиотек необходимо решить следующие задачи:

  1. Перенести ресурсы из приложения в отдельные языковые библиотеки и перевести их.
  2. Обеспечить выбор и подключение языковой библиотеки в зависимости от текущих настроек.
  3. Поддерживать синхронизацию переводов во множестве языковых библиотек при выходе новых версий вашего приложения.

Создание языковых библиотек

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

Ручное создание

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

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

Автоматическое создание

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

ПРИМЕЧАНИЕ

Как уже обсуждалось в статье RSDN 2005 #3, Lingobit Localizer значительно облегчает синхронизацию переводов между различными языками и позволяет осуществлять эффективное управление процессом локализации, как с вовлечением в процесс переводчиков, так и без них.

Рассмотрим процесс создания языковой библиотеки в Lingobit Localizer. Стоит отметить, что интерфейс программы был недавно отлично русифицирован. Создадим проект, добавим в него переводимые файлы, выставим настройку создания файлов в меню Сервис\Опции.


Рисунок 2 Настройки проекта.

Теперь переведем несколько элементов и создадим локализованные файлы. В папке Output нашего проекта появятся языковые библиотеки, созданные для нашего перевода.

Подключение языковых библиотек

Библиотека Multilingual

Теперь, после создания языковых библиотек, необходимо подключить их к нашему приложению. Для облегчения этой задачи можно воспользоваться небольшой бесплатной библиотекой с открытым кодом, доступной на сайте Lingobit Technologies. Библиотека Multilingual позволяет автоматизировать задачу подключения языковых библиотек к приложению, что, в свою очередь, ведет к значительному сокращению трудозатрат.

Библиотека Multilingual выполняет следующие действия. При первом запуске приложения составляется список языков пользовательского интерфейса на основе набора доступных языковых библиотек. Используя настройки Windows, библиотека определяет язык пользовательского интерфейса, и все вызовы на загрузку ресурсов перенаправляются в соответствующие языковые библиотеки. Для управления языком пользовательского интерфейса создается меню, содержащее список всех доступных языков. Выбранный пользователем язык сохраняется в реестре и используется при следующих запусках.


Рисунок 3. Меню выбора языка пользовательского интерфейса.

Подключение библиотеки

Для подключения библиотеки Multilingual к приложению вам необходимо выполнить следующие шаги:

Подключить библиотеку можно, добавив строку multilang.lib в свойства проекта на закладку Linker\Input. Для инициализации библиотеки в исполняемом файле добавьте следующий код после вызова метода CWinApp::InitInstance.

MultiLangInitLocalization(ID_LANGUAGE_FIRST,MAX_LANGUAGES, HKEY_CURRENT_USER, "Software/YourCompanyName/YourProductName", GUILanguage");

В DLL-проектах нужно будет вставить следующий вызов в функцию DllMain.

YourDLLNameDLL.hResource = MultiLangLoadLibrary(hInstance, HKEY_CURRENT_USER, "Software/YourCompanyName/YourProductName", "GUILanguage");

Этот вызов должен располагаться между строчками

if (!AfxInitExtensionModule(YourDLLNameDLL, hInstance)) return 0;

и

new CDynLinkLibrary(YourDLLNameDLL);

Для отображения языкового меню необходимо указать место в меню, куда нужно добавлять языки и перенаправить запросы по обработке этого меню в библиотеку Mulitlingual.

Добавьте в stdafx.h

#define ID_LANGUAGE_FIRST 32000
#define MAX_LANGUAGES 100

В меню добавьте элемент с идентификатором 32000. А в карту сообщений CMainFrame вставьте следующие элементы:

ON_COMMAND_RANGE(
  ID_LANGUAGE_FIRST,ID_LANGUAGE_FIRST+MAX_LANGUAGES, OnLanguageFirst)
ON_UPDATE_COMMAND_UI_RANGE(
  ID_LANGUAGE_FIRST, ID_LANGUAGE_FIRST+MAX_LANGUAGES, OnUpdateLanguageFirst)

В обработчиках этих сообщений перенаправьте вызовы в библиотеку Multilingual.

void CMainFrame::OnLanguageFirst(UINT nID)
{
  MultiLangOnClickMenu(nID);
  AfxMessageBox(_T("Please restart application for changes to take effect"));
}

void CMainFrame::OnUpdateLanguageFirst(CCmdUI *pCmdUI)
{
  MultiLangUpdateMenu(pCmdUI);
}

Механизм работы

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

Динамическая смена языка

Необходимость перезагрузки приложения является самым неприятным моментом в применении библиотеки Multilingual. Было бы значительно удобнее выполнять смену языка пользовательского интерфейса на лету. Однако это сопряжено с некоторыми трудностями. Легко перенаправить все новые запросы к ресурсам на другую языковую библиотеку, но как быть с объектами, которые уже загрузили информацию из ресурсов и больше с ними не взаимодействуют? Для этого придется отказаться от стандартного механизма работы с ресурсами и использовать некоторый специализированный механизм обновления. В результате значительно повысится сложность создания многоязычного приложения и будет потеряна возможность работы с ресурсами в мастерах и редакторах Microsoft Visual Studio. Поэтому не стоит реализовывать динамическую смену языка без действительно веских причин, т.к. простое решение с перезагрузкой приложения будет устраивать вас в большинстве случаев.

Подмена ресурсов

Рассмотрим механизм, используемый для перенаправления вызовов на загрузку ресурсов из главных модулей в языковые. Библиотека Multilingual использует для этого вызов функции AfxSetResourceHandle, передав ей дескриптор загруженной языковой библиотеки.

{
  // Загрузка библиотеки ресурсов Load resurce-only library
  HINSTANCE hRes = LoadLibrary("MyAppRUS.dll");

  // Перенаправление вызовов на новую библиотеку
  if(hRes)
    AfxSetResourceHandle(hRes);
}

Использование одного языка

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

Хранение базового языка в оригинальном файле

Можно хранить ресурсы с базовым языком (обычно это английский) не только в языковых DLL, но и в основном файле. Это позволит вашей программе работать даже при отсутствии языковых библиотек. Иногда такая возможность оказывается крайне полезной.

Заключение

Создание многоязычных приложений при использовании языковых библиотек является не такой уж сложной задачей, как может показаться на первый взгляд. Этап перевода и создания отдельных языковых библиотек автоматизирован в средствах локализации. Подключить библиотеки к вашему приложению, вставив в него всего пару строчек кода, можно при использовании Multilingual. День работы – и ваша программа начала поддерживать множество языков! А дальше уже работа переводчиков. :)


Эта статья опубликована в журнале RSDN Magazine #2-2006. Информацию о журнале можно найти здесь
    Сообщений 11    Оценка 25        Оценить