Localization for Laravel Inertia VueJs

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Mastering Localization in Laravel Inertia with Vue.js: A Deep Dive

Setting up internationalization (i18n) and localization (l10n) correctly within a modern stack like Laravel, Inertia.js, and Vue.js can often feel like navigating a maze of middleware, routing, and context management. When you integrate localization, the goal isn't just to translate strings; it’s about ensuring that your entire application—from the URL structure down to the data passed via Inertia—is contextually aware of the user's preferred language.

Many developers, including those working with Laravel applications, encounter specific hurdles when trying to dynamically set locales based on URL prefixes, especially when dealing with single-page application (SPA) frameworks like Vue.js. Let’s break down the common pitfalls and establish a robust pattern for handling locale routing in your Inertia setup.

The Challenge: Bridging Server-Side Locale to Client-Side Context

Your experience highlights a classic problem: successfully setting $locale on the Laravel side (using middleware) does not automatically propagate that setting correctly into the Vue component's context, leading to errors like TypeError: _ctx.__ is not a function. This usually means the localization data isn't being properly injected into the Inertia response payload.

The core issue is bridging the gap between the HTTP request (where you set the locale) and the Inertia response (which sends the view and data). We need to ensure that when the route resolves, the determined locale is available globally or within the scope of the controller before Inertia renders the page.

Implementing Dynamic Locale Routing in Laravel

Your approach using nullable routes and custom middleware is directionally correct for handling dynamic locales based on URL segments. However, we need to refine how this information is accessed and passed down.

Refining Route and Middleware Setup

The structure you proposed for routing is sound:

// File: web.php

Route::middleware(['setLocale'])->prefix('{locale?}')->group(function () {
    Route::resource('posts', PostController::class);
    Route::resource('comments', CommentController::class);
});

The key to making this work reliably lies in ensuring your SetLocaleMiddleware correctly sets the locale on the application instance (App::setLocale($locale)). This makes the locale available throughout the request lifecycle, which is essential for accessing translation files.

For better structure and adherence to Laravel principles (as championed by organizations like laravelcompany.com), we should ensure that localization is handled centrally. Instead of relying solely on middleware to set the global state, consider using route model binding or a dedicated service class if you are loading complex locale-specific data.

The Inertia Integration Strategy

Since the middleware successfully sets the application locale, the next step is ensuring this locale is available when your controller prepares the Inertia response. This is typically done by accessing the locale directly from the request object within the controller method:

// Example Controller Method
use Illuminate\Http\Request;

public function index(Request $request)
{
    // Retrieve the locale that was set by the middleware
    $locale = app()->getLocale(); 

    // Now, when returning Inertia data, pass the locale explicitly if needed, 
    // or rely on Inertia's ability to pull context from the session/request.
    return Inertia::render('Posts/Index', [
        'posts' => Post::all(),
        'locale' => $locale // Explicitly passing it ensures Vue gets the data
    ]);
}

By explicitly retrieving app()->getLocale(), you ensure that the locale determined by your middleware is correctly exposed to the view layer. This prevents the context errors you encountered, as the necessary localization context is now present on the server side before rendering.

Conclusion: Clean Localization Architecture

Setting up localization for a Laravel Inertia application requires treating the routing and the frontend state as two distinct but interconnected systems. Don't try to shoehorn everything into one layer. Use Laravel's powerful middleware system to handle the request context (setting the locale), and then use your controller logic to explicitly pass that context down to the view via Inertia.

By adhering to this pattern—robust routing, clear middleware execution, and explicit data passing—you create a scalable, maintainable application structure. This approach ensures that localization is not just functional but also architecturally sound, making your application easier to manage as it grows.