Laravel - 使用 Ajax 更改语言环境
Laravel - Change locale using Ajax
我正在尝试使用 ajax 更改我的系统语言,但我不知道如何更改区域设置并使其永久化,直到用户决定再次更改。当前,app.php
中的语言环境设置为 'en'
,我想使用 select 菜单将其更改为 '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);
}
您没有描述任何错误,但您可能不熟悉区域设置在 Laravel 中的工作方式。语言环境是根据请求设置的。因此,如果您在访问站点时在此控制器方法中设置语言环境(假设它工作正常),那么语言环境将再次与配置文件中的设置相同。
要在 boot
方法中解决此 AppServiceProvider,您可以添加如下代码:
if ($user = auth()->user()) {
App::setLocale($user->language);
}
这样,当用户登录并且区域设置保存在他的个人资料中时,每次他访问网站(假设他已登录)时,他将看到有效区域设置的网站。当然,当用户未登录时,它不能解决问题。对于这种情况,您可能希望为用户创建额外的 cookie,以便在用户未登录的情况下从 cookie 设置区域设置。
你必须有某种中间件,因为会话(语言)不是持久的。你可以尝试这样的事情(语言中间件):
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);
}
如您所见,我将每个用户的语言存储在数据库中。在控制器中你可以有这样的东西:
if (auth()->check()) {
auth()->user()->language = $language;
auth()->user()->save();
return back();
}
Session::put('applocale', $language);
return back();
}
尝试考虑这样的事情
您需要中间件来保持本地化
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,
]
];
我正在尝试使用 ajax 更改我的系统语言,但我不知道如何更改区域设置并使其永久化,直到用户决定再次更改。当前,app.php
中的语言环境设置为 'en'
,我想使用 select 菜单将其更改为 '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);
}
您没有描述任何错误,但您可能不熟悉区域设置在 Laravel 中的工作方式。语言环境是根据请求设置的。因此,如果您在访问站点时在此控制器方法中设置语言环境(假设它工作正常),那么语言环境将再次与配置文件中的设置相同。
要在 boot
方法中解决此 AppServiceProvider,您可以添加如下代码:
if ($user = auth()->user()) {
App::setLocale($user->language);
}
这样,当用户登录并且区域设置保存在他的个人资料中时,每次他访问网站(假设他已登录)时,他将看到有效区域设置的网站。当然,当用户未登录时,它不能解决问题。对于这种情况,您可能希望为用户创建额外的 cookie,以便在用户未登录的情况下从 cookie 设置区域设置。
你必须有某种中间件,因为会话(语言)不是持久的。你可以尝试这样的事情(语言中间件):
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);
}
如您所见,我将每个用户的语言存储在数据库中。在控制器中你可以有这样的东西:
if (auth()->check()) {
auth()->user()->language = $language;
auth()->user()->save();
return back();
}
Session::put('applocale', $language);
return back();
}
尝试考虑这样的事情
您需要中间件来保持本地化
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,
]
];