You are here

class GoogleTranslator in TMGMT Translator Google 8

Google translator plugin.

Plugin annotation


@TranslatorPlugin(
  id = "google",
  label = @Translation("Google"),
  description = @Translation("Google Translator service."),
  ui = "Drupal\tmgmt_google\GoogleTranslatorUi",
  logo = "icons/google.svg",
)

Hierarchy

Expanded class hierarchy of GoogleTranslator

1 file declares its use of GoogleTranslator
GoogleTranslatorTest.php in tests/src/Functional/GoogleTranslatorTest.php

File

src/Plugin/tmgmt/Translator/GoogleTranslator.php, line 37
Contains \Drupal\tmgmt_microsoft\Plugin\tmgmt\Translator\MicrosoftTranslator.

Namespace

Drupal\tmgmt_google\Plugin\tmgmt\Translator
View source
class GoogleTranslator extends TranslatorPluginBase implements ContainerFactoryPluginInterface, ContinuousTranslatorInterface {

  /**
   * Translation service URL.
   *
   * @var string
   */
  protected $translatorUrl = 'https://www.googleapis.com/language/translate/v2';

  /**
   * Name of parameter that contains source string to be translated.
   *
   * @var string
   */
  protected $qParamName = 'q';

  /**
   * Maximum supported characters.
   *
   * @var int
   */
  protected $maxCharacters = 5000;

  /**
   * Available actions for Google translator.
   *
   * @var array
   */
  protected $availableActions = array(
    'translate',
    'languages',
    'detect',
  );

  /**
   * Max number of text queries for translation sent in one request.
   *
   * @var int
   */
  protected $qChunkSize = 5;

  /**
   * Guzzle HTTP client.
   *
   * @var \GuzzleHttp\ClientInterface
   */
  protected $client;

