createGuid();
        $args = array(
            'q' => $q,
            'appKey' => self::APP_KEY,
            'salt' => $salt,
        );
        $args['from'] = 'zh-CHS';
        $args['to'] = 'EN';
        $args['signType'] = 'v3';
        $curtime = strtotime("now");
        $args['curtime'] = $curtime;
        $signStr = self::APP_KEY . $this->truncate($q) . $salt . $curtime . self::SEC_KEY;
        $args['sign'] = hash("sha256", $signStr);
        $ret = $this->call(self::URL, $args);
        return $ret;
    }
    function bubbleSort($arr)
    {
        $len = count($arr);
        for ($i = 0; $i < $len - 1; $i++) {
            for ($j = 0; $j < $len - 1 - $i; $j++) {
                if (mb_strlen($arr[$j]['source']) < mb_strlen($arr[$j + 1]['source'])) {
                    $tmp = $arr[$j];
                    $arr[$j] = $arr[$j + 1];
                    $arr[$j + 1] = $tmp;
                }
            }
        }
        return $arr;
    }
    public function htmlRequest(string $q)
    {
        $pattern = "/
(.*?)<\/tr>/is";
        $source_q = $q;
        $q = preg_replace($pattern, '', $q);//去掉表格
        $q = explode('翻译分割符', preg_replace('/(<.*?>)/', '翻译分割符', $q));
        $source_array = array();
        foreach ($q as $value) {
            $source = trim($value);
            if (!$source) continue;
            $source_target['source'] = $source;
            $source_target['source_q'] = $value;
            $source_array[] = $source_target;
        }
        foreach ($source_array as $inx => $val) {
            $data = json_decode($this->request($val['source']), true);
            $source_array[$inx]['target'] = $data['translation'][0] ?? '';
        }
        $this->bubbleSort(array_values($source_array));
        foreach ($source_array as $value) {
            $source_q = str_replace($value['source_q'], $value['target'], $source_q);
        }
        return $source_q;
    }
    protected function call($url, $args = null, $method = "post", $timeout = self::CURL_TIMEOUT, $headers = array())
    {
        $ret = false;
        $i = 0;
        while ($ret === false) {
            if ($i > 1)
                break;
            if ($i > 0) {
                sleep(1);
            }
            $ret = $this->callOnce($url, $args, $method, false, $timeout, $headers);
            $i++;
        }
        return $ret;
    }
    protected function callOnce($url, $args = null, $method = "post", $withCookie = false, $timeout = self:: CURL_TIMEOUT, $headers = array())
    {
        $ch = curl_init();
        if ($method == "post") {
            $data = $this->convert($args);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
            curl_setopt($ch, CURLOPT_POST, 1);
        } else {
            $data = $this->convert($args);
            if ($data) {
                if (stripos($url, "?") > 0) {
                    $url .= "&$data";
                } else {
                    $url .= "?$data";
                }
            }
        }
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        if (!empty($headers)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }
        if ($withCookie) {
            curl_setopt($ch, CURLOPT_COOKIEJAR, $_COOKIE);
        }
        $r = curl_exec($ch);
        curl_close($ch);
        return $r;
    }
    protected function convert(&$args)
    {
        $data = '';
        if (is_array($args)) {
            foreach ($args as $key => $val) {
                if (is_array($val)) {
                    foreach ($val as $k => $v) {
                        $data .= $key . '[' . $k . ']=' . rawurlencode($v) . '&';
                    }
                } else {
                    $data .= "$key=" . rawurlencode($val) . "&";
                }
            }
            return trim($data, "&");
        }
        return $args;
    }
    protected function createGuid()
    {
        $microTime = microtime();
        list($a_dec, $a_sec) = explode(" ", $microTime);
        $dec_hex = dechex($a_dec * 1000000);
        $sec_hex = dechex($a_sec);
        $this->ensureLength($dec_hex, 5);
        $this->ensureLength($sec_hex, 6);
        $guid = "";
        $guid .= $dec_hex;
        $guid .= $this->create_guid_section(3);
        $guid .= '-';
        $guid .= $this->create_guid_section(4);
        $guid .= '-';
        $guid .= $this->create_guid_section(4);
        $guid .= '-';
        $guid .= $this->create_guid_section(4);
        $guid .= '-';
        $guid .= $sec_hex;
        $guid .= $this->create_guid_section(6);
        return $guid;
    }
    protected function create_guid_section($characters)
    {
        $return = "";
        for ($i = 0; $i < $characters; $i++) {
            $return .= dechex(mt_rand(0, 15));
        }
        return $return;
    }
    /**
     * 截断
     * @param $q
     * @return string
     */
    protected function truncate($q)
    {
        $len = mb_strlen($q);
        return $len <= 20 ? $q : (mb_substr($q, 0, 10) . $len . mb_substr($q, $len - 10, $len));
    }
    protected function ensureLength(&$string, $length)
    {
        $strLen = mb_strlen($string);
        if ($strLen < $length) {
            $string = str_pad($string, $length, "0");
        } else if ($strLen > $length) {
            $string = mb_substr($string, 0, $length);
        }
    }
}