skip to Main Content

I am trying to change the language of my system using ajax but I don’t know how to change the locale and make it permanent until the user decides to change again. Currently, the locale in the app.php is set to 'en' and I want to change it to 'nl' using a select menu. I tried using App::setLocale($value) but that does not do anything, unfortunately. How can I accomplish this?

Form

<form method="POST" action="{{ route('change_language',['id' => Auth::user()->id]) }}" class="form-row my-3">
  {{ csrf_field() }}
  {{ method_field('PATCH') }}
  <div class="form-group col-9">
     <h4 class="mb-0">{{ __('Language') }}</h4>
     <p class="m-0 sub-text">{{ __('Change the language of the dashboard') }}</p>
  </div>
  <div class="form-group col-3 d-flex justify-content-end align-items-center">
    <select name="language" id="language" class="form-control">
       <option value="nl" {{ ( Auth::user()->language == 'nl') ? 'selected' : '' }}>{{ __('Dutch') }}</option>
        <option value="en" {{ ( Auth::user()->language == 'en') ? 'selected' : '' }}>{{ __('English') }}</option>
    </select>
  </div>
  <div class="col-md-12 text-right">
    <p class="text-success saved-message" style="display: none">{{ __('The language has changed!') }}</p>
  </div>
</form>

AJAX

$('#language').change(function() {
  $.ajax({
    headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
    url: '{{ route('change_language', ['id' => Auth::user()->id]) }}',
    type: 'PATCH',
    data: {"language": $(this).children("option:selected").val()},
    success: function(data) {
             $('.saved-message').fadeIn();
                setTimeout(function() {
                   $('.saved-message').fadeOut();
                }, 1000);
           }
      })
});

Route

Route::patch('/dashboard/user/{id}/language', 'PreferencesController@changeLanguage')->name('change_language');

Controller method

public function changeLanguage(Request $request, $id)
    {
        $user = User::findOrFail($id);

        $user->language = $request->get('language');
        $user->save();

        App::setLocale($request->language);
    }

3

Answers


  1. You haven’t described any error but probably you are not familiar how locale works in Laravel. Locale is set per requets. So if you set locale in this controller method (assuming it’s working fine) when you visit site then locale will be again same as set in configuration file.

    To solve this AppServiceProvider in boot method you could add code like this:

    if ($user = auth()->user()) {
        App::setLocale($user->language);
    }
    

    This way, when user is logged and locale is saved in his profile each time he visit site (assuming he is logged) he will see site in valid locale. Of course it does not solve the issue when user is not logged. For such case you might want to create additional cookie for user to set locale from cookie in case user is not logged.

    Login or Signup to reply.
  2. You must have some kind of middleware because session (language) is not persistent. You can try something like this (Language Middleware):

    public function handle($request, Closure $next)
        {
            if (auth()->check()) {
                $language = auth()->user()->language;
                if (empty($language)) {
                    $language = config('app.fallback_locale');
                }
                app()->setLocale($language);
                Session::put('applocale', $language);
                auth()->user()->language = $language;
                auth()->user()->save();
                return $next($request);
            }
            if (Session::has('applocale')) {
                app()->setLocale(Session::get('applocale'));
            } else {
                app()->setLocale(config('app.fallback_locale'));
                Session::put('applocale', config('app.fallback_locale'));
            }
            return $next($request);
        }
    

    as you can see I store language per user in db. In controller you could have something like this:

    
            if (auth()->check()) {
                auth()->user()->language = $language;
                auth()->user()->save();
                return back();
            } 
                Session::put('applocale', $language);
                return back();
            }
    
    

    try consider something like this

    Login or Signup to reply.
  3. You need middleware to persist the localization

    class Language
    {
        protected $app;
    
        public function __construct(Application $app, Request $request) {
            $this->app = $app;
        }
    
        public function handle($request, Closure $next)
        {
            $this->app->setLocale(session('user_locale', config('app.locale')));
    
            return $next($request);
        }
    }
    

    And this middleware should work on every route:

    protected $middlewareGroups = [
            'web' => [
                  // ...
                  AppHttpMiddlewareLanguage::class,
            ]
    ];
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search