Skip to content

Commit 91eb39f

Browse files
authored
feat(api): add the Translation Memory Segments API support (#158)
1 parent 37f7f5a commit 91eb39f

File tree

13 files changed

+420
-0
lines changed

13 files changed

+420
-0
lines changed

src/main/java/com/crowdin/client/translationmemory/TranslationMemoryApi.java

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,14 @@
1212
import com.crowdin.client.core.model.ResponseList;
1313
import com.crowdin.client.core.model.ResponseObject;
1414
import com.crowdin.client.translationmemory.model.AddTranslationMemoryRequest;
15+
import com.crowdin.client.translationmemory.model.CreateTmSegmentRequest;
1516
import com.crowdin.client.translationmemory.model.SearchConcordance;
1617
import com.crowdin.client.translationmemory.model.SearchConcordanceRequest;
1718
import com.crowdin.client.translationmemory.model.SearchConcordanceResponse;
1819
import com.crowdin.client.translationmemory.model.SearchConcordanceResponseList;
20+
import com.crowdin.client.translationmemory.model.TmSegment;
21+
import com.crowdin.client.translationmemory.model.TmSegmentResponseList;
22+
import com.crowdin.client.translationmemory.model.TmSegmentResponseObject;
1923
import com.crowdin.client.translationmemory.model.TranslationMemory;
2024
import com.crowdin.client.translationmemory.model.TranslationMemoryExportRequest;
2125
import com.crowdin.client.translationmemory.model.TranslationMemoryExportStatus;
@@ -206,4 +210,99 @@ public ResponseObject<TranslationMemoryImportStatus> checkTmImportStatus(Long tm
206210
TranslationMemoryImportStatusResponseObject translationMemoryImportStatusResponseObject = this.httpClient.get(this.url + "/tms/" + tmId + "/imports/" + importId, new HttpRequestConfig(), TranslationMemoryImportStatusResponseObject.class);
207211
return ResponseObject.of(translationMemoryImportStatusResponseObject.getData());
208212
}
213+
214+
//<editor-fold desc="Segments">
215+
216+
/**
217+
* @param tmId translation memory identifier
218+
* @param limit maximum number of items to retrieve (default 25)
219+
* @param offset starting offset in the collection (default 0)
220+
* @return list of translation memory segments
221+
* @see <ul>
222+
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.tms.segments.getMany" target="_blank"><b>API Documentation</b></a></li>
223+
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.tms.segments.getMany" target="_blank"><b>Enterprise API Documentation</b></a></li>
224+
* </ul>
225+
*/
226+
public ResponseList<TmSegment> listTmSegments(Long tmId, Integer limit, Integer offset) throws HttpException, HttpBadRequestException {
227+
String url = formUrl_tmSegments(tmId);
228+
Map<String, Optional<Object>> queryParams = HttpRequestConfig.buildUrlParams(
229+
"limit", Optional.ofNullable(limit),
230+
"offset", Optional.ofNullable(offset)
231+
);
232+
TmSegmentResponseList responseList = this.httpClient.get(url, new HttpRequestConfig(queryParams), TmSegmentResponseList.class);
233+
return TmSegmentResponseList.to(responseList);
234+
}
235+
236+
/**
237+
* @param tmId translation memory identifier
238+
* @param request request object
239+
* @return newly created translation memory segment
240+
* @see <ul>
241+
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.tms.segments.post" target="_blank"><b>API Documentation</b></a></li>
242+
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.tms.segments.post" target="_blank"><b>Enterprise API Documentation</b></a></li>
243+
* </ul>
244+
*/
245+
public ResponseObject<TmSegment> createTmSegment(Long tmId, CreateTmSegmentRequest request) throws HttpException, HttpBadRequestException {
246+
String url = formUrl_tmSegments(tmId);
247+
TmSegmentResponseObject responseObject = this.httpClient.post(url, request, new HttpRequestConfig(), TmSegmentResponseObject.class);
248+
return ResponseObject.of(responseObject.getData());
249+
}
250+
251+
/**
252+
* @param tmId translation memory identifier
253+
* @param segmentId segment identifier
254+
* @return translation memory segment
255+
* @see <ul>
256+
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.tms.segments.get" target="_blank"><b>API Documentation</b></a></li>
257+
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.tms.segments.get" target="_blank"><b>Enterprise API Documentation</b></a></li>
258+
* </ul>
259+
*/
260+
public ResponseObject<TmSegment> getTmSegment(Long tmId, Long segmentId) throws HttpException, HttpBadRequestException {
261+
String url = formUrl_tmSegmentId(tmId, segmentId);
262+
TmSegmentResponseObject responseObject = this.httpClient.get(url, new HttpRequestConfig(), TmSegmentResponseObject.class);
263+
return ResponseObject.of(responseObject.getData());
264+
}
265+
266+
/**
267+
* @param tmId translation memory identifier
268+
* @param segmentId segment identifier
269+
* @see <ul>
270+
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.tms.segments.delete" target="_blank"><b>API Documentation</b></a></li>
271+
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.tms.segments.delete" target="_blank"><b>Enterprise API Documentation</b></a></li>
272+
* </ul>
273+
*/
274+
public void deleteTmSegment(Long tmId, Long segmentId) throws HttpException, HttpBadRequestException {
275+
String url = formUrl_tmSegmentId(tmId, segmentId);
276+
this.httpClient.delete(url, new HttpRequestConfig(), Void.class);
277+
}
278+
279+
/**
280+
* @param tmId translation memory identifier
281+
* @param segmentId segment identifier
282+
* @param request request object
283+
* @return updated translation memory segment
284+
* @see <ul>
285+
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.tms.segments.patch" target="_blank"><b>API Documentation</b></a></li>
286+
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.tms.segments.patch" target="_blank"><b>Enterprise API Documentation</b></a></li>
287+
* </ul>
288+
*/
289+
public ResponseObject<TmSegment> editTmSegment(Long tmId, Long segmentId, List<PatchRequest> request) throws HttpException, HttpBadRequestException {
290+
String url = formUrl_tmSegmentId(tmId, segmentId);
291+
TmSegmentResponseObject responseObject = this.httpClient.patch(url, request, new HttpRequestConfig(), TmSegmentResponseObject.class);
292+
return ResponseObject.of(responseObject.getData());
293+
}
294+
295+
//<editor-fold desc="Helper methods">
296+
297+
private String formUrl_tmSegments(Long tmId) {
298+
return this.url + "/tms/" + tmId + "/segments";
299+
}
300+
301+
private String formUrl_tmSegmentId(Long tmId, Long segmentId) {
302+
return this.url + "/tms/" + tmId + "/segments/" + segmentId;
303+
}
304+
305+
//</editor-fold>
306+
307+
//</editor-fold>
209308
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.crowdin.client.translationmemory.model;
2+
3+
import lombok.Data;
4+
5+
import java.util.List;
6+
7+
@Data
8+
public class CreateTmSegmentRequest {
9+
private List<TmSegmentRecordForm> records;
10+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.crowdin.client.translationmemory.model;
2+
3+
import lombok.Data;
4+
5+
import java.util.List;
6+
7+
@Data
8+
public class TmSegment {
9+
private Long id;
10+
private List<TmSegmentRecord> records;
11+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.crowdin.client.translationmemory.model;
2+
3+
import lombok.Data;
4+
5+
import java.util.Date;
6+
7+
@Data
8+
public class TmSegmentRecord {
9+
private Long id;
10+
private String languageId;
11+
private String text;
12+
private Long usageCount;
13+
private Long createdBy;
14+
private Long updatedBy;
15+
private Date createdAt;
16+
private Date updatedAt;
17+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.crowdin.client.translationmemory.model;
2+
3+
import lombok.Data;
4+
5+
@Data
6+
public class TmSegmentRecordForm {
7+
private String languageId;
8+
private String text;
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.crowdin.client.translationmemory.model;
2+
3+
import lombok.Data;
4+
5+
@Data
6+
public class TmSegmentRecordOperationAdd {
7+
private String text;
8+
private String languageId;
9+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.crowdin.client.translationmemory.model;
2+
3+
import com.crowdin.client.core.model.Pagination;
4+
import com.crowdin.client.core.model.ResponseList;
5+
import com.crowdin.client.core.model.ResponseObject;
6+
import lombok.Data;
7+
8+
import java.util.List;
9+
import java.util.stream.Collectors;
10+
11+
@Data
12+
public class TmSegmentResponseList {
13+
private List<TmSegmentResponseObject> data;
14+
private Pagination pagination;
15+
16+
public static ResponseList<TmSegment> to(TmSegmentResponseList responseList) {
17+
return ResponseList.of(
18+
responseList.getData().stream()
19+
.map(TmSegmentResponseObject::getData)
20+
.map(ResponseObject::of)
21+
.collect(Collectors.toList()),
22+
responseList.getPagination()
23+
);
24+
}
25+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.crowdin.client.translationmemory.model;
2+
3+
import lombok.Data;
4+
5+
@Data
6+
public class TmSegmentResponseObject {
7+
private TmSegment data;
8+
}
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
package com.crowdin.client.translationmemory;
2+
3+
import com.crowdin.client.core.model.PatchOperation;
4+
import com.crowdin.client.core.model.PatchRequest;
5+
import com.crowdin.client.core.model.ResponseList;
6+
import com.crowdin.client.core.model.ResponseObject;
7+
import com.crowdin.client.framework.RequestMock;
8+
import com.crowdin.client.framework.TestClient;
9+
import com.crowdin.client.translationmemory.model.*;
10+
11+
import lombok.SneakyThrows;
12+
import org.apache.http.client.methods.HttpDelete;
13+
import org.apache.http.client.methods.HttpGet;
14+
import org.apache.http.client.methods.HttpPatch;
15+
import org.apache.http.client.methods.HttpPost;
16+
import org.junit.jupiter.api.Test;
17+
18+
import java.text.SimpleDateFormat;
19+
import java.util.*;
20+
21+
import static org.junit.jupiter.api.Assertions.assertEquals;
22+
import static org.junit.jupiter.api.Assertions.assertNotNull;
23+
24+
public class TranslationMemorySegmentsApiTest extends TestClient {
25+
private final Long tmId = 1L;
26+
private final Long segmentId = 1L;
27+
28+
@Override
29+
public List<RequestMock> getMocks() {
30+
return Arrays.asList(
31+
// LIST
32+
RequestMock.build(
33+
formUrl_tmSegments(tmId),
34+
HttpGet.METHOD_NAME,
35+
"api/translationmemory/segments/listTmSegmentsResponse.json",
36+
new HashMap<String, Integer>() {{
37+
put("limit", 20);
38+
put("offset", 10);
39+
}}
40+
),
41+
42+
// CREATE
43+
RequestMock.build(
44+
formUrl_tmSegments(tmId),
45+
HttpPost.METHOD_NAME,
46+
"api/translationmemory/segments/createTmSegmentRequest.json",
47+
"api/translationmemory/segments/commonResponses_single.json"
48+
),
49+
50+
// GET
51+
RequestMock.build(
52+
formUrl_tmSegmentId(tmId, segmentId),
53+
HttpGet.METHOD_NAME,
54+
"api/translationmemory/segments/commonResponses_single.json"
55+
),
56+
57+
// DELETE
58+
RequestMock.build(
59+
formUrl_tmSegmentId(tmId, segmentId),
60+
HttpDelete.METHOD_NAME
61+
),
62+
63+
// EDIT
64+
RequestMock.build(
65+
formUrl_tmSegmentId(tmId, segmentId),
66+
HttpPatch.METHOD_NAME,
67+
"api/translationmemory/segments/editTmSegmentRequest.json",
68+
"api/translationmemory/segments/commonResponses_single.json"
69+
)
70+
);
71+
}
72+
73+
//<editor-fold desc="Form Url methods for mocks">
74+
75+
private String formUrl_tmSegments(Long tmId) {
76+
return this.url + "/tms/" + tmId + "/segments";
77+
}
78+
79+
private String formUrl_tmSegmentId(Long tmId, Long segmentId) {
80+
return this.url + "/tms/" + tmId + "/segments/" + segmentId;
81+
}
82+
83+
//</editor-fold>
84+
85+
@Test
86+
public void listTmSegments() {
87+
ResponseList<TmSegment> response = this.getTranslationMemoryApi().listTmSegments(tmId, 20, 10);
88+
assertTmSegment(response.getData().get(0).getData());
89+
}
90+
91+
@Test
92+
public void createTmSegment() {
93+
CreateTmSegmentRequest request = new CreateTmSegmentRequest() {{
94+
setRecords(Collections.singletonList(new TmSegmentRecordForm() {{
95+
setLanguageId("uk");
96+
setText("Перекладений текст");
97+
}}));
98+
}};
99+
100+
ResponseObject<TmSegment> response = this.getTranslationMemoryApi().createTmSegment(tmId, request);
101+
assertTmSegment(response.getData());
102+
}
103+
104+
@Test
105+
public void getTmSegment() {
106+
ResponseObject<TmSegment> response = this.getTranslationMemoryApi().getTmSegment(tmId, segmentId);
107+
assertTmSegment(response.getData());
108+
}
109+
110+
@Test
111+
public void deleteTmSegment() {
112+
this.getTranslationMemoryApi().deleteTmSegment(tmId, segmentId);
113+
}
114+
115+
@Test
116+
public void editTmSegment() {
117+
List<PatchRequest> request = new ArrayList<PatchRequest>() {{
118+
add(new PatchRequest() {{
119+
setOp(PatchOperation.ADD);
120+
setPath("/records/-");
121+
setValue(new TmSegmentRecordOperationAdd() {{
122+
setText("Перекладений текст");
123+
setLanguageId("uk");
124+
}});
125+
}});
126+
add(new PatchRequest() {{
127+
setOp(PatchOperation.REPLACE);
128+
setPath("/records/1/text");
129+
setValue("Перекладений текст 2");
130+
}});
131+
add(new PatchRequest() {{
132+
setOp(PatchOperation.REMOVE);
133+
setPath("/records/2");
134+
}});
135+
}};
136+
137+
ResponseObject<TmSegment> response = this.getTranslationMemoryApi().editTmSegment(tmId, segmentId, request);
138+
assertTmSegment(response.getData());
139+
}
140+
141+
@SneakyThrows
142+
private static void assertTmSegment(TmSegment tmSegment) {
143+
assertNotNull(tmSegment);
144+
145+
assertNotNull(tmSegment.getRecords());
146+
assertEquals(1, tmSegment.getRecords().size());
147+
148+
TmSegmentRecord record = tmSegment.getRecords().get(0);
149+
assertNotNull(record);
150+
151+
assertEquals(1, record.getId());
152+
assertEquals("uk", record.getLanguageId());
153+
assertEquals("Перекладений текст", record.getText());
154+
assertEquals(13, record.getUsageCount());
155+
assertEquals(1, record.getCreatedBy());
156+
assertEquals(1, record.getUpdatedBy());
157+
158+
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
159+
160+
assertEquals(sdf.parse("2019-09-16T13:48:04+00:00"), record.getCreatedAt());
161+
assertEquals(sdf.parse("2019-09-16T13:48:04+00:00"), record.getUpdatedAt());
162+
}
163+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"data": {
3+
"id": 4,
4+
"records": [
5+
{
6+
"id": 1,
7+
"languageId": "uk",
8+
"text": "Перекладений текст",
9+
"usageCount": 13,
10+
"createdBy": 1,
11+
"updatedBy": 1,
12+
"createdAt": "2019-09-16T13:48:04+00:00",
13+
"updatedAt": "2019-09-16T13:48:04+00:00"
14+
}
15+
]
16+
}
17+
}

0 commit comments

Comments
 (0)