Laravel 在区域设置更改时重定向到路由

Posted

技术标签:

【中文标题】Laravel 在区域设置更改时重定向到路由【英文标题】:Laravel redirect to route on locale change 【发布时间】:2018-12-29 15:48:40 【问题描述】:

我正在尝试在 Laravel 5.6.28 中基于语言环境实现简单的多语言路由,但在语言更改后一直坚持重定向。

每当用户从页面上的表单选择中更改时,我想根据更改的区域设置立即将用户重定向到正确的路线。

我还做了两个中间件类: 1. SetLocale - 如果未使用 HTTP_ACCEPT_LANGUAGE 设置或考虑 reqeust 的第一段(准确的区域设置),则用于设置区域设置。 2. LocaleRedirect - 用于比较用户和请求区域设置,如果它们不匹配则重定向。

例如,如果路由是 '/en/blog/***' 更改语言环境后,它应该是 '/gr/blog/***' 但不会发生重定向。我做错了什么? 非常感谢。

区域设置

'locales' => [
        'en' => 'English',
        'es' => 'Spanish',
        'gr' => 'Greek'
    ]

页面

!! Form::open(['route' => 'language.change']) !!
    Language:
    !! Form::select('lang', config('translatable.locales'), app()->getLocale(), ['id' => 'language-select']); !!
!! Form::close() !!

<script>
    $(function () 
        $('#language-select').on('change', function () 
            $(this).closest('form').submit();
        );
    );
</script>

路线

Route::post('language/change', 'LanguageController@postChangeLanguage')->name('language.change');

Route::group([
    'prefix' => 'locale',
    'middleware' => ['setlocale', 'locale-redirect'],
    'where' => ['locale' => implode('|', array_keys(config('translatable.locales')))]
], function () 
    Route::get('page', function ($locale) 
        return view(Helper::getLocaleView($locale, 'page'));
    );

    Route::get('home', function ($locale) 
        return view(Helper::getLocaleView($locale, 'home'));
    );
);

Route::get('/', function () 
    return redirect()->to('en/home');
);

语言控制器

class LanguageController extends Controller

    public function postChangeLanguage(Request $request)
    
        $changeLang = $request->input('lang');
        $userLang = app()->getLocale();

        if ($userLang !== $changeLang && array_key_exists($changeLang, config('translatable.locales')))
        
            session(['locale' => $changeLang]);
            app()->setLocale($changeLang);
        

        return redirect()->back();
    

SetLocale 中间件:

class SetLocale

    public function handle($request, Closure $next)
    
        if ($request->method() === 'GET')
        
            $requestLocale = $request->segment(1);

            if (array_key_exists($requestLocale, config('translatable.locales')))
            
                session(['locale' => $requestLocale]);
            
            else if (!session()->has('locale'))
            
                $browserLanguage = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);

                if (array_key_exists($browserLanguage, config('translatable.locales')))
                
                    session(['locale' => $browserLanguage]);
                
                else
                
                    session(['locale' => config('translatable.fallback_locale')]);
                
            

            app()->setLocale(session('locale'));
        

        return $next($request);
    

LocaleRedirect 中间件:

class LocaleRedirect

    public function handle($request, Closure $next)
    
        $requestLocale = $request->segment(1);
        $userLocale = session('locale');

        if ($requestLocale !== $userLocale)
        
            $segments = $request->segments();
            array_shift($segments);
            array_unshift($segments, $userLocale);

            return redirect()->to(implode('/', $segments));
        

        return $next($request);
    

【问题讨论】:

您是否将setlocalelocale-redirect 映射到App\Http\Kernel$routeMiddleware 下的正确类? @Azeame 是的,映射正确。 【参考方案1】:

我想出了解决方法,不再需要 LocaleRedirect 中间件。

class LanguageController extends Controller

    public function postChangeLanguage(Request $request)
    
        $changeLang = $request->input('lang');
        $userLang = session('locale');

        if ($userLang !== $changeLang && array_key_exists($changeLang, config('translatable.locales')))
        
            session(['locale' => $changeLang]);
            app()->setLocale($changeLang);

            $segments = str_replace(url('/'), '', url()->previous());
            $segments = array_filter(explode('/', $segments));
            array_shift($segments);
            array_unshift($segments, $changeLang);

            return redirect()->to(implode('/', $segments));
        

        return redirect()->back();
    

【讨论】:

【参考方案2】:

我通过编辑@khasky 的答案解决了这个问题

   public function changeLanguage(Request $request)
    
        $changeLang = $request->lang;
        $userLang = session('locale');

        session(['locale' => $changeLang]);
        app()->setLocale($changeLang);

        $segments = str_replace(url('/'), '', url()->previous());
        $segments = array_filter(explode('/', $segments));
        array_shift($segments);
        array_unshift($segments, $changeLang);

        return redirect()->to(implode('/', $segments));

    

【讨论】:

以上是关于Laravel 在区域设置更改时重定向到路由的主要内容,如果未能解决你的问题,请参考以下文章

Laravel Spark - 登录时重定向

使用Laravel 5.7中的Auth激活用户会话时重定向到页面的方法

在角度 UI 路由器中单击时重定向到相应的单个产品页面

Vue路由器在重新加载时重定向到主页

RouterBrowser 不会在刷新时重定向到默认页面

scala路由设置(重定向)