Problem
The add-or-update endpoint returned validation errors in a custom JSON shape (message plus a metadata bag with field, language, and drf_code) instead of the DRF standardized error format used elsewhere in Weblate. Clients could not rely on consistent detail/attr/code fields or the type: validation_error envelope for HTTP 400 responses.
Acceptance Criteria
Implementation Notes
- Introduced
to_error_entry, attr_for_field, and flatten_validation_detail in errors.py to build and flatten DRF-standard entries; BoostEndpointError.to_dict() now emits detail/attr instead of message/metadata
- Serializer validation accumulates
ErrorDetail objects with boost error codes in nested field-keyed detail, replacing parallel _custom_validation_errors / structured_errors lists
AddOrUpdateView delegates to serializer.is_valid(raise_exception=True) so DRF's exception handler produces the standardized response envelope
References
src/boost_weblate/endpoint/errors.py
src/boost_weblate/endpoint/serializers.py
src/boost_weblate/endpoint/tasks.py
src/boost_weblate/endpoint/views.py
tests/endpoint/test_errors.py
tests/endpoint/test_serializers.py
tests/endpoint/test_views.py
Problem
The add-or-update endpoint returned validation errors in a custom JSON shape (
messageplus ametadatabag withfield,language, anddrf_code) instead of the DRF standardized error format used elsewhere in Weblate. Clients could not rely on consistentdetail/attr/codefields or thetype: validation_errorenvelope for HTTP 400 responses.Acceptance Criteria
type: validation_errorand anerrorslist where each entry hascode,detail, andattrattrpaths (e.g.add_or_update.zh_Hans) rather than ametadatabag on API validation errorsAddOrUpdateRequestSerializerexposesstandardized_errorsflattened from DRF validation detail viaflatten_validation_detailto_error_dict,append_error) still support an optionalmetadatabag for Celery task and per-submodule resultsImplementation Notes
to_error_entry,attr_for_field, andflatten_validation_detailinerrors.pyto build and flatten DRF-standard entries;BoostEndpointError.to_dict()now emitsdetail/attrinstead ofmessage/metadataErrorDetailobjects with boost error codes in nested field-keyed detail, replacing parallel_custom_validation_errors/structured_errorslistsAddOrUpdateViewdelegates toserializer.is_valid(raise_exception=True)so DRF's exception handler produces the standardized response envelopeReferences
src/boost_weblate/endpoint/errors.pysrc/boost_weblate/endpoint/serializers.pysrc/boost_weblate/endpoint/tasks.pysrc/boost_weblate/endpoint/views.pytests/endpoint/test_errors.pytests/endpoint/test_serializers.pytests/endpoint/test_views.py