From 8d7b4d1b5fd65f77940981748e7d06e65cb88c3a Mon Sep 17 00:00:00 2001 From: Andrii Bodnar <29282228+andrii-bodnar@users.noreply.github.com> Date: Mon, 15 Jun 2026 12:36:39 +0300 Subject: [PATCH 1/5] feat(translations): add new pre-translate parameters (#681) --- src/translations/index.ts | 31 ++++++++++++++++++++++++- tests/translations/api.test.ts | 42 ++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/translations/index.ts b/src/translations/index.ts index 932da4fae..13fa53b74 100644 --- a/src/translations/index.ts +++ b/src/translations/index.ts @@ -317,36 +317,56 @@ export namespace TranslationsModel { languageIds: string[]; fileIds: number[]; method?: Method; + priority?: Priority; engineId?: number; aiPromptId?: number; autoApproveOption?: AutoApproveOption; duplicateTranslations?: boolean; skipApprovedTranslations?: boolean; + /** + * @deprecated Use {@link scope} instead + */ translateUntranslatedOnly?: boolean; + scope?: Scope; + translationModifiedBefore?: string; + replaceTranslationsOption?: ReplaceTranslationsOption; + resetApprovalStatus?: boolean; translateWithPerfectMatchOnly?: boolean; fallbackLanguages?: { languageId?: string[]; }; labelIds?: number[]; excludeLabelIds?: number[]; + sourceLanguageId?: string; + customInstruction?: string; } export interface PreTranslateStringsRequest { languageIds: string[]; branchIds?: number[]; method?: Method; + priority?: Priority; engineId?: number; aiPromptId?: number; autoApproveOption?: AutoApproveOption; duplicateTranslations?: boolean; skipApprovedTranslations?: boolean; + /** + * @deprecated Use {@link scope} instead + */ translateUntranslatedOnly?: boolean; + scope?: Scope; + translationModifiedBefore?: string; + replaceTranslationsOption?: ReplaceTranslationsOption; + resetApprovalStatus?: boolean; translateWithPerfectMatchOnly?: boolean; fallbackLanguages?: { languageId: string[]; }; labelIds?: number[]; excludeLabelIds?: number[]; + sourceLanguageId?: string; + customInstruction?: string; } export interface BuildProjectDirectoryTranslationRequest { @@ -407,7 +427,16 @@ export namespace TranslationsModel { export type Method = 'tm' | 'mt' | 'ai'; - export type AutoApproveOption = 'all' | 'exceptAutoSubstituted' | 'perfectMatchOnly' | 'none'; + export type AutoApproveOption = + | 'all' + | 'exceptAutoSubstituted' + | 'perfectMatchOnly' + | 'perfectMatchApprovedOnly' + | 'none'; + + export type Scope = 'untranslated' | 'translated' | 'all'; + + export type ReplaceTranslationsOption = 'none' | 'autoTranslated' | 'all'; export type Priority = 'low' | 'normal' | 'high'; diff --git a/tests/translations/api.test.ts b/tests/translations/api.test.ts index 98ac5ebd0..6522763e4 100644 --- a/tests/translations/api.test.ts +++ b/tests/translations/api.test.ts @@ -355,6 +355,32 @@ describe('Translations API', () => { }, }, ) + .reply(200, { + data: { + identifier: preTranslationId, + attributes: {}, + }, + }) + .post( + `/projects/${projectId}/pre-translations`, + { + languageIds: [], + fileIds: [], + method: 'ai', + priority: 'high', + scope: 'untranslated', + translationModifiedBefore: '2024-01-01T00:00:00+00:00', + replaceTranslationsOption: 'autoTranslated', + resetApprovalStatus: true, + sourceLanguageId: 'en', + customInstruction: 'Translate formally', + }, + { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }, + ) .reply(200, { data: { identifier: preTranslationId, @@ -392,6 +418,22 @@ describe('Translations API', () => { expect(preTranslation.data.identifier).toBe(preTranslationId); }); + it('Apply Pre-Translation with new options', async () => { + const preTranslation = await api.applyPreTranslation(projectId, { + fileIds: [], + languageIds: [], + method: 'ai', + priority: 'high', + scope: 'untranslated', + translationModifiedBefore: '2024-01-01T00:00:00+00:00', + replaceTranslationsOption: 'autoTranslated', + resetApprovalStatus: true, + sourceLanguageId: 'en', + customInstruction: 'Translate formally', + }); + expect(preTranslation.data.identifier).toBe(preTranslationId); + }); + it('Pre-translation status', async () => { const preTranslation = await api.preTranslationStatus(projectId, preTranslationId); expect(preTranslation.data.identifier).toBe(preTranslationId); From 0be8ff6f77c30915957b841606f4bcc56694583e Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Jun 2026 14:21:11 +0300 Subject: [PATCH 2/5] feat: add styleGuideIds to AI translation request interfaces (#683) --- src/ai/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ai/index.ts b/src/ai/index.ts index 6c6a88a18..1f850ba48 100644 --- a/src/ai/index.ts +++ b/src/ai/index.ts @@ -1704,6 +1704,7 @@ export namespace AiModel { parserVersion?: number; tmIds?: number[]; glossaryIds?: number[]; + styleGuideIds?: number[]; aiPromptId?: number; aiProviderId?: number; aiModelId?: string; @@ -1733,6 +1734,7 @@ export namespace AiModel { sourceLanguageId?: string; tmIds?: number[]; glossaryIds?: number[]; + styleGuideIds?: number[]; aiPromptId?: number; aiProviderId?: number; aiModelId?: string; From 2e5b10137fb80372dad33b1d0a2952d95c1bb082 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Jun 2026 14:26:19 +0300 Subject: [PATCH 3/5] feat(glossaries): add multi-value term filters and exportType to Export Glossary (#682) --- src/glossaries/index.ts | 59 ++++++++++++++++++++++++++++++++++++ tests/glossaries/api.test.ts | 38 +++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/src/glossaries/index.ts b/src/glossaries/index.ts index 0132c85f7..7823f5a1d 100644 --- a/src/glossaries/index.ts +++ b/src/glossaries/index.ts @@ -394,6 +394,39 @@ export namespace GlossariesModel { export interface ExportGlossaryRequest { format?: GlossaryFormat; exportFields?: ExportField[]; + exportType?: ExportType; + text?: string; + caseSensitive?: boolean; + searchStrict?: boolean; + searchFullMatch?: boolean; + statuses?: TermStatus[]; + partsOfSpeech?: TermPartOfSpeech[]; + types?: TermType[]; + genders?: TermGender[]; + authorIds?: number[]; + languageIds?: string[]; + dateFrom?: string; + dateTo?: string; + /** + * @deprecated use `statuses` instead + */ + status?: TermStatus; + /** + * @deprecated use `partsOfSpeech` instead + */ + partOfSpeech?: TermPartOfSpeech; + /** + * @deprecated use `types` instead + */ + type?: TermType; + /** + * @deprecated use `genders` instead + */ + gender?: TermGender; + /** + * @deprecated use `authorIds` instead + */ + authorId?: number; } export interface GlossaryExportStatusAttribute { @@ -486,6 +519,32 @@ export namespace GlossariesModel { export type GlossaryFormat = 'tbx' | 'tbx_v3' | 'csv' | 'xlsx'; + export type ExportType = 'concepts' | 'terms'; + + export type TermStatus = 'PREFERRED' | 'ADMITTED' | 'NOT_RECOMMENDED' | 'OBSOLETE' | 'DRAFT'; + + export type TermPartOfSpeech = + | 'NOUN' + | 'VERB' + | 'ADJ' + | 'PRON' + | 'PROPN' + | 'DET' + | 'ADV' + | 'ADP' + | 'CCONJ' + | 'SCONJ' + | 'NUM' + | 'INTJ' + | 'AUX' + | 'PRT' + | 'SYM' + | 'X'; + + export type TermType = 'FULL_FORM' | 'ACRONYM' | 'ABBREVIATION' | 'SHORT_FORM' | 'PHRASE' | 'VARIANT'; + + export type TermGender = 'MASCULINE' | 'FEMININE' | 'NEUTER' | 'COMMON' | 'OTHER'; + export interface GlossaryFileScheme { [key: string]: number; } diff --git a/tests/glossaries/api.test.ts b/tests/glossaries/api.test.ts index ca9f0fd9f..4f65f9651 100644 --- a/tests/glossaries/api.test.ts +++ b/tests/glossaries/api.test.ts @@ -14,6 +14,7 @@ describe('Glossaries API', () => { const glossaryFormat = 'csv'; const glossaryLink = 'test.com'; const exportId = '1111'; + const exportIdWithFilters = '3333'; const importId = '2222'; const storageId = 1232131; const termId = 5555; @@ -124,6 +125,29 @@ describe('Glossaries API', () => { identifier: exportId, }, }) + .post( + `/glossaries/${glossaryId}/exports`, + { + format: glossaryFormat, + exportType: 'terms', + statuses: ['PREFERRED', 'ADMITTED'], + partsOfSpeech: ['NOUN', 'VERB'], + types: ['ACRONYM'], + genders: ['MASCULINE'], + authorIds: [1, 2], + languageIds: ['uk', 'de'], + }, + { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }, + ) + .reply(200, { + data: { + identifier: exportIdWithFilters, + }, + }) .get(`/glossaries/${glossaryId}/exports/${exportId}/download`, undefined, { reqheaders: { Authorization: `Bearer ${api.token}`, @@ -389,6 +413,20 @@ describe('Glossaries API', () => { expect(exportStatus.data.identifier).toBe(exportId); }); + it('Export glossary with filters', async () => { + const exportStatus = await api.exportGlossary(glossaryId, { + format: glossaryFormat, + exportType: 'terms', + statuses: ['PREFERRED', 'ADMITTED'], + partsOfSpeech: ['NOUN', 'VERB'], + types: ['ACRONYM'], + genders: ['MASCULINE'], + authorIds: [1, 2], + languageIds: ['uk', 'de'], + }); + expect(exportStatus.data.identifier).toBe(exportIdWithFilters); + }); + it('Download glossary', async () => { const link = await api.downloadGlossary(glossaryId, exportId); expect(link.data.url).toBe(glossaryLink); From fbec5d757f09169dd44fdca21602dc04584996ab Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Jun 2026 14:56:03 +0300 Subject: [PATCH 4/5] feat(ai): remove deprecated `assist` action and add context fields (#684) --- src/ai/index.ts | 54 ++++++++++++++++++++++---------------------- tests/ai/api.test.ts | 1 - 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/ai/index.ts b/src/ai/index.ts index 1f850ba48..5740aabd6 100644 --- a/src/ai/index.ts +++ b/src/ai/index.ts @@ -1368,8 +1368,8 @@ export namespace AiModel { enabledProjectIds: number[]; config: | AiModel.AiPromptConfigBasicPreTranslate - | AiModel.AiPromptConfigBasicAssistAction | AiModel.AiPromptConfigBasicAligmentAction + | AiModel.AiPromptConfigBasicQaCheckAction | AiModel.AiPromptConfigAdvanced | AiModel.AiPromptConfigExternal; promptPreview: string; @@ -1407,38 +1407,39 @@ export namespace AiModel { fileContent?: boolean; fileContext?: boolean; screenshots?: boolean; + projectContext?: boolean; + /** + * @deprecated Use `projectContext` instead. + */ publicProjectDescription?: boolean; siblingsStrings?: boolean; + organizationContext?: boolean; } - export interface AiPromptConfigBasicAssistAction { + export interface AiPromptConfigBasicAligmentAction { mode: 'basic'; + customPlaceholders?: string[]; + projectContext?: boolean; /** - * @deprecated - */ - companyDescription?: string; - /** - * @deprecated - */ - projectDescription?: string; - /** - * @deprecated + * @deprecated Use `projectContext` instead. */ - audienceDescription?: string; - otherLanguageTranslations?: AiModel.AiPromptConfigBasicOtherLanguageTranslations; - glossaryTerms?: boolean; - tmSuggestions?: boolean; - fileContext?: boolean; - screenshots?: boolean; publicProjectDescription?: boolean; - siblingsStrings?: boolean; - filteredStrings?: boolean; + organizationContext?: boolean; } - export interface AiPromptConfigBasicAligmentAction { + export interface AiPromptConfigBasicQaCheckAction { mode: 'basic'; - customPlaceholders?: string[]; + evaluationSteps: string[]; + glossaryTerms?: boolean; + tmSuggestions?: boolean; + fileContext?: boolean; + screenshots?: boolean; + projectContext?: boolean; + /** + * @deprecated Use `projectContext` instead. + */ publicProjectDescription?: boolean; + organizationContext?: boolean; } export interface AiPromptConfigAdvanced { @@ -1464,8 +1465,8 @@ export namespace AiModel { enabledProjectIds?: number[]; config: | AiModel.AiPromptConfigBasicPreTranslate - | AiModel.AiPromptConfigBasicAssistAction | AiModel.AiPromptConfigBasicAligmentAction + | AiModel.AiPromptConfigBasicQaCheckAction | AiModel.AiPromptConfigAdvanced | AiPromptConfigExternal; } @@ -1473,8 +1474,8 @@ export namespace AiModel { export interface GenerateAiPromptCompletionRequest { resources: | AiModel.AiPromptResourceWithPreTranslate - | AiModel.AiPromptResourceWithAssist | AiModel.AiPromptResourceWithAlignment + | AiModel.AiPromptResourceWithQaCheck | AiModel.AiPromptResourceWithCustom; tools?: { tool: { @@ -1509,12 +1510,11 @@ export namespace AiModel { overridePromptValues?: OverridePromptValues; } - export interface AiPromptResourceWithAssist { + export interface AiPromptResourceWithQaCheck { projectId: number; sourceLanguageId?: string; targetLanguageId?: string; stringIds?: number[]; - filteredStringsIds?: number[]; overridePromptValues?: OverridePromptValues; } @@ -1582,7 +1582,7 @@ export namespace AiModel { } export interface AiProviderConfigActionRule { - action?: 'pre_translate' | 'assist'; + action?: 'pre_translate' | 'alignment' | 'qa_check'; availableAiModelIds?: string[]; } @@ -1749,7 +1749,7 @@ export namespace AiModel { } /* ai Translate Strings Section END*/ - export type Action = 'pre_translate' | 'assist'; + export type Action = 'pre_translate' | 'alignment' | 'qa_check'; export type ProviderType = | 'open_ai' | 'azure_open_ai' diff --git a/tests/ai/api.test.ts b/tests/ai/api.test.ts index 1eb859894..95b708073 100644 --- a/tests/ai/api.test.ts +++ b/tests/ai/api.test.ts @@ -38,7 +38,6 @@ describe('AI API', () => { projectId, targetLanguageId: 'uk', stringIds: [1], - filteredStringsIds: [1], overridePromptValues: { sourceLanguage: 'English', targetLanguage: 'Ukrainian', From bee628b8e67896af0dd8db64000849402c00f248 Mon Sep 17 00:00:00 2001 From: andrii-bodnar Date: Mon, 15 Jun 2026 12:03:29 +0000 Subject: [PATCH 5/5] chore: version 1.56.0 [skip ci] --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6c27b2758..30321c80c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@crowdin/crowdin-api-client", - "version": "1.55.4", + "version": "1.56.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@crowdin/crowdin-api-client", - "version": "1.55.4", + "version": "1.56.0", "license": "MIT", "dependencies": { "axios": "1.17.0" diff --git a/package.json b/package.json index 1c856239a..b21a0724a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@crowdin/crowdin-api-client", - "version": "1.55.4", + "version": "1.56.0", "description": "JavaScript library for Crowdin API", "main": "out/index.js", "types": "out/index.d.ts",