protected function handle($query, $target, $source = null, $plainText = false)
    {
        if (null === $source) {
            $source = $this->getDetector()->detect($query);
        }

        // Split up the query if it is too long. See MAXIMUM_TEXT_SIZE description for more info.
        {
            $queryArray = [];
            $remainingQuery = $query;
            while (strlen($remainingQuery) >= self::MAXIMUM_TEXT_SIZE) {
                // Get closest breaking character, but not farther than MAXIMUM_TEXT_SIZE characters away.
                $i = 0;
                $find = ["\n", '.', ' '];

                while (false === ($pos = strrpos($remainingQuery, $find[$i], -(strlen($remainingQuery) - self::MAXIMUM_TEXT_SIZE)))) {
                    $i++;
                    if ($i >= count($find)) {
                        break;
                    }
                }
                if (false === $pos || 0 === $pos) {
                    break;
                }

                // Split.
                $queryArray[] = substr($remainingQuery, 0, $pos);
                $remainingQuery = substr($remainingQuery, $pos);
            }
            $queryArray[] = $remainingQuery;
        }

        // Translate piece by piece.
        $result = '';
        foreach ($queryArray as $subQuery) {
            $options = [
                'key'    => $this->apiKey,
                'q'      => $subQuery,
                'source' => $source,
                'target' => $target,
                'format' => ($plainText ? 'text' : 'html'),
            ];

            $result .= $this->process($options);
        }

        return $result;
    }