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

API Platform v3中ConstraintViolationList的propertyPath翻译问题

解决API Platform v3中ConstraintViolation的propertyPath翻译问题

问题核心

API Platform默认不会自动翻译propertyPath字段——它直接映射实体的属性名,而translation:extract命令仅提取验证消息,不会处理属性路径的翻译逻辑。

解决方案步骤

1. 自定义ConstraintViolationListNormalizer

重写默认序列化器,对propertyPath做翻译处理:

<?php

namespace App\Serializer;

use ApiPlatform\Serializer\SerializerContextBuilderInterface;
use Symfony\Component\Serializer\Normalizer\ConstraintViolationListNormalizer as BaseNormalizer;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\ConstraintViolationListInterface;

class ConstraintViolationListNormalizer extends BaseNormalizer
{
    public function __construct(
        private readonly TranslatorInterface $translator,
        ?SerializerContextBuilderInterface $serializerContextBuilder = null,
        string $format = 'json'
    ) {
        parent::__construct($serializerContextBuilder, $format);
    }

    public function normalize($object, string $format = null, array $context = []): array
    {
        $data = parent::normalize($object, $format, $context);
        $locale = $context['locale'] ?? $this->translator->getLocale();

        foreach ($data['violations'] as &$violation) {
            if (isset($violation['propertyPath'])) {
                $violation['propertyPath'] = $this->translatePropertyPath($violation['propertyPath'], $locale);
            }
        }

        return $data;
    }

    private function translatePropertyPath(string $path, string $locale): string
    {
        $parts = explode('.', $path);
        $translatedParts = [];

        foreach ($parts as $part) {
            if (preg_match('/^(\w+)\[(\d+)\]$/', $part, $matches)) {
                $field = $matches[1];
                $index = $matches[2];
                $translatedField = $this->translator->trans($field, [], 'validators', $locale);
                $translatedParts[] = "{$translatedField}[{$index}]";
            } else {
                $translatedParts[] = $this->translator->trans($part, [], 'validators', $locale);
            }
        }

        return implode('.', $translatedParts);
    }

    public function supportsNormalization($data, string $format = null, array $context = []): bool
    {
        return $data instanceof ConstraintViolationListInterface && $format === $this->format;
    }
}

2. 注册自定义Normalizer

在config/services.yaml中配置服务,确保优先级高于默认序列化器:

services:
    App\Serializer\ConstraintViolationListNormalizer:
        arguments:
            $translator: '@translator'
            $serializerContextBuilder: '@api_platform.serializer.context_builder'
        tags:
            - { name: serializer.normalizer, priority: 100 }

3. 补充属性名翻译

在translations/validators.es.yaml中添加对应属性的翻译键:

phones: teléfonos
number: número

4. 验证效果

发送POST请求时携带Accept-Language: es,此时propertyPath会被翻译为teléfonos[0].número。

可选优化

如果希望展示更友好的名称(如“número de teléfono”),可以修改translatePropertyPath方法,直接返回翻译后的友好名称,或者在响应中新增translatedField字段单独展示,避免破坏原有propertyPath的结构。


内容的提问来源于stack exchange,提问作者Matías Cánepa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 11:40:14