【问题标题】:Laravel - Change locale using AjaxLaravel - 使用 Ajax 更改语言环境
【发布时间】:2020-04-22 08:45:23
【问题描述】:

我正在尝试使用 ajax 更改系统的语言,但我不知道如何更改语言环境并使其永久化,直到用户决定再次更改。目前,app.php 中的语言环境设置为'en',我想使用选择菜单将其更改为'nl'。我尝试使用App::setLocale($value),但不幸的是,这并没有做任何事情。我怎样才能做到这一点?

表格

<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::patch('/dashboard/user/{id}/language', 'PreferencesController@changeLanguage')->name('change_language');

控制器方法

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

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

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

【问题讨论】:

    标签: php jquery ajax laravel laravel-6


    【解决方案1】:

    您必须有某种中间件,因为会话(语言)不是持久的。您可以尝试这样的事情(语言中间件):

    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);
        }
    

    如您所见,我将每个用户的语言存储在 db 中。在控制器中你可以有这样的东西:

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

    尝试考虑这样的事情

    【讨论】:

    • 嘿@knubbe,感谢您的回复,我实现了您的代码,但即使我在用户表中的语言字段不为空并且设置为nl,它也会自动转到备用语言。 ajax 请求也返回 405 Method Not Allowed。为什么? iit 更改了数据库中的值,但它在Session::put() 中断我相信
    • 嗯,奇怪。想不通
    【解决方案2】:

    您没有描述任何错误,但可能您不熟悉语言环境在 Laravel 中的工作方式。区域设置是根据请求设置的。因此,如果您在访问站点时在此控制器方法中设置语言环境(假设它工作正常),那么语言环境将再次与配置文件中设置的相同。

    要在boot 方法中解决这个 AppServiceProvider,您可以添加如下代码:

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

    这样,当用户登录并且每次访问站点(假设他已登录)时将区域设置保存在其个人资料中时,他将看到有效区域设置的站点。当然,当用户未登录时,它并不能解决问题。对于这种情况,您可能希望为用户创建额外的 cookie,以便在用户未登录的情况下从 cookie 设置区域设置。

    【讨论】:

      【解决方案3】:

      您需要中间件来保持本地化

      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);
          }
      }
      

      而且这个中间件应该适用于每条路线:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多