加入切換語系的機制,加入紀錄網站狀態的全域物件及相關設定機制
This commit is contained in:
parent
deecddd2ec
commit
675fb36dc8
@ -35,11 +35,14 @@ class Kernel extends HttpKernel
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
\App\Http\Middleware\SetAppLanguage::class,
|
||||
\App\Http\Middleware\SetSiteStates::class,
|
||||
],
|
||||
|
||||
'api' => [
|
||||
'throttle:60,1',
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
\App\Http\Middleware\SetSiteStates::class,
|
||||
],
|
||||
];
|
||||
|
||||
@ -79,5 +82,6 @@ class Kernel extends HttpKernel
|
||||
\Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
\Illuminate\Auth\Middleware\Authorize::class,
|
||||
\App\Http\Middleware\SetAppLanguage::class,
|
||||
];
|
||||
}
|
||||
|
||||
106
app/Http/Middleware/SetAppLanguage.php
Normal file
106
app/Http/Middleware/SetAppLanguage.php
Normal file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
|
||||
/**
|
||||
* 設定網站語系
|
||||
*
|
||||
* Class SetAppLanguage
|
||||
* @package App\Http\Middleware
|
||||
*/
|
||||
class SetAppLanguage
|
||||
{
|
||||
/**
|
||||
* Cookie及Session存放Locale資訊的Key
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $cookieAndSessionKey = 'appLocale';
|
||||
|
||||
/**
|
||||
* 設定Locale時的參數Key
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $localeRequestKey = 'locale';
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
//取得所有語言清單
|
||||
$availableLocales = (array)config('languages');
|
||||
//要被回傳的Cookie
|
||||
$setLocaleCookie = false;
|
||||
//要被設定的語言
|
||||
$setLocale = false;
|
||||
//如果有Locale參數
|
||||
if($request->get($this->localeRequestKey) !== null) {
|
||||
//取得傳入的Locale值
|
||||
$requestLocale = $request->get($this->localeRequestKey);
|
||||
//如果有在語言清單內
|
||||
if(array_key_exists($requestLocale, $availableLocales)) {
|
||||
//設定session
|
||||
$request->session()->put($this->cookieAndSessionKey, $requestLocale);
|
||||
//設定要被回傳的Cookie及目標Locale
|
||||
$setLocale = $setLocaleCookie = $requestLocale;
|
||||
}
|
||||
}
|
||||
//假如沒有目標Locale,再讀取Session、Cookie、瀏覽器的Locale
|
||||
if(!$setLocale) {
|
||||
$cookieLocale = $request->cookies->get($this->cookieAndSessionKey);
|
||||
$sessionLocale = $request->session()->get($this->cookieAndSessionKey);
|
||||
if(array_key_exists($sessionLocale, $availableLocales)) {
|
||||
//設定要被回傳的Cookie及目標Locale
|
||||
$setLocale = $sessionLocale;
|
||||
if(!$cookieLocale) {
|
||||
$setLocaleCookie = $sessionLocale;
|
||||
}
|
||||
} elseif(array_key_exists($cookieLocale, $availableLocales)) {
|
||||
//設定Session及目標Locale
|
||||
$request->session()->put($this->cookieAndSessionKey, $cookieLocale);
|
||||
$setLocale = $cookieLocale;
|
||||
} else {
|
||||
//Session及Cookie都沒有Locale值時,讀取HTTP Header的資訊
|
||||
$browserLocales = $request->server('HTTP_ACCEPT_LANGUAGE');
|
||||
$browserLocales = preg_replace('/;q=0\.\d+/', '', $browserLocales);
|
||||
$browserLocales = explode(',', $browserLocales);
|
||||
$browserLocales = array_map(function($lang){
|
||||
return strtolower($lang);
|
||||
}, $browserLocales);
|
||||
|
||||
//與語言清單比對
|
||||
$validBrowserLocales = array_intersect($browserLocales, array_keys($availableLocales));
|
||||
|
||||
if(!empty($validBrowserLocales)) {
|
||||
//取得第一個瀏覽器Locale
|
||||
$validBrowserLocale = head($validBrowserLocales);
|
||||
//設定Session及目標Locale
|
||||
$request->session()->put($this->cookieAndSessionKey, $validBrowserLocale);
|
||||
$setLocale = $setLocaleCookie = $validBrowserLocale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($setLocale) {
|
||||
//如果有目標Locale
|
||||
app()->setLocale($setLocale);
|
||||
} else {
|
||||
//如果沒有目標Locale,則設定成預設語言
|
||||
app()->setLocale(config('app.fallback_locale'));
|
||||
}
|
||||
|
||||
//如果有Cookie,則帶入request
|
||||
if($setLocaleCookie) {
|
||||
return $next($request)->withCookie(cookie()->forever($this->cookieAndSessionKey, $setLocaleCookie));
|
||||
} else {
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
}
|
||||
52
app/Http/Middleware/SetSiteStates.php
Normal file
52
app/Http/Middleware/SetSiteStates.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Services\SiteStateService;
|
||||
use Closure;
|
||||
|
||||
/**
|
||||
* 設定SiteStateService中的資料
|
||||
*
|
||||
* Class SetSiteStates
|
||||
* @package App\Http\Middleware
|
||||
*/
|
||||
class SetSiteStates
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$siteState = app(SiteStateService::class);
|
||||
//是否網站後台,判斷route prefix
|
||||
if($request->is(config('admin.route') . '/*')) {
|
||||
$siteState->isAdminArea = true;
|
||||
}
|
||||
|
||||
//所有可用語系及其原文名稱
|
||||
$siteState->languagesWithLabel = config('languages');
|
||||
|
||||
//所有可用語系
|
||||
$siteState->languages = array_keys($siteState->languagesWithLabel);
|
||||
|
||||
//所有其他可用語系,排除現在語系
|
||||
$siteState->otherLanguages = collect($siteState->languages)->filter(function($locale){
|
||||
return $locale !== app()->getLocale();
|
||||
})->all();
|
||||
|
||||
//所有語系的當前語言翻譯
|
||||
foreach ($siteState->languages as $locale) {
|
||||
$siteState->languageTranslations[$locale] = trans('languages.' . $locale);
|
||||
}
|
||||
|
||||
//預設語系
|
||||
$siteState->defaultLanguage = config('app.fallback_locale');
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
21
app/Presenters/UrlPresenter.php
Normal file
21
app/Presenters/UrlPresenter.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Presenters;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class UrlPresenter
|
||||
{
|
||||
private $request;
|
||||
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function appendLocale($locale)
|
||||
{
|
||||
$url = $this->request->fullUrlWithQuery(['locale' => $locale]);
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
39
app/Providers/SingletonServiceProvider.php
Normal file
39
app/Providers/SingletonServiceProvider.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Option;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
/**
|
||||
* 初始化所有singleton class 的 instance
|
||||
*
|
||||
* Class SingletonServiceProvider
|
||||
* @package App\Providers
|
||||
*/
|
||||
class SingletonServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
// Services
|
||||
$this->app->alias(\App\Services\SiteStateService::class, 'SiteState');
|
||||
$this->app->singleton(\App\Services\SiteStateService::class, function($app){
|
||||
return new \App\Services\SiteStateService;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
64
app/Services/SiteStateService.php
Normal file
64
app/Services/SiteStateService.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
/**
|
||||
* 紀錄全域的網站狀態
|
||||
*
|
||||
* Class SiteStateService
|
||||
* @package App\Services
|
||||
*/
|
||||
class SiteStateService
|
||||
{
|
||||
/**
|
||||
* 是否為後台
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $isAdminArea = false;
|
||||
|
||||
/**
|
||||
* 所有可用語系
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $languages = [];
|
||||
|
||||
/**
|
||||
* 所有其他可用語系,排除現在語系
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $otherLanguages = [];
|
||||
|
||||
/**
|
||||
* 所有可用語系及其原文名稱
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $languagesWithLabel = [];
|
||||
|
||||
/**
|
||||
* 所有語系的當前語言翻譯
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $languageTranslations = [];
|
||||
|
||||
/**
|
||||
* 預設語系
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $defaultLanguage = '';
|
||||
|
||||
/**
|
||||
* 取得所有變數
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
return get_object_vars($this);
|
||||
}
|
||||
}
|
||||
@ -175,7 +175,7 @@ return [
|
||||
// App\Providers\BroadcastServiceProvider::class,
|
||||
App\Providers\EventServiceProvider::class,
|
||||
App\Providers\RouteServiceProvider::class,
|
||||
|
||||
App\Providers\SingletonServiceProvider::class,
|
||||
],
|
||||
|
||||
/*
|
||||
|
||||
8
config/languages.php
Normal file
8
config/languages.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
return [
|
||||
'en' => 'English',
|
||||
'zh-tw' => '繁體中文',
|
||||
'zh-cn' => '简体中文',
|
||||
'ja' => '日本語',
|
||||
'ko' => '한국어'
|
||||
];
|
||||
1
resources/js/admin/app.js
vendored
1
resources/js/admin/app.js
vendored
@ -1 +1,2 @@
|
||||
import './lib';
|
||||
import '../app-common'
|
||||
|
||||
4
resources/js/app-common.js
vendored
Normal file
4
resources/js/app-common.js
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
$('.logout-btn').on('click', e => {
|
||||
e.preventDefault()
|
||||
$('#logout-form').submit()
|
||||
})
|
||||
3
resources/js/app.js
vendored
3
resources/js/app.js
vendored
@ -1 +1,2 @@
|
||||
require('./bootstrap');
|
||||
import './lib'
|
||||
import './app-common'
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav ml-auto">
|
||||
@component('components.languageDropdown')@endcomponent
|
||||
</ul>
|
||||
|
||||
<button class="navbar-toggler aside-menu-toggler d-md-down-none" type="button" data-toggle="aside-menu-lg-show">
|
||||
|
||||
9
resources/views/components/languageDropdown.blade.php
Normal file
9
resources/views/components/languageDropdown.blade.php
Normal file
@ -0,0 +1,9 @@
|
||||
@inject('url', App\Presenters\UrlPresenter)
|
||||
<li class="nav-item dropdown">
|
||||
<a href="#" class="nav-link btn-icon dropdown-toggle switch-language" data-toggle="dropdown" role="button" aria-expanded="false" aria-haspopup="true">{{ app('SiteState')->languagesWithLabel[app()->getLocale()] }}</a>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
@foreach (app('SiteState')->otherLanguages as $locale)
|
||||
<a href="{{ $url->appendLocale($locale) }}" class="dropdown-item">{{ app('SiteState')->languagesWithLabel[$locale] }}</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</li>
|
||||
@ -26,24 +26,14 @@
|
||||
</li>
|
||||
@endif
|
||||
@else
|
||||
<li class="nav-item dropdown">
|
||||
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
|
||||
{{ Auth::user()->name }} <span class="caret"></span>
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
|
||||
<a class="dropdown-item" href="{{ route('logout') }}"
|
||||
onclick="event.preventDefault();
|
||||
document.getElementById('logout-form').submit();">
|
||||
{{ __('Logout') }}
|
||||
</a>
|
||||
|
||||
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
|
||||
@csrf
|
||||
</form>
|
||||
</div>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link logout-btn" href="#">{{ __('Logout') }}</a>
|
||||
<form id="logout-form" action="{{ route('logout') }}" method="post" style="display: none;">
|
||||
@csrf
|
||||
</form>
|
||||
</li>
|
||||
@endguest
|
||||
@include('components.languageDropdown')
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user