Laravel 13 - Build a Real-Time Google Translator.
Laravel 13 - Build a Real-Time Google Translator.
In this tutorial, we will learn how to build a real-time Google Translator in Laravel 13 using the stichoza/google-translate-php package, with automatic language detection, English translation, and live JavaScript updates.
Quick Overview
This guide walks you through adding Google Translate functionality to a Laravel 13 application using the stichoza/google-translate-php package. You’ll start by creating a fresh Laravel project with Blade, install the translation package, and build a dedicated controller to handle language detection and English translation. Next, you’ll configure the required routes and create a responsive translator interface where users can enter text in any language and see the English translation automatically as they type. The guide also covers the package’s shorthand static method for quick translations and shows how to test both the interactive translator and a simple translation route directly in the browser. By the end, you’ll have a working Laravel 13 translator that can handle both interactive text translation and quick translation snippets.
Step # 1 : Create and Configure the Laravel 13 Project.
Let’s start by setting up a fresh Laravel 13 application called translator. The simplest way to create the project is with the Laravel Installer. Since the Installer relies on Composer, make sure Composer is installed and available on your system. If Laravel Installer is not installed yet, install it globally using.
composer global require laravel/installer
After the installation is complete, create the new Laravel application with.
laravel new translator
During the setup process, Laravel will ask you to choose a few configuration options. For this project, use the following selections.
- Starter Kit: Choose No, as we’ll build the project without any pre-configured authentication or starter scaffolding.
- Frontend Stack: Select Blade to use Laravel’s native Blade templating engine.
- Boost Features: Keep the default option and press Enter.
- Boost Integrations: Leave the default selection unchanged and press Enter.
- AI Agents: When Laravel asks you to choose an AI agent, select Amp. This will automatically add the required Amp configuration to the project.
With these choices, Laravel will generate a clean application using no starter kit, Blade for the frontend, the default Boost configuration, no Boost integrations, and Amp as the AI agent.
Step # 2 : Open Your Laravel Project Directory.
Once the application has been created, open your preferred terminal and navigate to the translator project folder. You can use PowerShell, Command Prompt, Git Bash, or the integrated terminal in VS Code. Run the following command.
cd translator
Once you are inside the project directory, Laravel will recognize it as the working directory, allowing you to execute Artisan, Composer, and other Laravel commands for this application.
Step # 3 : Install the Google Translate Package.
Now, let’s add Google Translate functionality to the Laravel application by installing the stichoza/google-translate-php package. Run the following command in your terminal.
composer require stichoza/google-translate-php
The package provides the functionality we need to translate text within our application. It supports automatic language detection, translation into more than 100 languages, and shorthand methods for performing quick translations. This will allow us to add the required translation features without building the entire translation process ourselves.
Step # 4 : Set Up the Translation Controller.
Now that the translation package is installed, let’s create a controller to manage the translation requests. Run the following Artisan command in your terminal.
php artisan make:controller TranslatorController
Once the controller has been created, open app/Http/Controllers/TranslatorController.php and update it with the following code.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Stichoza\GoogleTranslate\GoogleTranslate;
class TranslatorController extends Controller
{
// Load the translation page
public function index()
{
return view('translate');
}
// Handle the translation request
public function translate(Request $request)
{
$tr = new GoogleTranslate();
// Automatically detect the language of the input text
$tr->setSource('auto');
// Translate the input text into English
$tr->setTarget('en');
// Translate the requested text and return the result as JSON
$result = $tr->translate($request->text);
return response()->json(['translation' => $result]);
}
}
The controller now takes care of both displaying the translation page and processing translation requests. The index() method loads the Blade view where users will enter their text, while the translate() method receives the submitted text, automatically detects its language, translates it into English, and returns the translated result as a JSON response. Since the frontend can handle this response directly, the page does not need to reload for each translation, keeping the translator smooth and interactive.
Step # 5 : Set Up the Translation Routes.
Next, we need to connect our controller methods to the application routes. Open routes/web.php and add the following.
use App\Http\Controllers\TranslatorController;
Route::get('/', [TranslatorController::class, 'index']);
Route::post('/translate', [TranslatorController::class, 'translate']);
The / route is responsible for displaying the translator page through the index() method. The /translate route, on the other hand, points to the translate() method and handles the translation requests sent from the frontend.
Step # 6 : Create the Translator Interface.
Now that the backend and routes are ready, let’s build the frontend interface for our translator. Create a new Blade view at resources/views/translate.blade.php and add the following code.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Laravel 13 - Code Shotcut Google Translator</title>
<meta name="csrf-token" content="{{ csrf_token() }}">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/lucide@latest"></script>
</head>
<body class="min-h-screen bg-gray-950 text-gray-100">
<div class="min-h-screen flex flex-col">
<!-- Header -->
<header class="border-b border-gray-800 bg-gray-950">
<div class="max-w-7xl mx-auto px-6 py-4 flex items-center justify-between">
<div class="flex items-center gap-3">
<div class="w-10 h-10 rounded-xl bg-indigo-500/10 border border-indigo-400/20 flex items-center justify-center text-indigo-400">
<i data-lucide="globe" class="w-5 h-5"></i>
</div>
<div>
<h1 class="text-lg font-bold tracking-wide">
Code Shotcut
</h1>
<p class="text-xs text-gray-500">
Laravel Translator
</p>
</div>
</div>
<div class="hidden sm:flex items-center gap-2 text-sm text-gray-400">
<span class="w-2 h-2 rounded-full bg-emerald-400"></span>
Translation Ready
</div>
</div>
</header>
<!-- Main Content -->
<main class="flex-1 flex items-center justify-center px-4 py-5 sm:px-6">
<div class="w-full max-w-6xl">
<!-- Intro -->
<div class="text-center mb-5">
<div class="inline-flex items-center gap-2 px-3 py-1.5 mb-2 rounded-full border border-indigo-400/20 bg-indigo-500/10 text-indigo-300 text-sm">
<i data-lucide="sparkles" class="w-4 h-4 text-amber-300"></i>
Simple & Fast Translation
</div>
<h2 class="text-3xl sm:text-4xl lg:text-5xl font-bold tracking-tight">
Code Shotcut
<span class="text-indigo-400">
Translate your text instantly.
</span>
</h2>
<p class="mt-2 text-gray-500 max-w-2xl mx-auto">
Enter text in any language and get the English translation automatically as you type.
</p>
</div>
<!-- Translator -->
<div class="rounded-3xl border border-gray-800 bg-gray-900 shadow-2xl overflow-hidden">
<div class="grid grid-cols-1 lg:grid-cols-2">
<!-- Source -->
<div class="p-6 border-b lg:border-b-0 lg:border-r border-gray-800">
<div class="flex items-center justify-between mb-3">
<div>
<p class="text-xs uppercase tracking-widest text-gray-500 mb-1">
Source
</p>
<h3 class="text-lg font-semibold">
Your Text
</h3>
</div>
<div class="px-3 py-1.5 rounded-lg bg-gray-800 border border-gray-700 text-sm text-gray-400">
Auto Detect
</div>
</div>
<textarea
id="source"
class="w-full h-72 bg-gray-950 border border-gray-800 rounded-2xl p-4 text-gray-100 text-base placeholder-gray-600 resize-none focus:outline-none focus:border-indigo-500/60 focus:ring-4 focus:ring-indigo-500/10 transition"
placeholder="Start typing here..."
></textarea>
<div class="flex items-center justify-between mt-2">
<span id="sourceStatus" class="text-xs text-gray-400">
Enter text to translate
</span>
<span class="text-xs text-gray-600">
Auto translation
</span>
</div>
</div>
<!-- Translation -->
<div class="p-6">
<div class="flex items-center justify-between mb-3">
<div>
<p class="text-xs uppercase tracking-widest text-gray-500 mb-1">
Translation
</p>
<h3 class="text-lg font-semibold">
English
</h3>
</div>
<div class="w-9 h-9 rounded-lg bg-indigo-500/10 border border-indigo-400/20 flex items-center justify-center text-indigo-400">
<i data-lucide="arrow-right" class="w-5 h-5"></i>
</div>
</div>
<textarea
id="target"
readonly
class="w-full h-72 bg-gray-800 border border-gray-700 rounded-2xl p-4 text-gray-300 text-base placeholder-gray-600 resize-none focus:outline-none"
placeholder="Your translation will appear here..."
></textarea>
<div class="flex items-center justify-between mt-2">
<span id="translationStatus" class="text-xs text-gray-400">
Waiting for text...
</span>
<span class="flex items-center gap-2 text-xs text-gray-500">
<span class="w-1.5 h-1.5 rounded-full bg-gray-600"></span>
English
</span>
</div>
</div>
</div>
<!-- Learn More -->
<div class="border-t border-gray-800 bg-gray-950 px-6 py-5">
<div class="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
<div class="max-w-xl">
<p class="text-xs font-medium uppercase tracking-widest text-indigo-400">
Learn More
</p>
<h3 class="mt-1 text-lg font-semibold text-gray-100">
Learn Laravel with Code Shotcut
</h3>
<p class="mt-1 text-sm leading-5 text-gray-500">
Explore practical Laravel tutorials, integrations, packages, and real-world development examples on Code Shotcut.
</p>
</div>
<div class="flex flex-col gap-2 sm:flex-row">
<a
href="https://codeshotcut.com/"
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center justify-center gap-2 rounded-xl bg-indigo-500 px-4 py-2.5 text-sm font-semibold text-white transition hover:bg-indigo-600"
>
<i data-lucide="external-link" class="w-4 h-4"></i>
Visit Website
</a>
<a
href="https://www.youtube.com/@CodeShotcut"
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center justify-center gap-2 rounded-xl border border-gray-700 bg-gray-900 px-4 py-2.5 text-sm font-semibold text-gray-300 transition hover:border-red-500/50 hover:text-red-400"
>
<i data-lucide="play" class="w-4 h-4"></i>
Watch on YouTube
</a>
</div>
</div>
</div>
<!-- Footer -->
<div class="border-t border-gray-800 px-6 py-3 flex flex-col sm:flex-row items-center justify-between gap-2 bg-gray-900">
<p class="text-xs text-gray-600">
Powered by Google Translate
</p>
<p class="text-xs text-gray-600">
Built with Laravel & Tailwind CSS
</p>
</div>
</div>
</div>
</main>
</div>
<script>
// Activate all Lucide icons used on the page.
lucide.createIcons();
// Get references to the HTML elements.
const source = document.getElementById('source');
const target = document.getElementById('target');
const sourceStatus = document.getElementById('sourceStatus');
const translationStatus = document.getElementById('translationStatus');
// Get Laravel's CSRF token.
const csrf = document.querySelector('meta[name="csrf-token"]').content;
// Store the timer and current request.
let timeout = null;
let controller = null;
// Run whenever the user types something.
source.addEventListener('input', function () {
// Get the current text.
const text = source.value.trim();
// Stop the previous timer.
clearTimeout(timeout);
// Cancel the previous request.
if (controller) {
controller.abort();
controller = null;
}
// Clear the translation when the input is empty.
if (text === '') {
target.value = '';
sourceStatus.textContent = 'Enter text to translate';
translationStatus.textContent = 'Waiting for text...';
return;
}
// Show the current translation status.
sourceStatus.textContent = 'Translating...';
translationStatus.textContent = 'Processing...';
// Wait 300ms after the user stops typing.
timeout = setTimeout(async () => {
// Create a controller for the current request.
controller = new AbortController();
try {
// Send the text to Laravel.
const response = await fetch('/translate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrf,
'Accept': 'application/json'
},
body: JSON.stringify({
text: text
}),
signal: controller.signal
});
// Convert the response to JSON.
const data = await response.json();
// Handle Laravel errors.
if (!response.ok) {
throw new Error(
data.message || 'Translation failed.'
);
}
// Display the translated text.
target.value = data.translation || '';
// Update the status after successful translation.
sourceStatus.textContent = 'Translation complete';
translationStatus.textContent = 'Translated successfully';
} catch (error) {
// Ignore intentionally cancelled requests.
if (error.name === 'AbortError') {
return;
}
// Show an error message if translation fails.
target.value = 'Unable to translate text.';
sourceStatus.textContent = 'Translation failed';
translationStatus.textContent = 'Please try again.';
}
}, 300);
});
</script>
</body>
</html>
The page uses Tailwind CSS to create a clean, responsive dark interface with separate areas for entering the source text and displaying the English translation. It also uses Lucide icons for a lightweight and consistent icon set. On the JavaScript side, the translation is triggered automatically as the user types. A short 300ms delay prevents unnecessary requests while the user is still typing, while AbortController cancels any previous request when new text is entered. The text is then sent to the /translate route using a POST request, and the JSON response from Laravel is displayed directly in the translation field without reloading the page.
Step # 7 : Verify the Translation Workflow.
Now that everything is configured, let’s test the translator and make sure the translation flow is working correctly. Start the Laravel development server.
php artisan serve
Then open your browser and visit: http://127.0.0.1:8000. Try entering text in German, Spanish, French, Hindi, or any other supported language in the left textarea. The application will automatically detect the source language and display the English translation on the right side as you type.
Quick Translation with the Static Method:
The Google Translate package also provides a shorthand static method for translating individual text snippets without creating a GoogleTranslate instance. Open app/Http/Controllers/TranslatorController.php and add the following method.
public function quickDemo()
{
// Translate a French phrase directly into English.
return GoogleTranslate::trans(
'Bienvenue sur Code Shotcut',
'en',
'fr'
);
}
This static method is useful when you only need to translate a short piece of text without building an interactive translation interface. For the live translator, however, the existing translate() method is more suitable because it handles text submitted from the textarea. Now that the quickDemo() method has been added, we need to create a route that points to this method. Open routes/web.php and add the following route.
Route::get('/quick-demo', [
App\Http\Controllers\TranslatorController::class,
'quickDemo'
]);
Now visit: http://127.0.0.1:8000/quick-demo .You should see the translated text directly in the browser. This approach is useful for quick translation checks, while the interactive textarea is better suited for live typing and dynamic translations.
Conclusion
By following this guide, you’ve successfully added Google Translate functionality to your Laravel 13 application using the stichoza/google-translate-php package. You learned how to set up the project, install the package, create a translation controller, define routes, build a Blade-based translator interface, and implement real-time translation with JavaScript. You also explored the package’s shorthand static method for quick translations. This integration gives you a solid foundation for adding multilingual and translation features to your Laravel applications.
For more advanced features and options, check out the official Stichoza Google Translate documentation: https://github.com/Stichoza/google-translate-php.
Share this with friends!
To engage in commentary, kindly proceed by logging in or registering
Subscribe to Our Newsletter
Stay ahead of the curve! Join our newsletter to see what everyone’s talking about.
0 Comments