Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

thesnakebite's avatar

Changing the language in my app

Hi everyone, I need to change the language of my app using a select. From my web.php file

Route::get('language/{locale}', [LanguageController::class, 'changeLanguage'])- >name('language.change');

In my LanguageController.php controller in the changeLanguage method...

<?php

namespace App\Http\Controllers;

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

class LanguageController extends Controller
{
    public function changeLanguage($locale)
    {
        if (array_key_exists($locale, config('app.available_locales'))) {
            session()->put('locale', $locale);
            app()->setLocale($locale);
        }

        return redirect()->back();
    }
}

Now in my config/app.php file I added the variable available:locales ...

'locale' => env('APP_LOCALE', 'es'),

    'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),

    'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'),
    
    'available_locales' => [
        'Español (España)' => 'es',
        'English' => 'en',
    ],

... Below I have created a new middleware...

 public function handle(Request $request, Closure $next): Response
    {
        if (session()->has('locale')) {
            app()->setLocale(session()->get('locale'));
        } else {
            app()->setLocale(config('app.locale'));
        }

        return $next($request);
    } 

... From my HandleInertiaRequest.php file I enter...

public function share(Request $request): array
    {
        $currentLocale = session('locale', config('app.locale'));
        Log::info('Inertia sharing locale:', ['locale' => $currentLocale]);

        return array_merge(parent::share($request), [
            'locale' => $currentLocale,
            'available_locales' => config('app.available_locales'),
            'translation' => function() {
                $locale = app()->getLocale();
                $path = base_path("/lang/{$locale}.json");
                $content = file_get_contents($path);

                return json_decode($content);
            },
        ]);
    }

... Also registered the Localization middleware in the bootstrap/app.php file ...

 ->withMiddleware(function (Middleware $middleware) {
        $middleware->web(append: [
            \App\Http\Middleware\HandleInertiaRequests::class,
            \Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets::class,
            \App\Http\Middleware\Localization::class,
        ]);

        //
    }) 

... And finally in my vue component in your script...

<script setup>
 import { Link, usePage } from '@inertiajs/vue3'

 const page = usePage()

 const changeLanguage = (locale) => {
 window.location.href = route('language.change', locale);
 };
</script> 

...and in your template...

 <select
 v-model="page.props.locale"
 @change="changeLanguage(page.props.locale)"
 class="appearance-none border-0 bg-transparent text-gray-600 text-xs cursor-pointer focus:outline-none focus:ring-0 hover:border-0 active:border-0"
 aria-label="Change language"
 >
 <option v-for="(code, name) in page.props.available_locales" :key="code" :value="code">
 {{name}}
 </option>
 </select>

The behavior I'm getting is that the selector doesn't change and the language change isn't added either, any suggestions?

0 likes
15 replies
Rebwar's avatar

@thesnakebite In your changeLanguage method, you are looking for the keys of available_locales array in your config. However, the condition never evaluates to true because the keys in available_locales are Español (España) and English, while you are passing es or en. Please update changeLanguage in your controller to the following:

public function changeLanguage($locale)
{
    if (in_array($locale, config('app.available_locales'))) {
        session()->put('locale', $locale);
        app()->setLocale($locale);
    }

    return redirect()->back();
}
thesnakebite's avatar

In the Footer component, the language change is not functional because the implementation is not properly updating the page.props.locale variable.

<script setup>
    import { Link, usePage } from '@inertiajs/vue3'

    const page = usePage()

    const changeLanguage = (locale) => {
        router.get(route('language.change', locale), {}, {
            preserveScroll: true,
            onSuccess: () => window.location.reload(),
        });
    };
</script>

<div class="flex flex-col xs:flex-row justify-center items-center static overflow-y-visible overflow-x-visible gap-1 xs:gap-4">
	<!-- Idiomas -->
    <select @change="changeLanguage(page.props.locale)"
                  class="appearance-none border-0 bg-transparent text-gray-600 text-xs cursor-pointer focus:outline-none focus:ring-0 hover:border-0 active:border-0" 
aria-label="Cambiar idioma">
		<option v-for="(name, code) in page.props.available_locales" :key="code" :value="code">
        	{{ name }}
        </option>
    </select>
 
    <!-- Copyright -->
    <span class="text-gray-600 text-xs block max-w-full break-all m-0 wrap min-w-0 overflow-y-visible overflow-x-visible relative">
     @ 2024 Setupstagram from Álvaro dev
    </span>
</div>

The problem is that the @change event does not update page.props.locale when the user selects a new language. This means that the app does not correctly reflect the language change. In another component of my app called SuggestionsPanel, the language change is functional because the implementation uses a modal with checkboxes that directly update the selected language. This allows the language change to be correctly reflected throughout the app.

Because I don't have the same consistency with the select_ element?

Rebwar's avatar

@thesnakebite For the select options, use v-model for two-way binding, and avoid passing page.props.locale to the changeLanguage.

