Skip to content

v2.8.0 — Translatable error message templates

Latest

Choose a tag to compare

@hcuadra811 hcuadra811 released this 15 Sep 02:07

Translatable error message templates

An error's MESSAGE can now contain {marker} placeholders, so a client can translate the source text and then fill in the values. Every error body documents both:

class PlanLimitError extends ApiError
{
    public const CODE = 'plan_limit_reached';
    public const MESSAGE = 'Your plan allows up to {limit} projects.';
    public const STATUS = 402;

    public function __construct(
        #[Example(5)]
        public int $limit,
    ) {}
}
"error": {
  "message": "Your plan allows up to 5 projects.",
  "code": "plan_limit_reached",
  "template": "Your plan allows up to {limit} projects.",
  "params": { "limit": 5 },
  "details": { "limit": 5 }
}
  • template is MESSAGE verbatim and is present on every error body.
  • params has one property per marker, documented from the same-named public property: its type, #[Description] and #[Example]. It is required when MESSAGE has markers and omitted when it has none.
  • The message example fills in each marker that has an #[Example] value.
  • A marker must name a public property of the class. Generation fails otherwise, naming the class and the marker.
  • Rename or omit either field with errors.error_fields.template and errors.error_fields.params; null omits it.

Fix: implied errors for annotations on helper methods

When an @OA annotation sits on a helper method rather than the route's action, implied-error rules, the Data-parameter validation check and model-binding detection now inspect the matched route's real action. #[Throws] is still read from both methods.

Behavior changes for apps using error documentation

  • Every error body now includes a required template field.
  • A {marker} in MESSAGE that names no public property now fails generation.
  • template and params are reserved error-object names, so an #[EnvelopeField] with either name now fails generation.

No effect otherwise — apps without errors.base_class configured are unaffected.

See the README for full details.