laravel 多语言切换

甄云
2023-12-01

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处理

 类似资料: