Skip to content

Commit de9be13

Browse files
committed
Add free Google translate
1 parent d31952a commit de9be13

File tree

5 files changed

+279
-53
lines changed

5 files changed

+279
-53
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ php artisan laravelcms --action=clear
5050
}
5151
```
5252

53+
## Where can I get the app_id & app_key
54+
55+
- Option 1: Provider Baidu, From https://api.fanyi.baidu.com/, free, only 1 translate allowed per second
56+
- Option 2: Provider Google, From https://cloud.google.com/translate/docs/
57+
58+
## Use free Google translate
59+
60+
- Set provider to Google_Free
61+
- Set both app_id & app_key to google_free_001, then our CMS will use package https://github.com/dejurin/php-google-translate-for-free to do the translate. (It's the default)
62+
- Set both app_id & app_key to google_free_002, then our CMS will use the package https://github.com/Stichoza/google-translate-php to do the translate, YOU NEED INSTALL THE PACKAGE VIA COMMAND LINE FIRST: composer require stichoza/google-translate-php
63+
5364
## Improve this plugin & documents
5465

5566
- You are very welcome to improve this plugin and how to use documents
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
<?php
2+
3+
namespace Amila\LaravelCms\Plugins\Translator\Controllers;
4+
5+
/**
6+
* GoogleTranslateForFree.php.
7+
*
8+
* Class for free use Google Translator. With attempts connecting on failure and array support.
9+
*
10+
* @category Translation
11+
*
12+
* @author Yuri Darwin
13+
* @author Yuri Darwin <gkhelloworld@gmail.com>
14+
* @copyright 2019 Yuri Darwin
15+
* @license https://opensource.org/licenses/MIT
16+
*
17+
* @version 1.0.0
18+
*/
19+
20+
/**
21+
* Main class GoogleTranslateForFree.
22+
*/
23+
class GoogleTranslateForFree
24+
{
25+
/**
26+
* @param string $source
27+
* @param string $target
28+
* @param string|array $text
29+
* @param int $attempts
30+
*
31+
* @return string|array With the translation of the text in the target language
32+
*/
33+
public static function translate($source, $target, $text, $attempts = 5)
34+
{
35+
// Request translation
36+
if (is_array($text)) {
37+
// Array
38+
$translation = self::requestTranslationArray($source, $target, $text, $attempts = 5);
39+
} else {
40+
// Single
41+
$translation = self::requestTranslation($source, $target, $text, $attempts = 5);
42+
}
43+
44+
return $translation;
45+
}
46+
47+
/**
48+
* @param string $source
49+
* @param string $target
50+
* @param array $text
51+
* @param int $attempts
52+
*
53+
* @return array
54+
*/
55+
protected static function requestTranslationArray($source, $target, $text, $attempts)
56+
{
57+
$arr = [];
58+
foreach ($text as $value) {
59+
// timeout 0.5 sec
60+
usleep(500000);
61+
$arr[] = self::requestTranslation($source, $target, $value, $attempts = 5);
62+
}
63+
64+
return $arr;
65+
}
66+
67+
/**
68+
* @param string $source
69+
* @param string $target
70+
* @param string $text
71+
* @param int $attempts
72+
*
73+
* @return string
74+
*/
75+
protected static function requestTranslation($source, $target, $text, $attempts)
76+
{
77+
// Google translate URL
78+
$url = 'https://translate.google.com/translate_a/single?client=at&dt=t&dt=ld&dt=qca&dt=rm&dt=bd&dj=1&hl=uk-RU&ie=UTF-8&oe=UTF-8&inputm=2&otf=2&iid=1dd3b944-fa62-4b55-b330-74909a99969e';
79+
80+
$fields = [
81+
'sl' => urlencode($source),
82+
'tl' => urlencode($target),
83+
'q' => urlencode($text),
84+
];
85+
86+
if (strlen($fields['q']) >= 5000) {
87+
throw new \Exception('Maximum number of characters exceeded: 5000');
88+
}
89+
// URL-ify the data for the POST
90+
$fields_string = self::fieldsString($fields);
91+
92+
$content = self::curlRequest($url, $fields, $fields_string, 0, $attempts);
93+
94+
if (null === $content) {
95+
//echo $text,' Error',PHP_EOL;
96+
return '';
97+
} else {
98+
// Parse translation
99+
return self::getSentencesFromJSON($content);
100+
}
101+
}
102+
103+
/**
104+
* Dump of the JSON's response in an array.
105+
*
106+
* @param string $json
107+
*
108+
* @return string
109+
*/
110+
protected static function getSentencesFromJSON($json)
111+
{
112+
$arr = json_decode($json, true);
113+
$sentences = '';
114+
115+
if (isset($arr['sentences'])) {
116+
foreach ($arr['sentences'] as $s) {
117+
$sentences .= isset($s['trans']) ? $s['trans'] : '';
118+
}
119+
}
120+
121+
return $sentences;
122+
}
123+
124+
/**
125+
* Curl Request attempts connecting on failure.
126+
*
127+
* @param string $url
128+
* @param array $fields
129+
* @param string $fields_string
130+
* @param int $i
131+
* @param int $attempts
132+
*
133+
* @return string
134+
*/
135+
protected static function curlRequest($url, $fields, $fields_string, $i, $attempts)
136+
{
137+
++$i;
138+
$ch = curl_init();
139+
curl_setopt($ch, CURLOPT_URL, $url);
140+
curl_setopt($ch, CURLOPT_POST, count($fields));
141+
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
142+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
143+
curl_setopt($ch, CURLOPT_ENCODING, 'UTF-8');
144+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
145+
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
146+
//curl_setopt($ch, CURLOPT_HEADER, true);
147+
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
148+
curl_setopt($ch, CURLOPT_USERAGENT, 'AndroidTranslate/5.3.0.RC02.130475354-53000263 5.1 phone TRANSLATE_OPM5_TEST_1');
149+
150+
$result = curl_exec($ch);
151+
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
152+
153+
if (false === $result || 200 !== $httpcode) {
154+
// echo $i,'/',$attempts,' Aborted, trying again... ',curl_error($ch),PHP_EOL;
155+
156+
if ($i >= $attempts) {
157+
//echo 'Could not connect and get data.',PHP_EOL;
158+
return;
159+
//die('Could not connect and get data.'.PHP_EOL);
160+
} else {
161+
// timeout 1.5 sec
162+
usleep(1500000);
163+
164+
return self::curlRequest($url, $fields, $fields_string, $i, $attempts);
165+
}
166+
} else {
167+
return $result; //self::getBodyCurlResponse();
168+
}
169+
curl_close($ch);
170+
}
171+
172+
/**
173+
* Make string with post data fields.
174+
*
175+
* @param array $fields
176+
*
177+
* @return string
178+
*/
179+
protected static function fieldsString($fields)
180+
{
181+
$fields_string = '';
182+
foreach ($fields as $key => $value) {
183+
$fields_string .= $key.'='.$value.'&';
184+
}
185+
186+
return rtrim($fields_string, '&');
187+
}
188+
}

src/Controllers/TranslatorController.php

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class TranslatorController extends Controller
1111
private $user = null;
1212
private $helper;
1313

14-
private $app_id = null;
14+
private $app_id = null;
1515
private $app_key = null;
1616

1717
public function __construct()
@@ -31,18 +31,19 @@ public function create($form_data, $page, $plugin_settings)
3131
{
3232
// set a default select box value to the form
3333
// any better idea than change the $_GET?
34-
$_GET['translate_to'] = $_COOKIE['translate_to'] ?? $this->helper->s('template.frontend_language');
34+
$_GET['translate_to'] = $_COOKIE['translate_to'] ?? $this->helper->s('template.frontend_language');
3535
$data['translate_from'] = $_COOKIE['translate_from'] ?? 'en';
3636

3737
$_GET['append_source_content'] = $_COOKIE['append_source_content'] ?? 'yes';
3838

3939
$_GET['translate_result_add_to_field'] = $_COOKIE['translate_result_add_to_field'] ?? 'main_content';
4040

41-
if ($plugin_settings['api_provider'] == 'baidu') {
42-
$data['translate_languages'] = ["en"=>"English", "zh"=>"Chinese", "epa"=>"Spanish", "ara"=>"Arabic", "jp"=>"Japanese", "hi"=>"Hindi", "pt"=>"Portuguese", "fra"=>"French", "ru"=>"Russian", "de"=>"German", "kor"=>"Korean", "it"=>"Italian", "th"=>"Thai"];
41+
if ('baidu' == strtolower($plugin_settings['api_provider'])) {
42+
$data['translate_languages'] = ['en'=>'English', 'zh'=>'Chinese', 'epa'=>'Spanish', 'ara'=>'Arabic', 'jp'=>'Japanese', 'hi'=>'Hindi', 'pt'=>'Portuguese', 'fra'=>'French', 'ru'=>'Russian', 'de'=>'German', 'kor'=>'Korean', 'it'=>'Italian', 'th'=>'Thai'];
4343
} else {
44-
$data['translate_languages'] = ["en"=>"English", "zh"=>"Chinese", "es"=>"Spanish", "ar"=>"Arabic", "ja"=>"Japanese", "hi"=>"Hindi", "pt"=>"Portuguese", "fr"=>"French", "ru"=>"Russian", "de"=>"German", "ko"=>"Korean", "it"=>"Italian", "la"=>"Latin"];
44+
$data['translate_languages'] = ['en'=>'English', 'zh'=>'Chinese', 'es'=>'Spanish', 'ar'=>'Arabic', 'ja'=>'Japanese', 'hi'=>'Hindi', 'pt'=>'Portuguese', 'fr'=>'French', 'ru'=>'Russian', 'de'=>'German', 'ko'=>'Korean', 'it'=>'Italian', 'la'=>'Latin'];
4545
}
46+
4647
return $data;
4748
}
4849

@@ -56,11 +57,12 @@ public function edit($id, $page, $plugin_settings)
5657

5758
$page->translate_result_add_to_field = $_COOKIE['translate_result_add_to_field'] ?? 'main_content';
5859

59-
if ($plugin_settings['api_provider'] == 'baidu') {
60-
$data['translate_languages'] = ["en"=>"English", "zh"=>"Chinese", "epa"=>"Spanish", "ara"=>"Arabic", "jp"=>"Japanese", "hi"=>"Hindi", "pt"=>"Portuguese", "fra"=>"French", "ru"=>"Russian", "de"=>"German", "kor"=>"Korean", "it"=>"Italian", "th"=>"Thai"];
60+
if ('baidu' == strtolower($plugin_settings['api_provider'])) {
61+
$data['translate_languages'] = ['en'=>'English', 'zh'=>'Chinese', 'epa'=>'Spanish', 'ara'=>'Arabic', 'jp'=>'Japanese', 'hi'=>'Hindi', 'pt'=>'Portuguese', 'fra'=>'French', 'ru'=>'Russian', 'de'=>'German', 'kor'=>'Korean', 'it'=>'Italian', 'th'=>'Thai'];
6162
} else {
62-
$data['translate_languages'] = ["en"=>"English", "zh"=>"Chinese", "es"=>"Spanish", "ar"=>"Arabic", "ja"=>"Japanese", "hi"=>"Hindi", "pt"=>"Portuguese", "fr"=>"French", "ru"=>"Russian", "de"=>"German", "ko"=>"Korean", "it"=>"Italian", "la"=>"Latin"];
63+
$data['translate_languages'] = ['en'=>'English', 'zh'=>'Chinese', 'es'=>'Spanish', 'ar'=>'Arabic', 'ja'=>'Japanese', 'hi'=>'Hindi', 'pt'=>'Portuguese', 'fr'=>'French', 'ru'=>'Russian', 'de'=>'German', 'ko'=>'Korean', 'it'=>'Italian', 'la'=>'Latin'];
6364
}
65+
6466
return $data;
6567
}
6668

@@ -71,34 +73,60 @@ public function store($form_data, $page, $plugin_settings)
7173

7274
public function update($form_data, $page, $plugin_settings)
7375
{
74-
if (trim($form_data['translate_content']) == '') {
76+
if ('' == trim($form_data['translate_content'])) {
7577
return false;
7678
}
77-
if ($plugin_settings['api_provider'] == 'baidu') {
78-
$this->app_id = $plugin_settings['app_id'];
79+
if ('baidu' == $plugin_settings['api_provider']) {
80+
$this->app_id = $plugin_settings['app_id'];
7981
$this->app_key = $plugin_settings['app_key'];
8082

8183
$api_result = $this->baiduTranslate($form_data['translate_content'], $form_data['translate_from'], $form_data['translate_to']);
8284
if (isset($api_result['trans_result'][0]['dst'])) {
8385
$translate_result = '<div class="translate-content">';
8486
foreach ($api_result['trans_result'] as $rs) {
85-
if ($form_data['append_source_content'] == 'yes') {
86-
$translate_result .= '<div class="src">' . $rs['src'] . '</div>';
87+
if ('yes' == $form_data['append_source_content']) {
88+
$translate_result .= '<div class="src">'.$rs['src'].'</div>';
8789
}
88-
$translate_result .= '' . $rs['dst'] . '<br/><br/>';
90+
$translate_result .= ''.$rs['dst'].'<br/><br/>';
8991
}
9092
$translate_result .= '</div>';
91-
$new_content = $page[$form_data['translate_result_add_to_field']] . $translate_result;
93+
$new_content = $page[$form_data['translate_result_add_to_field']].$translate_result;
9294
} else {
9395
if (request()->debug) {
9496
$this->helper->debug($api_result);
9597
}
98+
9699
return false;
97100
}
98-
}
101+
} elseif ('google_free' == $plugin_settings['api_provider']) {
102+
if ('google_free_002' == $plugin_settings['app_key']) {
103+
// https://github.com/Stichoza/google-translate-php
104+
// Need the end-user install via composer first
99105

106+
$tr = new \Stichoza\GoogleTranslate\GoogleTranslate($form_data['translate_to'], $form_data['translate_from'], ['verify' => false]);
107+
$api_result = $tr->translate($form_data['translate_content']);
108+
} else {
109+
// https://github.com/dejurin/php-google-translate-for-free
110+
// Need copy the class code to the GoogleTranslateForFree.php
100111

101-
// $this->helper->debug($api_result);
112+
$tr = new GoogleTranslateForFree();
113+
$api_result = $tr->translate($form_data['translate_from'], $form_data['translate_to'], $form_data['translate_content'], 2).$plugin_settings['app_key'];
114+
}
115+
116+
if ($api_result) {
117+
$translate_result = '<div class="translate-content">'.nl2br($api_result).'</div>';
118+
119+
if ('yes' == $form_data['append_source_content']) {
120+
$translate_result .= '<div class="pt-3 source-content"><hr class="source-hr" />'.nl2br($form_data['translate_content']).'</div>';
121+
}
122+
123+
$new_content = $page[$form_data['translate_result_add_to_field']].$translate_result;
124+
}
125+
126+
$this->helper->debug([$new_content, $form_data]);
127+
}
128+
129+
$this->helper->debug($api_result);
102130
if (isset($new_content)) {
103131
$page->update([$form_data['translate_result_add_to_field']=>$new_content]);
104132
}
@@ -120,14 +148,13 @@ public function update($form_data, $page, $plugin_settings)
120148
* Other methods.
121149
*/
122150

123-
124151
// baidu FanYi translate
125152
public function baiduTranslate($query, $from, $to)
126153
{
127154
$app_id = $this->app_id;
128155
$app_key = $this->app_key;
129156
if (strlen($app_id) < 10 || strlen($app_key) < 10) {
130-
exit("Please edit the app_id & app_key in the translator plugin setting page, you can get them from https://api.fanyi.baidu.com/");
157+
exit('Please edit the app_id & app_key in the translator plugin setting page, you can get them from https://api.fanyi.baidu.com/');
131158
}
132159

133160
$args = [
@@ -153,8 +180,6 @@ public function buildSign($query, $appID, $salt, $secKey)
153180
return $ret;
154181
}
155182

156-
157-
158183
//发起网络请求
159184
public function baiduCall($url, $args=null, $method='post', $testflag = 0, $timeout = 10, $headers=[])
160185
{
@@ -174,8 +199,6 @@ public function baiduCall($url, $args=null, $method='post', $testflag = 0, $time
174199
return $ret;
175200
}
176201

177-
178-
179202
public function baiduCallOnce($url, $args=null, $method='post', $withCookie = false, $timeout = 10, $headers=[])
180203
{
181204
$ch = curl_init();
@@ -208,8 +231,6 @@ public function baiduCallOnce($url, $args=null, $method='post', $withCookie = fa
208231
return $r;
209232
}
210233

211-
212-
213234
public function baiduConvert(&$args)
214235
{
215236
$data = '';

src/database/migrations/2020_01_19_114400_update_plugin_settings_table.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,9 @@ public function up()
3030
"blade_file": "translator",
3131
"tab_name": "<i class=\'fas fa-language mr-1\'></i>__(translator)",
3232
"php_class": "App\\\\LaravelCms\\\\Plugins\\\\Translator\\\\Controllers\\\\TranslatorController",
33-
"api_provider": "baidu",
34-
"app_id": "",
35-
"app_key": "",
36-
"append_source_content": "yes"
37-
33+
"api_provider": "google_free",
34+
"app_id": "google_free_001",
35+
"app_key": "google_free_002"
3836
}',
3937
];
4038
LaravelCmsSetting::UpdateOrCreate(

0 commit comments

Comments
 (0)