Перейти к основному содержимому

Для программиста

Механика

В этом разделе описывается, как реализовать поддержку родного языка в программе или библиотеке, которая является частью дистрибутива PostgreSQL. В настоящее время это касается только программ на C

Добавление языковой поддержки для программы

  1. Вставьте этот код в начало программы:

    #ifdef ENABLE_NLS
    #include <locale.h>
    #endif

    ...

    #ifdef ENABLE_NLS
    setlocale(LC_ALL, "");
    bindtextdomain("progname", LOCALEDIR);
    textdomain("progname");
    #endif

    progname может быть выбрано произвольно.

  2. Везде, где встречается сообщение, претендующее на перевод, необходимо вставить вызов gettext(). Например:

    fprintf(stderr, "panic level %d\n", lvl);

    Необходимо заменить на:

    fprintf(stderr, gettext("panic level %d\n"), lvl);

    Если поддержка NLS не настроена, gettext не работает

    Это приводит к большому количеству ошибок. Одним из распространенных способов сокращения является использование:

    #define _(x) gettext(x)

    Другое решение возможно, если программа осуществляет большую часть своих коммуникаций через одну или несколько функций, например ereport() в бэкенде. Тогда эта функция внутренне вызывает gettext для всех входных строк.

  3. Добавьте файл nls.mk в каталог с источниками программы. Этот файл будет считываться сборочным файлом (makefile). В нем нужно назначить следующие переменные:

    • CATALOG_NAME – имя программы, как указано в вызове textdomain();
    • AVAIL_LANGUAGES – список выполненных переводов – изначально пустой;
    • GETTEXT_FILES – список файлов, которые содержат переводимые строки, т.е., которые помечены gettext или альтернативным решением. В конце концов, это будет почти все исходные файлы программы. Если этот список становится слишком длинным, необходимо сделать первый «файл» +, а второе слово - файл, который содержит одно имя файла в строке;
    • GETTEXT_TRIGGERS – инструменты, генерирующие каталоги сообщений для переводчиков, должны знать, какие вызовы функций содержат переводимые строки. По умолчанию известны только вызовы gettext(). Если вы использовали _ или другие идентификаторы, их нужно перечислить здесь. Если переводимая строка не является первым аргументом, элемент должен иметь форму func:2 (для второго аргумента). Если у вас есть функция, которая поддерживает множественные сообщения, элемент должен выглядеть как func:1,2 (определяющий аргументы сообщений в единственном и множественном числах).

Система сборки автоматически займется сборкой и установкой каталогов сообщений

Рекомендации по написанию сообщений

Ниже приведены несколько рекомендаций по написанию легко переводимых сообщений:

  • Не стройте предложения во время выполнения, например:

    printf("Files were %s.\n", flag ? "copied" : "removed");

    Порядок слов в предложении может отличаться в других языках. Кроме того, даже если помните, что нужно вызвать gettext() для каждого фрагмента, фрагменты по отдельности могут переводиться не очень хорошо. Лучше продублировать небольшой код, чтобы каждое переводимое сообщение представляло собой единое целое. Во время выполнения в текст сообщения следует вставлять только числа, имена файлов и подобные переменные времени выполнения.

  • По тем же причинам это не сработает:

    printf("copied %d file%s", n, n!=1 ? "s" : "");

    Потому что в нем предполагается, как образуется множественное число. Если думаете, что сможете решить это таким способом:

    if (n==1)
    printf("copied 1 file");
    else
    printf("copied %d files", n):

    возможно, будете разочарованы. В некоторых языках существует более двух форм с особыми правилами. Часто лучше составить сообщение так, чтобы избежать этой проблемы, например, так:

    printf("number of copied files: %d", n);

    Если хотите создать сообщение с правильным множественным числом, поддержка этого есть, но она немного неудобна. При генерации основного или подробного сообщения об ошибке в ereport() можно написать что-то вроде этого:

    errmsg_plural("copied %d file",
    "copied %d files",
    n,
    n)

    Первый аргумент - строка формата, соответствующая английской форме единственного числа, второй - строка формата, соответствующая английской форме множественного числа, а третий - целочисленное управляющее значение, определяющее, какую форму множественного числа использовать. Последующие аргументы форматируются в соответствии со строкой формата обычным образом. (Обычно управляющее значение множественного числа также является одним из форматируемых значений, поэтому его приходится записывать дважды). В английском языке имеет значение только то, равно ли n 1 или не равно 1, но в других языках может быть множество различных форм множественного числа. Переводчик рассматривает две английские формы как группу и имеет возможность предоставить несколько строк-заменителей, причем подходящая будет выбрана на основе значения n.

    Если необходимо преобразовать во множественное число сообщение, которое не направляется непосредственно в отчет errmsg или errdetail, используйте базовую функцию ngettext. См. документацию по gettext.

  • Если необходимо что-то сообщить переводчику, например, о том, как сообщение должно сочетаться с другими выводами, предварите вхождение строки комментарием, начинающимся с translator, например:

    /* translator: This message is not what it seems to be. */

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