Книга: Linux программирование в примерах
13.3.8. Создание переводов
13.3.8. Создание переводов
После интернационализации программы необходимо подготовить переводы. Это осуществляется с помощью нескольких инструментов уровня оболочки. Мы начнем с интернационализированной версии ch06-echodate.c
из раздела 6.1.4 «Преобразование разложенного времени в time_t
»:
/* ch13-echodate.c --- демонстрация переводов */
#include <stdio.h>
#include <time.h>
#include <locale.h>
#define ENABLE_NLS 1
#include "gettext.h"
#define _(msgid) gettext(msgid)
#define N_(msgid) msgid
int main (void) {
struct tm tm;
time_t then;
setlocale(LC_ALL, "");
bindtextdomain("echodate", ".");
textdomain("echodate");
printf("%s", _("Enter a Date/time as YYYY/MM/DD HH:MM:SS : "));
scanf("%d/%d/%d %d:%d:%d",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
&tm.tm_hour, &tm.tm_min, &tm.tm_sec);
/* Проверка ошибок для краткости опущена. */
tm.tm_year -= 1900;
tm.tm_mon -= 1;
tm.tm_isdst = -1; /* О летнем времени ничего не известно */
then = mktime(&tm);
printf(_("Got: %s"), ctime(&then));
exit(0);
}
Мы намеренно использовали "gettext.h"
, а не <gettext.h>
. Если наше приложение поставляется с отдельной копией библиотеки gettext
, тогда "gettext.h"
найдет ее, избежав использования системной копии. С другой стороны, если имеется лишь системная копия, она будет найдена, если локальной копии нет. Общеизвестно, что ситуация усложнена фактом наличия на системах Solaris библиотеки gettext
, которая не имеет всех возможностей версии GNU.
Переходя к созданию переводов, первым шагом является извлечение переводимых строк. Это осуществляется программой xgettext
:
$ xgettext --keyword=_ --keyword=N_
> --default-domain=echodate ch13-echodate.с
Опции --keyword
сообщает xgettext
, что нужно искать макросы _()
и N_()
. Программа уже знает, как извлекать строки из gettext()
и ее вариантов, а также из gettext_noop()
.
Вывод xgettext
называется переносимым объектным файлом. Имя файла по умолчанию messages.ро
, что соответствует текстовому домену по умолчанию "messages"
. Опция --default-domain
обозначает текстовый домен для использования в имени выходного файла. В данном случае, файл назван echodate.ро
. Вот его содержание:
# SOME DESCRIPTIVE TITLE. /* Шаблон, нужно отредактировать */
# Copyright (С) 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 VERSIONn"
"Report-Msgid-Bugs-To: n"
"POT-Creation-Date: 2003-07-14 18:46-0700n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONEn"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>n"
"Language-Team: LANGUAGE <[email protected]>n"
"MIME-Version: 1.0n"
"Content-Type: text/plain; charset=CHARSETn"
"Content-Transfer-Encoding: 8bitn"
#: ch13-echodate.c:19 /* Местоположение сообщения */
msgid "Enter a Date/time as YYYY/MM/DD HH:MM:SS : " /* Оригинальное
сообщение */
msgstr "" /* Здесь перевод */
#: ch13-echodate.с:32 /* To же самое для каждого сообщения */
#, с-format
msgid "Got: %s"
msgstr ""
Этот первоначальный файл используется повторно для каждого перевода. Таким образом, это шаблон для переводов, и по соглашению, для отображения этого факта он должен быть переименован с расширением .pot
(portable object template — переносимый объектный шаблон):
$ mv echodate.ро echodate.pot
He владея свободно несколькими языками, мы решили перевести сообщения на свинский латинский. Следующим шагом является создание перевода. Это осуществляется копированием файла шаблона и добавлением к новой копии перевода:
$ cp echodate.pot piglat.po
$ vi piglat.po /* Добавить переводы, используя любимый редактор */
Имя по соглашению должно быть язык.po
, где язык
является стандартным международным сокращением из двух или трех букв для обозначения языка. Иногда используется форма язык_страна.po
: например, pt_BR.po
для португальского в Бразилии. Поскольку свинский латинский не является настоящим языком, мы назвали файл piglat.ро
.[147] Вот содержание после добавления перевода:
# echodate translations into pig Latin
# Copyright (C) 2004 Prentice-Hall
# This file is distributed under the same license as the echodate package.
# Arnold Robbins <[email protected]> 2004
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: echodate 1.0n"
"Report-Msgid-Bugs-To: [email protected]"
"POT-Creation-Date: 2003-07-14 18:46-0700n"
"PO-Revision-Date: 2003-07-14 19:00+8n"
"Last-Translator: Arnold Robbins <[email protected]>n"
"Language-Team: Pig Latin <[email protected]>n"
"MIME-Version: 1.0n"
"Content-Type: text/plain; charset=ASCIIn"
"Content-Transfer-Encoding: 8bitn"
#: ch13-echodate.с:19
msgid "Enter a Date/time as YYYY/MM/DD HH:MM:SS : "
msgstr "Enteray A Ateday/imetay asay YYYY/MM/DD HH:MM:SS : "
#: ch13-echodate.c:32
#, c-format
msgid "Got: %s"
msgstr "Otgay: %s"
Хотя можно было бы произвести линейный поиск в переносимом объектном файле, такой поиск был бы медленным. Например, в gawk
имеется примерно 350 отдельных сообщений, а в GNU Coreutils — свыше 670. Линейный поиск в файле с сотнями сообщений был бы заметно медленным. Поэтому GNU gettext
использует для быстрого поиска сообщений двоичный формат. Сравнение осуществляет msgfmt
, выдавая объектный файл сообщений:
$ msgfmt piglat.po -о piglat.mo
При сопровождении программы изменяются строки, используемые программой: добавляются новые, другие удаляются или изменяются. По крайней мере, может измениться положение строки в исходном файле. Таким образом, файлы переводов .ро
, вероятно, устареют. Программа msgmerge
объединяет старые файлы переводов с новым файлом .pot
. Затем результат может быть обновлен. Этот пример выполняет объединение и повторное компилирование:
$ msgmerge piglat.po echodate.pot -o piglat.new.po /* Объединить файлы */
$ mv piglat.new.po piglat.po /* Переименовать результат */
$ vi piglat.po /* Модернизировать перевод */
$ msgfmt piglat.po -o piglat.mo /* Восстановить файл .mo */
Откомпилированные файлы .mo
помещаются в файл base/locale/category/textdomain.mo
. На системах GNU/Linux base
является /usr/share/locale
. locale
является обозначением языка, например, 'es
', 'fr
' и т.д. category
является категорией локали; для сообщений это LC_MESSAGES
. textdomain
является текстовым доменом программы, в нашем случае это echodate
. В качестве реального примера в /usr/share/locale/es/LC_MESSAGES/coreutils.mo
находится перевод GNU Coreutils на испанский.
Функция bindtextdomain()
изменяет в местоположении часть base
. В ch13-echodate.c
мы меняем ее на '.
'. Таким образом, нужно создать соответствующие каталоги и поместить туда перевод на свинский латинский:
$ mkdir -р en_US/LC_MESSAGES /* Нужно использовать реальную локаль */
$ cp piglat.mo en_US/LC_MESSAGES/echodate.mo /* Поместить файл в нужное место */
Должна использоваться реальная локаль[148]; мы «притворяемся» использующими "en_US
". Разместив перевод, устанавливаем соответствующим образом LC_ALL
, скрещиваем пальцы и запускаем программу:
$ LC_ALL=en_US ch13-echodate /* Запуск программы */
Enteray A Ateday/imetay asay YYYY/MM/DD HH:MM:SS : 2003/07/14 21:19:26
Otgay: Mon Jul 14 21:19:26 2003
Последнюю версию GNU gettext
можно найти в каталоге дистрибутива GNU gettext
.[149]
Этот раздел лишь слегка коснулся поверхности процесса локализации. GNU gettext
предоставляет множество инструментов для работы с переводами, и в особенности для облегчения поддержания современности переводов по мере развития исходного кода программы. Процесс ручного обновления переводов осуществим, но утомителен. Эта задача легко автоматизируется с помощью make
; в частности, GNU gettext
хорошо интегрируется для обеспечения этой возможности с Autoconf и Automake, снимая с программиста значительный груз по разработке.
Рекомендуем прочесть документацию GNU gettext
, чтобы больше узнать как об этих проблемах в частности, так и о GNU gettext
в общем.
- 13.3.1. Установка текстового домена: textdomain()
- 13.3.2. Перевод сообщений: gettext()
- 13.3.3. Работа с множественными числами: ngettext()
- 13.3.4. Упрощение использования gettext()
- 13.3.5. Перестановка порядка слов с помощью printf()
- 13.3.6. Тестирование переводов в персональном каталоге
- 13.3.7. Подготовка интернационализированных программ
- 13.3.8. Создание переводов
- 13.3.6. Тестирование переводов в персональном каталоге
- 5.5. Оплата посредством почтовых переводов
- Создание файлов с блокировкой
- Создание свободно позиционируемых элементов
- 12. Лекция: Создание приложений с графическим интерфейсом пользователя.
- Создание объектов Collection
- 7.4.2.4. Создание своего первого LiveCD
- 4.2. Создание трехмерной модели и построение горизонтальной проекции детали
- 7.4.2. Создание собственного LiveCD
- Создание пользователя и группы на рабочей станции
- Создание корня документа:
- Создание многофайловой базы данных