多语言
This commit is contained in:
parent
81ee0d339d
commit
ae018d803f
|
|
@ -10,6 +10,7 @@ use App\Event\LogEvent;
|
||||||
use App\Model\Account;
|
use App\Model\Account;
|
||||||
use App\Model\AccountLog;
|
use App\Model\AccountLog;
|
||||||
use App\Model\Online;
|
use App\Model\Online;
|
||||||
|
use App\Model\Translation as tModel;
|
||||||
use App\Utils\Param;
|
use App\Utils\Param;
|
||||||
use App\Utils\Str;
|
use App\Utils\Str;
|
||||||
use App\Utils\Token;
|
use App\Utils\Token;
|
||||||
|
|
@ -216,4 +217,14 @@ class Login extends Base
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[GetMapping(path: "translations")]
|
||||||
|
#[Auth(needLogin: false)]
|
||||||
|
public function translations()
|
||||||
|
{
|
||||||
|
// 获取多语言信息
|
||||||
|
$locale = $this->request->input("locale", "zh-cn");
|
||||||
|
$data = tModel::getLang($locale);
|
||||||
|
return $this->success('ok', $data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Middleware;
|
||||||
|
|
||||||
|
use Hyperf\Context\ApplicationContext;
|
||||||
|
use Hyperf\Contract\TranslatorInterface;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
|
class LanguageMiddleware implements MiddlewareInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||||
|
{
|
||||||
|
$lang = $request->getHeaderLine('Accept-Language') ?: 'zh_cn';
|
||||||
|
$lang = str_replace('-', '_', strtolower($lang));
|
||||||
|
$translator = ApplicationContext::getContainer()->get(TranslatorInterface::class);
|
||||||
|
$translator->setLocale($lang);
|
||||||
|
return $handler->handle($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,13 +7,13 @@ namespace App\Model;
|
||||||
use Hyperf\DbConnection\Db;
|
use Hyperf\DbConnection\Db;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property int $translation_id
|
* @property int $translation_id
|
||||||
* @property string $group
|
* @property string $group
|
||||||
* @property string $translation_key
|
* @property string $translation_key
|
||||||
* @property string $remark
|
* @property string $remark
|
||||||
* @property string $create_time
|
* @property string $create_time
|
||||||
* @property string $update_time
|
* @property string $update_time
|
||||||
* @property string $deleted_at
|
* @property string $deleted_at
|
||||||
*/
|
*/
|
||||||
class Translation extends Model
|
class Translation extends Model
|
||||||
{
|
{
|
||||||
|
|
@ -48,6 +48,34 @@ class Translation extends Model
|
||||||
->paginate((int)$param['limit']);
|
->paginate((int)$param['limit']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getLangValue(string $locale, string $key): string|null
|
||||||
|
{
|
||||||
|
list($group, $key) = explode('.', $key);
|
||||||
|
return (new self())->setTable("t")
|
||||||
|
->from("translation as t")
|
||||||
|
->join("translation_value as tv", "tv.translation_id", "=", "t.translation_id")
|
||||||
|
->where("t.group", $group)
|
||||||
|
->where("t.translation_key", $key)
|
||||||
|
->where("tv.lang_code", strtolower(str_replace("_", "-", $locale)))
|
||||||
|
->value("tv.lang_value");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getLang(string $locale)
|
||||||
|
{
|
||||||
|
$data = self::with(["values" => function ($query) use ($locale) {
|
||||||
|
var_dump(strtolower(str_replace("_", "-", $locale)));
|
||||||
|
$query->where('lang_code', strtolower(str_replace("_", "-", $locale)))->select(['lang_value','translation_id']);
|
||||||
|
}])->select(['group', 'translation_key', 'translation_id'])
|
||||||
|
->get()
|
||||||
|
->toArray();
|
||||||
|
// 组合数据
|
||||||
|
$json = [];
|
||||||
|
foreach ($data as $item) {
|
||||||
|
$json[$item['group']][$item['translation_key']] = count($item['values']) > 0 ? $item['values'][0]['lang_value'] : "";
|
||||||
|
}
|
||||||
|
return $json;
|
||||||
|
}
|
||||||
|
|
||||||
public function values()
|
public function values()
|
||||||
{
|
{
|
||||||
return $this->hasMany(TranslationValue::class, 'translation_id', 'translation_id');
|
return $this->hasMany(TranslationValue::class, 'translation_id', 'translation_id');
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
use Hyperf\Cache\Cache;
|
||||||
|
use Hyperf\Contract\TranslatorInterface;
|
||||||
|
use Hyperf\Contract\TranslatorLoaderInterface;
|
||||||
|
use Hyperf\Translation\Translator;
|
||||||
|
use App\Model\Translation as tModel;
|
||||||
|
use Psr\Container\ContainerInterface;
|
||||||
|
use function Hyperf\Config\config;
|
||||||
|
|
||||||
|
class TranslationService extends Translator implements TranslatorInterface
|
||||||
|
{
|
||||||
|
protected Cache $cache;
|
||||||
|
|
||||||
|
public function __construct(TranslatorLoaderInterface $loader, ContainerInterface $container)
|
||||||
|
{
|
||||||
|
parent::__construct($loader, 'zh_CN');
|
||||||
|
$this->cache = $container->get(Cache::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get($key, array $replace = [], $locale = null, $fallback = true): array|string
|
||||||
|
{
|
||||||
|
$locale = $locale ?: $this->getLocale();
|
||||||
|
|
||||||
|
$cacheKey = "lang:{$locale}:{$key}";
|
||||||
|
// 先查缓存
|
||||||
|
$cached = $this->cache->get($cacheKey);
|
||||||
|
if ($cached !== null) {
|
||||||
|
return $this->makeReplacements($cached, $replace);
|
||||||
|
}
|
||||||
|
// 查数据库
|
||||||
|
$value = tModel::getLangValue($locale, $key);
|
||||||
|
if ($value) {
|
||||||
|
$this->cache->set($cacheKey, $value, (int)config("translation.ttl"));
|
||||||
|
return $this->makeReplacements($value, $replace);
|
||||||
|
}
|
||||||
|
// 文件翻译
|
||||||
|
$fallbackValue = parent::get($key, $replace, $locale, $fallback);
|
||||||
|
// fallback 结果也缓存
|
||||||
|
$this->cache->set($cacheKey, $fallbackValue, (int)config("translation.ttl"));
|
||||||
|
return $fallbackValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -151,4 +151,13 @@ class Str
|
||||||
return "other";
|
return "other";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function splitKey(string $key): array
|
||||||
|
{
|
||||||
|
$parts = explode('.', $key);
|
||||||
|
$first = array_shift($parts);
|
||||||
|
$rest = implode('.', $parts);
|
||||||
|
return [$first, $rest];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
"hyperf/process": "~3.1.0",
|
"hyperf/process": "~3.1.0",
|
||||||
"hyperf/rate-limit": "^3.1",
|
"hyperf/rate-limit": "^3.1",
|
||||||
"hyperf/redis": "~3.1.0",
|
"hyperf/redis": "~3.1.0",
|
||||||
|
"hyperf/translation": "^3.1",
|
||||||
"hyperf/validation": "^3.1",
|
"hyperf/validation": "^3.1",
|
||||||
"hyperf/view": "^3.1",
|
"hyperf/view": "^3.1",
|
||||||
"hyperf/websocket-server": "^3.1",
|
"hyperf/websocket-server": "^3.1",
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
/**
|
|
||||||
* This file is part of Hyperf.
|
use Hyperf\Contract\TranslatorInterface;
|
||||||
*
|
|
||||||
* @link https://www.hyperf.io
|
|
||||||
* @document https://hyperf.wiki
|
|
||||||
* @contact group@hyperf.io
|
|
||||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
|
||||||
*/
|
|
||||||
return [
|
return [
|
||||||
|
// 多语言翻译
|
||||||
|
TranslatorInterface::class => \App\Service\TranslationService::class,
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,6 @@ declare(strict_types=1);
|
||||||
|
|
||||||
use function Hyperf\Support\env;
|
use function Hyperf\Support\env;
|
||||||
|
|
||||||
/**
|
|
||||||
* This file is part of hyperf-ext/jwt
|
|
||||||
*
|
|
||||||
* @link https://github.com/hyperf-ext/jwt
|
|
||||||
* @contact eric@zhu.email
|
|
||||||
* @license https://github.com/hyperf-ext/jwt/blob/master/LICENSE
|
|
||||||
*/
|
|
||||||
return [
|
return [
|
||||||
// 公钥
|
// 公钥
|
||||||
'public' => env('JWT_PUBLIC_KEY'),
|
'public' => env('JWT_PUBLIC_KEY'),
|
||||||
|
|
@ -21,5 +14,5 @@ return [
|
||||||
// 使用者
|
// 使用者
|
||||||
'aud' => 'member',
|
'aud' => 'member',
|
||||||
// 过期时间
|
// 过期时间
|
||||||
'ttl' => 30 * 24 * 60 *60
|
'ttl' => 30 * 24 * 60 * 60
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ return [
|
||||||
'http' => [
|
'http' => [
|
||||||
Hyperf\Validation\Middleware\ValidationMiddleware::class,
|
Hyperf\Validation\Middleware\ValidationMiddleware::class,
|
||||||
App\Middleware\JWTMiddleware::class,
|
App\Middleware\JWTMiddleware::class,
|
||||||
App\Middleware\CorsMiddleware::class
|
App\Middleware\CorsMiddleware::class,
|
||||||
|
App\Middleware\LanguageMiddleware::class,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
// 默认语言
|
||||||
|
'locale' => 'zh_CN',
|
||||||
|
// 回退语言,当默认语言的语言文本没有提供时,就会使用回退语言的对应语言文本
|
||||||
|
'fallback_locale' => 'en',
|
||||||
|
// 语言文件存放的文件夹
|
||||||
|
'path' => BASE_PATH . '/static/languages',
|
||||||
|
// 缓存时长
|
||||||
|
'ttl' => 30 * 24 * 60 * 60
|
||||||
|
];
|
||||||
Loading…
Reference in New Issue