Многоязычная PHP функция перевода gtranslate()

Ещё 26 мая 2011 года Google закрыл свой Translate API, но не отказался от использования того же JSON в переводчике. Поэтому мы имеем неофициальную возможность, использовать данный источник для создания PHP-функции, которая позволяет переводить слова, фразы и целые документы с одного языка на другой. В этой статье я хочу привести пример своей PHP-функции многоязычного перевода gtranslate(). Ничего сложного в ней нет, но тем не менее.

А начну я с того, что переводчик Google достаточно динамичный сервис. Помимо использования кнопки «Перевести», перевод, вводимых в форму данных, может осуществляться и автоматически, т.е. налету. Каждый такой перевод, это запрос к серверу. Таким образом, можно сказать, что наш запрос не создаст особой проблемы. Тем не менее, злоупотреблять данной возможностью, пожалуй, не стоит.

В своей функции перевода я использую file_get_contents() с контекстным потоком для подмены user_agent, у меня это Firefox 26, но Вы можете прописать и свой. В целом, этого должно хватить для придания запросу естественного вида. В тоже время, таким образом, мы не сможем скрыть реферер или IP-адрес и это стоит учесть.

Для получения результата в формате JSON параметру client надо присвоить значение x. В параметре q передаётся текст, который надо перевести. Параметр sl содержит идентификатор языка с которого осуществляется перевод, а tl – идентификатор языка на который осуществляется перевод. И ещё, результат будет в кодировке UTF-8.

В принципе, ничего сложного, а вот и PHP-код функции:

function gtranslate($str, $lang_from, $lang_to) {
  $query_data = array(
    'client' => 'x',
    'q' => $str,
    'sl' => $lang_from,
    'tl' => $lang_to
  );
  $filename = 'http://translate.google.ru/translate_a/t';
  $options = array(
    'http' => array(
      'user_agent' => 'Mozilla/5.0 (Windows NT 6.0; rv:26.0) Gecko/20100101 Firefox/26.0',
      'method' => 'POST',
      'header' => 'Content-type: application/x-www-form-urlencoded',
      'content' => http_build_query($query_data)
    )
  );
  $context = stream_context_create($options);
  $response = file_get_contents($filename, false, $context);
  return json_decode($response);
}

Обращаю Ваше внимание на то, что функция gtranslate() вернёт объект с соответствующими свойствами. Таким образом, функция получается достаточно гибкой и динамичной.

Ниже я приведу пример получения значения строки перевода:

$gt = gtranslate('пример использования машинного масла', 'ru', 'en');
echo $gt->sentences['0']->trans; // вернёт строку: example of the use of engine oil

Для того чтобы просмотреть весь перечень свойств и значений, Вы можете использовать тот же var_dump():

echo '<pre>'; var_dump($gt); echo '</pre>';

В случае с приведённым примером, Вы получите следующее:

object(stdClass)#1 (3) {
  ["sentences"]=>
  array(1) {
    [0]=>
    object(stdClass)#2 (4) {
      ["trans"]=>
      string(32) "example of the use of engine oil"
      ["orig"]=>
      string(69) "пример использования машинного масла"
      ["translit"]=>
      string(0) ""
      ["src_translit"]=>
      string(38) "primer ispol'zovaniya mashinnogo masla"
    }
  }
  ["src"]=>
  string(2) "ru"
  ["server_time"]=>
  int(1)
}

Обратите внимание, что Google переводчик возвращает результат разбитый на предложения (англ. sentences), я бы назвал фрагменты. При большом объёме данных, мы получим целый массив таких предложений. Обработать их можно, например, так:

foreach ( $gt->sentences as $sentence ) {
  echo '<p>'. $sentence->trans .'</p>';
  echo '<p>'. $sentence->orig .'</p>';
}

С учётом того, что в моей функции теперь используется метод передачи данных POST, проблем с большими данными возникнуть не должно.

Интересным здесь является и параметр src_translit, которое содержит транслит фрагмента, в данном случае написание русского текста латинскими буквами. Впрочем, для этого лучше использовать локальный вариант, см. php-функцию translit(). Правда последняя заточена в большей степени для создания ЧПУ.

Возвращаясь же к Google переводчику, стоит ещё сказать и о параметре dict, который появляется при переводе одного слова. Он будет содержать ряд дополнительных словарных данных, вроде определения части речи, вариантов перевода и т.д., но тут смотрите сами.

На этом у меня всё. Спасибо за внимание. Удачи!

Максим
Максим комментирует...

Осталось лишь понять, куда это всё присобачить...

Константин Кирилюк
Константин Кирилюк комментирует...

@Максим один из вариантов - генерация ЧПУ. Конечно, можно использовать и локальный транслит, но я думаю куда как результативней расширите ключевика за счет ЧПУ на английском. На blogger этого конечно не сделать, я сам, вручную, перевожу в транслите нужный фрагмент и прописываю постоянную ссылку. Если же речь идёт о своём хостинге, то вполне возможно делать перевод заголовка и генерировать ЧПУ на английском. К слову, здесь будет не лишним использовать Ajax, т.к. сервис может быть и не доступен.

