Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions src/ai/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,60 @@
return this.post(url, request, this.defaultConfig());
}

/**
* @param request request body
* @see https://support.crowdin.com/developer/enterprise/api/v2/#tag/AI/operation/api.ai.file-translations.post
*/
startAiOrganizationFileTranslation(
request: AiModel.AiFileTranslationRequest,
): Promise<ResponseObject<Status<AiModel.AiFileTranslationAttribute>>> {
const url = `${this.url}/ai/file-translations`;

return this.post(url, request, this.defaultConfig());
}

/**
* @param jobIdentifier job identifier
* @see https://support.crowdin.com/developer/enterprise/api/v2/#tag/AI/operation/api.ai.file-translations.get
*/
getAiOrganizationFileTranslationStatus(
jobIdentifier: string,
): Promise<ResponseObject<Status<AiModel.AiFileTranslationAttribute>>> {
const url = `${this.url}/ai/file-translations/${jobIdentifier}`;

return this.get(url, this.defaultConfig());
}

/**
* @param jobIdentifier job identifier
* @see https://support.crowdin.com/developer/enterprise/api/v2/#tag/AI/operation/api.ai.file-translations.delete
*/
cancelAiOrganizationFileTranslation(jobIdentifier: string): Promise<void> {
const url = `${this.url}/ai/file-translations/${jobIdentifier}`;

return this.delete(url, this.defaultConfig());
}

/**
* @param jobIdentifier job identifier
* @see https://support.crowdin.com/developer/enterprise/api/v2/#tag/AI/operation/api.ai.file-translations.download
*/
downloadAiOrganizationFileTranslation(jobIdentifier: string): Promise<ResponseObject<DownloadLink>> {
const url = `${this.url}/ai/file-translations/${jobIdentifier}/download`;

return this.get(url, this.defaultConfig());
}

/**
* @param jobIdentifier job identifier
* @see https://support.crowdin.com/developer/enterprise/api/v2/#tag/AI/operation/api.ai.file-translations.download-strings
*/
downloadAiOrganizationFileTranslationStrings(jobIdentifier: string): Promise<ResponseObject<DownloadLink>> {
const url = `${this.url}/ai/file-translations/${jobIdentifier}/translations`;

return this.get(url, this.defaultConfig());
}

// Community

/**
Expand Down Expand Up @@ -997,6 +1051,67 @@

return this.post(url, request, this.defaultConfig());
}

/**
* @param userId user identifier
* @param request request body
* @see https://support.crowdin.com/developer/api/v2/#tag/AI/operation/api.users.ai.file-translations.post
*/
startAiUserFileTranslation(
userId: number,
request: AiModel.AiFileTranslationRequest,
): Promise<ResponseObject<Status<AiModel.AiFileTranslationAttribute>>> {
const url = `${this.url}/users/${userId}/ai/file-translations`;

return this.post(url, request, this.defaultConfig());
}

/**
* @param userId user identifier
* @param jobIdentifier job identifier
* @see https://support.crowdin.com/developer/api/v2/#tag/AI/operation/api.users.ai.file-translations.get
*/
getAiUserFileTranslationStatus(
userId: number,
jobIdentifier: string,
): Promise<ResponseObject<Status<AiModel.AiFileTranslationAttribute>>> {
const url = `${this.url}/users/${userId}/ai/file-translations/${jobIdentifier}`;

return this.get(url, this.defaultConfig());
}

/**
* @param userId user identifier
* @param jobIdentifier job identifier
* @see https://support.crowdin.com/developer/api/v2/#tag/AI/operation/api.users.ai.file-translations.delete
*/
cancelAiUserFileTranslation(userId: number, jobIdentifier: string): Promise<void> {
const url = `${this.url}/users/${userId}/ai/file-translations/${jobIdentifier}`;

return this.delete(url, this.defaultConfig());
}

