Обратите внимание, что мы сделали два изменения. Во-первых,
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"
#define _(msgid) gettext(msgid)
#define N_(msgid) msgid
...
static char copyrights[] =
N_("Copyright 2004, Jane Programmer\n"
"Permission is granted ...\n"
/* ... Здесь куча легальностей */
"So there.");
void copyright(void) {
printf("%s\n", gettext(copyrights));
}
int main(void) {
setlocale(LC_ALL, ""); /* gettext.h gets <locale.h> for us too */
printf("%s\n", _("hello, world"));
copyright;
exit(0);
}
Эти макросы скромны, и на практике все GNU программы, использующие GNU
gettext
, следуют этому соглашению. Если вы собираетесь использовать GNU
gettext
, вам тоже нужно следовать этому соглашению.
13.3.4.2. Только GLIBC:
<libintl.h>
Для программ, которые будут использоваться лишь на системах с GLIBC, использование заголовочных файлов и макросов похоже, но проще:
#include <stdio.h>
#include <libintl.h>
#define _(msgid) gettext(msgid)
#define N_(msgid) msgid
/* ...
все остальное то же ... */
Как мы видели ранее, заголовочный файл
<libintl.h>
объявляет
gettext
и другие функции. Вам все равно нужно определять
_
и
N_
, но не нужно беспокоиться о
ENABLE_NLS
или включении с исходным кодом вашей программы файла
gettext.h
.
13.3.5. Перестановка порядка слов с помощью
printf
Иногда при переводах порядок слов, естественный для английского языка, не подходит в других языках. Например, на английском прилагательные идут перед определяемыми существительными, а на многих других языках — после. Таким образом, следующий код представляет проблему:
char *animal_color, *animal;
if (...) {
animal_color = _("brown");
animal = _("cat");
} else if (...) {
...
} else {
...
}
printf(_("the %s %s looks at you enquiringly.\n"), animal_color, color);
Здесь форматирующая строка,
animal_color
и
animal
неудачно включены в вызов
gettext
. Однако, после перевода утверждение будет неверным, поскольку порядок аргументов не может быть изменен во время исполнения.
Чтобы обойти это, версия семейства
printf
POSIX (но не ISO С) допускает использовать в описателе формата указатель положения. Он принимает форму десятичного числа, за которым следует символ
$
, сразу после начального символа
%
. Например
printf("%2$s, %1s\n", "world", "hello")
;
Указатель положения обозначает аргумент из списка, который следует использовать, отсчет начинается с 1 и не включает саму форматирующую строку. Этот пример выводит знаменитое сообщение '
hello, world
' в правильном порядке.
GLIBC и Solaris реализуют эту возможность. Поскольку это часть POSIX, если
printf
вашего поставщика Unix не реализует ее, она вскоре должна появиться.
За указателем положения могут следовать любые обычные флаги
printf
, указатели ширины полей и точности. Вот правила для использования указателей положения:
• Форма с указателем положения не может смешиваться с формой без нее. Другими словами, или каждый указатель формата включает указатель положения, или ни один его не включает. Конечно,