laravel 有本地化功能,setLocale,但不是持久化的,需要借助session
采用策略,域名加语言后缀,laravel是可以使用路由后缀的,如www.exame.com/en
所以先配置路由,很简单,只需要在现有路由的基础上加一个前缀就可以了
Route::prefix('en')
要实时识别路由前缀并获取到当前语言,我借助了中间件middleware,新建中间件,如LangLocale
public function handle($request, Closure $next)
{
$langs = ['zh-CN', 'en'];
$local = 'zh-CN';
// 获取路由前缀
$routePrefix = $request->route()->getPrefix();
if (!empty($routePrefix)) {
// 是否有多个前缀
$localeIndex = strrpos($routePrefix, "/");
if ($localeIndex === false) {
$local = $routePrefix == 'admin' ? 'zh-CN' : $routePrefix;
} else {
$local = substr($routePrefix, 0, $localeIndex);
}
}
if (in_array($local, $langs)) {
$request->session()->put('current_locale', $local);
if ($local == 'zh-CN') {
$request->session()->put('prefix');
} else {
$request->session()->put('prefix', '/'. $local);
}
app()->setLocale($local);
}
return $next($request);
}
为什么判断多个前缀,因为可能有用户中心,至少也有个后台,也是需要中英文切换的
注册中间件, 在kernel.php中注册路由中间件
'lang_local' => \App\Http\Middleware\LangLocale::class,
使用中间件
protected function mapEnRoutes()
{
Route::prefix('en')
->middleware('web', 'lang_local')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
}
url生成部分我们也需要处理
先建立2个全局函数,或者在主类建立,使用继承,一般都这样吧
public function getUrlPrefix()
{
$locale = session('current_locale');
$url_prefix = 'backend';
if(!empty($locale) && $locale != 'zh-CN')
{
$url_prefix = 'backend/' . $locale;
}
return $url_prefix;
}
public function showUrlPrefix()
{
$url_prefix = $this->getUrlPrefix();
view()->share('url_prefix', $url_prefix);
}
在构造函数中添加,这里注意,laravel中构造函数是先与session的,官网给出了相应解决方式
public function __construct()
{
$this->middleware(function ($request, $next) {
$this->showUrlPrefix();
return $next($request);
});
}
这样在前端view中使用url就可以这样
{{ url($url_prefix . '/index') }}
在controller中使用时可以这样
return redirect($this->getUrlPrefix() . '/index');
这样本地化部分基本完成了
但我们做中英文,不止本地化,数据库也的跟着
先把所有需要多语言的数据表复制一份
现在我们要做英文,则为复制出来的数据表加上en_前缀
然后在模型中建立构造函数,在构造函数中识别当前语言
如在Article.php中
protected $table = 'articles';
public function __construct(array $attributes = [])
{
parent::__construct($attributes);
$locale = session('current_locale');
if(!empty($locale) && $locale != 'zh-CN')
{
$this->table = $locale."_articles";
}
}
这里在提一次,session能不能识别的关键,是在controller中的构造函数中是否有做middleware处理