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
相关产品推荐
相关产品推荐