/**
* @param userId user identifier
* @param jobIdentifier job identifier
* @see https://support.crowdin.com/developer/api/v2/#tag/AI/operation/api.users.ai.file-translations.download
*/
downloadAiUserFileTranslation(userId: number, jobIdentifier: string): Promise<ResponseObject<DownloadLink>> {
const url = `${this.url}/users/${userId}/ai/file-translations/${jobIdentifier}/download`;

return this.get(url, this.defaultConfig());
}

/**
* @param userId user identifier
* @param jobIdentifier job identifier
* @see https://support.crowdin.com/developer/api/v2/#tag/AI/operation/api.users.ai.file-translations.download-strings
*/
downloadAiUserFileTranslationStrings(userId: number, jobIdentifier: string): Promise<ResponseObject<DownloadLink>> {
const url = `${this.url}/users/${userId}/ai/file-translations/${jobIdentifier}/translations`;

return this.get(url, this.defaultConfig());
}
}

export namespace AiModel {
Expand Down Expand Up @@ -1189,7 +1304,7 @@
mode: 'external';
identifier: string;
key: string;
options?: any;

Check warning on line 1307 in src/ai/index.ts

View workflow job for this annotation

GitHub Actions / code-coverage

Unexpected any. Specify a different type
}

export interface AddAiPromptRequest {
Expand Down Expand Up @@ -1265,7 +1380,7 @@
}

export interface OverridePromptValues {
[key: string]: any;

Check warning on line 1383 in src/ai/index.ts

View workflow job for this annotation

GitHub Actions / code-coverage

Unexpected any. Specify a different type
}
/* ai Prompts Section END*/

Expand Down Expand Up @@ -1393,7 +1508,7 @@

export interface OtherChatCompletionRequest {
stream?: boolean;
[key: string]: any;

Check warning on line 1511 in src/ai/index.ts

View workflow job for this annotation

GitHub Actions / code-coverage

Unexpected any. Specify a different type
}

export interface GoogleGeminiChatCompletionRequest extends OtherChatCompletionRequest {
Expand Down Expand Up @@ -1432,6 +1547,37 @@
}
/* ai Settings Section END*/

/* ai File Translation Section START*/
export interface AiFileTranslationRequest {
storageId: number;
targetLanguageId: string;
sourceLanguageId?: string;
type?: string;
parserVersion?: number;
tmIds?: number[];
glossaryIds?: number[];
aiPromptId?: number;
aiProviderId?: number;
aiModelId?: string;
instructions?: string[];
attachmentIds?: number[];
}

export interface AiFileTranslationAttribute {
stage: string;
error: {
stage: string;
message: string;
} | null;
downloadName: string | null;
sourceLanguageId: string | null;
targetLanguageId: string;
originalFileName: string;
detectedType: string | null;
parserVersion: number | null;
}
/* ai File Translation Section END*/

