DevsDawn
DevsDawn

ThinkPHP 6.0 实现二级目录多语言功能

建议使用下方文章中的扩展包,它对本文中实现的多语言功能中间件进行了封装,同时计划加入更多相关功能。

前言

ThinkPHP内置了多语言功能,但是它是通过判断URL参数、Cookies、HTTP_ACCEPT_LANGUAGE请求参数来返回语言包的,由于多种语言的URL固定的,在搜索引擎抓取页面时,页面返回哪种语言取决于爬虫所带的请求头,这种方法对SEO有一定的影响,难以全面收录各种语言的版本。例如Google webmaster support的“管理多区域和多语言网站”一文中提及到:

Google 建议对每种语言版本的网页使用不同的网址,而不是使用 Cookie 或浏览器设置来调整网页上的内容语言。

如果您希望根据语言设置来动态更改内容或重新路由用户,则请注意,Google 可能无法找到并抓取您的所有变体。这是因为,Googlebot 抓取工具通常来自美国。另外,该抓取工具在发送 HTTP 请求时并不会在请求标头中设置 Accept-Language。

实现

示例项目可在文章底部下载。
1. 进入tp6项目目录,首先在config\lang.php设置默认语言允许的语言列表。我设置了允许简体中文、繁体中文以及英文。

2. 设置config\route.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. 编辑controller\Index.php,设置Index方法,返回上述语言包的lang字段,以便测试时识别当前选择的语言。
  2. 编辑route\app.php路由配置,替换为以下内容。后续添加路由可参照下方Route::get的方法。
    这里没有用路由分组功能,以避免访问根目录(如http://localhost/zh-cn/)时提示路由不正确,但是不加上末尾的斜杠又可匹配的问题(http://localhost/zh-cn)。
use think\facade\Route;
use think\facade\Config;
Route::get('/', 'index/index');
$langs = Config::get('lang.allow_lang_list');
foreach($langs as $lang){
    Route::get($lang . '/', 'index/index');
}
  1. 新建app\middleware目录,增加LoadLangPack.php中间件。
<?php
declare (strict_types = 1);

namespace app\middleware;

use Closure;
use think\App;
use think\Lang;
use think\Request;

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. app\middleware.php文件中添加注册中间件。
    return [
        \app\middleware\LoadLangPack::class
    ];
  1. 尝试访问。访问根目录时,应也会根据参数自动跳转到对应语言。


  2. 另外,还需要对如url()助手函数等涉及到URL生成的函数进行重写。以url()助手函数为例,打开app\common.php,写入以下代码:
use think\facade\Lang;
use think\facade\Route;
use think\route\Url 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函数时,会自动加上语言路径。使用时需要把除语言外的路径写完整。

下载

若无特别说明,本文采用 CC BY-SA 4.0 协议进行许可。如需转载,请附上本文链接和本声明。
本文链接:https://devsdawn.com/2019/08/implementing-secondary-directory-multilingual-function-in-thinkphp-6-0/
DigitalOcean云服务,美国上市公司,注册即送200USD体验金
Vultr云服务,全球25+地域,注册即送100USD体验金

发表回复

textsms
account_circle
email

DevsDawn

ThinkPHP 6.0 实现二级目录多语言功能
建议使用下方文章中的扩展包,它对本文中实现的多语言功能中间件进行了封装,同时计划加入更多相关功能。 前言 ThinkPHP内置了多语言功能,但是它是通过判断URL参数、Cookies、HTTP_…
扫描二维码继续阅读
2019-08-13