ThinkPHP8 中间件:多应用模式实现多语言功能

ThinkPHP8 中的多语言支持。\think\middleware\LoadLangPack.php 好像并不能很好的支持多语言的切换,其中$this->lang->setLangSet($langSet) 和$this->lang->switchLangSet($langset)两个语句并不能实现通过传参的方式切换语言。所以自己搞了一个车轮子。

1.创建应用及目录

php think build index

将在app目录下面创建index应用目录,生产相应的默认文件。

index:.
│  common.php
│  event.php
│  middleware.php  #中间件设置
│
├─config
│      lang.php    #语言设置
│
├─controller
│      Index.php   #语言测试
│
├─lang
│      en-us.php    #EN
│      zh-cn.php    #中文
│
├─middleware
│      IndexAppLangMiddleware.php  #探测lang的中间件
│
├─model
└─view
    └─index
            index.html   #前端显示View

app\index\middleware\IndexAppLangMiddleware.php 语言切换控制中间件

<?php
declare (strict_types = 1);

namespace app\index\middleware;

#use Closure;
use think\facade\App;     
use think\facade\Config;  #配置读取
use think\facade\Lang;    #语言支持与操作
use think\facade\Cookie;  #Cookie操作

/**
 * 多语言加载
 */
class IndexAppLangMiddleware
{
	protected $config;   #存放配置
	protected $lang;     #存放最近一次设置的语言
	
	public function __construct(protected App $app) {
		$this->config = config("lang");  #读取语言配置
		$this->lang =  ''; #$this->config['default_lang'];   #初始化默认语言
	}
		
    /**
     * 处理请求
     *
     * @param \think\Request $request
     * @param \Closure       $next
     * @return Response
     */
    public function handle($request, \Closure $next)
    {
        // 自动侦测当前语言
        $langset = $this->detect($request);
		
        if ($this->lang != $langset) {
            $this->lang = $langset; #暂存语言
			Lang::setLangSet($this->lang); #切换当前语言		
        }

        $this->saveToCookie($langset); #修改Cookie
			
        return $next($request);
    }
	
    /**
     * 自动侦测设置获取语言选择
     * @access protected
     * @param Request $request
     * @return string
     */
    protected function detect($request): string
    {
        // 自动侦测设置获取语言选择
        $langSet = '';

        if ($request->get($this->config['detect_var'])) {
            // url中设置了语言变量
            $langSet = $request->get($this->config['detect_var']);	
        } elseif ($request->header($this->config['header_var'])) {
            // Header中设置了语言变量
            $langSet = $request->header($this->config['header_var']);
        } elseif ($request->cookie($this->config['cookie_var'])) {
            // Cookie中设置了语言变量
            $langSet = $request->cookie($this->config['cookie_var']);
        } elseif ($request->server('HTTP_ACCEPT_LANGUAGE')) {
            // 自动侦测浏览器语言
            $langSet = $request->server('HTTP_ACCEPT_LANGUAGE');
        }

        if (preg_match('/^([a-z\d\-]+)/i', $langSet, $matches)) {
            $langSet = strtolower($matches[1]);
            if (isset($this->config['accept_language'][$langSet])) {
                $langSet = $this->config['accept_language'][$langSet];
            }
        } else {
            $langSet = $this->config['default_lang']; #未检查到语言切换参数,使用默认语言
        }

        if (empty($this->config['allow_lang_list']) || in_array($langSet, $this->config['allow_lang_list'])) {
            // 合法的语言
			//Lang::setLangSet($langSet);			
        } else {
            $langSet = $this->config['default_lang'];
        }

        return $langSet;
    }
	
    /**
     * 保存当前语言到Cookie
     * @access protected
     * @param Cookie $cookie Cookie对象
     * @param string $langSet 语言
     * @return void
     */
    protected function saveToCookie(string $langSet): void
    {	
        if ($this->config['use_cookie']) {
			Cookie::forever($this->config['cookie_var'], $langSet);		
        }
    }	
}

app\index\config\lang.php 语言配置

<?php
// +----------------------------------------------------------------------
// | index-APP多语言设置
// +----------------------------------------------------------------------

return [
    // 默认语言
    'default_lang'    => env('DEFAULT_LANG', 'zh-cn'),
    // 允许的语言列表
    'allow_lang_list' => ['zh-cn', 'en-us'],
    // 多语言自动侦测变量名
    'detect_var'      => 'lang',
    // 是否使用Cookie记录
    'use_cookie'      => true,
    // 多语言cookie变量
    'cookie_var'      => 'index_app_lang',
    // 多语言header变量
    'header_var'      => 'index-app-lang',
    // 扩展语言包
    'extend_list'     => [],
    // Accept-Language转义为对应语言包名称
    'accept_language' => [
        'zh-hans-cn' => 'zh-cn',
    ],
    // 是否支持语言分组
    'allow_group'     => true,
];

语言列表

app\index\lang\en-us.php

<?php

return [
    'welcome' => 'Welcome to our website222',
    // 其他英文语言项
];

?>

app\index\lang\zh-cn.php

<?php

return [
    'welcome' => '欢迎访问我们的网站',
    // 其他中文语言项
];

?>

app\index\controller\Index.php

<?php
declare (strict_types = 1);

namespace app\index\controller;

use think\facade\Lang;
use think\facade\View;
use app\index\middleware\IndexAppLangMiddleware;

class Index
{
	protected $middleware = [IndexAppLangMiddleware::class];
	
    public function index()
    {
		$welcome = Lang::get('welcome');
		View::assign('welcome', $welcome);
		
		// 渲染模板并显示
		return View::fetch('index');
    }
}

app\index\view\index\index.html

<!DOCTYPE html>
<html>
<head>
    <title>切换语言</title>
</head>
<body>
    <p><?php echo $welcome; ?>, ThinkPHP8</p>
	
    <a href="{:url('index', ['lang'=>'zh-cn'])}">中文</a>
    <a href="{:url('index', ['lang'=>'en-us'])}">English</a>
</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值