Linux программирование в примерах - Роббинс Арнольд
Шрифт:
Интервал:
Закладка:
13.3.4. Упрощение использования gettext()
Вызов gettext() в исходном коде программы служит двум целям. Во-первых, он осуществляет перевод во время исполнения, что является в конце концов главным. Однако, он служит также для отметки строк, которые нужно перевести. Утилита xgettext читает исходный код программы и извлекает все оригинальные строки, которые нужно перевести. (Далее в главе мы кратко рассмотрим это.)
Рассмотрим все-таки случай, когда статические строки не используются непосредственно:
static char *copyrights[] = {
"Copyright 2004, Jane Programmer",
"Permission is granted ...",
/* ... Здесь куча легальностей */
NULL
};
void copyright(void) {
int i;
for (i = 0; copyrights[i] != NULL, i++)
printf("%sn", gettext(copyrights[i]));
}
Здесь мы хотели бы иметь возможность вывести переводы строк об авторских правах, если они доступны. Однако, как извлекающее устройство xgettext предполагает найти эти строки? Мы не можем заключить их в вызовы gettext(), поскольку это не будет работать во время компиляции:
/* ПЛОХОЙ КОД: не будет компилироваться */
static char *copyrights[] = {
gettext("Copyright 2004, Jane Programmer"),
gettext("Permission is granted ..."),
/* ... Здесь куча легальностей */
NULL
};
13.3.4.1. Переносимые программы: "gettext.h"
Здесь мы предполагаем, что вы хотите написать программу, которая может использоваться вместе с библиотекой GNU gettext на любой системе Unix, а не только GNU/Linux. Следующий раздел описывает, что сделать для программ только для GNU/Linux.
Пометка строк включает два шага. Первый заключается в использовании вспомогательного заголовка gettext.h, который поставляется с дистрибутивом GNU gettext. Этот файл обрабатывает несколько проблем переносимости и компиляции, упрощая использование gettext() в ваших собственных программах:
#define ENABLELNLS 1 /* ENABLE_NLS должен быть true, чтобы gettext() работала */
#include "gettext.h" /* Вместо <libintl.h> */
Если макрос ENABLE_NLS не определен[146] или установлен в ноль, gettext.h развертывает вызовы gettext() в первый аргумент. Это делает возможным перенос кода, использующего gettext(), на системы, в которых не установлены ни GNU gettext, ни собственная их версия. Помимо прочего, этот заголовочный файл определяет следующий макрос:
/* Вызов псевдофункции, который служит в качестве маркера для
автоматического извлечения сообщений, но не осуществляющий вызов
gettext(). Перевод времени исполнения осуществляется в другом
месте кода. Аргумент String должен быть символической строкой.
Сцепленные строки и другие строковые выражения не будут работать.
Разворачивание макроса не параметризовано, так что он подходит для
инициализации статических переменных 'char[]' или 'const char[]'. */
#define gettext_noop(String) String
Комментарий самодостаточен. С помощью этого макроса мы можем теперь перейти ко второму шагу. Мы перепишем код следующим образом:
#define ENABLE_NLS 1
#include "gettext.h"
static char copyrights[] =
gettext_noop("Copyright 2004, Jane Programmern"
"Permission is granted ...n"
/* ... Здесь куча легальностей */
"So there.");
void copyright(void) {
printf("%sn", gettext(copyrights));
}
Обратите внимание, что мы сделали два изменения. Во-первых, copyrights теперь является одной длинной строкой, созданной с использованием возможности конкатенации строк стандартного C. Эта простая строка затем включена в вызов gettext_noop(). Нам нужна одна строка, чтобы легальности могли быть переведены в виде одного элемента
Второе изменение заключается в непосредственном выводе перевода в виде одной строки в copyright().
К этому времени вы, возможно, думаете: «Вот здорово, набирать каждый раз 'gettext(...)' довольно неприятно». Ну, вы правы. Это не только создает лишнюю работу по набиванию, но также и затрудняет чтение исходного кода. Соответственно, когда вы используете заголовочный файл gettext.h, руководство GNU gettext рекомендует включить два других макроса с именами _() и N_() следующим образом:
#define ENABLE_NLS 1
#include "gettext.h"
#define _(msgid) gettext(msgid)
#define N_(msgid) msgid
Такой подход снижает накладные расходы по использованию gettext() всего лишь тремя дополнительными символами для переводимой строковой константы и всего лишь четырьмя символами для статических строк:
#include <stdio.h>
#define ENABLE_NLS 1
#include "gettext.h"