在之前的文章中提到了如果通过session切换语言
这个办法有个缺陷:不同语言共用同样的链接,这样对SEO很不友好,因此需要给不同的语言设置不同的链接,这样的话,对于同一个页面,中文版和英文版分别有自己的链接,搜索引擎喜欢这样的链接
具体方法如下:
1、新建一个middleware,如 App\Http\Middleware\Language
public function handle(Request $request, Closure $next) { if (session()->has('locale')) { App::setLocale(session()->get('locale')); } return $next($request); }
2、将此middleware注册到App\Http\kernel.php
protected $routeMiddleware = [ ......, 'language' => \App\Http\Middleware\Language::class, ......, ]
3、创建一个切换语言的Controller,如 HomeController.php
public function changeLanguage(Request $request) { $url = url()->previous(); $route = app('router') ->getRoutes($url) ->match(app('request')->create($url)) ->getName(); if(in_array($request->lang,['zh-CN','en'])){ App::setLocale($request->lang); session()->put('locale', $request->lang); return redirect()->route($route, ['locale' => $request->lang]); }else{ return back(); } }
不过上面这个写法,有个小问题,每个路由都需要给个名字才行,否则会找不到路由
4、route里面这样写
Route::get('language/change', [HomeController::class, 'changeLanguage'])->name('changeLang'); ///切换语言 //其他所有路由都写在这个分组下面 Route::group(['prefix' => '{locale}', 'where' => ['locale' => 'en|zh-CN|'], 'middleware' => 'language'],function(){ route::get('/','HomeController@homepage')->name('homepage'); });
5、在resource/lang目录下,分别新建不同的语言文件包
比如zh-CN/lang.php,en/lang.php,内容如下
<?php /// zh-CN/lang.php return [ 'test'=>'这是个测试' ];
<?php /// en/lang.php return [ 'test'=>'This is a test' ];
6、前端blade模板直接调用
{{trans('lang.test')}}
最后还有两个问题,一个是首页跳转,如果用户直接输入域名进入首页,没有附带上zh-CN,或者en之类,那么需要做个语言检测,并自动跳转到对应的语言版本
Controller里面这样写,还是假定写在HomeController文件里面
public function checklanguage(Request $request){ if(session()->has('locale')){ $lang=session('locale'); }else{ $lang = str_replace('_','-',$request->getPreferredLanguage()); if(!in_array($lang,['en|zh-CN'])){ $lang='zh-CN'; } } return redirect()->route('homepage', ['locale' => $lang]); } ///先检测sesson,看用户之前是否有设置过语言,如果设置过,则直接进入设定语言版本,如果没有设置过,则进入浏览器语言版本,如果网站没有针对浏览器默认语言做对应版本,则默认进入中文版
route里面这样写(注意,此route不要写在上面的分组里面,需要写在与changelanguage并列的位置)
route::get('/','HomeController@checklanguage');
第二个问题是,网页源码里面 <html lang=””>这里填写的值与实际语言是否匹配的问题
对于正常的用户来说,在浏览器里面通过设置session切换语言后,language.php这个middleware里面,能够正常的设置locale,进而选择语言,让后html标签也可以通过locale来设置对应的语言。
但是对于爬虫来说,它是不会去设置session的,它只会去爬链接,那此时这个html标签里面的语言,它是不知道的,或者说是空的,那么还需要在lanquage.php这个middleware文件里面,在进行一个设置,即:通过链接判断用户访问的是什么版本的语言,源码如下
public function handle(Request $request, Closure $next) { $path=explode('/',$request->path()); if(in_array($path[0],['en','zh-CN','it'])){ App::setLocale($path[0]); } ///上面的代码是通过访问链接来确定语言版本 elseif (session()->has('locale')) { App::setLocale(session()->get('locale')); } return $next($request); }