/* ai Translate Strings Section START*/
export interface AiTranslateStringsRequest {
strings: string[];
Expand Down
160 changes: 160 additions & 0 deletions tests/ai/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,59 @@ describe('AI API', () => {
translations: ['Перекладений текст'],
},
})
.post(
'/ai/file-translations',
{
storageId: 1,
targetLanguageId: 'uk',
},
{
reqheaders: {
Authorization: `Bearer ${api.token}`,
},
},
)
.reply(200, {
data: {
identifier: jobId,
},
})
.get(`/ai/file-translations/${jobId}`, undefined, {
reqheaders: {
Authorization: `Bearer ${api.token}`,
},
})
.reply(200, {
data: {
identifier: jobId,
},
})
.delete(`/ai/file-translations/${jobId}`, undefined, {
reqheaders: {
Authorization: `Bearer ${api.token}`,
},
})
.reply(200)
.get(`/ai/file-translations/${jobId}/download`, undefined, {
reqheaders: {
Authorization: `Bearer ${api.token}`,
},
})
.reply(200, {
data: {
url: link,
},
})
.get(`/ai/file-translations/${jobId}/translations`, undefined, {
reqheaders: {
Authorization: `Bearer ${api.token}`,
},
})
.reply(200, {
data: {
url: link,
},
})
.get(`/users/${userId}/ai/settings/custom-placeholders`, undefined, {
reqheaders: {
Authorization: `Bearer ${api.token}`,
Expand Down Expand Up @@ -1079,6 +1132,59 @@ describe('AI API', () => {
targetLanguageId: 'uk',
translations: ['Перекладений текст'],
},
})
.post(
`/users/${userId}/ai/file-translations`,
{
storageId: 1,
targetLanguageId: 'uk',
},
{
reqheaders: {
Authorization: `Bearer ${api.token}`,
},
},
)
.reply(200, {
data: {
identifier: jobId,
},
})
.get(`/users/${userId}/ai/file-translations/${jobId}`, undefined, {
reqheaders: {
Authorization: `Bearer ${api.token}`,
},
})
.reply(200, {
data: {
identifier: jobId,
},
})
.delete(`/users/${userId}/ai/file-translations/${jobId}`, undefined, {
reqheaders: {
Authorization: `Bearer ${api.token}`,
},
})
.reply(200)
.get(`/users/${userId}/ai/file-translations/${jobId}/download`, undefined, {
reqheaders: {
Authorization: `Bearer ${api.token}`,
},
})
.reply(200, {
data: {
url: link,
},
})
.get(`/users/${userId}/ai/file-translations/${jobId}/translations`, undefined, {
reqheaders: {
Authorization: `Bearer ${api.token}`,
},
})
.reply(200, {
data: {
url: link,
},
});
});

Expand Down Expand Up @@ -1328,6 +1434,33 @@ describe('AI API', () => {
expect(res.data.translations).toStrictEqual(['Перекладений текст']);
});

it('Start AI Organization File Translation', async () => {
const res = await api.startAiOrganizationFileTranslation({
storageId: 1,
targetLanguageId: 'uk',
});
expect(res.data.identifier).toBe(jobId);
});

it('Get AI Organization File Translation Status', async () => {
const res = await api.getAiOrganizationFileTranslationStatus(jobId);
expect(res.data.identifier).toBe(jobId);
});

it('Cancel AI Organization File Translation', async () => {
await api.cancelAiOrganizationFileTranslation(jobId);
});

it('Download AI Organization File Translation', async () => {
const res = await api.downloadAiOrganizationFileTranslation(jobId);
expect(res.data.url).toBe(link);
});

it('Download AI Organization File Translation Strings', async () => {
const res = await api.downloadAiOrganizationFileTranslationStrings(jobId);
expect(res.data.url).toBe(link);
});

it('List AI User Custom Placeholders', async () => {
const placeholders = await api.listAiUserCustomPlaceholders(userId);
expect(placeholders.data.length).toBe(1);
Expand Down Expand Up @@ -1569,4 +1702,31 @@ describe('AI API', () => {
expect(res.data.targetLanguageId).toBe('uk');
expect(res.data.translations).toStrictEqual(['Перекладений текст']);
});

it('Start AI User File Translation', async () => {
const res = await api.startAiUserFileTranslation(userId, {
storageId: 1,
targetLanguageId: 'uk',
});
expect(res.data.identifier).toBe(jobId);
});

it('Get AI User File Translation Status', async () => {
const res = await api.getAiUserFileTranslationStatus(userId, jobId);
expect(res.data.identifier).toBe(jobId);
});

it('Cancel AI User File Translation', async () => {
await api.cancelAiUserFileTranslation(userId, jobId);
});

it('Download AI User File Translation', async () => {
const res = await api.downloadAiUserFileTranslation(userId, jobId);
expect(res.data.url).toBe(link);
});

it('Download AI User File Translation Strings', async () => {
const res = await api.downloadAiUserFileTranslationStrings(userId, jobId);
expect(res.data.url).toBe(link);
});
});
Loading