Pavel Zaněk PavelZanek.com
Select language
Account

Easy Laravel application localization

Guide to localizing a Laravel application, including setting up language translations and modifying routes and middleware to support multilingual content. Focuses on string translations in an application template, with examples for Jetstream and Livewire.

Published at 2021-11-20 by Pavel Zaněk

Estimated Reading Time: 6 minutes

Easy Laravel application localization

Table of Contents

The text provided describes a simple method for localizing a Laravel application, focusing on translating parts of the application rather than content stored in the database or localizing URLs. The guide details how to set up translations for strings appearing in the Laravel application template.

Logic

The logic is quite straightforward, with no need for database intervention.

Language Settings

config/app.php:

...
'locales' => [
        'en' => 'English',
        'cs' => 'Czech',
 ],
...

Middleware Language

app/Http/Middleware/Language.php:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\URL;

class Language
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {        
        App::setLocale($request->language);
        URL::defaults(['language' => $request->language]);
        $request->route()->forgetParameter('language');
        return $next($request);
    }
}

Adding Middleware to the Kernel

app/Http/Kernel.php:

...
protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\Language::class, // Localization
        ],

        ...
];
...

Routes in web.php

routes/web.php:

...
Route::group([
    'prefix' => "{language}", 
    'where' => ['language' => '[a-zA-Z]{2}']
    ], function () {

    ...

});
...

LanguageController.php Controller

app/Http/Controllers/LanguageController.php:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\URL;

class LanguageController extends Controller
{
    public function switchLang(Request $request, $lang)
    {
        // $urlParts[1] == current lang
        $urlParts = explode('/', str_ireplace(array('http://', 'https://'), '', url()->previous()));

        $newUrl = str_replace(
            '/' . $urlParts[1] . '/', 
            '/' . $lang . '/',
            url()->previous() 
        );

        App::setLocale($lang);
        URL::defaults(['language' => $lang]);
        return redirect()->to($newUrl);
    }
}

Adding the Controller Route to web.php

routes/web.php:

...
Route::get('lang/{lang}', [App\Http\Controllers\LanguageController::class, 'switchLang'])->name('langSwitcher');
...

RouteServiceProvider.php

app/Providers/RouteServiceProvider.php:

...
public const DASHBOARD = '/en/dashboard';
...

Creating a Language Switcher

Example for use in the stack: Laravel, Jetstream – Livewire + Blade, Tailwindcss

resources/views/navigation-menu.blade.php:

Desktop

...
<!-- Language Dropdown -->
<div class="ml-3 relative">
    <x-jet-dropdown align="right" width="48">
        <x-slot name="trigger">
            <span class="inline-flex rounded-md">
                <button type="button" class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 bg-white hover:text-gray-700 focus:outline-none transition">
                    @lang(config('app.locales')[App::getLocale()])

                    <svg class="ml-2 -mr-0.5 h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
                        <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
                    </svg>
                </button>
            </span>
        </x-slot>

        <x-slot name="content">
            <!-- Language Switcher -->
            <div class="block px-4 py-2 text-xs text-gray-400">
                {{ __('Select language') }}
            </div>

            @foreach (config('app.locales') as $lang => $language)
                @if ($lang !== App::getLocale())
                    <x-jet-dropdown-link href="{{ route('langSwitcher', $lang) }}">
                        @lang($language)
                    </x-jet-dropdown-link>
                @endif
            @endforeach

        </x-slot>
    </x-jet-dropdown>
</div>
...

Responsive Version

...
<div class="mt-3 space-y-1">
    <div class="border-t border-gray-200"></div>

    <div class="block px-4 py-2 text-xs text-gray-400">
        {{ __('Select language') }}
    </div>
    
    @foreach (config('app.locales') as $lang => $language)
        @if ($lang !== App::getLocale())
            <x-jet-responsive-nav-link href="{{ route('langSwitcher', $lang) }}">
                @lang($language)
            </x-jet-responsive-nav-link>
        @endif
    @endforeach

    <div class="border-t border-gray-200"></div>
</div>
...

Adding Translations

For example, resources/lang/cs.json:

{
    "Dashboard": "Nástěnka",
    "Select language": "Vyberte jazyk",
    "Czech": "Čeština",
    ...
}

Result

Czech Version:

Result - Laravel localization - Czech version

English Version:

Result - Laravel localization - English version

Tip

