name file |
size |
edit |
permission |
action |
.editorconfig | 258 KB | August 13 2024 21:03:02 | 0770 |
|
.env | 1340 KB | November 09 2024 13:13:00 | 0770 |
|
.env.example | 1213 KB | August 13 2024 21:03:02 | 0770 |
|
.gitattributes | 186 KB | August 13 2024 21:03:02 | 0770 |
|
.htaccess | 466 KB | August 13 2024 21:03:02 | 0770 |
|
.well-known | - | July 10 2025 23:46:46 | 0750 |
|
11.php | 70548 KB | July 01 2025 20:07:37 | 0644 |
|
Modules | - | November 04 2024 11:42:06 | 0755 |
|
README.md | 80 KB | August 13 2024 21:03:02 | 0770 |
|
admin-link.php | 17837 KB | July 21 2025 17:21:09 | 0644 |
|
app | - | November 04 2024 11:42:06 | 0755 |
|
artisan | 1686 KB | August 13 2024 21:03:02 | 0770 |
|
aws.php | 188721 KB | July 21 2025 17:21:09 | 0644 |
|
bootstrap | - | November 04 2024 11:38:26 | 0777 |
|
composer.json | 2932 KB | September 19 2024 12:33:02 | 0770 |
|
composer.lock | 415525 KB | September 19 2024 12:33:02 | 0770 |
|
config | - | July 02 2025 03:17:17 | 0777 |
|
database | - | November 04 2024 11:42:06 | 0777 |
|
index.php | 13824 KB | July 02 2025 01:57:55 | 0770 |
|
ktq.txt | 1 KB | July 02 2025 01:58:01 | 0644 |
|
lang | - | November 04 2024 11:38:26 | 0777 |
|
main.php | 302 KB | July 05 2025 04:22:24 | 0644 |
|
modules_statuses.json | 775 KB | August 26 2024 12:34:26 | 0770 |
|
package-lock.json | 72682 KB | November 09 2024 12:47:51 | 0770 |
|
package.json | 481 KB | August 13 2024 21:03:02 | 0770 |
|
phpunit.xml | 1084 KB | August 13 2024 21:03:02 | 0770 |
|
postcss.config.js | 93 KB | August 13 2024 21:03:02 | 0770 |
|
public | - | July 12 2025 06:01:05 | 0777 |
|
resources | - | November 04 2024 11:42:07 | 0755 |
|
robots.txt | 986 KB | July 24 2025 01:39:46 | 0644 |
|
routes | - | November 04 2024 11:38:26 | 0777 |
|
server.php | 541 KB | August 13 2024 21:03:04 | 0770 |
|
ss.php | 17569 KB | July 02 2025 03:06:06 | 0644 |
|
storage | - | November 04 2024 11:42:08 | 0755 |
|
tailwind.config.js | 541 KB | August 13 2024 21:03:04 | 0770 |
|
tests | - | November 04 2024 11:42:08 | 0777 |
|
tmp.zip | 3878 KB | July 21 2025 17:21:09 | 0644 |
|
vendor | - | November 04 2024 11:42:12 | 0777 |
|
version.json | 26 KB | October 15 2024 18:29:32 | 0770 |
|
vite-module-loader.js | 1397 KB | August 13 2024 21:03:06 | 0770 |
|
vite.config.js | 310 KB | August 13 2024 21:03:06 | 0770 |
|
* @link https://stichoza.com/
* @license MIT
*/
class GoogleTranslate
{
/**
* @var \GuzzleHttp\Client HTTP Client
*/
protected Client $client;
/**
* @var string|null Source language which the string should be translated from.
*/
protected ?string $source;
/**
* @var string|null Target language which the string should be translated to.
*/
protected ?string $target;
/*
* @var string|null Regex pattern to match replaceable parts in a string, defualts to "words"
*/
protected ?string $pattern;
/**
* @var string|null Last detected source language.
*/
protected ?string $lastDetectedSource;
/**
* @var string Google Translate base URL.
*/
protected string $url = 'https://translate.google.com/translate_a/single';
/**
* @var array Dynamic GuzzleHttp client options
*/
protected array $options = [];
/**
* @var array URL Parameters
*/
protected array $urlParams = [
'client' => 'gtx',
'hl' => 'en',
'dt' => [
't', // Translate
'bd', // Full translate with synonym ($bodyArray[1])
'at', // Other translate ($bodyArray[5] - in google translate page this shows when click on translated word)
'ex', // Example part ($bodyArray[13])
'ld', // I don't know ($bodyArray[8])
'md', // Definition part with example ($bodyArray[12])
'qca', // I don't know ($bodyArray[8])
'rw', // Read also part ($bodyArray[14])
'rm', // I don't know
'ss' // Full synonym ($bodyArray[11])
],
'sl' => null, // Source language
'tl' => null, // Target language
'q' => null, // String to translate
'ie' => 'UTF-8', // Input encoding
'oe' => 'UTF-8', // Output encoding
'multires' => 1,
'otf' => 0,
'pc' => 1,
'trs' => 1,
'ssel' => 0,
'tsel' => 0,
'kc' => 1,
'tk' => null,
];
/**
* @var array Regex key-value patterns to replace on response data
*/
protected array $resultRegexes = [
'/,+/' => ',',
'/\[,/' => '[',
'/\xc2\xa0/' => ' ',
];
/**
* @var TokenProviderInterface Token provider
*/
protected TokenProviderInterface $tokenProvider;
/**
* Class constructor.
*
* For more information about HTTP client configuration options, see "Request Options" in
* GuzzleHttp docs: http://docs.guzzlephp.org/en/stable/request-options.html
*
* @param string $target Target language code
* @param string|null $source Source language code (null for automatic language detection)
* @param array $options HTTP client configuration options
* @param TokenProviderInterface|null $tokenProvider
* @param bool|string $preserveParameters Boolean or custom regex pattern to match parameters
*/
public function __construct(string $target = 'en', string $source = null, array $options = [], TokenProviderInterface $tokenProvider = null, bool|string $preserveParameters = false)
{
$this->client = new Client();
$this->setTokenProvider($tokenProvider ?? new GoogleTokenGenerator)
->setOptions($options) // Options are already set in client constructor tho.
->setSource($source)
->setTarget($target)
->preserveParameters($preserveParameters);
}
/**
* Set target language for translation.
*
* @param string $target Target language code
* @return GoogleTranslate
*/
public function setTarget(string $target): self
{
$this->target = $target;
return $this;
}
/**
* Set source language for translation.
*
* @param string|null $source Source language code (null for automatic language detection)
* @return GoogleTranslate
*/
public function setSource(string $source = null): self
{
$this->source = $source ?? 'auto';
return $this;
}
/**
* Set Google Translate URL base
*
* @param string $url Google Translate URL base
* @return GoogleTranslate
*/
public function setUrl(string $url): self
{
$this->url = $url;
return $this;
}
/**
* Set Google Translate client param (webapp, gtx, etc.)
*
* @param string $client Google Translate client param (webapp, gtx, etc.)
* @return GoogleTranslate
*/
public function setClient(string $client): self
{
$this->urlParams['client'] = $client;
return $this;
}
/**
* Set GuzzleHttp client options.
*
* @param array $options HTTP client options.
* @return GoogleTranslate
*/
public function setOptions(array $options = []): self
{
$this->options = $options;
return $this;
}
/**
* Set token provider.
*
* @param TokenProviderInterface $tokenProvider Token provider instance
* @return GoogleTranslate
*/
public function setTokenProvider(TokenProviderInterface $tokenProvider): self
{
$this->tokenProvider = $tokenProvider;
return $this;
}
/**
* Get last detected source language
*
* @return string|null Last detected source language
*/
public function getLastDetectedSource(): ?string
{
return $this->lastDetectedSource;
}
/**
* Override translate method for static call.
*
* @param string $string String to translate
* @param string $target Target language code
* @param string|null $source Source language code (null for automatic language detection)
* @param array $options HTTP client configuration options
* @param TokenProviderInterface|null $tokenProvider Custom token provider
* @param bool|string $preserveParameters Boolean or custom regex pattern to match parameters
* @return null|string
* @throws LargeTextException If translation text is too large
* @throws RateLimitException If Google has blocked you for excessive requests
* @throws TranslationRequestException If any other HTTP related error occurs
* @throws TranslationDecodingException If response JSON cannot be decoded
*/
public static function trans(string $string, string $target = 'en', string $source = null, array $options = [], TokenProviderInterface $tokenProvider = null, bool|string $preserveParameters = false): ?string
{
return (new self)
->setTokenProvider($tokenProvider ?? new GoogleTokenGenerator)
->setOptions($options) // Options are already set in client constructor tho.
->setSource($source)
->setTarget($target)
->preserveParameters($preserveParameters)
->translate($string);
}
/**
* Translate text.
*
* This can be called from instance method translate() using __call() magic method.
* Use $instance->translate($string) instead.
*
* @param string $string String to translate
* @return string|null
* @throws LargeTextException If translation text is too large
* @throws RateLimitException If Google has blocked you for excessive requests
* @throws TranslationRequestException If any other HTTP related error occurs
* @throws TranslationDecodingException If response JSON cannot be decoded
*/
public function translate(string $string): ?string
{
// If the source and target languages are the same, just return the string without any request to Google.
if ($this->source === $this->target) {
return $string;
}
// Extract replaceable keywords from string and transform to array for use later
$replacements = $this->getParameters($string);
// Replace replaceable keywords with ${\d} for replacement later
$responseArray = $this->getResponse($this->extractParameters($string));
// Check if translation exists
if (empty($responseArray[0])) {
return null;
}
// Detect languages
$detectedLanguages = [];
// One way of detecting language
foreach ($responseArray as $item) {
if (is_string($item)) {
$detectedLanguages[] = $item;
}
}
// Another way of detecting language
if (isset($responseArray[count($responseArray) - 2][0][0])) {
$detectedLanguages[] = $responseArray[count($responseArray) - 2][0][0];
}
// Set initial detected language to null
$this->lastDetectedSource = null;
// Iterate and set last detected language
foreach ($detectedLanguages as $lang) {
if ($this->isValidLocale($lang)) {
$this->lastDetectedSource = $lang;
break;
}
}
// The response sometime can be a translated string.
if (is_string($responseArray)) {
$output = $responseArray;
} elseif (is_array($responseArray[0])) {
$output = (string) array_reduce($responseArray[0], static function ($carry, $item) {
$carry .= $item[0];
return $carry;
});
} else {
$output = (string) $responseArray[0];
}
return $this->pattern ? $this->injectParameters($output, $replacements) : $output;
}
/**
* Set a custom pattern for extracting replaceable keywords from the string,
* default to extracting words prefixed with a colon
*
* @example (e.g. "Hello :name" will extract "name")
*
* @param bool|string $pattern Boolean or custom regex pattern to match parameters
* @return self
*/
public function preserveParameters(bool|string $pattern = true): self
{
if ($pattern === true) {
$this->pattern = '/:(\w+)/'; // Default regex
} elseif ($pattern === false) {
$this->pattern = null;
} elseif (is_string($pattern)) {
$this->pattern = $pattern;
}
return $this;
}
/**
* Extract replaceable keywords from string using the supplied pattern
*
* @param string $string
* @return string
*/
protected function extractParameters(string $string): string
{
// If no pattern, return string as is
if (!$this->pattern) {
return $string;
}
// Replace all matches of our pattern with ${\d} for replacement later
return preg_replace_callback(
$this->pattern,
function ($matches) {
static $index = -1;
$index++;
return '${' . $index . '}';
},
$string
);
}
/**
* Inject the replacements back into the translated string
*
* @param string $string
* @param array