Как сделать локализацию php

Добавил пользователь Владимир З.
Обновлено: 05.10.2024

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

Список локалей для всех языков смотрите здесь.

  • Что переводить?
  • Как работает перевод в WordPress (теория)
  • Этап 1: Создадим свой плагин и переведем его
  • Этап 2: Перевод. Создание .mo .po файлов (под нужную локаль)
  • Обновление перевода (при изменении кода)
  • Создание POT файла
  • Подключение .mo файла перевода
  • Функций перевода
  • Ошибки при использовании функций перевода
  • Перевод множественного числа
  • В заключение
  • Размещение файла перевода в глобальной папке
  • Термины связанные с переводом
  • Плагин для перевода

Что переводить?

Прежде чем переходить к переводу, давайте определимся что нам нужно перевести, потому что это влияет на то, как нужно переводить.

Перевод темы/плагина из каталога WordPress

  1. Авторизоваться.
  2. Выбрать нужный язык перевода
  3. Найти плагин/тему которую нужно перевести.
  4. И прям на сайте переводить.

После того, как ваш перевод будет проверен, в админке вашего сайта на WordPress вы уведите обновления перевода для плагина/темы.

Перевод темы/плагина НЕ из каталога WordPress

В этом случае, нужно:

Перевод своей темы/плагина

Как работает перевод в WordPress (теория)

Начать надо с самого главного - это файлы перевода. Их бывает три: .mo .po .pot . PHP работает только с .mo файлом, .po и .pot - для людей и программ перевода.

.pot файл (Portable Object Template) — содержит оригинальные строки перевода (без перевода). Это шаблон перевода. POT файл является основой для создания .po файла (для создания перевода на любой язык). POT файл не является обязательным файлом, перевод можно делать и без него - это просто шаблон. Как создать .pot файл читайте ниже.

.po файл (Portable Object) — содержит оригинальные строки перевода и сам перевод этих строк. Его можно изменять в любом текстовом редакторе или в программе (например Poedit, с ней мы и будет работать ниже). Из .po файла автоматически создается .mo файл.

В WordPress для перевода используется только файл .mo . Во время генерации страницы этот файл подключается — из него создается PHP объект с переводами строк и помещается в память. Далее, при использовании функций перевода в коде, из этого объекта берется перевод запрашиваемой строки.

Вот так просто это работает.

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

Создать файл .mo и разместить его в папку темы/плагина. Или в глобальную папку переводов.

Подключить этот файл в теме/плагине с помощью одной из функций: load_theme_textdomain(), load_plugin_textdomain(). (Если размещается в глобальной папке подключать необязательно, WP сам это сделает).

Важно понимать, что при подключении .mo файла ему задается идентификатор (параметр $domain ) и такой идентификатор (домен) указывается для функций перевода строк. Домен связывает файл .mo с функциями перевода. Т.е. при переводе, в функции мы указываем из какого MO файла нужно получить перевод указанной строки. Пример:

Этап 1: Создадим свой плагин и переведем его

Если у вас уже есть готовая тема/плагин и её простой нужно перевести, переходите сразу к переводу (этап 2).

Чтобы процесс перевода был понятен, давайте создадим очень просто плагин и переведем его на русский язык. Назовем плагин my-translation-demo . У нас должна получиться такая структура плагина:

  1. В папке плагинов WordPress создадим папку my-translation-demo : /plugins/my-translation-demo .
  2. В этой папке создадим папку lang : /my-translation-demo/lang .
  3. Создадим файл my-translation-demo.php : /my-translation-demo/my-translation-demo.php .
  4. Добавим следующий код в созданный php файл:

Плагин готов! Зайдем в админку, активируем плагин, перейдем на страницу плагина.


В плагине используются все функции перевода, которые есть в WordPress. А также подключается еще не существующий .mo файл перевода myl10n-ru_RU.mo . После создания .mo файла плагин будет переведен (его мы создадим ниже).

Локализация названия плагина

Обратите внимание на параметры в заголовках плагина. Их нужно указать правильно, чтобы на странице плагинов работал перевод для названия и описания плагина.

Также для этого мы добавляем Название и Описание в функции перевода, чтобы парсер их нашел.

Также, WordPress использует параметр Text Domain: чтобы искать файл перевода в глобальной папке переводов. Там файл должен называться ДОМЕН-ПЕРЕВОДА_ЛОКАЛЬ.mo .

