google/cloud-translate
Idiomatic PHP client for Google Cloud Translation. Supports V2 (handwritten) and V3 (generated) APIs to translate text, detect language, and manage datasets/models. Auth via Google Cloud credentials; install with Composer for easy integration.
composer require google/cloud-translate
putenv('GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json');
.env:
GOOGLE_APPLICATION_CREDENTIALS=/path/to/production-key.json
use Google\Cloud\Translate\V3\TranslationServiceClient;
$client = new TranslationServiceClient();
$response = $client->translateText(
'Hello, world!',
['targetLanguageCode' => 'es']
);
echo $response->getTranslations()[0]->getTranslatedText();
// In a Laravel controller or service
public function translateText(string $text, string $targetLang): string
{
$client = app(TranslationServiceClient::class);
$response = $client->translateText($text, [
'targetLanguageCode' => $targetLang,
'mimeType' => 'text/html', // For HTML content
]);
return $response->getTranslations()[0]->getTranslatedText();
}
Register the client as a singleton in AppServiceProvider:
public function register()
{
$this->app->singleton(TranslationServiceClient::class, function () {
return new TranslationServiceClient();
});
}
Usage:
$translation = app(TranslationServiceClient::class)->translateText(...);
Create a facade (app/Facades/Translate.php):
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Translate extends Facade
{
protected static function getFacadeAccessor() => 'google.translate';
}
Register in AppServiceProvider:
$this->app->bind('google.translate', function () {
return new \Google\Cloud\Translate\V3\TranslationServiceClient();
});
Usage:
use App\Facades\Translate;
$translated = Translate::translateText('Hello', 'fr');
For high-volume translations (e.g., bulk content updates), use Laravel queues:
// Job: TranslateTextJob.php
public function handle()
{
$client = app(TranslationServiceClient::class);
$response = $client->translateText($this->text, [
'targetLanguageCode' => $this->targetLang,
]);
$this->updateTranslatedContent($response->getTranslatedText());
}
Dispatch jobs in batches:
TranslateTextJob::dispatchEach($texts, 'es')->onQueue('translations');
Auto-detect source language:
$response = $client->detectLanguage('Bonjour le monde!');
$sourceLang = $response->getLanguages()[0]->getLanguageCode();
Fine-tune translations for domain-specific terminology:
$datasetName = 'projects/YOUR_PROJECT/locations/global/adaptiveMtDatasets/YOUR_DATASET';
$response = $client->translateText('Medical term', [
'targetLanguageCode' => 'de',
'adaptiveMtDatasetName' => $datasetName,
]);
Translate entire documents:
$gcsUri = 'gs://your-bucket/document.pdf';
$response = $client->translateDocument(
$gcsUri,
['targetLanguageCode' => 'ja']
);
Customize translations with domain-specific terms:
$glossaryName = 'projects/YOUR_PROJECT/locations/global/glossaries/YOUR_GLOSSARY';
$response = $client->translateText('Term to translate', [
'targetLanguageCode' => 'es',
'glossaryConfig' => ['glossary' => $glossaryName],
]);
Wrap API calls in a service class:
public function safeTranslate(string $text, string $targetLang): ?string
{
try {
$response = $client->translateText($text, ['targetLanguageCode' => $targetLang]);
return $response->getTranslations()[0]->getTranslatedText();
} catch (\Google\ApiCore\ApiException $e) {
\Log::error('Translation failed: ' . $e->getMessage());
return null;
}
}
Service Account Permissions:
roles/cloudtranslate.user role.Environment Variables:
.env may not load GOOGLE_APPLICATION_CREDENTIALS automatically. Use:
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . env('GOOGLE_CREDENTIALS_PATH'));
Deprecated credentials Option:
putenv() instead.Caching:
$cacheKey = "translate:{$text}:{$targetLang}";
return cache()->remember($cacheKey, now()->addHours(1), function () use ($text, $targetLang) {
return $this->safeTranslate($text, $targetLang);
});
Batch Requests:
translateText in a loop or batch via DocumentTranslation.Async Processing:
TranslateTextJob::dispatch($text, $targetLang)->onQueue('translations');
return response()->json(['status' => 'queued']);
| Error | Cause | Solution |
|---|---|---|
InvalidArgument: Invalid target language code |
Invalid ISO code (e.g., en-US instead of en) |
Use 2-letter codes (e.g., es, fr). |
ApiException: Quota exceeded |
Hitting Google’s free tier limits (~500K characters/day) | Upgrade quota or implement exponential backoff. |
ApiException: Request contains an invalid argument |
Malformed request (e.g., missing mimeType) |
Validate inputs; check API docs. |
ApiException: 403 Forbidden |
Missing permissions on the service account | Grant roles/cloudtranslate.user to the account. |
Enable Logging:
$client = new TranslationServiceClient([
'logger' => new \Monolog\Logger('translate', [
new \Monolog\Handler\StreamHandler(storage_path('logs/translate.log'), \Monolog\Logger::DEBUG),
]),
]);
Retry Logic:
use Google\ApiCore\RetrySettings;
$retrySettings = new RetrySettings();
$retrySettings->setMaxAttempts(3);
$client = new TranslationServiceClient(['retrySettings' => $retrySettings]);
Validate Responses:
getTranslations() length (may return empty for unsupported pairs):
if (empty($response->getTranslations())) {
throw new \RuntimeException('Translation failed for language pair.');
}
Custom Response Handling:
$client->translateText($text, ['targetLanguageCode' => 'de'])->then(function ($response) {
$translation = $response->getTranslations()[0];
$data = [
'text' => $translation->getTranslatedText(),
'confidence' => $translation->getDetectedLanguageCode() === 'auto' ? 0.9 : 0.7,
];
return $data;
});
Pre/Post-Processing:
$cleanText = strip_tags($dirtyText);
$translated = $client->translateText($cleanText, ['targetLanguageCode' => 'es']);
Fallback Logic:
How can I help you explore Laravel packages today?