Skip to content

Commit

Permalink
feat(api): add the Translation Memory Segments API support (#158)
Browse files Browse the repository at this point in the history
  • Loading branch information
innomaxx authored Jun 30, 2023
1 parent 37f7f5a commit 91eb39f
Show file tree
Hide file tree
Showing 13 changed files with 420 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@
import com.crowdin.client.core.model.ResponseList;
import com.crowdin.client.core.model.ResponseObject;
import com.crowdin.client.translationmemory.model.AddTranslationMemoryRequest;
import com.crowdin.client.translationmemory.model.CreateTmSegmentRequest;
import com.crowdin.client.translationmemory.model.SearchConcordance;
import com.crowdin.client.translationmemory.model.SearchConcordanceRequest;
import com.crowdin.client.translationmemory.model.SearchConcordanceResponse;
import com.crowdin.client.translationmemory.model.SearchConcordanceResponseList;
import com.crowdin.client.translationmemory.model.TmSegment;
import com.crowdin.client.translationmemory.model.TmSegmentResponseList;
import com.crowdin.client.translationmemory.model.TmSegmentResponseObject;
import com.crowdin.client.translationmemory.model.TranslationMemory;
import com.crowdin.client.translationmemory.model.TranslationMemoryExportRequest;
import com.crowdin.client.translationmemory.model.TranslationMemoryExportStatus;
Expand Down Expand Up @@ -206,4 +210,99 @@ public ResponseObject<TranslationMemoryImportStatus> checkTmImportStatus(Long tm
TranslationMemoryImportStatusResponseObject translationMemoryImportStatusResponseObject = this.httpClient.get(this.url + "/tms/" + tmId + "/imports/" + importId, new HttpRequestConfig(), TranslationMemoryImportStatusResponseObject.class);
return ResponseObject.of(translationMemoryImportStatusResponseObject.getData());
}

//<editor-fold desc="Segments">

/**
* @param tmId translation memory identifier
* @param limit maximum number of items to retrieve (default 25)
* @param offset starting offset in the collection (default 0)
* @return list of translation memory segments
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.tms.segments.getMany" target="_blank"><b>API Documentation</b></a></li>
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.tms.segments.getMany" target="_blank"><b>Enterprise API Documentation</b></a></li>
* </ul>
*/
public ResponseList<TmSegment> listTmSegments(Long tmId, Integer limit, Integer offset) throws HttpException, HttpBadRequestException {
String url = formUrl_tmSegments(tmId);
Map<String, Optional<Object>> queryParams = HttpRequestConfig.buildUrlParams(
"limit", Optional.ofNullable(limit),
"offset", Optional.ofNullable(offset)
);
TmSegmentResponseList responseList = this.httpClient.get(url, new HttpRequestConfig(queryParams), TmSegmentResponseList.class);
return TmSegmentResponseList.to(responseList);
}

/**
* @param tmId translation memory identifier
* @param request request object
* @return newly created translation memory segment
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.tms.segments.post" target="_blank"><b>API Documentation</b></a></li>
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.tms.segments.post" target="_blank"><b>Enterprise API Documentation</b></a></li>
* </ul>
*/
public ResponseObject<TmSegment> createTmSegment(Long tmId, CreateTmSegmentRequest request) throws HttpException, HttpBadRequestException {
String url = formUrl_tmSegments(tmId);
TmSegmentResponseObject responseObject = this.httpClient.post(url, request, new HttpRequestConfig(), TmSegmentResponseObject.class);
return ResponseObject.of(responseObject.getData());
}

/**
* @param tmId translation memory identifier
* @param segmentId segment identifier
* @return translation memory segment
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.tms.segments.get" target="_blank"><b>API Documentation</b></a></li>
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.tms.segments.get" target="_blank"><b>Enterprise API Documentation</b></a></li>
* </ul>
*/
public ResponseObject<TmSegment> getTmSegment(Long tmId, Long segmentId) throws HttpException, HttpBadRequestException {
String url = formUrl_tmSegmentId(tmId, segmentId);
TmSegmentResponseObject responseObject = this.httpClient.get(url, new HttpRequestConfig(), TmSegmentResponseObject.class);
return ResponseObject.of(responseObject.getData());
}

/**
* @param tmId translation memory identifier
* @param segmentId segment identifier
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.tms.segments.delete" target="_blank"><b>API Documentation</b></a></li>
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.tms.segments.delete" target="_blank"><b>Enterprise API Documentation</b></a></li>
* </ul>
*/
public void deleteTmSegment(Long tmId, Long segmentId) throws HttpException, HttpBadRequestException {
String url = formUrl_tmSegmentId(tmId, segmentId);
this.httpClient.delete(url, new HttpRequestConfig(), Void.class);
}

/**
* @param tmId translation memory identifier
* @param segmentId segment identifier
* @param request request object
* @return updated translation memory segment
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.tms.segments.patch" target="_blank"><b>API Documentation</b></a></li>
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.tms.segments.patch" target="_blank"><b>Enterprise API Documentation</b></a></li>
* </ul>
*/
public ResponseObject<TmSegment> editTmSegment(Long tmId, Long segmentId, List<PatchRequest> request) throws HttpException, HttpBadRequestException {
String url = formUrl_tmSegmentId(tmId, segmentId);
TmSegmentResponseObject responseObject = this.httpClient.patch(url, request, new HttpRequestConfig(), TmSegmentResponseObject.class);
return ResponseObject.of(responseObject.getData());
}

//<editor-fold desc="Helper methods">

private String formUrl_tmSegments(Long tmId) {
return this.url + "/tms/" + tmId + "/segments";
}

private String formUrl_tmSegmentId(Long tmId, Long segmentId) {
return this.url + "/tms/" + tmId + "/segments/" + segmentId;
}

//</editor-fold>

//</editor-fold>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.crowdin.client.translationmemory.model;

import lombok.Data;

import java.util.List;

@Data
public class CreateTmSegmentRequest {
private List<TmSegmentRecordForm> records;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.crowdin.client.translationmemory.model;

import lombok.Data;

import java.util.List;

@Data
public class TmSegment {
private Long id;
private List<TmSegmentRecord> records;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.crowdin.client.translationmemory.model;

import lombok.Data;

import java.util.Date;

@Data
public class TmSegmentRecord {
private Long id;
private String languageId;
private String text;
private Long usageCount;
private Long createdBy;
private Long updatedBy;
private Date createdAt;
private Date updatedAt;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.crowdin.client.translationmemory.model;

import lombok.Data;

@Data
public class TmSegmentRecordForm {
private String languageId;
private String text;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.crowdin.client.translationmemory.model;

import lombok.Data;

@Data
public class TmSegmentRecordOperationAdd {
private String text;
private String languageId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.crowdin.client.translationmemory.model;

import com.crowdin.client.core.model.Pagination;
import com.crowdin.client.core.model.ResponseList;
import com.crowdin.client.core.model.ResponseObject;
import lombok.Data;

import java.util.List;
import java.util.stream.Collectors;

@Data
public class TmSegmentResponseList {
private List<TmSegmentResponseObject> data;
private Pagination pagination;

public static ResponseList<TmSegment> to(TmSegmentResponseList responseList) {
return ResponseList.of(
responseList.getData().stream()
.map(TmSegmentResponseObject::getData)
.map(ResponseObject::of)
.collect(Collectors.toList()),
responseList.getPagination()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.crowdin.client.translationmemory.model;

import lombok.Data;

@Data
public class TmSegmentResponseObject {
private TmSegment data;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package com.crowdin.client.translationmemory;

import com.crowdin.client.core.model.PatchOperation;
import com.crowdin.client.core.model.PatchRequest;
import com.crowdin.client.core.model.ResponseList;
import com.crowdin.client.core.model.ResponseObject;
import com.crowdin.client.framework.RequestMock;
import com.crowdin.client.framework.TestClient;
import com.crowdin.client.translationmemory.model.*;

import lombok.SneakyThrows;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.client.methods.HttpPost;
import org.junit.jupiter.api.Test;

import java.text.SimpleDateFormat;
import java.util.*;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

public class TranslationMemorySegmentsApiTest extends TestClient {
private final Long tmId = 1L;
private final Long segmentId = 1L;

@Override
public List<RequestMock> getMocks() {
return Arrays.asList(
// LIST
RequestMock.build(
formUrl_tmSegments(tmId),
HttpGet.METHOD_NAME,
"api/translationmemory/segments/listTmSegmentsResponse.json",
new HashMap<String, Integer>() {{
put("limit", 20);
put("offset", 10);
}}
),

// CREATE
RequestMock.build(
formUrl_tmSegments(tmId),
HttpPost.METHOD_NAME,
"api/translationmemory/segments/createTmSegmentRequest.json",
"api/translationmemory/segments/commonResponses_single.json"
),

// GET
RequestMock.build(
formUrl_tmSegmentId(tmId, segmentId),
HttpGet.METHOD_NAME,
"api/translationmemory/segments/commonResponses_single.json"
),

// DELETE
RequestMock.build(
formUrl_tmSegmentId(tmId, segmentId),
HttpDelete.METHOD_NAME
),

// EDIT
RequestMock.build(
formUrl_tmSegmentId(tmId, segmentId),
HttpPatch.METHOD_NAME,
"api/translationmemory/segments/editTmSegmentRequest.json",
"api/translationmemory/segments/commonResponses_single.json"
)
);
}

//<editor-fold desc="Form Url methods for mocks">

private String formUrl_tmSegments(Long tmId) {
return this.url + "/tms/" + tmId + "/segments";
}

private String formUrl_tmSegmentId(Long tmId, Long segmentId) {
return this.url + "/tms/" + tmId + "/segments/" + segmentId;
}

//</editor-fold>

@Test
public void listTmSegments() {
ResponseList<TmSegment> response = this.getTranslationMemoryApi().listTmSegments(tmId, 20, 10);
assertTmSegment(response.getData().get(0).getData());
}

@Test
public void createTmSegment() {
CreateTmSegmentRequest request = new CreateTmSegmentRequest() {{
setRecords(Collections.singletonList(new TmSegmentRecordForm() {{
setLanguageId("uk");
setText("Перекладений текст");
}}));
}};

ResponseObject<TmSegment> response = this.getTranslationMemoryApi().createTmSegment(tmId, request);
assertTmSegment(response.getData());
}

@Test
public void getTmSegment() {
ResponseObject<TmSegment> response = this.getTranslationMemoryApi().getTmSegment(tmId, segmentId);
assertTmSegment(response.getData());
}

@Test
public void deleteTmSegment() {
this.getTranslationMemoryApi().deleteTmSegment(tmId, segmentId);
}

@Test
public void editTmSegment() {
List<PatchRequest> request = new ArrayList<PatchRequest>() {{
add(new PatchRequest() {{
setOp(PatchOperation.ADD);
setPath("/records/-");
setValue(new TmSegmentRecordOperationAdd() {{
setText("Перекладений текст");
setLanguageId("uk");
}});
}});
add(new PatchRequest() {{
setOp(PatchOperation.REPLACE);
setPath("/records/1/text");
setValue("Перекладений текст 2");
}});
add(new PatchRequest() {{
setOp(PatchOperation.REMOVE);
setPath("/records/2");
}});
}};

ResponseObject<TmSegment> response = this.getTranslationMemoryApi().editTmSegment(tmId, segmentId, request);
assertTmSegment(response.getData());
}

@SneakyThrows
private static void assertTmSegment(TmSegment tmSegment) {
assertNotNull(tmSegment);

assertNotNull(tmSegment.getRecords());
assertEquals(1, tmSegment.getRecords().size());

TmSegmentRecord record = tmSegment.getRecords().get(0);
assertNotNull(record);

assertEquals(1, record.getId());
assertEquals("uk", record.getLanguageId());
assertEquals("Перекладений текст", record.getText());
assertEquals(13, record.getUsageCount());
assertEquals(1, record.getCreatedBy());
assertEquals(1, record.getUpdatedBy());

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");

assertEquals(sdf.parse("2019-09-16T13:48:04+00:00"), record.getCreatedAt());
assertEquals(sdf.parse("2019-09-16T13:48:04+00:00"), record.getUpdatedAt());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"data": {
"id": 4,
"records": [
{
"id": 1,
"languageId": "uk",
"text": "Перекладений текст",
"usageCount": 13,
"createdBy": 1,
"updatedBy": 1,
"createdAt": "2019-09-16T13:48:04+00:00",
"updatedAt": "2019-09-16T13:48:04+00:00"
}
]
}
}
Loading

0 comments on commit 91eb39f

Please sign in to comment.