Многоязычная 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, который появляется при переводе одного слова. Он будет содержать ряд дополнительных словарных данных, вроде определения части речи, вариантов перевода и т.д., но тут смотрите сами.

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

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

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

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

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

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

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

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

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

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

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

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

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 комментирует...

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

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

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

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

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

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

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

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

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));
}

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

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

Анонимный
Анонимный комментирует...

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

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

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

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

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

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

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

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

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

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

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

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

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

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