ThinkPHP 使用请求 Header 侦测语言

ThinkPHP 使用请求 Header 侦测语言

TP v6.0.3 版本已经支持了通过 header 来自定义用户语种,本文将介绍使用方式。

侦测语言顺序:

  1. 判断请求 GET 是否存在语言变量
  2. 判断请求 cookie 是否存在语言变量
  3. 判断请求 header 是否存在语言变量
  4. 判断请求 header 中的 Accept-Language 是否在配置中设置转换
  5. 采用配置的默认语言

处理流程:

  1. GET 存在语言变量应该与前端沟通避免请求中存在该变量,前端要是不听话我们可以把该配置修改成个随机生成的字符串(内置的侦测代码并没有判断名称是否为空,所以才提出更换随机生成的)。
  2. cookie 的处理也是和 GET 差不多的; use_cookie 设置为 false ,避免新客户端被保存了 cookie 。

好了,上面两个流程都不符合就到了读取 header 了。默认读取的是 header 中的 think-lang ,这个你的配置文件夹是没有的。如果你需要换成其他的可以在你语言配置文件中进行定义。

config/lang.php

1
'header_var' => 'hongfs-lang',

关于 header 名称你还需要了解的是,获取方法会自动将你的名称转换为小写,且 _ 将被替换成 -

vendor\topthink\framework\src\think\Request.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 设置或者获取当前的Header
* @access public
* @param string $name header名称
* @param string $default 默认值
* @return string|array
*/
public function header(string $name = '', string $default = null)
{
if ('' === $name) {
return $this->header;
}

$name = str_replace('_', '-', strtolower($name));

return $this->header[$name] ?? $default;
}

和其他侦测方式一样,通过 header 拿到的值需要在语言配置中 allow_lang_list 存在,不存在则采用默认语言。

现在我们来测试下能不能获取到设置的语言,可以通过 app('lang')->getLangSet() 拿到侦测后的语言值。

config/lang.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php

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

未设置语言

设置语言已存在

设置语言不存在

现在 header 侦测已经可以使用了,不过这种侦测基本都是用于 API 接口,所以又引发了跨域问题。

先创建一个中间件

1
$ php think make:middleware Cros

配置跨域处理

app\middleware\Cors.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
declare (strict_types = 1);

namespace app\middleware;

class Cors
{
/**
* 处理请求
*
* @param \think\Request $request
* @param \Closure $next
* @return Response
*/
public function handle($request, \Closure $next)
{
return $next($request)->header([
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Max-Age' => 1800,
'Access-Control-Allow-Methods' => 'GET, POST, PATCH, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers' => 'Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With, ' . config('lang.header_var', 'think-lang'),
]);
}
}

引入该中间件

app\middleware.php

1
2
3
4
5
<?php
return [
...
\app\middleware\Cors::class,
];

完成。

往上