Этап 2: Перевод. Создание .mo .po файлов (под нужную локаль)

Чтобы создать MO файл, нам нужно иметь готовый PO файл, поэтому вся задача сводиться к созданию PO файла.

Создать PO файл можно через Poedit, но мы создадим его нестандартно - так гораздо проще:

Просто создадим файл с расширением .po в папке lang нашего плагина. Файл должен иметь название ДОМЕН_ПЕРЕВОДА-ЛОКАЛЬ.po , у нас это myl10n-ru_RU.po . (создавать файл нужно в кодировке UTF-8).

Именно такое название файла требует функция load_plugin_textdomain() и язык перевода (русский).

  • myl10n - это название нашего перевода (домен), который используется в функции load_plugin_textdomain() .
  • ru_RU - это язык перевода (локаль в WordPress, когда мы переключаемся на русский язык).

Для темы название файла должно быть ЛОКАЛЬ.po , подробнее см. ниже.

Откроем файл и скопируем в него следующий текст (при сохранении не забываем про кодировку UTF-8):

Пояснения по параметрам:

  • Project-Id-Version — название и версия проекта.
  • Last-Translator — имя и email переводчика.
  • Language-Team — название команды переводчиков.
  • Language — язык на который переводит файл.
  • Plural-Forms — форма множественного числа.
  • X-Poedit-KeywordsList — названия и параметры функций, строки из которых будут взяты для перевода. (тут указаны все возможные функции WordPress).
  • X-Poedit-Basepath — основная папка. Файлы в ней и в её подпапках будут просматриваться на наличие строк перевода. .. две точки тут означает, что основная папка находится на уровень выше папки текущего файла. Так как .po файл у нас лежит в /lang папке, то папка на уровень выше - это корневая папка плагина.
  • X-Poedit-SearchPath-0 — папки (относительно основной), в которых нужно просматривать файлы. . точка тут означает, что нужно просматривать все файлы.

X-Poedit-SearchPathExcluded-0 — тут можно указать папку (относительно основной), где не нужно просматривать файлы.

Все эти параметры можно изменить из программы Poedit, в любой момент. Для этого зайдите в Каталог > Свойства в Poedit.

Подробнее про формат PO файла смотрите в документации.

Откроем установленную программу Poedit и закинем в нее наш, пока еще пустой, файл .po .


В появившемся окне меняем настройки перевода (не обязательно) и жмем OK.


Ждем пока программа просканирует код и соберет из него все строки перевода.




Перевод готов и работает. Если теперь зайти на страницу плагина, то все строки будут переведены:


Почему удобно создавать .po файл вручную, а не через программу Poedit?

А чтобы создать файл через Poedit нужно:

  1. Открыть Poedit.
  2. Выбрать: Файл > Создать. .
  3. В появившемся окне выбрать язык на который переводим.
  4. Окно просто пропадет, а мы сидим тупим "а что дальше то делать?".
  5. А дальше, нужно нажать на кнопку Сохранить, в появившемся проводнике найти папку темы зайти в папку lang , вписать название файла myl10n-ru_RU.po и нажать ОК.
  6. Окно опять пропадает, а мы дальше тупим "что теперь делать?".

А теперь, нужно нажать кнопку: Извлечь из исходного кода. Откроется окно где нужно выставить настройки для PO файла. Все то что написано в коде для PO файла выше: название проекта, команда проекта, кодировки, папки где собирать строки перевода, ключевые слова для поиска строк перевода. В общем, тут надо будет повозиться и не ошибиться.

Обновление перевода (при изменении кода)

Тут все предельно просто:


Создание POT файла

.pot файл — это шаблон перевода. Это прям копия .po файла, только когда не переведена ни одна строка. Т.е. все строки перевода получены из файлов проекта, но еще ничего не переведено.

Из вышесказанного следует, чтобы создать POT файл нужно пройти всю процедуру по созданию .po файла, и под конец ничего не переводить, а зайти в Файл > Сохранить как и сохранить файл с расширением .pot .

Создать POT файл можно еще проще. Взять .po файл и поменять ему расширение на .pot . Это грубый метод, но такой файл с переведенными строками, тоже можно использовать как шаблон для создания перевода на любой язык (по крайней мере так работает Poedit).

