{lang: 'hu'}

Yesterday I decided that I’m going to extend the functionality of my “learn words” application. With the new functionality the user will be able to listen to a given word or expression and I hope this way it will be more easier to learn the words and expressions. I didn’t know where to start writing the backend part, but I knew a service which provides such a functionality and this is the google translate. I took a look at the network panel in my browsers console and started to investigate if google forbids an akin request from a different domain. Luckily they don’t, so I set myself to patch the code. And here is the result! Feel free to use the class! Any feedback is appreciated.

P.s.: I hope it’s allowed to use the service even though the guys at google don’t forbid it, but if it’s not the case, just ping me and I try to find another solution.

Usage:


<?php

require_once 'ReadIt.class.php';

// The text can be passed to the constructor
// or to the setText method
$r = new ReadIt('Valami');

// You can change on the language by passing
// the 2 character country code to this method
$r->setLanguage('hu');

// Push the data back to the browser (or cli)
$r->readIt();

// Or write out data into a file
$r->writeIt('filename.mpeg');
?>

Class’s code:


<?php
/**
  * Helper class to read up a text with the Google Translate's service
  * 
  * Copyright (C) 2013  Gabor Szabo <szabo.gabor@szabogabor.net>
  * 
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  * 
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * 
  */
  
class ReadIt
{

    const BASE_URL = 'http://translate.google.com/translate_tts';

    const DEFAULT_LANGUAGE = 'en';

    /**
     * Sets the proper headers if the result
     * will be redirected to the standard output
     * 
     * @return void 
     */
    private function setHeaders()
    {

        header('Cache-Control:private, max-age=86400');
        header('Content-Length:' . strlen($this->response));
        header('Content-Type:audio/mpeg');

        return $this;

    }

    /**
     * Return with the GET parameters of the request
     * 
     * @return string The urlencoded parameters
     */
    private function getParameters()
    {

        $parameters = array(
            'ie'      => 'UTF-8',
            'q'       => $this->text,
            'tl'      => $this->getLanguage(),
            'total'   => '1',
            'idx'     => '0',
            'textlen' => strlen($this->text),
            'prev'    =>'input'
        );

        return http_build_query($parameters);

    }

    /**
     * Return with the given language or the pre-defined
     * default language if was not given
     * 
     * @return string The language code
     */
    private function getLanguage()
    {

        if(!empty($this->language))
        {
            return $this->language;
        }

        return self::DEFAULT_LANGUAGE;

    }

    public function __construct($text = NULL)
    {

        if(!function_exists('curl_init'))
        {
            throw new Exception('You must install cURL module to be able to use the class!');
        }

        if( $text !== NULL )
        {
            $this->setText($text);
        }

    }

    /**
     * Sets the text what will be read up in the audio file
     * 
     * @param string|array $text The text
     */
    public function setText($text)
    {

        if(empty($text))
        {
            throw new Exception('The text cannot be empty!');
        }

        if(is_array($text))
        {
            $text = implode('', $text);
        }

        $this->text = $text;

        return $this;

    }

    /**
     * Sets the language code
     * 
     * @param string $lang The 2 character length code of the language
     * @return void
     */
    public function setLanguage($lang)
    {

        if(empty($lang))
        {
            throw new Exception('The language code cannot be empty!');
        }

        $this->language = $lang;

        return $this;

    }

    /**
     * Performs the cURL request and returns
     * with the raw response
     * 
     * @return string The response of the service
     */
    private function doRequest()
    {

        $curlRequest = curl_init();

        curl_setopt($curlRequest, CURLOPT_URL, self::BASE_URL . '?' . $this->getParameters()); 
        curl_setopt($curlRequest, CURLOPT_HTTPGET, true); 
        curl_setopt($curlRequest, CURLOPT_RETURNTRANSFER, 1); 

        $response = curl_exec($curlRequest);
        $error = curl_error($curlRequest);
        $returnCode = curl_getinfo($curlRequest, CURLINFO_HTTP_CODE);
        
        curl_close($curlRequest);

        if(!empty($error) || $returnCode !== 200)
        {
            throw new Exception('Error occured during the request!');
        }

        return $response;

    }

    /**
     * Sets the proper headers and writes the
     * audio data to the standard output
     * 
     * @return void
     */
    public function readIt()
    {

        if(empty($this->text))
        {
            throw new Exception('You must give a text to read!');
        }

        $this->response = $this->doRequest();
        $this->setHeaders();

        echo $this->response;

        return $this;

    }

    /**
     * Writes the audio data into a file
     * 
     * @param  string $filename The filename to write the result into
     * @return void
     */
    public function writeIt($filename)
    {

        if($filename === NULL)
        {
            throw new Exception('Filename cannot be empty!');
        }

        $this->response = $this->doRequest();
        
        if(file_put_contents($filename, $this->response) === false)
        {
            throw new Exception('Failed to write out the response into the file!');
        }

        return $this;

    }

}

?>