ThinkPHP 6.0 實現二級目錄多語言功能

  • 2019 年 10 月 6 日
  • 筆記

前言

ThinkPHP內置了多語言功能,但是它是通過判斷URL參數、Cookies、HTTP_ACCEPT_LANGUAGE請求參數來返回語言包的,由於多種語言的URL固定的,在搜索引擎抓取頁面時,頁面返回哪種語言取決於爬蟲所帶的請求頭,這種方法對SEO有一定的影響,難以全面收錄各種語言的版本。例如Google webmaster support的「管理多區域和多語言網站」一文中提及到:

Google 建議對每種語言版本的網頁使用不同的網址,而不是使用 Cookie 或瀏覽器設置來調整網頁上的內容語言。 如果您希望根據語言設置來動態更改內容或重新路由用戶,則請注意,Google 可能無法找到並抓取您的所有變體。這是因為,Googlebot 抓取工具通常來自美國。另外,該抓取工具在發送 HTTP 請求時並不會在請求標頭中設置 Accept-Language。

實現

示例項目可在文章底部下載。 1. 進入tp6項目目錄,首先在configlang.php設置默認語言允許的語言列表。我設置了允許簡體中文、繁體中文以及英文。

2. 設置configroute.php中的路由配置,打開強制路由url_route_must以及完全匹配route_complete_match以避免設置後可能導致的衝突問題。 3. 進入app目錄,新建lang目錄,編寫語言包。

//zh_cn.php  <?php  return [      'lang' => '簡體中文'  ];
//zh_tw.php  <?php  return [      'lang' => '繁體中文'  ];
//en_us.php  <?php  return [      'lang' => 'English'  ];
  1. 編輯controllerIndex.php,設置Index方法,返回上述語言包的lang字段,以便測試時識別當前選擇的語言。
  1. 編輯routeapp.php路由配置,替換為以下內容。後續添加路由可參照下方Route::get的方法。 這裡沒有用路由分組功能,以避免訪問根目錄(如http://localhost/zh-cn/)時提示路由不正確,但是不加上末尾的斜杠又可匹配的問題(http://localhost/zh-cn)。
use thinkfacadeRoute;  use thinkfacadeConfig;  Route::get('/', 'index/index');  $langs = Config::get('lang.allow_lang_list');  foreach($langs as $lang){      Route::get($lang . '/', 'index/index');  }
  1. 新建appmiddleware目錄,增加LoadLangPack.php中間件。
<?php  declare (strict_types = 1);    namespace appmiddleware;    use Closure;  use thinkApp;  use thinkLang;  use thinkRequest;    class LoadLangPack  {      public function handle($request, Closure $next, Lang $lang, App $app)      {          $path = explode('/', $request->pathinfo());          if(sizeof($path) > 0){                if(empty($path[0])){                  $langset = $lang->detect();                  return redirect('/' . $langset . '/');              }else{                  $langset = $path[0];              }                $lang->setLangSet($langset);                $lang->load([                  $app->getThinkPath() . 'lang' . DIRECTORY_SEPARATOR . $langset . '.php',              ]);                $app->LoadLangPack($langset);          }          return $next($request);      }  }
  1. appmiddleware.php文件中添加註冊中間件。
    return [          appmiddlewareLoadLangPack::class      ];
  1. 嘗試訪問。訪問根目錄時,應也會根據參數自動跳轉到對應語言。
  1. 另外,還需要對如url()助手函數等涉及到URL生成的函數進行重寫。以url()助手函數為例,打開appcommon.php,寫入以下代碼:
use thinkfacadeLang;  use thinkfacadeRoute;  use thinkrouteUrl as UrlBuild;    function url(string $url = '', array $vars = [], $suffix = true, $domain = false): UrlBuild  {      $lang = Lang::getLangSet();      return Route::buildUrl('/' . $lang . '/' . $url, $vars)->suffix($suffix)->domain($domain);  }

這樣在調用url函數時,會自動加上語言路徑。使用時需要把除語言外的路徑寫完整。