  /**
   * Constructs a LocalActionBase object.
   *
   * @param \GuzzleHttp\ClientInterface $client
   *   The Guzzle HTTP client.
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param array $plugin_definition
   *   The plugin implementation definition.
   */
  public function __construct(ClientInterface $client, array $configuration, $plugin_id, array $plugin_definition) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->client = $client;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static($container
      ->get('http_client'), $configuration, $plugin_id, $plugin_definition);
  }

  /**
   * Overrides TMGMTDefaultTranslatorPluginController::checkAvailable().
   */
  public function checkAvailable(TranslatorInterface $translator) {
    if ($translator
      ->getSetting('api_key')) {
      return AvailableResult::yes();
    }
    return AvailableResult::no(t('@translator is not available. Make sure it is properly <a href=:configured>configured</a>.', [
      '@translator' => $translator
        ->label(),
      ':configured' => $translator
        ->toUrl()
        ->toString(),
    ]));
  }

  /**
   * Overrides TMGMTDefaultTranslatorPluginController::checkTranslatable().
   */
  public function checkTranslatable(TranslatorInterface $translator, JobInterface $job) {
    foreach (\Drupal::service('tmgmt.data')
      ->filterTranslatable($job
      ->getData()) as $value) {

      // If one of the texts in this job exceeds the max character count
      // the job can't be translated.
      if (mb_strlen($value['#text']) > $this->maxCharacters) {
        return TranslatableResult::no(t('The length of the job exceeds tha max character count (@count).', [
          '@count' => $this->maxCharacters,
        ]));
      }
    }
    return parent::checkTranslatable($translator, $job);
  }

  /**
   * Implements TMGMTTranslatorPluginControllerInterface::requestTranslation().
   */
  public function requestTranslation(JobInterface $job) {
    $this
      ->requestJobItemsTranslation($job
      ->getItems());
    if (!$job
      ->isRejected()) {
      $job
        ->submitted('The translation job has been submitted.');
    }
  }

  /**
   * Helper method to do translation request.
   *
   * @param Job $job
   *   TMGMT Job to be used for translation.
   * @param array|string $q
   *   Text/texts to be translated.
   *
   * @return array
   *   Userialized JSON containing translated texts.
   */
  protected function googleRequestTranslation(Job $job, $q) {
    $translator = $job
      ->getTranslator();
    return $this
      ->doRequest($translator, 'translate', array(
      'source' => $job
        ->getRemoteSourceLanguage(),
      'target' => $job
        ->getRemoteTargetLanguage(),
      $this->qParamName => $q,
    ), array(
      'headers' => array(
        'Content-Type' => 'text/plain',
      ),
    ));
  }

  /**
   * Overrides TMGMTDefaultTranslatorPluginController::getSupportedRemoteLanguages().
   */
  public function getSupportedRemoteLanguages(TranslatorInterface $translator) {
    $languages = array();

    // Prevent access if the translator isn't configured yet.
    if (!$translator
      ->getSetting('api_key')) {
      return $languages;
    }
    try {
      $request = $this
        ->doRequest($translator, 'languages');
      if (isset($request['data'])) {
        foreach ($request['data']['languages'] as $language) {
          $languages[$language['language']] = $language['language'];
        }
      }
    } catch (\Exception $e) {
      \Drupal::messenger()
        ->addMessage($e
        ->getMessage(), 'error');
      return $languages;
    }
    return $languages;
  }

  /**
   * Overrides TMGMTDefaultTranslatorPluginController::getDefaultRemoteLanguagesMappings().
   */
  public function getDefaultRemoteLanguagesMappings() {
    return array(
      'zh-hans' => 'zh-CHS',
      'zh-hant' => 'zh-CHT',
    );
  }

  /**
   * Overrides TMGMTDefaultTranslatorPluginController::getSupportedTargetLanguages().
   */
  public function getSupportedTargetLanguages(TranslatorInterface $translator, $source_language) {
    $languages = $this
      ->getSupportedRemoteLanguages($translator);

    // There are no language pairs, any supported language can be translated
    // into the others. If the source language is part of the languages,
    // then return them all, just remove the source language.
    if (array_key_exists($source_language, $languages)) {
      unset($languages[$source_language]);
      return $languages;
    }
    return array();
  }

  /**
   * Overrides TMGMTDefaultTranslatorPluginController::hasCheckoutSettings().
   */
  public function hasCheckoutSettings(JobInterface $job) {
    return FALSE;
  }

  /**
   * Local method to do request to Google Translate service.
   *
   * @param Translator $translator
   *   The translator entity to get the settings from.
   * @param string $action
   *   Action to be performed [translate, languages, detect]
   * @param array $request_query
   *   (Optional) Additional query params to be passed into the request.
   * @param array $options
   *   (Optional) Additional options that will be passed into drupal_http_request().
   *
   * @return array object
   *   Unserialized JSON response from Google.
   *
   * @throws TMGMTException
   *   - Invalid action provided
   *   - Unable to connect to the Google Service
   *   - Error returned by the Google Service
   */
  protected function doRequest(Translator $translator, $action, array $request_query = array(), array $options = array()) {
    if (!in_array($action, $this->availableActions)) {
      throw new TMGMTException('Invalid action requested: @action', array(
        '@action' => $action,
      ));
    }
    $query_string = '';

    // Translate action is requested without this argument.
    if ($action == 'translate') {
      $action = '';
    }

    // Get custom URL for testing purposes, if available.
    $custom_url = $translator
      ->getSetting('url');
    $url = ($custom_url ? $custom_url : $this->translatorUrl) . '/' . $action;

    // Prepare Guzzle Object.
    $request = new Request('GET', $url);

    // Build the query.
    $query_string .= '&key=' . $translator
      ->getSetting('api_key');
    if (isset($request_query['q'])) {
      foreach ($request_query['q'] as $source_text) {
        $query_string .= '&q=' . urlencode($source_text);
      }
    }
    if (isset($request_query['source'])) {
      $query_string .= '&source=' . $request_query['source'];
    }
    if (isset($request_query['target'])) {
      $query_string .= '&target=' . $request_query['target'];
    }

    // Send the request with the query.
    try {
      $response = $this->client
        ->send($request, [
        'query' => $query_string,
      ]);
    } catch (BadResponseException $e) {
      $error = json_decode($e
        ->getResponse()
        ->getBody(), TRUE);
      throw new TMGMTException('Google Translate service returned following error: @error', [
        '@error' => $error['error']['message'],
      ]);
    }

    // Process the JSON result into array.
    return json_decode($response
      ->getBody(), TRUE);
  }

  /**
   * We provide translatorUrl setter so that we can override its value
   * in automated testing.
   *
   * @param $translator_url
   */
  public final function setTranslatorURL($translator_url) {
    $this->translatorUrl = $translator_url;
  }

  /**
   * The q parameter name needs to be overridden for Drupal testing as it
   * collides with Drupal q parameter.
   *
   * @param $name
   */
  public final function setQParamName($name) {
    $this->qParamName = $name;
  }

  /**
   * {@inheritdoc}
   */
  public function requestJobItemsTranslation(array $job_items) {

    /** @var \Drupal\tmgmt\Entity\Job $job */
    $job = reset($job_items)
      ->getJob();
    foreach ($job_items as $job_item) {
      if ($job
        ->isContinuous()) {
        $job_item
          ->active();
      }

      // Pull the source data array through the job and flatten it.
      $data = \Drupal::service('tmgmt.data')
        ->filterTranslatable($job_item
        ->getData());
      $translation = array();
      $q = array();
      $keys_sequence = array();
      $i = 0;

      // Build Google q param and preserve initial array keys.
      foreach ($data as $key => $value) {
        $q[] = $value['#text'];
        $keys_sequence[] = $key;
      }
      try {

        // Split $q into chunks of self::qChunkSize.
        foreach (array_chunk($q, $this->qChunkSize) as $_q) {

          // Get translation from Google.
          $result = $this
            ->googleRequestTranslation($job, $_q);

          // Collect translated texts with use of initial keys.
          foreach ($result['data']['translations'] as $translated) {
            $translation[$keys_sequence[$i]]['#text'] = Html::decodeEntities($translated['translatedText']);
            $i++;
          }
        }

        // Save the translated data through the job.
        // NOTE that this line of code is reached only in case all translation
        // requests succeeded.
        $job_item
          ->addTranslatedData(\Drupal::service('tmgmt.data')
          ->unflatten($translation));
      } catch (TMGMTException $e) {
        $job
          ->rejected('Translation has been rejected with following error: @error', array(
          '@error' => $e
            ->getMessage(),
        ), 'error');
      }
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
GoogleTranslator::$availableActions protected property Available actions for Google translator.
GoogleTranslator::$client protected property Guzzle HTTP client.
GoogleTranslator::$maxCharacters protected property Maximum supported characters.
GoogleTranslator::$qChunkSize protected property Max number of text queries for translation sent in one request.
GoogleTranslator::$qParamName protected property Name of parameter that contains source string to be translated.
GoogleTranslator::$translatorUrl protected property Translation service URL.
GoogleTranslator::checkAvailable public function Overrides TMGMTDefaultTranslatorPluginController::checkAvailable(). Overrides TranslatorPluginBase::checkAvailable
GoogleTranslator::checkTranslatable public function Overrides TMGMTDefaultTranslatorPluginController::checkTranslatable(). Overrides TranslatorPluginBase::checkTranslatable
GoogleTranslator::create public static function Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface::create
GoogleTranslator::doRequest protected function Local method to do request to Google Translate service.
GoogleTranslator::getDefaultRemoteLanguagesMappings public function Overrides TMGMTDefaultTranslatorPluginController::getDefaultRemoteLanguagesMappings(). Overrides TranslatorPluginBase::getDefaultRemoteLanguagesMappings
GoogleTranslator::getSupportedRemoteLanguages public function Overrides TMGMTDefaultTranslatorPluginController::getSupportedRemoteLanguages(). Overrides TranslatorPluginBase::getSupportedRemoteLanguages
GoogleTranslator::getSupportedTargetLanguages public function Overrides TMGMTDefaultTranslatorPluginController::getSupportedTargetLanguages(). Overrides TranslatorPluginBase::getSupportedTargetLanguages
GoogleTranslator::googleRequestTranslation protected function Helper method to do translation request.
GoogleTranslator::hasCheckoutSettings public function Overrides TMGMTDefaultTranslatorPluginController::hasCheckoutSettings(). Overrides TranslatorPluginBase::hasCheckoutSettings
GoogleTranslator::requestJobItemsTranslation public function Requests the translation of a JobItem. Overrides ContinuousTranslatorInterface::requestJobItemsTranslation
GoogleTranslator::requestTranslation public function Implements TMGMTTranslatorPluginControllerInterface::requestTranslation(). Overrides TranslatorPluginInterface::requestTranslation
GoogleTranslator::setQParamName final public function The q parameter name needs to be overridden for Drupal testing as it collides with Drupal q parameter.
GoogleTranslator::setTranslatorURL final public function We provide translatorUrl setter so that we can override its value in automated testing.
GoogleTranslator::__construct public function Constructs a LocalActionBase object. Overrides PluginBase::__construct
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
TranslatorPluginBase::$escapeEnd protected property Characters that indicate the end of an escaped string. 1
TranslatorPluginBase::$escapeStart protected property Characters that indicate the beginning of an escaped string. 1
TranslatorPluginBase::abortTranslation public function Aborts a translation job. Overrides TranslatorPluginInterface::abortTranslation
TranslatorPluginBase::acceptedDataItem public function Accept a single data item. Overrides TranslatorPluginInterface::acceptedDataItem
TranslatorPluginBase::defaultSettings public function Defines default settings. Overrides TranslatorPluginInterface::defaultSettings 1
TranslatorPluginBase::escapeText public function Returns the escaped #text of a data item. Overrides TranslatorPluginInterface::escapeText
TranslatorPluginBase::getEscapedString protected function Returns the escaped string.
TranslatorPluginBase::getSupportedLanguagePairs public function Default implementation that gets target languages for each remote language. This approach is ineffective and therefore it is advised that a plugin should provide own implementation. Overrides TranslatorPluginInterface::getSupportedLanguagePairs 1
TranslatorPluginBase::unescapeText public function Removes escape patterns from an escaped text. Overrides TranslatorPluginInterface::unescapeText