From ae018d803fe35427c1f56ac062c2308480a83521 Mon Sep 17 00:00:00 2001 From: zhang zhuo Date: Fri, 5 Dec 2025 16:42:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=9A=E8=AF=AD=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Controller/Admin/Login.php | 11 +++++++ app/Middleware/LanguageMiddleware.php | 23 ++++++++++++++ app/Model/Translation.php | 42 ++++++++++++++++++++----- app/Service/TranslationService.php | 45 +++++++++++++++++++++++++++ app/Utils/Str.php | 9 ++++++ composer.json | 1 + config/autoload/dependencies.php | 13 +++----- config/autoload/jwt.php | 9 +----- config/autoload/middlewares.php | 3 +- config/autoload/translation.php | 12 +++++++ 10 files changed, 144 insertions(+), 24 deletions(-) create mode 100644 app/Middleware/LanguageMiddleware.php create mode 100644 app/Service/TranslationService.php create mode 100644 config/autoload/translation.php diff --git a/app/Controller/Admin/Login.php b/app/Controller/Admin/Login.php index e021923..fe112c3 100644 --- a/app/Controller/Admin/Login.php +++ b/app/Controller/Admin/Login.php @@ -10,6 +10,7 @@ use App\Event\LogEvent; use App\Model\Account; use App\Model\AccountLog; use App\Model\Online; +use App\Model\Translation as tModel; use App\Utils\Param; use App\Utils\Str; 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); + } } \ No newline at end of file diff --git a/app/Middleware/LanguageMiddleware.php b/app/Middleware/LanguageMiddleware.php new file mode 100644 index 0000000..bf5743b --- /dev/null +++ b/app/Middleware/LanguageMiddleware.php @@ -0,0 +1,23 @@ +getHeaderLine('Accept-Language') ?: 'zh_cn'; + $lang = str_replace('-', '_', strtolower($lang)); + $translator = ApplicationContext::getContainer()->get(TranslatorInterface::class); + $translator->setLocale($lang); + return $handler->handle($request); + } +} \ No newline at end of file diff --git a/app/Model/Translation.php b/app/Model/Translation.php index aaa3b98..510235a 100644 --- a/app/Model/Translation.php +++ b/app/Model/Translation.php @@ -7,13 +7,13 @@ namespace App\Model; use Hyperf\DbConnection\Db; /** - * @property int $translation_id - * @property string $group - * @property string $translation_key - * @property string $remark - * @property string $create_time - * @property string $update_time - * @property string $deleted_at + * @property int $translation_id + * @property string $group + * @property string $translation_key + * @property string $remark + * @property string $create_time + * @property string $update_time + * @property string $deleted_at */ class Translation extends Model { @@ -48,6 +48,34 @@ class Translation extends Model ->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() { return $this->hasMany(TranslationValue::class, 'translation_id', 'translation_id'); diff --git a/app/Service/TranslationService.php b/app/Service/TranslationService.php new file mode 100644 index 0000000..00c6f5c --- /dev/null +++ b/app/Service/TranslationService.php @@ -0,0 +1,45 @@ +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; + } +} \ No newline at end of file diff --git a/app/Utils/Str.php b/app/Utils/Str.php index 1edbf6d..64bcc27 100644 --- a/app/Utils/Str.php +++ b/app/Utils/Str.php @@ -151,4 +151,13 @@ class Str return "other"; } } + + static function splitKey(string $key): array + { + $parts = explode('.', $key); + $first = array_shift($parts); + $rest = implode('.', $parts); + return [$first, $rest]; + } + } \ No newline at end of file diff --git a/composer.json b/composer.json index c3fc680..2f7ddde 100644 --- a/composer.json +++ b/composer.json @@ -31,6 +31,7 @@ "hyperf/process": "~3.1.0", "hyperf/rate-limit": "^3.1", "hyperf/redis": "~3.1.0", + "hyperf/translation": "^3.1", "hyperf/validation": "^3.1", "hyperf/view": "^3.1", "hyperf/websocket-server": "^3.1", diff --git a/config/autoload/dependencies.php b/config/autoload/dependencies.php index f46bd96..2b2ad6a 100644 --- a/config/autoload/dependencies.php +++ b/config/autoload/dependencies.php @@ -1,13 +1,10 @@ \App\Service\TranslationService::class, ]; diff --git a/config/autoload/jwt.php b/config/autoload/jwt.php index 3c4abef..936a3e8 100644 --- a/config/autoload/jwt.php +++ b/config/autoload/jwt.php @@ -4,13 +4,6 @@ declare(strict_types=1); 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 [ // 公钥 'public' => env('JWT_PUBLIC_KEY'), @@ -21,5 +14,5 @@ return [ // 使用者 'aud' => 'member', // 过期时间 - 'ttl' => 30 * 24 * 60 *60 + 'ttl' => 30 * 24 * 60 * 60 ]; diff --git a/config/autoload/middlewares.php b/config/autoload/middlewares.php index 307ffb8..6e6f2ea 100644 --- a/config/autoload/middlewares.php +++ b/config/autoload/middlewares.php @@ -13,6 +13,7 @@ return [ 'http' => [ Hyperf\Validation\Middleware\ValidationMiddleware::class, App\Middleware\JWTMiddleware::class, - App\Middleware\CorsMiddleware::class + App\Middleware\CorsMiddleware::class, + App\Middleware\LanguageMiddleware::class, ], ]; diff --git a/config/autoload/translation.php b/config/autoload/translation.php new file mode 100644 index 0000000..f2dfbce --- /dev/null +++ b/config/autoload/translation.php @@ -0,0 +1,12 @@ + 'zh_CN', + // 回退语言,当默认语言的语言文本没有提供时,就会使用回退语言的对应语言文本 + 'fallback_locale' => 'en', + // 语言文件存放的文件夹 + 'path' => BASE_PATH . '/static/languages', + // 缓存时长 + 'ttl' => 30 * 24 * 60 * 60 +]; \ No newline at end of file