Зачем нужен .pot файл?
Для того, чтобы был какой-то один файл, в котором всегда актуальные строки перевода. Чтобы использовать его как основу для создания перевода на очередной язык.

Повторюсь: если PO файл лежит в папке плагина, то POT файл не нужен, перевод можно создать из PO файла.

Подключение .mo файла перевода

Как подключить MO файл в плагине, уже есть в коде плагина выше. А тут я сделаю акцент на функциях WordPress для подключения этого файла. Функции:

load_plugin_textdomain( $domain, false, $plugin_rel_path ) Подключает MO файл из плагина. Обертка для load_textdomain() . Сначала ищет MO файл в общей папке переводов плагинов: /wp-content/language/plugins . Файл должен называться ДОМЕН_ПЕРЕВОДА-ЛОКАЛЬ.mo . load_muplugin_textdomain( $domain, $plugin_rel_path ) Подключает MO файл из MU плагина. Обертка для load_textdomain() . Сначала ищет MO файл в общей папке переводов плагинов: /wp-content/language/plugins . Файл должен называться ДОМЕН_ПЕРЕВОДА-ЛОКАЛЬ.mo . load_theme_textdomain( $domain, $path ) Подключает MO файл из темы. Обертка для load_textdomain() . Сначала ищет MO файл в общей папке переводов тем: /wp-content/language/themes . Файл должен называться ЛОКАЛЬ.mo (когда файл внутри темы) и ПАПКА_ТЕМЫ-ЛОКАЛ.mo (когда файл в общей папке). load_child_theme_textdomain( $domain, $path ) Подключает MO файл из дочерней темы. Обертка для load_theme_textdomain() . load_textdomain( $domain, $mofile ) Подключает MO файл из любого места (нужно указать полный путь до MO файла, вместе с названием файла).

Рассмотрим примеры подключения MO файлов.

Подразумевается, что код подключения будет расположен в основном файле плагина/темы или в файле, который находится в корневой директории плагина/темы. Если это не так, то __FILE__ нужно заменить на соответствующий путь.

Не обязательно подключать функции на хуки, но в примерах я все же сделал как рекомендуется.

Заметка: если файл перевода размещается в глобальной папке переводов, то эти функции можно не использовать. WordPress автоматически подключает файлы переводов из глобальной папки, опираясь на параметр Text Domain: в заголовке плагина.

Функций перевода

Как использовать функции перевода, уже есть в коде плагина выше. А тут я опишу каждую функцию (подробное описание читайте в описании функции).

__( $text, $domain ) Переводит указанный текст и возвращает его для обработки. _e( $text, $domain ) Переводит указанный текст и выводит его на экран. _x( $text, $context, $domain ) Переводит указанный текст с учетом указанного контекста и возвращает его для обработки. _ex( $text, $context, $domain ) Переводит указанный текст с учетом указанного контекста и выводит его на экран. _n( $single, $plural, $number, $domain ) Получает строку перевода единственного или множественного числа, ту которая соответствует указанному числу (1 комментарий, 2 комментария). _nx( $single, $plural, $number, $context, $domain ) Получает строку перевода единственного или множественного числа с учетом указанного контекста. _n_noop( $singular, $plural, $domain ) Функция пустышка. Аналог _n() . Используется когда нужно определить строки перевода для множественных числе, но использовать их где-то позднее в коде. Результат который возвразает функцию нужно обрабатывать функцией translate_nooped_plural(). Результат этой функции, например, удобно использовать в параметрах, когда мы заранее не знаем какое будет число и нужно сделать перевод позднее. _nx_noop( $singular, $plural, $context, $domain ) Тоже что _n_noop(), только с контекстом. esc_attr__( $text, $domain ) Перевод для значений атрибутов HTML тегов. Сокращение для esc_attr( __() ) . esc_attr_e( $text, $domain ) Тоже что esc_attr__() , только сразу выводит результат на экран. esc_html__( $text, $domain ) Перевод текста в котором могут быть HTML теги. Сокращение для esc_html( __() ) . esc_html_e( $text, $domain ) Тоже что esc_html__() , только сразу выводит результат на экран. меню

Ошибки при использовании функций перевода

Потому что программы умеют парсить только строки, но не переменные. Программы не анализируют что там в указанной переменной, а просто сканируют код как текст и вытаскивают строки для перевода.

Например, если указать

В 90% случаев HTML теги можно и нужно выносить за пределы строки перевода, рассмотрим несколько примеров:

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

