Отправляет email-рассылки с помощью сервиса Sendsay

Практические советы по GTK+

  Все выпуски  

Практические советы по GTK+ Image Viewer 1.4



Image Viewer 1.4

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

У нас будет два языка - русский и английский. Основной - английский, на нём будет написано приложение, переводы на остальных языках будут содержаться во внешних файлах. Как уже было сказано, у нас будет только один дополнительный язык - русский, но никто не мешает Вам самостоятельно перевести и на другие языки.

Добавим в основной заголовочный файл image_viewer.h следующий код:

// Для локализации
#include <libintl.h>
#define _(String) gettext (String)

#define PACKAGE "image_viewer"

#ifdef WIN32
#define PACKAGE_LOCALE_DIR "../locale"
#else
#define PACKAGE_LOCALE_DIR "/usr/share/locale"
#endif

libintl.h - это заголовочный файл содержащий функцию char* gettext(const char *text),
gettext() ищет текст, который её передали в качестве параметра, во внешнем файле с переводом и в случае успеха возвращает перевод,
а если не находит его, то возвращвет первоначальный текст. Очень удобно, теперь остаётся все строки, подлежащие переводу
упаковать в функцию gettext(), но можно сделать ещё проще - чтобы каждый раз не писать gettext, его обычно заменяют на _("string").

Итак, теперь остаётся  все строки, различные на разных язаках, написать на английском и упаковать в _(""), например: _("Bit per sample")
Но как наше приложение узнает каким языком пользоваться? Мы должны ему сказать об этом. Самый простой способ изменить локаль, это установить переменную окружения locale, например, для русского языка locale=ru, это будет работать как к Linux, так и в Windows. Мы сделаем немного по-другому, язык будет автоматически браться из системы. В самое начало функции main()  добавим следующий код:

 char *ret;
// используем язык по умолчанию.
ret = setlocale(LC_ALL,"");
// устанавливаем имя каталога с переводами;
ret = bindtextdomain(PACKAGE,PACKAGE_LOCALE_DIR);
// устанавливаем кодировку перевода;
ret = bind_textdomain_codeset (PACKAGE, "UTF-8");
// устанавливаем имя файла с переводом для нашего пректа PACKAGE.mo,
// который нужно будет положить в каталог PACKAGE_LOCALE_DIR/ru/LC_MESSAGES
ret = textdomain(PACKAGE);

setlocale() это POSIX функция, присутствует как к Linux, так и в Windows, она задаёт язык для приложения, в нашем случае язык берётся из системы.
Далее мы устанавливаем имя файла и каталог, откуда приложение будет брать перевод. Если заглянуть в  image_viewer.h, то можно увидеть, что файл с переводом будет называться PACKAGE=image_viewer.mo (расширение .mo писать не надо) , а расположен он будет в каталоге PACKAGE_LOCALE_DIR. В Linux уже есть специальный каталог для переводов PACKAGE_LOCALE_DIR=/usr/share/locale, для Windows ничего подобного не придумали, поэтому перевод будем держать рядом с приложением в каталоге: PACKAGE_LOCALE_DIR=../locale.
Потом устанавливаем кодировку перевода и наконец выбираем из какого файла в данный момент брать перевод:
ret = textdomain(PACKAGE);
Во время выполнения программы можно постоянно менять файл с переводами, вызывая textdomain().

Теперь в gtk_init() GTK+ определит для себя язык с переводом и возьмёт его из соответствующей папки.
Но файл с переводом непосредственно в папку PACKAGE_LOCALE_DIR  ложить нельзя, ведь переводы могут быть на разных языках, а файл у нас всегда называется одиноково. Поэтому в каталоге с переводами создаются папки для каждого языка (для русского - "ru"), внутри языка ещё одна папка LC_MESSAGES, а уже в ней файлы *.mo

Осталось самое главное - сделать файл с переводом image_viewer.mo. Для облегчения этой работы создано множество полезных утилит.

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

xgettext --from-code=UTF-8 -o image_viewer.pot  -d image_viewer  -k_ -c -C -f list.txt

Должен появиться файл image_viewer.pot, вот его начало:

# SOME DESCRIPTIVE TITLE.

# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2008-04-24 09:13+0600\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#. создаём диалог с одной кнопкой OK
#: create_menu.c:14
msgid "About program"
msgstr ""

#. Создать диалог открытия файла с двумя кнопками 'Open' и 'Cancel'
#: create_menu.c:47
msgid "Select graphic file"
msgstr ""

#. Первый элемент главного меню [с подменю] - File
#: create_menu.c:144
msgid "_File"
msgstr ""
...

Переименуем его в image_viewer.po файл и займёмся переводом.
Строки вроде Last-Translator и Language-Team переводчик должен заменить на свои реквизиты.
Для перевода фраз нужно заполнить строки msgstr""  во всех парах  msgid/msgstr, пример:
msgid "Open File"
msgstr "Открыть файл"

Теперь можно сформировать бинарный файл image_viewer.mo командой:

msgfmt image_viewer.po -o image_viewer.mo

Должен появится файл image_viewer.mo, который положим в папку /usr/share/locale/ru/LC_MESSAGES в Linuxe,
или в locale/ru/LC_MESSAGES в Windowse.
Теперь всё готово, можно запускать приложение, и в нём должен появиться русския язык, попробуйте убрать файл с переводом
и приложение будет на английском языке.

Но если мы изменим приложение, добавим новые строки с переводами, уберём или изменим старые, неужели придётся вручную всё делать заново? Конечно нет, об этом разработчики тоже позаботились, при изменениях снова создаём pot файл и запускаем команду обновления po файла:

msgmerge -U image_viewer.po image_viewer.pot

Новые, еще не переведённые строки из pot файла попадут в ро файл, в котором старые строки останутся переведёнными, а убранные  строки исчезнут в po файле. Теперь понятно, почему сначала создаётся pot файл,  а не сразу po.

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

Существует удобный визуальный редактор .po файлов poEdit, он совершенно бесплатен и доступен для многих платформ, а также в виде исходных кодов. Используя его, можно позабыть о msgfmt и msgmerge.
Страница poEdit: http://sourceforge.net/project/showfiles.php?group_id=27043

Для пользователей Windows: Если у Вас нет файлов xgettext.exe, msgfmt.exe и т.д., поставьте MinGW или Gygwin, там они есть.
Как вариант - можно скачать poEdit, там тоже есть все эти файлы.


Исходные коды приложения с файлами локализации доступны по ссылке: image-viewer1.4.tar.gz [15 кб]

Все вопросы, пожелания и замечания можно отсылать по адресу: comp.soft.prog.gtk-owner@subscribe.ru

 


В избранное