If you use Jetstream with Livewire as in the example and want to localize the default routes, then a few more minor adjustments are necessary.

From the /vendor/jetstream/routes/ folder, copy the routes to your routes. The file can then look like this (routes/web.php):

<?php

use Illuminate\Support\Facades\Route;
use Laravel\Jetstream\Http\Controllers\CurrentTeamController;
use Laravel\Jetstream\Http\Controllers\Livewire\ApiTokenController;
use Laravel\Jetstream\Http\Controllers\Livewire\PrivacyPolicyController;
use Laravel\Jetstream\Http\Controllers\Livewire\TeamController;
use Laravel\Jetstream\Http\Controllers\Livewire\TermsOfServiceController;
use Laravel\Jetstream\Http\Controllers\Livewire\UserProfileController;
use Laravel\Jetstream\Http\Controllers\TeamInvitationController;
use Laravel\Jetstream\Jetstream;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('lang/{lang}', [App\Http\Controllers\LanguageController::class, 'switchLang'])->name('langSwitcher');

Route::get('/', function () {
    return redirect()->route('login');
});

Route::group([
    'prefix' => "{language}", 
    'where' => ['language' => '[a-zA-Z]{2}']
    ], function () {

    Route::group(['middleware' => config('jetstream.middleware', ['web'])], function () {
        if (Jetstream::hasTermsAndPrivacyPolicyFeature()) {
            Route::get('/terms-of-service', [TermsOfServiceController::class, 'show'])->name('terms.show');
            Route::get('/privacy-policy', [PrivacyPolicyController::class, 'show'])->name('policy.show');
        }

        Route::group(['middleware' => ['auth:sanctum', 'verified']], function () {
            // User & Profile...
            Route::get('/user/profile', [UserProfileController::class, 'show'])
                        ->name('profile.show');

            // API...
            if (Jetstream::hasApiFeatures()) {
                Route::get('/user/api-tokens', [ApiTokenController::class, 'index'])->name('api-tokens.index');
            }

            // Teams...
            if (Jetstream::hasTeamFeatures()) {
                Route::get('/teams/create', [TeamController::class, 'create'])->name('teams.create');
                Route::get('/teams/{team}', [TeamController::class, 'show'])->name('teams.show');
                Route::put('/current-team', [CurrentTeamController::class, 'update'])->name('current-team.update');

                Route::get('/team-invitations/{invitation}', [TeamInvitationController::class, 'accept'])
                            ->middleware(['signed'])
                            ->name('team-invitations.accept');
            }
        });
    });

    Route::group(['middleware' => ['auth:sanctum', 'verified']], function () {
        
        // Dashboard
        Route::get('/dashboard', function () {
            return view('dashboard');
        })->name('dashboard');

    });

});

For instance, if we modify the route for displaying the profile, like this (routes/web.php):

...
// Old value: /user/profile
Route::get('/profile', [UserProfileController::class, 'show'])->name('profile.show');
...

If we make the above change, the profile display will be available on our route /profile, and we can also use the default route /user/profile (loaded from the package – laravel/jetstream/routes/livewire.php). If we want to disable the default routes, then we must modify JetsreamServiceProvider.php (app/Providers/JetsreamServiceProvider.php).

...
public function register()
{
    Jetstream::ignoreRoutes();
}
...
Share:
You have not rated yet.
Pavel Zaněk

Full-stack developer & SEO consultant

Pavel Zaněk is an experienced full-stack developer with expertise in SEO and programming in Laravel. His skills include website optimization, implementing effective strategies to increase traffic and improve search engine rankings. Pavel is an expert in Laravel and its related technologies, including Livewire, Vue.js, MariaDB, Redis, TailwindCSS/Bootstrap and much more. In addition to his programming skills, he also has a strong background in VPS management, enabling him to handle complex server-side challenges. Pavel is a highly motivated and dedicated professional who is committed to delivering exceptional results. His goal is to help clients achieve success in the online space and achieve their goals with the help of the best web technologies and SEO strategies.

Comments

No comment has been added yet.

Add a comment

Suggested Articles

How to create RSS feed in Laravel framework

Published at 2023-08-10 by Pavel Zaněk

Estimated Reading Time: 10 minutes

laravel

Guide to creating RSS feed in Laravel framework without external packages. From basic principles to advanced techniques. Ideal for developers looking for an efficient and secure solution.

Continue reading

Your experience on this site will be improved by allowing cookies. - Cookies Policy