Перевод множественного числа

В плагине выше, уже есть пример как переводить строки где используются числа. Тут я сделаю на этом акцент.

Для перевода строк с числами, когда нужно получить разные переводы в зависимости от числа, в WordPress используется функция _n( $single, $plural, $number, $domain ) или _nx() (с контекстом). Она вернет разный вариант строки в зависимости от указанного числа. Например:

Однако, чтобы все это правильно работало нужно:

В настройках .po файла правильно указать форму множественного числа. Мы её указали в параметре Plural-Forms :


В настройках .po файла правильно указать шаблоны поиска функций:

  • _n:1,2 - для функции _n() . 1 и 2 - это параметры функции для множ. и единс. числа.
  • _nx:1,2,4c - для функции _nx() . Тут 4с - значит что 4 параметр функции это строка контекста.


При переводе правильно перевести строки. Для русского языка нужно указать три варианта для перевода одной строки.


В заключение

Размещение файла перевода в глобальной папке

В WordPress есть общая папка для файлов перевода: /wp-content/languages . В ней лежат файлы перевода самого WordPress, а также могут лежать файлы переводов тем и плагинов (это работает в WordPress по умолчанию).

Все функции подключения MO файлов (кроме load_textdomain() ), сначала проверяют наличие файла перевода в общей папке, и только потом ищут его в папке плагина или темы. Это чем-то похоже на иерархию файлов шаблона, только тут иерархия файлов перевода.

Общая папка переводов для:

  • плагинов /wp-content/languages/plugins/ДОМЕН_ПЕРЕВОДА-ЛОКАЛЬ.mo .
  • тем /wp-content/languages/themes/ДОМЕН_ПЕРЕВОДА-ЛОКАЛЬ.mo .

Заметка: если файл перевода есть в глобальной папке, то в плагине его подключать через функции load_(plugin/theme)_textdomain() не обязательно! WordPress автоматически его подключит, опираясь на параметр Text Domain: в заголовке плагина.

Термины связанные с переводом

Некоторые термины, которые нужно знать. Это самые основные (сокращением этих терминов в WordPress названы некоторые функции и хуки):

Интернационализация (internationalization - i18n) — процесс изменения программного обеспечения, чтобы оно не было привязано к одному языку. Т.е. это весь комплекс функций и классов ядра WordPress позволяющий переводить сайт на разные языки.

Локализация (localization - l10n) — процесс добавления соответствующих ресурсов в ваше программное обеспечение для поддержки определенного языка/локали. Т.е. это сам процесс перевода на разные языки.

Плагин для перевода

Что такое локализация мы уже знаем. Что означает термин плюрализация?

Плюрализация

Плюрализация (pluralization) - придание чему-л. характера множественности, разнообразия на основе принципов плюрализма.

Singularize - образовывать форму единственного числа.

Так-то) Но, если просто, то этот термин подразумевает определение правильного окончания для слова в зависимости от численности, т.е. 1 депутат, 11 депутатов, 24 депутата..

Есть хороший ресурс, на котором собраны правила плюрализации для всех языков - Localization Guide  (или тут  ). В таблице указаны:

  • язык и его ISO обозначение;
  • nplurals - это число форм, которые может принимать существительное;
  • plural - это правило-алгоритм, по которому можно выбрать нужную нам форму слова по указанному количеству;

Для Russian ( ru ) мы имеем 3 возможных формы ( nplurals=3; ) и следующее правило:

plural определяет нужную позицию в заранее подготовленном нами массиве слов и находится в . Например:

Внимание!

Symfony 2 и Laravel 4

В Symfony 2 для локализации и плюрализации используется компонент Translation . Приведу пример описания plural форм для слова яблоко в словарях En и Ru :

Внимание! Вы не сможете описать все plural формы для русского языка через явные интервалы!

При описании plural форм в словаре, по умолчанию используются стандартные правила определения формы. Но, если вы опишете свой диапазон интервалов - форма слова будет определяться только на основе ваших правил!

Синтаксис определения явных интервалов (Explicit Interval Pluralization  ) в компоненте Translation не позволяет лаконично описать все формы склонения существительного для русского языка (и некоторых других). Так что используйте явные диапазоны только для En . Хотя Вам это должно понадобиться крайне редко, как например:

Примечание для Laravel 4