Please ensure your code is well-organized and properly imports the required components. Wrap your HTML code within <template></template> in your Vue component.

thesnakebite's avatar

After receiving your suggestions @rebwar, I have made several adjustments to my implementation of language switching in the Footer component of my app. Let me share the steps I have followed and the results I have obtained:

Verifying the language settings in the config/app.php file:

I have confirmed that the language codes ('es', 'en') and language names ('Español (España)', 'English') are defined correctly.

Debugging the language switching logic:

I have added several console.log in the changeLanguage function to verify that it is being called correctly and that it receives the expected language value. However, I have noticed that even when a different language is selected, the select in the Footer component still displays the default language.

Verifying the server response:

I added a console.log to inspect the server response after redirecting the user to the language change route. The response appears to be correct and the language change is being processed properly on the server.

After performing these tests, I am still unable to determine the cause of the problem. The language change is being processed correctly, but it is not being reflected in the Footer component.

Rebwar's avatar

@thesnakebite

change:

<option v-for="(name, code) in page.props.available_locales" :key="code" :value="code"> {{ name }}</option>

to:

<option v-for="(code, name) in page.props.available_locales" :key="code" :value="code"> {{ name }}</option>
thesnakebite's avatar

Thanks for the feedback but this change only shows the config/app.php options in the front-end. The behavior I get is when I select the language from the home page using the select element, it automatically returns to the app's default language.

Rebwar's avatar

@thesnakebite Ensure that your frontend sends the correct locale and verify in your controller that you are receiving and setting the locale correctly. If you'd like to share your code, please provide only the portion responsible for handling the locale change, without including any unrelated code.

thesnakebite's avatar

The problem is that although the language change seems to work correctly in the backend, the Footer component of my application does not reflect the language change selected by the user.

public function changeLanguage($locale)
    {
        logger()->info('Changing language to:' , ['locale' => $locale]);

        if(in_array($locale, config('app.available_locales'))) {
            logger()->info('Valid locale, updating session and app...');

            session()->put('locale', $locale);
            app()->setLocale($locale);
        } else {
            logger()->warning('Invalid locale received:', ['locale' => $locale]);
        }

        return redirect()->back();
    }

The Localization middleware created ...

 class Localization
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        if (session()->has('locale')) {
            app()->setLocale(session()->get('locale'));
        } else {
            app()->setLocale(config('app.locale'));
        }

        return $next($request);
    }
}

And my config/app.php file ...

/*
    |--------------------------------------------------------------------------
    | Application Locale Configuration
    |--------------------------------------------------------------------------
    |
    | The application locale determines the default locale that will be used
    | by Laravel's translation / localization methods. This option can be
    | set to any locale for which you plan to have translation strings.
    |
    */

    'locale' => env('APP_LOCALE', 'en'),

    'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),

    'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'),
    
    'available_locales' => [
        'Español (España)' => 'es',
        'English' => 'en',
    ],

356 / 5.000 The problem persists in the select element, because...

1 - On the home page, when you change the language in the Footer component's select to "English", the select automatically reverts to displaying the "Spanish" language. 2 - However, once you log in and enter the application, the menus and other elements are displayed correctly translated.

thesnakebite's avatar

It is very strange that nothing is being received in the dd($locale) of the LanguageController controller. I have checked the route and controller but I cannot figure out why I am not receiving the dd value on the screen.

// Idioma
        Route::get('/language/{locale}', [LanguageController::class, 'changeLanguage'])->name('language.change');
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class LanguageController extends Controller
{
    public function changeLanguage($locale)
    {
        dd($locale);

        if(in_array($locale, config('app.available_locales'))) {
            session()->put('locale', $locale);
            app()->setLocale($locale);
        }

        return redirect()->back();
    }
}
Rebwar's avatar

@thesnakebite This means your controller is not being reached when selecting a locale from the frontend. Check the language select field, the function used to send the request to the controller, and ensure there are no typos. Additionally, inspect your browser's console for any errors when selecting the locale.

thesnakebite's avatar

Hi, thanks @juanjota for the link and for a more concise look at the problem I'm facing with my app's language change.

When implementing the changes in my app I realized that the routes file is within the group of routes protected by authentication, which shouldn't be the case, since the language change should be available for both authenticated and unauthenticated users.

Once the route was moved out of the group it is now functional in my app, but I have implemented the language change in two different components of my app: one on the home page (where unauthenticated users can access) and another in an options panel (which only authenticated users can access).

The problem I'm getting is that, when an authenticated user makes the language change in the options panel and then logs out, the application returns to the default language on the home page, even though the user had selected a different language.

class Localization
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        if (session()->has('locale')) {
            app()->setLocale(session()->get('locale'));
        } else {
            app()->setLocale(config('app.locale'));
        }

        return $next($request);
    }
}

You should ensure that the selected language value is being updated correctly in the user session, and that the Localization middleware is setting the application language appropriately.

Please or to participate in this conversation.