Ya
Ya комментирует...

Когда предложений несколько, почему-то выдает только первое. Использую такую конструкцию: $gt->sentences['0']->trans;
Как получить весь текст целиком в одну переменную? Спасибо!

Константин Кирилюк
Константин Кирилюк комментирует...

2Ya для того чтобы ответить на Ваш вопрос нужно разобраться, что такое объект (object) и что такое массив (array). Или всё таки стоит начать с того, что такое переменная?

Ya
Ya комментирует...

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

Константин Кирилюк
Константин Кирилюк комментирует...

2Ya: да, GET запрос невелик, но можно использовать POST. Для этого понадобится немного изменить функцию, а точнее значения переменных $filename и $options:

$filename = 'http://translate.google.ru/translate_a/t';
$options = array('http' => array('user_agent' => 'Mozilla/5.0 (Windows NT 6.0; rv:26.0) Gecko/20100101 Firefox/26.0','method' => 'POST','header'=>'Content-type: application/x-www-form-urlencoded','content'=>http_build_query($query_data)));

Правда следует учесть, что Google Translate разбивает большой текст на предложения. Вот вариант вывода предложений перевода и оригинала:

foreach ( $gt->sentences as $sentence ) {
echo '<p>'. $sentence->trans .'</p>';
echo '<p>'. $sentence->orig .'</p>';
}

Ya
Ya комментирует...

Константин, спасибо, Вы мне здорово помогли! :)

Денис Сташук
Денис Сташук комментирует...

чет не работает

Константин Кирилюк
Константин Кирилюк комментирует...

2Денис Сташук что именно не работает?.. Проверил, вроде все примеры работают.

Siren DS
Siren DS комментирует...

Удивительно как здорово все работает ! Думаю gtranslate() и вправду будет на много полезнее для чпу чем translit() ! Спасибо вам огромное за вашу работу !

Константин Кирилюк
Константин Кирилюк комментирует...

2Siren DS да, тема интересная, но зависимость от онлайн сервиса тоже надо учитывать ...

Назир Гебеков
Назир Гебеков комментирует...

В прошлом коде транслитерации вырезался пробел перед словом начинающимся с Е|Ё вот исправленный вариант:

function translit (&$string) {
$string = preg_replace('#\s+#is', ' ', mb_strtolower($string));

$string = preg_replace('#(а|и|о|у|ы|э|ю|я|ъ|ь|\s)(е|ё)#isu', 'ye', ' '. $string);

$string = str_replace(
array('а','б','в','г','д','е','ё','ж','з','и','й','к','л','м','н','о','п','р','с','т','у','ф','х','ц','ч','ш','щ','ъ','ы','ь','э','ю','я'),
array('a','b','v','g','d','e','e','zh','z','i','y','k','l','m','n','o','p','r','s','t','u','f','kh','ts','ch','sh','shch','"','y',"'",'e','yu','ya'),
$string
);

$string = trim(preg_replace('#\s+#is', ' ', $string));
}

Константин Кирилюк
Константин Кирилюк комментирует...

2Назир Гебеков в моей функции translit() буква "ё" тоже учтена. Здесь просто не нужно забывать, что код зависим от кодировки из-за кириллицы.

Назир Гебеков
Назир Гебеков комментирует...

так я использую только utf-8 кодировку это и так должно быть понятно потому что я использовал mb_strtolower а не strtolower.

А насчет моих слов "В прошлом коде транслитерации вырезался пробел перед словом начинающимся с Е|Ё вот исправленный вариант" я имел ввиду свой первый комментарий в котором код был немного не корректен что я исправил во втором комментарии (первый не опубликовался по ходу) я говорил не о вашем коде.

И еще в этой функции учитываются моменты когда необходимо использовать "ye" а когда "e" вместо русских "е" и "ё" что собственно и делает гугловский транслитер.

Насчет разных кодировок что мешает использовать iconv перед применением translit?

Константин Кирилюк
Константин Кирилюк комментирует...

2Назир Гебеков согласен для транслита сойдёт и локальная функция, а вот для полноценного перевода всё таки придётся использовать сервис, что и делает моя функция.

Александр Гентеров
Александр Гентеров комментирует...

Перевод перестал работать, делает теперь редирект на http://ipv4.google.com/sorry/IndexRedirect?continue=http://translate.google.com/ помогите исправить!

Константин Кирилюк
Константин Кирилюк комментирует...

2Александр Гентеров увы и ах, при большом количестве обращений с одного IP идёт блокировка, т.к. функция не использует официального API Google Translate. Как вариант, можно попробовать использовать промежуточный сервер, который находится на другом IP для получения данных.

GalS
GalS комментирует...

а у меня почему то эта функция gtranslate() вместо русских букв выдает сплошные ?????????? ((( как с этим справиться?

Константин Кирилюк
Константин Кирилюк комментирует...

GalS кодировка должна быть UTF-8, читайте внимательней.