Статьи

Локализация PHP-приложений «Правильный путь», часть 4

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

Формы множественного числа

Ранние программисты, которые впервые написали сообщения для отображения пользователю, вскоре столкнулись с проблемой. При использовании переменных чисел в качестве части сообщения должна использоваться правильная форма подсчитанного существительного. Например, правильно сказать «1 файл удален», а «30 файл удален» — нет. Слово «файл» должно появиться в форме множественного числа, так как 30 является множественным числом на английском языке.

Оператор if часто является обходным решением для языков с простыми грамматическими падежами, таких как английский:

 <?php if ($i == 1) { echo $i . " file deleted."; } else { echo $i . " files deleted."; } 

Если бы все языки следовали тем же грамматическим номерам, что и английский, то такого кода, вероятно, было бы достаточно. Работа с формами множественного числа может быть неприятной, но проблема не будет уделена должного внимания. Но многие языки имеют более богатый набор грамматических чисел. Например, в польском языке формы множественного числа различаются для разных чисел:

  1 плик (файл)
 2-4 плики
 5-21 пликов
 22-24 плики 
 25-31 пликов
 ... 

Другим примером является арабский язык, который имеет по крайней мере 6 правил для определения множественных форм существительных. Очевидно, что жестко выраженный оператор if не является устойчивым решением в приложении, которое нацелено на несколько локалей!

К счастью, подход gettext к этой проблеме намного чище. Сначала вы предоставляете правило, которое задает формы множественного числа в заголовке домена, а затем вы предоставляете сообщения перевода для каждой из возможных форм множественного числа. Затем gettext использует правило для определения правильного перевода для отображения.

Множественные формы в действии

Чтобы иметь возможность использовать множественные формы внутри вашего домена, вам нужно написать правило для работы с множественным числом для целевого языка каталога; это правило будет включено в заголовок PO-файла, сообщая gettext, как обрабатывать множественные формы при поиске переводов.

Создайте новый каталог для польского языка ( pl_PL ), создайте каталог LC_MESSAGES и messages.po как описано в предыдущих частях этой статьи, так что теперь ваш сценарий Hello World поддерживает польский язык.

Откройте messages.po с помощью текстового редактора и добавьте следующую строку в его заголовок:

  "Множественные формы: nplurals = 3; множественное число = n == 1? 0: n% 10> = 2 && n% 10 <= 4 && (n% 100 <10 || n% 100> = 20)? 1: 2; п» 

и добавьте следующее к строкам сообщений:

 msgstr "% d файл удален."
 msgid_plural "% d файлов удалено."
 msgstr [0] "% d plik został usunięty."
 msgstr [1] "% d pliki zostały usunięte."
 msgstr [2] "% d plików zostało usuniętych." 

Сохраните файл, откройте его в Poedit, скомпилируйте и закройте его. Затем перейдите к test-locale.php и добавьте следующие строки:

 <?php echo "<br>"; echo ngettext("%d file deleted.", "%d files deleted.", 1); echo "<br>"; echo ngettext("%d file deleted.", "%d files deleted.", 2); echo "<br>"; echo ngettext("%d file deleted.", "%d files deleted.", 5); 

Теперь, когда вы запустите скрипт с параметром lang=pl_PL вы должны увидеть последние три строки, отображаемые на польском языке:

  1 plik został usuniętye.
 2 pliki zostały usunięte.
 5 лет работы. 

Правило множественных форм

Давайте подробнее рассмотрим правило множественных форм, добавленное в заголовочный раздел:

  "Множественные формы: nplurals = 3; множественное число = n == 1? 0: n% 10> = 2 && n% 10 <= 4 && (n% 100 <10 || n% 100> = 20)? 1: 2; п» 

Правило начинается с метки «Plural-Forms:», которая сообщает gettext, что следует использовать следующее правило, чтобы решить, какую форму использовать, учитывая число n . «Nplurals = 3» говорит gettext, что в этом языке есть три формы множественного числа для каждого существительного. Точка с запятой затем отделяет это от остальной части правила.

Следующая часть правила начинается с «множественного числа =» и является выражением, описывающим критерии выбора для форм множественного числа. Он использует типичный синтаксис языка Си с несколькими исключениями: отрицательные числа не допускаются, числа должны быть десятичными, и единственной допустимой переменной является n . В выражении допускаются пробелы, но не начинаются с обратной косой черты.

Предоставленное выражение будет оцениваться всякий раз, когда dngettext() одна из функций ngettext() , dngettext() или dcngettext() . Числовое значение, переданное этим функциям, затем подставляется для всех случаев использования переменной n . Результирующее значение должно быть больше или равно нулю, но меньше значения, указанного в качестве значения nplurals . Например, если nplurals заявляет, что есть три формы множественного числа, выражение для множественного числа не должно давать значение 5.

Конечное целое число, вычисленное выражением множественного числа, указывает, какую форму множественного числа выбрать для конкретного значения n , поэтому, если возвращаемое целое число из выражения равно 0 при замене, например, n=1 , будет использоваться форма множественного числа «0», если оно равно 1, используется форма множественного числа «1» и так далее.

Чтобы сказать, что формы множественного числа управляют словами: если n равно 1, будет использоваться форма «0», то есть plik . В противном случае, если n деленное на 10, возвращает что-то в диапазоне от 2 до 4, и если n деленное на 100, возвращает что-то меньше, чем 10 или больше или равно 20, будет использоваться форма «1», которая является pliki , иначе используйте форму « 2 ”, который является plików .

Вы можете найти правила множественных форм для различных языковых семейств и узнать больше о том, как перевести множественные формы в ваши домены, прочитав документацию по GNT gettext. В частности, разделы «множественные формы» и «перевод множественных форм» будут наиболее полезными.

Резюме

В этой части серии по локализации вы увидели одну из самых мощных функций gettext. Программисты, которые могут попытаться написать свои собственные встроенные операторы if каждый раз, когда им необходимо представить множественное сообщение, вскоре найдут такой подход громоздким и хрупким. Gettext абстрагирует логику, чтобы вы могли сохранить свой код в чистоте. Все, что вам нужно сделать, это определить правильное выражение для расчета индекса множественных форм для каждого языка, который вы переводите, предоставить пару msgid и msgid_plural, а затем набор индексированных msgstrs, из которых может выбрать gettext, а gettext позаботится обо всем остальном.

Следующая (и последняя) часть цикла покажет вам, как автоматизировать процесс извлечения строк msgid из вашего PHP-кода в файл шаблона, из которого вы можете создавать каталоги вашей отдельной локали.

Изображение через sgame / Shutterstock