Laravel 4 использует тот же компонент Translation . Однако в Symfony 2 переменные для подстановки задаются в формате: %count% apple , а в Laravel 4 через двоеточие :count apple .

На написание статьи меня натолкнули костыль подсмотренный в одном проекте и этот комментарий  .

К сожалению данный компонент не решает проблему склонения слова перед числительным:

Реализация на PHP

Пример реализации twig -фильтра plural() . Также можно использовать как нативную PHP ф-цию:

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

Он работает отлично, он очень быстро на этом этапе, но моя разметка теперь завален метками языка php, и я не уверен, что принял правильное решение. Я никогда не делал этого раньше, поэтому я понятия не имею, с чем я с нетерпением жду. Также кажется, что к тому времени, когда я закончу, этот файл будет длиной в милю.

Это хороший способ сделать это? Есть ли лучший способ, который вы могли бы предложить?

Related of "Локализация PHP"

это то, что я делаю в своих cms:

все это было разработано с учетом производительности и совместимости .

в вашем случае строка в таком файле может выглядеть так:

в en.txt

в de.txt

Текущий язык может храниться в сеансе как $ _SESSION ["language"]; и использовать это как отправную точку. Затем вы можете читать переводы:

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

Какой язык в настоящее время используется (например, выбранный пользователем), может быть определен с помощью какой-либо глобальной доступной переменной.

Идея: Использовать языковые теги IETF в качестве языковых ключей.

Вы должны использовать механизм шаблонов, который поддерживает интернализацию.
Например, мой собственный механизм шаблонов позволяет мне делать что-то вроде:

И текст внутри этого маркера будет переведен. Это позволяет не открывать каждый раз, когда теги php в файле шаблона:

Локализация в Laravel

В этой статье мы расскажем всё, что вам нужно знать о том, как сделать локализацию в Laravel.

  1. Настройка локали.
  2. Типы файлов перевода.
  3. Расположение файлов перевода.
  4. Функции, хелперы и директивы.
  5. Как получить строку с переводом.
  6. Плейсхолдеры.
  7. Плюрализация.
  8. Как перевести языковые файлы установленных пакетов.

1. Настройка локали

Дефолтный язык вашего приложения хранится в конфигурационном файле config/app.php (‘locale’ => ‘en’,) .
Вы можете настроить резервный язык, который будет использоваться, если активный язык не содержит заданную строку перевода (‘fallback_locale’ => ‘en’,) .
Вы также можете изменить активный язык во время выполнения, используя App::setLocale().

2. Типы файлов перевода

Существует два типа файлов перевода:

  1. Файлы, которые возвращают массив ключевых строк.
  2. Файлы перевода JSON в виде ключей.

3. Расположение файлов перевода

Переводы хранятся в файлах каталога resources/lang.
Для массива ключевых строк каждый язык, поддерживаемый приложением, должен находиться в своём подкаталоге.
Для json перевода, если ваше приложение переведено на русский язык, вы должны создать файл resources/lang/ru.json.

4. Функции, хелперы и директивы.

Используйте App::getLocale() и App::isLocale(), чтобы определить текущую локаль и проверить, является ли локаль заданным значением.
Все функции, хелперы и директивы описаны в этой статье.

App::setLocale()
App::getLocale()
App::isLocale()
@lang()
__()
trans()
trans_choice()

5. Как получить строку с переводом

Если указанная строка перевода не существует, то __() вернет ключ строки перевода, в данном примере будет возвращено messages.welcome.

6. Плейсхолдеры (Placeholders)

Вы можете определить плейсхолдер в ваших переводах через префикс : (только для массива ключевых строк). Чтобы заполнить плейсхолдер при извлечении перевода, передайте массив для замены в качестве второго аргумента в функцию __().

7. Плюрализация

Используйте символ | для разделения единственного и множественного числа. Вы можете даже создать более сложные правила множественного числа для нескольких числовых диапазонов.
Используйте trans_choice() для получения строки с опциями плюрализации.
Вы также можете определять плейсхолдеры. Их можно заменить, передав массив в качестве третьего аргумента функции trans_choice().

8. Как перевести языковые файлы установленных пакетов

Некоторые пакеты могут поставляться со своими языковыми файлами. Вместо того, чтобы изменять основные файлы пакета, вы можете переопределить их, поместив файлы в каталог resources/lang/vendor/ / .

Читайте также: