**Description**
PUT /entities/properties/{property_id}/labels/{language_code}
**Acceptance criteria:**
- The respective successful responses should present the relevant data as a string -- similar to the responses of GET /entities/properties/{property_id}/labels/{language_code}.
- If a label in the given language didn't exist before the successful request the response should use 201 code.
- If the request changed the existing label the response code should be 200.
**Error cases to consider**
<table>
<tr>
<th>
</th>
<th>HTTP response code</th>
<th>response payload</th>
</tr>
<tr>
<td>Property does not exist </td>
<td>404</td>
<td>
`"code": "property-not-found"`
`"message": "Could not find a property with the ID: {property_id}"`
</td>
</tr>
<tr>
<td>Invalid property ID </td>
<td>400</td>
<td>
`"code": "invalid-property-id"`
`"message": "Not a valid property ID: {property_id}"`
`"context": {"property": "{property-id}"}`
</td>
</tr>
<tr>
<td>Invalid language code </td>
<td>400</td>
<td>
`{ "code": "invalid-language-code", "message": "Not a valid language code: {language_code}"}`
</td>
</tr>
<tr>
<td>Label is empty </td>
<td>400</td>
<td>
`{ "code": "label-empty", "message": "Label must not be empty" }`
</td>
</tr>
<tr>
<td>Label too long </td>
<td>400</td>
<td>
`{ "code": "label-too-long", "message": "Label must be no more than {limit} characters long", "context": { "value": "{label}", "character-limit": "{limit}" } }`
</td>
</tr>
<tr>
<td>Label description same value </td>
<td>400</td>
<td>
`{ "code": "label-description-same-value", "message": "Label and description for language code '{language}' can not have the same value", "context": { "language": "{language}" } }`
</td>
</tr>
<tr>
<td>property has the exact same label as another property</td>
<td>400</td>
<td>
`{ "code": "property-label-duplicate", "message": "Property {dupe_id} already has label "{label}" associated with language code {language}", "context": { "language": "{language}", "label": "{label}","matching-property-id": "{duplicate_property_id}" }}`
</td>
</tr>
<tr>
<td>Invalid edit tag</td>
<td>400</td>
<td>
`{ "code": "invalid-edit-tag", "message": "Invalid MediaWiki tag: {tag}" }`
</td>
</tr>
<tr>
<td>Comment too long</td>
<td>400</td>
<td>
`{"code": "comment-too-long", "message": "Comment must not be longer than {limit} characters"}`
</td>
</tr>
</table>
**Notes**
- Automated edit summaries similar as done for items: https://phabricator.wikimedia.org/T323813
- client can provide additional edit metadata: mediawiki tags, edit summary text to append to the automated summary, and a bot edit flag, like in GET /entities/properties/{property_id}/labels/{language_code}
- mul is a valid language code for a label but it is not allowed for descriptions
- Handle HTTP conditional request headers as in PUT /entities/items/{item_id}/labels/{language_code}
- Handle user authentication/authorization like in PUT /entities/items/{item_id}/labels/{language_code}
**Task breakdown notes**:
- Add the new route to OAS.
- create use case validation deserialization:
- create PropertyLabelValidator interface and implement it (WikibaseRepoPropertyLabelValidator)
- create PropertyLabelEditRequest interface
- create PropertyLabelEditRequestValidatingDeserializer
- rename TermValidatorFactoryLabelTextValidator to TermValidatorFactoryItemLabelTextValidator
- create a new TermValidatorFactoryPropertyLabelTextValidator
- happy path (with edit summary)
- use the use case validator for deserialization only, but don't handle or test any errors it throws yet
- ETag and Last-Modified
- differentiate between 200 OK for replaced and 201 CREATED for a newly added label
- Handle request validation errors
- Respond 404 if property not found
- Authorization
- Use the usual middlewares and add the route handler to RouteHandlersTest
- Add spec tests.
- Mark as production ready.