Текстовый домен, из которого нужно получить перевод. Таким образом, хотя main()
вызвала textdomain()
для установки собственного домена приложения, сообщения могут быть получены из других текстовых доменов. (Это наиболее применимо к сообщениям, которые могли бы быть, например, в текстовом домене библиотеки от третьей стороны.)
int category
Одна из описанных ранее категорий доменов (LC_TIME
и т.п.). Доменом по умолчанию является то, что было раньше установлено с помощью textdomain()
(«messages
», если textdomain()
никогда не вызывалась). Категорией по умолчанию является LC_MESSAGES
. Предположим, main()
делает следующий вызов:
textdomain("killerapp");
Тогда 'gettext("my message")
' эквивалентно 'dgettext("killerapp", "my message")
'. Обе функции, в свою очередь, эквивалентны 'dcgettext("killerapp", "my message", LC_MESSAGES)
'.
В 99,9% времени бывает нужно использовать gettext()
. Однако, другие функции обеспечивают гибкость при работе с другими текстовыми доменами или категориями локалей. Скорее всего, эта гибкость потребуется при программировании библиотек, поскольку автономная библиотека почти наверняка будет использовать свой собственный текстовый домен.
Все функции возвращают строки. Строка является либо переводом данного msgid
, либо, если перевода не существует, первоначальной строкой. Таким образом, всегда имеется какой-нибудь вывод, даже если это первоначальное сообщение (предположительно на английском). Например:
/* Каноническая первая программа, локализованная версия. */
#include
#include
#include
int main(void) {
setlocale(LC_ALL, "");
printf("%s\n", gettext("hello, world"));
return 0;
}
Хотя сообщение является простой строкой, мы не используем ее непосредственно в форматирующей строке printf()
, поскольку в общем перевод может содержать символы %
.
Вскоре, в разделе 13.3.4 «Упрощение использования gettext()
», мы увидим, как облегчить использование gettext()
в крупномасштабных, реальных программах.
Перевод во множественном числе доставляет дополнительные трудности. Простой код мог бы выглядеть примерно так:
printf("%d word%s misspelled\n", nwords, nwords > 1 ? "s" : "");
/* или */
printf("%d %s misspelled\n", nwords, nwords == 1 ? "word" : "words").
Это подходит для английского языка, но перевод становится трудным. Во-первых, во многих языках множественное число не образуется с такой же легкостью, как в английском (добавлением суффикса s
для большинства слов). Во-вторых, во многих языках, особенно в Восточной Европе, имеются несколько форм множественного числа, каждая из которых указывает на то, сколько объектов обозначает форма. Соответственно даже код наподобие следующего не будет достаточным:
if (nwords == l)
printf("one word misspelled\n");
else
printf("%d words misspelled\n", nwords);
Решением является параллельный набор процедур специально для форматирования множественных значений:
#include
char *ngettext(const char *msgid, const char *msgid_plural,
unsigned long int n);
char *dngettext(const char *domainname, const char *msgid,
const char *msgid_plural, unsigned long int n);
char *dcngettext(const char *domainname, const char *nmgid,
const char *msgid_plural, unsigned long int n,
int category)
Помимо первоначального аргумента msgid
, эти функции принимают дополнительные аргументы:
const char *msgid_plural
Строка по умолчанию для использования в качестве множественного числа. Вскоре будут примеры.
unsigned long int n
Число имеющихся элементов.
Список сообщений каждой локали указывает, как переводить множественные числа.[145] Функция ngettext()
(и ее варианты) проверяет n
и на основании спецификации в списке сообщений возвращает соответствующий перевод msgid
. Если в списке нет перевода для msgid
, или находясь в локали «С», ngettext()
возвращает msgid
, если 'n == 1
'; в противном случае она возвращает msgid_plural
. Таким образом, наш пример ошибочных слов выглядит следующим образом: