Skip to content

Commit c5b7fe7

Browse files
authored
Allow posting strings to translations endpoint (#313)
* Allow JWT in query string for reports * Allow posting strings to translation endpoint
1 parent 7c9d0d4 commit c5b7fe7

File tree

4 files changed

+90
-4
lines changed

4 files changed

+90
-4
lines changed

gramps_webapi/api/resources/translations.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"""Translate API Resource."""
2222

2323
import json
24-
from typing import Dict, Union
24+
from typing import Dict, List, Union
2525

2626
from flask import Response, abort
2727
from gramps.gen.const import GRAMPS_LOCALE
@@ -72,7 +72,18 @@ def get(self, args: Dict, language: str) -> Response:
7272
strings = json.loads(args["strings"])
7373
except json.JSONDecodeError:
7474
abort(400)
75+
return self._get_or_post(strings=strings, language=language)
7576

77+
@use_args(
78+
{"strings": fields.List(fields.Str, required=True)},
79+
location="json",
80+
)
81+
def post(self, args: Dict, language: str) -> Response:
82+
"""Get translation for posted strings."""
83+
return self._get_or_post(strings=args["strings"], language=language)
84+
85+
def _get_or_post(self, strings: List[str], language: str) -> Response:
86+
"""Get translation."""
7687
catalog = GRAMPS_LOCALE.get_language_dict()
7788
for entry in catalog:
7889
if catalog[entry] == language:

gramps_webapi/api/util.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from http import HTTPStatus
2929
from typing import BinaryIO, Optional, Sequence
3030

31-
from flask import abort, current_app, g, request
31+
from flask import abort, current_app, g, jsonify, make_response, request
3232
from gramps.gen.const import GRAMPS_LOCALE
3333
from gramps.gen.db.base import DbReadBase
3434
from gramps.gen.errors import HandleError
@@ -48,6 +48,16 @@ class Parser(FlaskParser):
4848
# raise in case of unknown query arguments
4949
DEFAULT_UNKNOWN_BY_LOCATION = {"query": RAISE}
5050

51+
def handle_error(self, error, req, schema, *, error_status_code, error_headers):
52+
status_code = error_status_code or self.DEFAULT_VALIDATION_STATUS
53+
abort(
54+
make_response(jsonify(error.messages), status_code),
55+
exc=error,
56+
messages=error.messages,
57+
schema=schema,
58+
headers=error_headers,
59+
)
60+
5161

5262
parser = Parser()
5363
use_args = parser.use_args

gramps_webapi/data/apispec.yaml

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4972,7 +4972,39 @@ paths:
49724972
description: "Not Found: Language code was not found."
49734973
422:
49744974
description: "Unprocessable Entity: Invalid or bad parameter provided."
4975-
4975+
post:
4976+
tags:
4977+
- translations
4978+
summary: "Get a translation in a specific language."
4979+
operationId: getTranslation
4980+
security:
4981+
- Bearer: []
4982+
parameters:
4983+
- name: language
4984+
in: path
4985+
required: true
4986+
type: string
4987+
description: "The language code or identifier."
4988+
- name: strings
4989+
in: body
4990+
required: true
4991+
type: string
4992+
description: "The list of strings to be translated. These must be provided in JSON format."
4993+
responses:
4994+
200:
4995+
description: "OK: Successful operation."
4996+
schema:
4997+
type: array
4998+
items:
4999+
$ref: "#/definitions/Translation"
5000+
400:
5001+
description: "Bad Request: Malformed request could not be parsed."
5002+
401:
5003+
description: "Unauthorized: Missing authorization header."
5004+
404:
5005+
description: "Not Found: Language code was not found."
5006+
422:
5007+
description: "Unprocessable Entity: Invalid or bad parameter provided."
49765008

49775009
##############################################################################
49785010
# Endpoint - Relations

tests/test_endpoints/test_translations.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
import unittest
2424

25+
from gramps_webapi.auth.const import ROLE_OWNER
26+
2527
from . import BASE_URL, get_test_client
2628
from .checks import (
2729
check_conforms_to_schema,
@@ -31,6 +33,7 @@
3133
check_resource_missing,
3234
check_success,
3335
)
36+
from .util import fetch_header
3437

3538
TEST_URL = BASE_URL + "/translations/"
3639

@@ -57,7 +60,7 @@ def test_get_translations_conforms_to_schema(self):
5760

5861

5962
class TestTranslationsLanguage(unittest.TestCase):
60-
"""Test cases for the /api/translations/{language} endpoint."""
63+
"""Test cases for the /api/translations/{language} endpoint using GET."""
6164

6265
@classmethod
6366
def setUpClass(cls):
@@ -93,3 +96,33 @@ def test_get_translations_language_expected_result_multiple_values(self):
9396
self.assertEqual(len(rv), 2)
9497
self.assertEqual(rv[0], {"original": "Birth", "translation": "Naissance"})
9598
self.assertEqual(rv[1], {"original": "Death", "translation": "Décès"})
99+
100+
101+
class TestTranslationsLanguagePost(unittest.TestCase):
102+
"""Test cases for the /api/translations/{language} endpoint using POST."""
103+
104+
@classmethod
105+
def setUpClass(cls):
106+
"""Test class setup."""
107+
cls.client = get_test_client()
108+
109+
def test_get_translations_language_expected_result_single_value(self):
110+
"""Test response for single translation."""
111+
header = fetch_header(self.client, role=ROLE_OWNER)
112+
data = {"strings": ["Birth"]}
113+
rv = self.client.post(TEST_URL + "fr", headers=header, json=data)
114+
self.assertEqual(rv.status_code, 200)
115+
rv = rv.json
116+
self.assertEqual(len(rv), 1)
117+
self.assertEqual(rv[0], {"original": "Birth", "translation": "Naissance"})
118+
119+
def test_get_translations_language_expected_result_multiple_values(self):
120+
"""Test response for multiple translations."""
121+
header = fetch_header(self.client, role=ROLE_OWNER)
122+
data = {"strings": ["Birth", "Death"]}
123+
rv = self.client.post(TEST_URL + "fr", headers=header, json=data)
124+
self.assertEqual(rv.status_code, 200)
125+
rv = rv.json
126+
self.assertEqual(len(rv), 2)
127+
self.assertEqual(rv[0], {"original": "Birth", "translation": "Naissance"})
128+
self.assertEqual(rv[1], {"original": "Death", "translation": "Décès"})

0 commit comments

Comments
 (0)