feat: 增强玩家端 API 鉴权中间件,支持多语言错误消息返回
This commit is contained in:
77
app/Http/Middleware/NegotiateLotteryLocale.php
Normal file
77
app/Http/Middleware/NegotiateLotteryLocale.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* 【API 语言协商中间件】
|
||||
*
|
||||
* - 挂载位置:bootstrap/app.php 中对 api 分组 prepend,所有 /api/* 请求都会先执行本中间件。
|
||||
* - 职责:解析客户端语言 → 写入 $request->attributes['lottery_locale'] → 调用 app()->setLocale(),
|
||||
* 便于 trans()、LotteryMessage 及后续按 zh/en/ne 选库表文案列时使用。
|
||||
*
|
||||
* 【协商顺序】① 请求头 X-Locale(必须为 config 支持的 zh/en/ne 之一);② Accept-Language 首选项;③ fallback。
|
||||
*
|
||||
* 【与前端】浏览器或 App 可直接带 X-Locale,或仅靠 Accept-Language;无需前端维护文案 JSON。
|
||||
*/
|
||||
class NegotiateLotteryLocale
|
||||
{
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
$locale = $this->resolveLocale($request);
|
||||
// attribute 名称固定为 lottery_locale,与 Request::lotteryLocale() 宏一致
|
||||
$request->attributes->set('lottery_locale', $locale);
|
||||
app()->setLocale($locale);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
/** 综合 X-Locale 与 Accept-Language,得到最终语言代码 */
|
||||
private function resolveLocale(Request $request): string
|
||||
{
|
||||
/** @var list<string> $supported */
|
||||
$supported = array_values(array_unique(config('lottery.locales.supported', ['en', 'zh', 'ne'])));
|
||||
$fallback = (string) config('lottery.locales.fallback', 'en');
|
||||
|
||||
$header = strtolower(trim((string) $request->header('X-Locale', '')));
|
||||
if ($header !== '' && in_array($header, $supported, true)) {
|
||||
return $header;
|
||||
}
|
||||
|
||||
return $this->fromAcceptLanguage((string) $request->header('Accept-Language', ''), $supported, $fallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析标准 Accept-Language(可带权重 q=),只认主语言段 zh / en / ne。
|
||||
*
|
||||
* @param list<string> $supported config('lottery.locales.supported')
|
||||
*/
|
||||
private function fromAcceptLanguage(string $header, array $supported, string $fallback): string
|
||||
{
|
||||
if ($header === '') {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
foreach (explode(',', $header) as $part) {
|
||||
$code = strtolower(trim(explode(';', trim($part), 2)[0] ?? ''));
|
||||
if ($code === '') {
|
||||
continue;
|
||||
}
|
||||
$primary = explode('-', $code, 2)[0] ?? $code;
|
||||
if ($primary === 'zh' && in_array('zh', $supported, true)) {
|
||||
return 'zh';
|
||||
}
|
||||
if ($primary === 'ne' && in_array('ne', $supported, true)) {
|
||||
return 'ne';
|
||||
}
|
||||
if ($primary === 'en' && in_array('en', $supported, true)) {
|
||||
return 'en';
|
||||
}
|
||||
}
|
||||
|
||||
return $fallback;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user