20 February 2012

Yandex Translate API: PHP и небольшое исследование сервиса

PHP
Sandbox
После закрытия Гуглом своих API для перевода проблема поиска онлайн-сервис для машинного перевода стала особенно актуальной.
В Интернете много сервисов перевода с громкими именами: Промт, Прагма и пр. Нет никакой проблемы в PHP смоделировать обращения к страницам сервисов и получить результаты перевода. Но есть проблема: почти все сервисы в ответ на простой GET или POST запрос отдают не результат перевода, а целиком страницу во всей красе, начиная с DTD. Как говорят у нас на Украине, “дурных нэма”.
После анализа было выяснено, что есть только два сервиса, которые отдают в ответ на запрос только результат перевода: Яндекс и Bing от Microsoft.

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

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

Bing этим не страдает, но зато:
— переводы, в которых участвует русский или украинский, страдают сильным “акцентом” и обязательно требуют правки
— использование Bing в режиме free имеет некоторые ограничения
— для использования Bing требуется некий идентификатор веб-приложения — appID, само по себе получение которого не связано с юридическими трудностями — это фактически просто регистрация, но которая представляет собой увлекательный и длинный квест.


Итак, какие задачи должна решать библиотека/класс для перевода?

1. Получение языков, с которых и на которые можно переводить, и их допустимых комбинаций
2. Собственно сам перевод текста

Сразу ремарка. Из соображений здравого смысла ясно, что в один заход перевести “Войну и мир” не получится. Приземление на технический уровень дает более четкое ограничение: переводчик Янекса использует GET-запросы, соотв. — очень грубо — примерно 2000 символов за один раз, не более. Это совсем немного, примерно 2 небольших абзаца текста, даже небольшая публикация на сайте выйдет за эти рамки.
Отсюда следующая задача:

3. Перевод больших фрагментов текста.

Ну и представим задачу: мультиязычный сайт. Гонять каждый раз переводчик за переводом элементов интерфейса и прочих текстов на сайте — это, мягко говоря, неразумно. Соответственно задача:

4. Кеширование.

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

Итак, Яндекс.Переводчик
Исходники доступны в репозитории Гугла и задокументированы на русском языке.

1) Языки перевода.
Класс Yandex_Translate содержит три метода с говорящими названиями:
yandexGetLangsPairs() — получение доступных пар языков FROM->TO
yandexGet_FROM_Langs()
yandexGet_TO_Langs()

Пример (этот пример — полный, ниже подключение файлов, создание экземпляра класса, элементы форматирования вывода и пр. буду опущены.)

<?php
include_once 'Yandex_Translate.php';
$pairs = $translator->yandexGetLangsPairs();
print_r($pairs);


Получим вот такие комбинации (они, кстати, меняются время от времени):
[0] => en-ru
[1] => ru-en
[2] => ru-uk
[3] => uk-ru
[4] => pl-ru
[5] => ru-pl
[6] => tr-ru
[7] => ru-tr
[8] => de-ru
[9] => ru-de
[10] => fr-ru
[11] => ru-fr
[12] => it-ru
[13] => es-ru
[14] => ru-es

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

Два других метода дают языки по отдельности и могут быть использованы, например, для формирования селектов или других элементов выбора.

2. Перевод
Один метод, три аргумента: с какого, на какой и собственно переводимый текст.
Обратите внимание также на важное свойство eolSymbol — окончание строки. Если его установить неверно, не будет форматирования выходного текста (см. комментарии в исходниках).

Пример:
$text = file_get_contents('text.txt');
$translatedText = $translator->yandexTranslate('ru', 'uk', $text);
echo $translatedText;


Начало файла text.txt:
Марио Пьюзо Крестный отец
Посвящается Энтони Клири
КНИГА ПЕРВАЯ
За всяким большим состоянием кроется преступление.


Результат выполнения скрипта:
Маріо п’юзо Хрещений батько
Присвячується Ентоні Клірі
ПЕРША КНИГА
За кожним великим станом криється злочин.


Сразу обратим внимание — перевод хороший, но правка требуется.

3. Перевод больших текстов
Для перевода больших текстов служит абстрактный класс Big_Text_Translate
Принцип следующий.
Сначала текст разбивается на предложения, используя разделитель sentensesDelimiter — по умолчанию точка.
Правильнее конечно было бы использовать точку с пробелом, но в реальных, например, “каментах” пробел после точки запросто может “ацуцтвовать”. Поэтому так, проблем в реальной работе это не вызывает, но свойство можно переопределить.
Затем предложения собираются в текстовые фрагменты, размер которых не превышает заданного значения symbolLimit — по умолчанию 2000.
Текстовые фрагменты готовы для перевода, семантика и форматирование — сохранены. Формированием фрагментов занимается статический метод toBigPieces, на выходе — массив.
Метод fromBigPieces склеивает переведенные фрагменты обратно в цельный текст.
Пример

$bigText = file_get_contents('text_big.txt');
$textArray = Big_Text_Translate::toBigPieces($bigText);

$numberOfTextItems = count($textArray);

foreach ($textArray as $key=>$textItem){

//Показываем прогресс перевода
echo 'Переведен фрагмент '.$key.' из '.$numberOfTextItems;
flush();

$translatedItem = $translator->yandexTranslate('ru', 'uk', $textItem);
$translatedArray[$key] = $translatedItem;
}

$translatedBigText = Big_Text_Translate::fromBigPieces($translatedArray);

echo $translatedBigText;

Выполнение примера пробуйте сами — все есть в репозитории.

Уважаемые хабражители! Если материал представляет интерес, то готовится его продолжение, включающее разделы:
— кеширование результатов перевода в несколько уровней
— работа с сервисом Bing
— полноценное демо: построение мультиязычного сайта.
Tags:переводYandexYandex APIYandex translate
Hubs: PHP
+26
41.4k 157
Comments 20