You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Lighthouse GraphQL动态语言翻译及扩展字段实现问询

基于Laravel Lighthouse的动态翻译与虚拟字段解决方案

一、实现动态指定翻译语言

1. 改造@translate指令支持语言参数

首先修改指令的GraphQL定义,让它支持传递语言参数,同时保留从请求头自动获取的能力:

directive @translate(language: String) on FIELD_DEFINITION

2. 更新指令PHP实现

调整指令逻辑,优先使用查询传递的语言参数,其次读取请求头Accept-Language,最后 fallback 到默认语言:

namespace App\GraphQL\Directives;

use Closure;
use GraphQL\Type\Definition\ResolveInfo;
use Nuwave\Lighthouse\Schema\Directives\BaseDirective;
use Nuwave\Lighthouse\Schema\Values\FieldValue;
use Nuwave\Lighthouse\Support\Contracts\FieldMiddleware;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;

class TranslateDirective extends BaseDirective implements FieldMiddleware
{
    public static function definition(): string
    {
        return /** @lang GraphQL */ <<<'GRAPHQL'
directive @translate(language: String) on FIELD_DEFINITION
GRAPHQL;
    }

    public function handleField(FieldValue $fieldValue, Closure $next): FieldValue
    {
        $resolver = $fieldValue->getResolver();
        // 获取指令配置的默认语言,默认值为'en'
        $defaultLang = $this->directiveArgValue('language', 'en');

        $fieldValue->setResolver(function ($root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo) use ($resolver, $defaultLang) {
            // 优先级:查询参数 > 请求头 > 默认语言
            $lang = $args['language'] ?? $context->request->header('Accept-Language', $defaultLang);
            // 简化语言码,比如将'zh-CN'转为'zh'
            $lang = explode(',', $lang)[0] ?? $defaultLang;

            $result = $resolver($root, $args, $context, $resolveInfo);
            return __($result, [], $lang);
        });

        return $next($fieldValue);
    }
}

3. 使用方式

方式1:查询时传递语言参数

query {
    standardLibraries(language: "zh") {
        id
        code
        title @translate
    }
}

方式2:通过请求头传递

前端请求时携带Accept-Language: zh-CN,后端自动识别并使用对应语言翻译,无需在查询中额外传参。

二、获取数据库不存在字段的翻译(如description)

1. 在GraphQL类型中定义虚拟字段

直接在StandardLibrary类型中添加不存在于数据库的字段,使用改造后的@translate指令:

type StandardLibrary @guard {
    id: ID!
    code: String!
    title: String! @translate
    description: String! @translate
}

2. 调整指令逻辑适配虚拟字段

修改@translate指令的解析逻辑,当原解析器返回null(说明字段不存在于数据库)时,通过记录ID读取JSON翻译文件:

// 在指令的resolver闭包中修改
public function handleField(FieldValue $fieldValue, Closure $next): FieldValue
{
    $resolver = $fieldValue->getResolver();
    $fieldName = $fieldValue->fieldDefinition->name;
    $defaultLang = $this->directiveArgValue('language', 'en');

    $fieldValue->setResolver(function ($root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo) use ($resolver, $defaultLang, $fieldName) {
        $lang = $args['language'] ?? $context->request->header('Accept-Language', $defaultLang);
        $lang = explode(',', $lang)[0] ?? $defaultLang;

        $result = $resolver($root, $args, $context, $resolveInfo);

        if (is_null($result)) {
            // 构建翻译键:类型名.字段名.记录ID
            $translationKey = "standard_library.{$fieldName}.{$root->id}";
            // 无翻译时返回空字符串或默认提示
            return __($translationKey, [], $lang) ?? '暂无描述';
        }

        return __($result, [], $lang);
    });

    return $next($fieldValue);
}

3. 翻译文件结构

在resources/lang目录下创建对应语言的翻译文件,例如resources/lang/zh/standard_library.php:

return [
    'title' => [
        1 => '标准库1标题',
        2 => '标准库2标题',
    ],
    'description' => [
        1 => '标准库1的详细描述内容',
        2 => '标准库2的详细描述内容',
    ]
];

注意事项

  • 确保Laravel语言文件路径正确,不同语言对应不同子目录(如en、zh)
  • 可通过Laravel中间件统一处理语言码转换,避免在指令中重复逻辑
  • 虚拟字段的翻译键可根据业务需求调整格式,保证与JSON文件结构匹配

内容的提问来源于stack exchange,提问作者JessicaNana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 04:21:48