diff --git a/src/applications/index.ts b/src/applications/index.ts index 97eb10008..776685c8e 100644 --- a/src/applications/index.ts +++ b/src/applications/index.ts @@ -11,7 +11,10 @@ export class Applications extends CrowdinApi { * @param path path implemented by the application * @see https://developer.crowdin.com/api/v2/#operation/api.applications.api.get */ - getApplicationData(applicationId: string, path: string): Promise> { + getApplicationData( + applicationId: string, + path: string, + ): Promise> { const url = `${this.url}/applications/${applicationId}/api/${path}`; return this.get(url, this.defaultConfig()); } @@ -26,7 +29,7 @@ export class Applications extends CrowdinApi { applicationId: string, path: string, request: ApplicationsModel.ApplicationData, - ): Promise> { + ): Promise> { const url = `${this.url}/applications/${applicationId}/api/${path}`; return this.put(url, request, this.defaultConfig()); } @@ -41,7 +44,7 @@ export class Applications extends CrowdinApi { applicationId: string, path: string, request: ApplicationsModel.ApplicationData, - ): Promise> { + ): Promise> { const url = `${this.url}/applications/${applicationId}/api/${path}`; return this.post(url, request, this.defaultConfig()); } @@ -66,7 +69,7 @@ export class Applications extends CrowdinApi { applicationId: string, path: string, request: ApplicationsModel.ApplicationData, - ): Promise> { + ): Promise> { const url = `${this.url}/applications/${applicationId}/api/${path}`; return this.patch(url, request, this.defaultConfig()); } diff --git a/src/bundles/index.ts b/src/bundles/index.ts index 894d4171f..ac8b2d250 100644 --- a/src/bundles/index.ts +++ b/src/bundles/index.ts @@ -114,15 +114,30 @@ export class Bundles extends CrowdinApi { projectId: number, bundleId: number, options?: PaginationOptions, - ): Promise> { + ): Promise> { const url = `${this.url}/projects/${projectId}/bundles/${bundleId}/files`; return this.getList(url, options?.limit, options?.offset); } + + /** + * @param projectId project identifier + * @param bundleId bundle identifier + * @param options optional parameters for the request + */ + listBundleBranches( + projectId: number, + bundleId: number, + options?: PaginationOptions, + ): Promise> { + const url = `${this.url}/projects/${projectId}/bundles/${bundleId}/branches`; + return this.getList(url, options?.limit, options?.offset); + } } export namespace BundlesModel { export interface Bundle { id: number; + name: string; format: string; sourcePatterns: string[]; ignorePatterns: string[]; @@ -130,6 +145,7 @@ export namespace BundlesModel { isMultilingual: boolean; includeProjectSourceLanguage: boolean; labelIds: number[]; + excludeLabelIds: number[]; createdAt: string; updatedAt: string; } @@ -143,18 +159,7 @@ export namespace BundlesModel { isMultilingual?: boolean; includeProjectSourceLanguage?: boolean; labelIds?: number[]; - } - - export interface BundleFile { - id: number; - projectId: number; - branchId: number; - directoryId: number; - name: string; - title: string; - type: SourceFilesModel.FileType; - path: string; - status: string; + excludeLabelIds?: number[]; } export interface ExportAttributes { diff --git a/src/clients/index.ts b/src/clients/index.ts new file mode 100644 index 000000000..ed9e90960 --- /dev/null +++ b/src/clients/index.ts @@ -0,0 +1,27 @@ +import { CrowdinApi, PaginationOptions, ResponseList } from '../core'; + +/** + * Clients are the organizations that order professional translation services from Vendors. + * Clients can invite an existing organization to become a Vendor for them. + * + * Use the API to get a list of the Clients you already cooperate with as a Vendor. + */ +export class Clients extends CrowdinApi { + /** + * @param options optional pagination parameters for the request + * @see https://developer.crowdin.com/enterprise/api/v2/#operation/api.clients.getMany + */ + listClients(options?: PaginationOptions): Promise> { + const url = `${this.url}/clients`; + return this.getList(url, options?.limit, options?.offset); + } +} + +export namespace ClientsModel { + export interface Client { + id: number; + name: string; + description: string; + status: 'pending' | 'confirmed' | 'rejected'; + } +} diff --git a/src/distributions/index.ts b/src/distributions/index.ts index 2fe2a69e9..4384ba4d2 100644 --- a/src/distributions/index.ts +++ b/src/distributions/index.ts @@ -41,7 +41,9 @@ export class Distributions extends CrowdinApi { */ createDistribution( projectId: number, - request: DistributionsModel.CreateDistributionRequest, + request: + | DistributionsModel.CreateDistributionRequest + | DistributionsModel.CreateDistributionStringsBasedRequest, ): Promise> { const url = `${this.url}/projects/${projectId}/distributions`; return this.post(url, request, this.defaultConfig()); @@ -90,7 +92,9 @@ export class Distributions extends CrowdinApi { getDistributionRelease( projectId: number, hash: string, - ): Promise> { + ): Promise< + ResponseObject + > { const url = `${this.url}/projects/${projectId}/distributions/${hash}/release`; return this.get(url, this.defaultConfig()); } @@ -104,7 +108,9 @@ export class Distributions extends CrowdinApi { createDistributionRelease( projectId: number, hash: string, - ): Promise> { + ): Promise< + ResponseObject + > { const url = `${this.url}/projects/${projectId}/distributions/${hash}/release`; return this.post(url, {}, this.defaultConfig()); } @@ -143,6 +149,11 @@ export namespace DistributionsModel { labelIds?: number[]; } + export interface CreateDistributionStringsBasedRequest { + name: string; + bundleIds: number[]; + } + export interface DistributionRelease { status: string; progress: number; @@ -151,5 +162,13 @@ export namespace DistributionsModel { date: string; } + export interface DistributionStringsBasedRelease { + status: string; + progress: number; + currentLanguageId: string; + currentBranchId: number; + date: string; + } + export type ExportMode = 'default' | 'bundle'; } diff --git a/src/glossaries/index.ts b/src/glossaries/index.ts index c0a88de69..ad6b6b531 100644 --- a/src/glossaries/index.ts +++ b/src/glossaries/index.ts @@ -433,6 +433,7 @@ export namespace GlossariesModel { type?: Type; gender?: Gender; note?: string; + url?: string; conceptId?: number; } diff --git a/src/index.ts b/src/index.ts index 78c9149d5..c5506bc01 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ import { Applications } from './applications'; import { Bundles } from './bundles'; +import { Clients } from './clients'; import { ClientConfig, Credentials, CrowdinApi } from './core'; import { Dictionaries } from './dictionaries'; import { Distributions } from './distributions'; @@ -30,6 +31,7 @@ import { Workflows } from './workflows'; export * from './applications'; export * from './bundles'; +export * from './clients'; export * from './core'; export * from './dictionaries'; export * from './distributions'; @@ -93,6 +95,7 @@ export default class Client extends CrowdinApi { readonly stringCommentsApi: StringComments; readonly bundlesApi: Bundles; readonly notificationsApi: Notifications; + readonly clientsApi: Clients; constructor(credentials: Credentials, config?: ClientConfig) { super(credentials, config); @@ -124,5 +127,6 @@ export default class Client extends CrowdinApi { this.stringCommentsApi = new StringComments(credentials, config); this.bundlesApi = new Bundles(credentials, config); this.notificationsApi = new Notifications(credentials, config); + this.clientsApi = new Clients(credentials, config); } } diff --git a/src/labels/index.ts b/src/labels/index.ts index 62e4126cf..4d6ff9482 100644 --- a/src/labels/index.ts +++ b/src/labels/index.ts @@ -8,7 +8,7 @@ export class Labels extends CrowdinApi { * @param options optional pagination parameters for the request * @see https://developer.crowdin.com/api/v2/#operation/api.projects.labels.getMany */ - listLabels(projectId: number, options?: PaginationOptions): Promise>; + listLabels(projectId: number, options?: LabelsModel.ListLabelsParams): Promise>; /** * @param projectId project identifier * @param limit maximum number of items to retrieve (default 25) @@ -19,13 +19,14 @@ export class Labels extends CrowdinApi { listLabels(projectId: number, limit?: number, offset?: number): Promise>; listLabels( projectId: number, - options?: number | PaginationOptions, + options?: number | LabelsModel.ListLabelsParams, deprecatedOffset?: number, ): Promise> { if (isOptionalNumber(options, '1' in arguments)) { options = { limit: options, offset: deprecatedOffset }; } - const url = `${this.url}/projects/${projectId}/labels`; + let url = `${this.url}/projects/${projectId}/labels`; + url = this.addQueryParam(url, 'isSystem', options.isSystem); return this.getList(url, options.limit, options.offset); } @@ -134,9 +135,14 @@ export class Labels extends CrowdinApi { } export namespace LabelsModel { + export interface ListLabelsParams extends PaginationOptions { + isSystem?: number; + } + export interface Label { id: number; title: string; + isSystem: boolean; } export interface AddLabelRequest { diff --git a/src/machineTranslation/index.ts b/src/machineTranslation/index.ts index 1adc921d2..9315bb565 100644 --- a/src/machineTranslation/index.ts +++ b/src/machineTranslation/index.ts @@ -103,17 +103,29 @@ export namespace MachineTranslationModel { type: number; credentials: Credentials; projectIds: number[]; + supportedLanguageIds: string[]; + supportedLanguagePairs: Record; + enabledLanguageIds: string[]; + enabledProjectIds: number[]; + isEnabled: boolean; } - export interface Credentials { - [key: string]: number; - } + export type Credentials = + | { apiKey: string } + | { credentials: string } + | { model: string; apiKey: string } + | { endpoint: string; apiKey: string } + | { url: string } + | { accessKey: string; secretKey: string }; export interface CreateMachineTranslationRequest { name: string; groupId?: number; type: string; - credentials: string[]; + credentials: Credentials; + enabledLanguageIds?: string[]; + enabledProjectIds?: number[]; + isEnabled?: boolean; } export interface TranslateRequest { diff --git a/src/notifications/index.ts b/src/notifications/index.ts index 4b6db6b74..1a140ef77 100644 --- a/src/notifications/index.ts +++ b/src/notifications/index.ts @@ -28,7 +28,10 @@ export class Notifications extends CrowdinApi { * @see https://developer.crowdin.com/enterprise/api/v2/#operation/api.notify.post */ sendNotificationToOrganizationMembers( - request: NotificationsModel.NotificationByUsers | NotificationsModel.NotificationByRole, + request: + | NotificationsModel.Notification + | NotificationsModel.NotificationByUsers + | NotificationsModel.NotificationByRole, ): Promise { const url = `${this.url}/notify`; return this.post(url, request, this.defaultConfig()); diff --git a/src/organizationWebhooks/index.ts b/src/organizationWebhooks/index.ts index 28c0c5058..a0425c82d 100644 --- a/src/organizationWebhooks/index.ts +++ b/src/organizationWebhooks/index.ts @@ -1,4 +1,5 @@ import { CrowdinApi, PaginationOptions, PatchRequest, ResponseList, ResponseObject } from '../core'; +import { WebhooksModel } from '../webhooks'; /** * Webhooks allow you to collect information about events that happen in your Crowdin account. @@ -10,7 +11,7 @@ export class OrganizationWebhooks extends CrowdinApi { * @param options optional pagination parameters for the request * @see https://developer.crowdin.com/api/v2/#operation/api.webhooks.getMany */ - listWebhooks(options?: PaginationOptions): Promise> { + listWebhooks(options?: PaginationOptions): Promise> { const url = `${this.url}/webhooks`; return this.getList(url, options?.limit, options?.offset); } @@ -19,9 +20,7 @@ export class OrganizationWebhooks extends CrowdinApi { * @param request request body * @see https://developer.crowdin.com/api/v2/#operation/api.webhooks.post */ - addWebhook( - request: OrganizationWebhooksModel.AddWebhookRequest, - ): Promise> { + addWebhook(request: WebhooksModel.AddWebhookRequest): Promise> { const url = `${this.url}/webhooks`; return this.post(url, request, this.defaultConfig()); } @@ -30,7 +29,7 @@ export class OrganizationWebhooks extends CrowdinApi { * @param webhookId webhook identifier * @see https://developer.crowdin.com/api/v2/#operation/api.webhooks.get */ - getWebhook(webhookId: number): Promise> { + getWebhook(webhookId: number): Promise> { const url = `${this.url}/webhooks/${webhookId}`; return this.get(url, this.defaultConfig()); } @@ -49,46 +48,8 @@ export class OrganizationWebhooks extends CrowdinApi { * @param request request body * @see https://developer.crowdin.com/api/v2/#operation/api.webhooks.patch */ - editWebhook( - webhookId: number, - request: PatchRequest[], - ): Promise> { + editWebhook(webhookId: number, request: PatchRequest[]): Promise> { const url = `${this.url}/webhooks/${webhookId}`; return this.patch(url, request, this.defaultConfig()); } } - -export namespace OrganizationWebhooksModel { - export interface Webhook { - id: number; - name: string; - url: string; - events: Event[]; - headers: string[]; - payload: string[]; - isActive: boolean; - batchingEnabled: boolean; - requestType: RequestType; - contentType: ContentType; - createdAt: string; - updatedAt: string; - } - - export interface AddWebhookRequest { - name: string; - url: string; - isActive?: boolean; - batchingEnabled?: boolean; - contentType?: ContentType; - events: Event[]; - headers?: Record; - requestType: RequestType; - payload?: any; - } - - export type ContentType = 'multipart/form-data' | 'application/json' | 'application/x-www-form-urlencoded'; - - export type Event = 'project.created' | 'project.deleted' | 'group.created' | 'group.deleted'; - - export type RequestType = 'POST' | 'GET'; -} diff --git a/src/projectsGroups/index.ts b/src/projectsGroups/index.ts index 6a35ef43d..88b398bff 100644 --- a/src/projectsGroups/index.ts +++ b/src/projectsGroups/index.ts @@ -360,6 +360,7 @@ export namespace ProjectsGroupsModel { export interface Project { id: number; + type?: Type; groupId: number; userId: number; sourceLanguageId: string; @@ -380,6 +381,7 @@ export namespace ProjectsGroupsModel { createdAt: string; updatedAt: string; lastActivity: string; + sourceLanguage: LanguagesModel.Language; targetLanguages: LanguagesModel.Language[]; } @@ -393,9 +395,9 @@ export namespace ProjectsGroupsModel { languageAccessPolicy?: LanguageAccessPolicy; cname?: string; description?: string; - translateDuplicates?: TranslateDuplicates; tagDetection?: TagDetection; isMtAllowed?: boolean; + taskBasedAccessControl?: boolean; autoSubstitution?: boolean; autoTranslateDialects?: boolean; publicDownloads?: boolean; @@ -413,8 +415,9 @@ export namespace ProjectsGroupsModel { qaChecksIgnorableCategories?: CheckCategories; languageMapping?: LanguageMapping; glossaryAccess?: boolean; - notificationSettings?: NotificationSettings; normalizePlaceholder?: boolean; + notificationSettings?: NotificationSettings; + tmContextType?: TmContextType; saveMetaInfoInSource?: boolean; } @@ -431,6 +434,7 @@ export namespace ProjectsGroupsModel { translateDuplicates?: TranslateDuplicates; tagsDetection?: TagDetection; isMtAllowed?: boolean; + taskBasedAccessControl?: boolean; autoSubstitution?: boolean; autoTranslateDialects?: boolean; publicDownloads?: boolean; @@ -440,21 +444,21 @@ export namespace ProjectsGroupsModel { skipUntranslatedStrings?: boolean; skipUntranslatedFiles?: boolean; exportApprovedOnly?: boolean; - inContext?: boolean; - inContextProcessHiddenStrings?: boolean; - inContextPseudoLanguageId?: string; qaCheckIsActive?: boolean; qaCheckCategories?: CheckCategories; qaChecksIgnorableCategories?: CheckCategories; languageMapping?: LanguageMapping; glossaryAccess?: boolean; notificationSettings?: NotificationSettings; + normalizePlaceholder?: boolean; + tmContextType?: TmContextType; } export interface CreateProjectEnterpriseRequest { name: string; sourceLanguageId: string; templateId?: number; + steps?: WorkflowTemplateStepConfig[]; groupId?: number; targetLanguageIds?: string[]; vendorId?: number; @@ -463,6 +467,7 @@ export namespace ProjectsGroupsModel { translateDuplicates?: TranslateDuplicates; tagsDetection?: TagDetection; isMtAllowed?: boolean; + taskBasedAccessControl?: boolean; autoSubstitution?: boolean; showTmSuggestionsDialects?: boolean; autoTranslateDialects?: boolean; @@ -479,19 +484,23 @@ export namespace ProjectsGroupsModel { inContextProcessHiddenStrings?: boolean; inContextPseudoLanguageId?: string; qaCheckIsActive?: boolean; + qaApprovalsCount?: number; qaCheckCategories?: CheckCategories; qaChecksIgnorableCategories?: CheckCategories; customQaCheckIds?: number[]; + tmContextType?: TmContextType; languageMapping?: LanguageMapping; - notificationSettings?: NotificationSettings; glossaryAccess?: boolean; + notificationSettings?: NotificationSettings; } export interface ProjectSettings extends Project { + clientOrganizationId?: number; translateDuplicates: TranslateDuplicates; tagsDetection: TagDetection; glossaryAccess: boolean; isMtAllowed: boolean; + taskBasedAccessControl: boolean; hiddenStringsProofreadersAccess: boolean; autoSubstitution: boolean; exportTranslatedOnly: boolean; @@ -503,6 +512,7 @@ export namespace ProjectsGroupsModel { autoTranslateDialects: boolean; showTmSuggestionsDialects: boolean; useGlobalTm: boolean; + tmContextType: TmContextType; normalizePlaceholder: boolean; saveMetaInfoInSource: boolean; inContext: boolean; @@ -511,6 +521,7 @@ export namespace ProjectsGroupsModel { inContextPseudoLanguage: LanguagesModel.Language; isSuspended: boolean; qaCheckIsActive: boolean; + qaApprovalsCount: number; qaCheckCategories: CheckCategories; qaChecksIgnorableCategories: CheckCategories; customQaCheckIds: number[]; @@ -521,6 +532,22 @@ export namespace ProjectsGroupsModel { defaultGlossaryId: number; assignedGlossaries: number[]; assignedTms: { [id: string]: { priority: number } }; + tmPenalties: { + autoSubstitution: number; + tmPriority: { + priority: number; + penalty: number; + }; + multipleTranslations: number; + timeSinceLastUsage: { + months: number; + penalty: number; + }; + timeSinceLastModified: { + months: number; + penalty: number; + }; + }; } export enum Type { @@ -600,6 +627,12 @@ export namespace ProjectsGroupsModel { | PropertyFileFormatSettings | CommonFileFormatSettings | XmlFileFormatSettings + | MdxV2FormatSettings + | FmHtmlFormatSettings + | HtmlFormatSettings + | JsonFormatSettings + | MdxV1FormatSettings + | JavaScriptFileFormatSettings | DocxFileFormatSettings; export interface ProjectFileFormatSettings { @@ -623,6 +656,11 @@ export namespace ProjectsGroupsModel { exportPattern?: string; } + export interface JavaScriptFileFormatSettings { + exportPattern?: 'string'; + exportQuotes?: 'single' | 'double'; + } + export interface CommonFileFormatSettings { contentSegmentation?: boolean; srxStorageId?: number; @@ -635,6 +673,30 @@ export namespace ProjectsGroupsModel { translatableElements?: string[]; } + export interface JsonFormatSettings extends CommonFileFormatSettings { + type?: 'i18next_json' | 'nestjs_i18n'; + } + + export interface MdxV2FormatSettings extends CommonFileFormatSettings { + excludeCodeBlocks?: boolean; + excludedFrontMatterElements?: string[]; + } + + export interface MdxV1FormatSettings extends CommonFileFormatSettings { + excludeCodeBlocks?: boolean; + excludedFrontMatterElements?: string[]; + type?: 'mdx_v1' | 'mdx_v2'; + } + + export interface FmHtmlFormatSettings extends CommonFileFormatSettings { + excludedElements?: boolean; + excludedFrontMatterElements?: string[]; + } + + export interface HtmlFormatSettings extends CommonFileFormatSettings { + excludedElements?: boolean; + } + export interface DocxFileFormatSettings extends CommonFileFormatSettings { cleanTagsAggressively?: boolean; translateHiddenText?: boolean; @@ -644,6 +706,41 @@ export namespace ProjectsGroupsModel { importHiddenSlides?: boolean; } + export type TmContextType = 'segmentContext' | 'auto' | 'prevAndNextSegment'; + + export type WorkflowTemplateStepConfig = + | WorkflowTemplateStepConfigTranslateProofread + | WorkflowTemplateStepConfigVendor + | WorkflowTemplateStepConfigTMPreTranslate + | WorkflowTemplateStepConfigMTPreTranslate; + + export interface WorkflowTemplateStepConfigTranslateProofread { + id: number; + languages?: string[]; + assignees?: number[]; + } + + export interface WorkflowTemplateStepConfigVendor { + id: number; + languages?: string[]; + vendorId?: number; + } + + export interface WorkflowTemplateStepConfigTMPreTranslate { + id: number; + languages?: string[]; + config?: { + minRelevant?: number; + autoSubstitution?: boolean; + }; + } + + export interface WorkflowTemplateStepConfigMTPreTranslate { + id: number; + languages?: string[]; + mtId?: number; + } + export type StringsExporterSettings = | AndroidStringsExporterSettings | MacOSXStringsExporterSettings diff --git a/src/reports/index.ts b/src/reports/index.ts index e9d643d25..d409eac07 100644 --- a/src/reports/index.ts +++ b/src/reports/index.ts @@ -57,8 +57,8 @@ export class Reports extends CrowdinApi { * @see https://support.crowdin.com/enterprise/api/#operation/api.reports.post */ generateOrganizationReport( - request: ReportsModel.GenerateGroupReportRequest, - ): Promise>>> { + request: ReportsModel.GenerateOrganizationReportRequest, + ): Promise>>> { const url = `${this.url}/reports`; return this.post(url, request, this.defaultConfig()); } @@ -69,7 +69,7 @@ export class Reports extends CrowdinApi { */ checkOrganizationReportStatus( reportId: string, - ): Promise>>> { + ): Promise>>> { const url = `${this.url}/reports/${reportId}`; return this.get(url, this.defaultConfig()); } @@ -187,14 +187,24 @@ export class Reports extends CrowdinApi { export namespace ReportsModel { export type GroupReportSchema = | GroupTranslationCostsPerEditingSchema + | GroupTranslationCostsPerEditingByTaskSchema + | CostsEstimationSchema + | CostsEstimationByTaskSchema | GroupTranslationCostSchema | GroupTopMembersSchema; + export type OrganizationReportSchema = GroupTranslationCostsPerEditingSchema | GroupTopMembersSchema; + export interface GenerateGroupReportRequest { name: string; schema: GroupReportSchema; } + export interface GenerateOrganizationReportRequest { + name: string; + schema: OrganizationReportSchema; + } + export interface GroupTranslationCostsPerEditingSchema { projectIds?: number[]; unit?: Unit; @@ -206,7 +216,51 @@ export namespace ReportsModel { groupBy?: GroupBy; dateFrom?: string; dateTo?: string; + languageId?: string[]; userIds?: number[]; + branchIds?: number[]; + labelIds?: number[]; + labelIncludeType?: LabelIncludeType; + } + + export interface GroupTranslationCostsPerEditingByTaskSchema { + unit?: Unit; + currency?: Currency; + format?: Format; + baseRates: BaseRate; + individualRates: IndividualRate[]; + netRateSchemes: NetRateSchemas; + taskId?: number; + } + + export interface CostsEstimationSchema { + projectIds?: number[]; + unit?: Unit; + currency?: Currency; + format?: Format; + baseRates: BaseRate; + individualRates: IndividualRate[]; + netRateSchemes: NetRateSchemas; + calculateInternalMatches?: boolean; + includePreTranslatedStrings?: boolean; + languageId?: string; + branchIds?: number[]; + dateFrom?: string; + dateTo?: string; + labelIds?: number[]; + labelIncludeType?: LabelIncludeType; + } + + export interface CostsEstimationByTaskSchema { + unit?: Unit; + currency?: Currency; + format?: Format; + baseRates?: BaseRate; + individualRates?: IndividualRate[]; + netRateSchemes?: NetRateSchemas; + calculateInternalMatches?: boolean; + includePreTranslatedStrings?: boolean; + taskId?: number; } export interface GroupTopMembersSchema { @@ -219,6 +273,15 @@ export namespace ReportsModel { dateTo?: string; } + export interface RawDataSchema { + mode: ContributionMode; + unit?: Unit; + languageId?: string; + userId?: number; + dateFrom?: string; + dateTo?: string; + } + export type ReportSchema = | CostEstimationPostEndingSchema | CostEstimationPostEndingSchemaByTask @@ -244,6 +307,7 @@ export namespace ReportsModel { export interface ReportStatusAttributes { format: Format; reportName: string; + projectIds?: number[]; schema: S; } @@ -384,11 +448,11 @@ export namespace ReportsModel { matchType: Mode; price: number; }[]; - mtMatch: { + mtMatch?: { matchType: Mode; price: number; }[]; - suggestionMatch: { + suggestionMatch?: { matchType: Mode; price: number; }[]; diff --git a/src/sourceStrings/index.ts b/src/sourceStrings/index.ts index b398c688f..1a6ca8acf 100644 --- a/src/sourceStrings/index.ts +++ b/src/sourceStrings/index.ts @@ -6,7 +6,9 @@ import { PatchRequest, ResponseList, ResponseObject, + Status, } from '../core'; +import { SourceFilesModel } from '../sourceFiles'; /** * Source strings are the text units for translation. Instead of modifying source files, you can manage source strings one by one. @@ -14,6 +16,30 @@ import { * Use API to add, edit, or delete some specific strings in the source-based and files-based projects. */ export class SourceStrings extends CrowdinApi { + /** + * @param projectId project identifier + * @param uploadId export identifier + */ + uploadStringsStatus( + projectId: number, + uploadId: string, + ): Promise>> { + const url = `${this.url}/projects/${projectId}/strings/uploads/${uploadId}`; + return this.get(url, this.defaultConfig()); + } + + /** + * @param projectId project identifier + * @param request request payload + */ + uploadStrings( + projectId: number, + request: SourceStringsModel.UploadStringsRequest, + ): Promise>> { + const url = `${this.url}/projects/${projectId}/strings/uploads`; + return this.post(url, request, this.defaultConfig()); + } + /** * @param projectId project identifier * @param options optional parameters for the request @@ -97,7 +123,7 @@ export class SourceStrings extends CrowdinApi { */ addString( projectId: number, - request: SourceStringsModel.CreateStringRequest, + request: SourceStringsModel.CreateStringRequest | SourceStringsModel.CreateStringStringsBasedRequest, ): Promise> { const url = `${this.url}/projects/${projectId}/strings`; return this.post(url, request, this.defaultConfig()); @@ -119,10 +145,16 @@ export class SourceStrings extends CrowdinApi { /** * @param projectId project identifier * @param stringId string identifier + * @param query query params * @see https://developer.crowdin.com/api/v2/#operation/api.projects.strings.get */ - getString(projectId: number, stringId: number): Promise> { - const url = `${this.url}/projects/${projectId}/strings/${stringId}`; + getString( + projectId: number, + stringId: number, + query?: { denormalizePlaceholders: BooleanInt }, + ): Promise> { + let url = `${this.url}/projects/${projectId}/strings/${stringId}`; + url = this.addQueryParam(url, 'denormalizePlaceholders', query?.denormalizePlaceholders); return this.get(url, this.defaultConfig()); } @@ -153,6 +185,45 @@ export class SourceStrings extends CrowdinApi { } export namespace SourceStringsModel { + export type UploadStringsType = + | 'auto' + | 'android' + | 'macosx' + | 'arb' + | 'csv' + | 'json' + | 'xliff' + | 'xliff_two' + | 'xlsx'; + + export interface UploadStringsStatus { + branchId: number; + storageId: number; + fileType: UploadStringsType; + parserVersion: number; + labelIds: number[]; + importOptions: { + firstLineContainsHeader: boolean; + importTranslations: boolean; + scheme: SourceFilesModel.Scheme; + }; + } + + export interface UploadStringsRequest { + branchId: number; + storageId: number; + type?: UploadStringsType; + parserVersion?: number; + labelIds?: number[]; + updateStrings?: boolean; + cleanupMode?: boolean; + importOptions?: { + firstLineContainsHeader: boolean; + importTranslations: boolean; + scheme: SourceFilesModel.Scheme; + }; + } + export interface ListProjectStringsOptions extends PaginationOptions { fileId?: number; filter?: string; @@ -195,6 +266,16 @@ export namespace SourceStringsModel { labelIds?: number[]; } + export interface CreateStringStringsBasedRequest { + text: string | PluralText; + identifier: string; + branchId: number; + context?: string; + isHidden?: boolean; + maxLength?: number; + labelIds?: number[]; + } + export interface PluralText { zero?: string; one?: string; diff --git a/src/stringTranslations/index.ts b/src/stringTranslations/index.ts index 3f56c3eb5..e7f3d6257 100644 --- a/src/stringTranslations/index.ts +++ b/src/stringTranslations/index.ts @@ -309,7 +309,7 @@ export class StringTranslations extends CrowdinApi { projectId: number, translationId: number, ): Promise> { - const url = `${this.url}/projects/${projectId}/translations/${translationId}/restore`; + const url = `${this.url}/projects/${projectId}/translations/${translationId}`; return this.put(url, {}, this.defaultConfig()); } @@ -434,7 +434,6 @@ export namespace StringTranslationsModel { translationId: number; stringId: number; languageId: string; - workflowStepId: number; createdAt: string; } @@ -445,9 +444,11 @@ export namespace StringTranslationsModel { export interface StringTranslation { id: number; text: string; - pluralCategoryName: string; + pluralCategoryName: PluralCategoryName; user: User; rating: number; + provider: string; + isPreTranslated: boolean; createdAt: string; } @@ -515,7 +516,7 @@ export namespace StringTranslationsModel { stringId: number; languageId: string; text: string; - pluralCategoryName?: string; + pluralCategoryName?: PluralCategoryName; } export interface ListTranslationVotesOptions extends PaginationOptions { @@ -551,4 +552,6 @@ export namespace StringTranslationsModel { export interface ListStringTranslationsOptions extends PaginationOptions { denormalizePlaceholders?: BooleanInt; } + + export type PluralCategoryName = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other'; } diff --git a/src/tasks/index.ts b/src/tasks/index.ts index ad40f3c51..5b53f71cb 100644 --- a/src/tasks/index.ts +++ b/src/tasks/index.ts @@ -8,6 +8,7 @@ import { ResponseList, ResponseObject, } from '../core'; +import { LanguagesModel } from '../languages'; /** * Create and assign tasks to get files translated or proofread by specific people. @@ -48,6 +49,7 @@ export class Tasks extends CrowdinApi { } let url = `${this.url}/projects/${projectId}/tasks`; url = this.addQueryParam(url, 'status', options.status); + url = this.addQueryParam(url, 'assigneeId', options.assigneeId); return this.getList(url, options.limit, options.offset); } @@ -60,12 +62,21 @@ export class Tasks extends CrowdinApi { projectId: number, request: | TasksModel.CreateTaskEnterpriseRequest + | TasksModel.CreateTaskEnterpriseVendorRequest + | TasksModel.CreateTaskEnterpriseStringsBasedRequest + | TasksModel.CreateTaskEnterpriseVendorStringsBasedRequest | TasksModel.CreateTaskRequest + | TasksModel.CreateTaskStringsBasedRequest | TasksModel.CreateLanguageServiceTaskRequest + | TasksModel.CreateLanguageServiceTaskStringsBasedRequest | TasksModel.CreateTaskVendorOhtRequest + | TasksModel.CreateTaskVendorOhtStringsBasedRequest | TasksModel.CreateTaskVendorGengoRequest + | TasksModel.CreateTaskVendorGengoStringsBasedRequest | TasksModel.CreateTaskVendorTranslatedRequest - | TasksModel.CreateTaskVendorManualRequest, + | TasksModel.CreateTaskVendorTranslatedStringsBasedRequest + | TasksModel.CreateTaskVendorManualRequest + | TasksModel.CreateTaskVendorManualStringsBasedRequest, ): Promise> { const url = `${this.url}/projects/${projectId}/tasks`; return this.post(url, request, this.defaultConfig()); @@ -261,6 +272,9 @@ export namespace TasksModel { buyUrl: string; createdAt: string; updatedAt: string; + sourceLanguage: LanguagesModel.Language; + targetLanguages: LanguagesModel.Language[]; + branchIds: number[]; } export interface ListUserTasksOptions extends PaginationOptions { @@ -285,13 +299,27 @@ export namespace TasksModel { } export interface CreateTaskEnterpriseRequest extends CreateTaskBase { - type?: Type; - workflowStepId?: number; + type: Type; + workflowStepId: number; + /** + * @deprecated + */ splitFiles?: boolean; + splitContent?: boolean; skipAssignedStrings?: boolean; assignees?: CreateTaskAssignee[]; + assignedTeams?: AssignedTeam[]; includePreTranslatedStringsOnly?: boolean; deadline?: string; + startedAt?: string; + } + + export interface CreateTaskEnterpriseVendorRequest extends CreateTaskBase { + workflowStepId: number; + skipAssignedStrings?: boolean; + includePreTranslatedStringsOnly?: boolean; + deadline?: string; + startedAt?: string; } export interface CreateTaskRequest extends CreateTaskBase { @@ -352,6 +380,36 @@ export namespace TasksModel { startedAt?: string; } + export type CreateTaskEnterpriseVendorStringsBasedRequest = Omit & { + branchIds: number[]; + }; + + export type CreateTaskEnterpriseStringsBasedRequest = Omit & { + branchIds: number[]; + }; + + export type CreateTaskStringsBasedRequest = Omit & { branchIds: number[] }; + + export type CreateTaskVendorManualStringsBasedRequest = Omit & { + branchIds: number[]; + }; + + export type CreateTaskVendorTranslatedStringsBasedRequest = Omit & { + branchIds: number[]; + }; + + export type CreateTaskVendorGengoStringsBasedRequest = Omit & { + branchIds: number[]; + }; + + export type CreateTaskVendorOhtStringsBasedRequest = Omit & { + branchIds: number[]; + }; + + export type CreateLanguageServiceTaskStringsBasedRequest = Omit & { + branchIds: number[]; + }; + export interface CreateTaskAssignee { id: number; wordsCount?: number; @@ -471,6 +529,7 @@ export namespace TasksModel { export interface ListTasksOptions extends PaginationOptions { status?: TasksModel.Status; + assigneeId?: number; } export interface TaskSettingsTemplate { @@ -487,6 +546,6 @@ export namespace TasksModel { } export interface TaskSettingsTemplateConfig { - languages: { languageId: string; userIds: number[]; teamIds?: number[] }[]; + languages: { languageId?: string; userIds?: number[]; teamIds?: number[] }[]; } } diff --git a/src/teams/index.ts b/src/teams/index.ts index 7c1607daf..5735632dd 100644 --- a/src/teams/index.ts +++ b/src/teams/index.ts @@ -147,6 +147,7 @@ export namespace TeamsModel { */ accessToAllWorkflowSteps?: boolean; managerAccess?: boolean; + developerAccess?: boolean; /** * @deprecated */ @@ -162,6 +163,7 @@ export namespace TeamsModel { export interface ProjectTeamResource { id: number; hasManagerAccess: boolean; + hasDeveloperAccess: boolean; /** * @deprecated */ diff --git a/src/translationMemory/index.ts b/src/translationMemory/index.ts index 6d7b3c22b..9dea2c52a 100644 --- a/src/translationMemory/index.ts +++ b/src/translationMemory/index.ts @@ -47,6 +47,7 @@ export class TranslationMemory extends CrowdinApi { } let url = `${this.url}/tms`; url = this.addQueryParam(url, 'groupId', options.groupId); + url = this.addQueryParam(url, 'userId', options.userId); return this.getList(url, options.limit, options.offset); } @@ -217,6 +218,22 @@ export class TranslationMemory extends CrowdinApi { } /** + * @param tmId tm identifier + * @param segmentId segment identifier + * @param request request body + * @see https://developer.crowdin.com/api/v2/#operation/api.tms.segments.patch + */ + editTmSegment( + tmId: number, + segmentId: number, + request: PatchRequest[], + ): Promise> { + const url = `${this.url}/tms/${tmId}/segments/${segmentId}`; + return this.patch(url, request, this.defaultConfig()); + } + + /** + * @deprecated * @param tmId tm identifier * @param segmentId segment identifier * @param recordId record identifier @@ -228,6 +245,7 @@ export class TranslationMemory extends CrowdinApi { } /** + * @deprecated * @param tmId tm identifier * @param segmentId segment identifier * @param recordId record identifier @@ -245,6 +263,7 @@ export class TranslationMemory extends CrowdinApi { } /** + * @deprecated * @param tmId tm identifier * @param segmentId segment identifier * @param request request body @@ -286,7 +305,11 @@ export namespace TranslationMemoryModel { targetLanguageId: string; autoSubstitution: boolean; minRelevant: number; - expression: string; + expressions: string[]; + /** + * @deprecated + */ + expression?: string; } export interface ConcordanceSearchResponse { @@ -332,6 +355,7 @@ export namespace TranslationMemoryModel { export interface ListTMsOptions extends PaginationOptions { groupId?: number; + userId?: number; } export interface TMSegment { diff --git a/src/translationStatus/index.ts b/src/translationStatus/index.ts index c847c496e..116e17165 100644 --- a/src/translationStatus/index.ts +++ b/src/translationStatus/index.ts @@ -1,4 +1,5 @@ import { CrowdinApi, isOptionalNumber, PaginationOptions, ResponseList } from '../core'; +import { LanguagesModel } from '../languages'; /** * Status represents the general localization progress on both translations and proofreading. @@ -249,20 +250,28 @@ export class TranslationStatus extends CrowdinApi { export namespace TranslationStatusModel { export interface LanguageProgress { - languageId: string; words: Words; phrases: Words; translationProgress: number; approvalProgress: number; eTag: string; + languageId: string; + language: LanguagesModel.Language; } export interface FileProgress { - fileId: number; words: Words; phrases: Words; translationProgress: number; approvalProgress: number; + /** + * for strings-based projects + */ + branchId: number; + /** + * for non strings-based projects + */ + fileId: number; eTag: string; } diff --git a/src/translations/index.ts b/src/translations/index.ts index d81ca772d..69a008cb0 100644 --- a/src/translations/index.ts +++ b/src/translations/index.ts @@ -35,7 +35,7 @@ export class Translations extends CrowdinApi { */ applyPreTranslation( projectId: number, - request: TranslationsModel.PreTranslateRequest, + request: TranslationsModel.PreTranslateRequest | TranslationsModel.PreTranslateStringsRequest, ): Promise>> { const url = `${this.url}/projects/${projectId}/pre-translations`; return this.post(url, request, this.defaultConfig()); @@ -143,6 +143,15 @@ export class Translations extends CrowdinApi { return this.post(url, request, this.defaultConfig()); } + uploadTranslationStrings( + projectId: number, + languageId: string, + request: TranslationsModel.UploadTranslationStringsRequest, + ): Promise> { + const url = `${this.url}/projects/${projectId}/translations/${languageId}`; + return this.post(url, request, this.defaultConfig()); + } + /** * @param projectId project identifier * @param buildId build identifier @@ -202,6 +211,24 @@ export namespace TranslationsModel { excludeLabelIds?: number[]; } + export interface PreTranslateStringsRequest { + languageIds: string[]; + branchIds?: number[]; + method?: Method; + engineId?: number; + autoApproveOption?: AutoApproveOption; + duplicateTranslations?: boolean; + skipApprovedTranslations?: boolean; + translateUntranslatedOnly?: boolean; + translateWithPerfectMatchOnly?: boolean; + markAddedTranslationsAsDone?: boolean; + fallbackLanguages?: { + languageId: string; + }[]; + labelIds?: number[]; + excludeLabelIds?: number[]; + } + export interface BuildProjectDirectoryTranslationRequest { targetLanguageIds?: string[]; skipUntranslatedStrings?: boolean; @@ -238,11 +265,14 @@ export namespace TranslationsModel { export interface PreTranslationStatusAttributes { languageIds: string[]; fileIds: number[]; + branchIds: number[]; method: Method; autoApproveOption: AutoApproveOption; duplicateTranslations: boolean; + skipApprovedTranslations: boolean; translateUntranslatedOnly: boolean; translateWithPerfectMatchOnly: boolean; + markAddedTranslationsAsDone: boolean; labelIds?: number[]; excludeLabelIds?: number[]; } @@ -297,6 +327,14 @@ export namespace TranslationsModel { translateHidden?: boolean; } + export interface UploadTranslationStringsRequest { + storageId: number; + branchId: number; + importEqSuggestions?: boolean; + autoApproveImported?: boolean; + translateHidden?: boolean; + } + export interface UploadTranslationResponse { projectId: number; storageId: number; @@ -304,6 +342,13 @@ export namespace TranslationsModel { fileId: number; } + export interface UploadTranslationStringsResponse { + projectId: number; + storageId: number; + languageId: string; + branchId: number; + } + export interface ExportProjectTranslationRequest { targetLanguageId: string; format?: string; @@ -312,8 +357,10 @@ export namespace TranslationsModel { directoryIds?: number[]; fileIds?: number[]; skipUntranslatedStrings?: boolean; + exportApprovedOnly?: boolean; skipUntranslatedFiles?: boolean; exportWithMinApprovalsCount?: number; + exportStringsThatPassedWorkflow?: boolean; } export interface ListProjectBuildsOptions extends PaginationOptions { diff --git a/src/users/index.ts b/src/users/index.ts index 8c3c01af7..d36e83d8c 100644 --- a/src/users/index.ts +++ b/src/users/index.ts @@ -64,6 +64,7 @@ export class Users extends CrowdinApi { url = this.addQueryParam(url, 'search', options.search); url = this.addQueryParam(url, 'role', options.role); url = this.addQueryParam(url, 'languageId', options.languageId); + url = this.addQueryParam(url, 'workflowStepId', options.workflowStepId); return this.getList(url, options.limit, options.offset); } @@ -212,6 +213,7 @@ export namespace UsersModel { search?: string; role?: Role; languageId?: string; + workflowStepId?: number; } export interface ListUsersOptions extends PaginationOptions { @@ -225,6 +227,7 @@ export namespace UsersModel { firstName?: string; lastName?: string; timezone?: string; + adminAccess?: boolean; } export interface User { @@ -267,6 +270,7 @@ export namespace UsersModel { firstName: string; lastName: string; isManager: boolean; + isDeveloperr: boolean; managerOfGroup: Group; /** * @deprecated @@ -291,11 +295,14 @@ export namespace UsersModel { export interface AddProjectMemberRequest { userIds: number[]; + usernames: string[]; + emails: string[]; /** * @deprecated */ accessToAllWorkflowSteps?: boolean; managerAccess?: boolean; + developerAccess?: boolean; /** * @deprecated */ @@ -304,8 +311,8 @@ export namespace UsersModel { } export interface AddProjectMemberResponse { - skipped: ResponseObject[]; - added: ResponseObject[]; + skipped: ResponseObject[]; + added: ResponseObject[]; pagination: Pagination; } diff --git a/src/vendors/index.ts b/src/vendors/index.ts index 790cc2b53..89d2a6907 100644 --- a/src/vendors/index.ts +++ b/src/vendors/index.ts @@ -36,6 +36,6 @@ export namespace VendorsModel { id: number; name: string; description: string; - status: string; + status: 'pending' | 'confirmed' | 'rejected'; } } diff --git a/src/webhooks/index.ts b/src/webhooks/index.ts index 93c999e17..6f77fdb44 100644 --- a/src/webhooks/index.ts +++ b/src/webhooks/index.ts @@ -88,8 +88,8 @@ export namespace WebhooksModel { name: string; url: string; events: Event[]; - headers: string[]; - payload: string[]; + headers: Record; + payload: Record; isActive: boolean; batchingEnabled: boolean; requestType: RequestType; @@ -107,7 +107,7 @@ export namespace WebhooksModel { events: Event[]; headers?: Record; requestType: RequestType; - payload?: any; + payload?: Record; } export type ContentType = 'multipart/form-data' | 'application/json' | 'application/x-www-form-urlencoded'; diff --git a/tests/bundles/api.test.ts b/tests/bundles/api.test.ts index 9829a052d..b8a2a6e03 100644 --- a/tests/bundles/api.test.ts +++ b/tests/bundles/api.test.ts @@ -11,6 +11,7 @@ describe('Bundles API', () => { const projectId = 2; const bundleId = 3; const fileId = 4; + const branchId = 41; const exportId = '123'; const exportUrl = 'test.com'; const name = 'test'; @@ -141,6 +142,24 @@ describe('Bundles API', () => { offset: 0, limit: limit, }, + }) + .get(`/projects/${projectId}/bundles/${bundleId}/branches`, undefined, { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }) + .reply(200, { + data: [ + { + data: { + id: branchId, + }, + }, + ], + pagination: { + offset: 0, + limit: limit, + }, }); }); @@ -206,4 +225,11 @@ describe('Bundles API', () => { expect(files.data[0].data.id).toBe(fileId); expect(files.pagination.limit).toBe(limit); }); + + it('Bundle list branches', async () => { + const branches = await api.listBundleBranches(projectId, bundleId); + expect(branches.data.length).toBe(1); + expect(branches.data[0].data.id).toBe(branchId); + expect(branches.pagination.limit).toBe(limit); + }); }); diff --git a/tests/clients/api.test.ts b/tests/clients/api.test.ts new file mode 100644 index 000000000..9e508e5cb --- /dev/null +++ b/tests/clients/api.test.ts @@ -0,0 +1,47 @@ +import * as nock from 'nock'; +import { Clients, Credentials } from '../../src'; + +describe('Clients API', () => { + let scope: nock.Scope; + const credentials: Credentials = { + token: 'testToken', + organization: 'testOrg', + }; + const api: Clients = new Clients(credentials); + const id = 2; + + const limit = 25; + + beforeAll(() => { + scope = nock(api.url) + .get('/clients', undefined, { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }) + .reply(200, { + data: [ + { + data: { + id: id, + }, + }, + ], + pagination: { + offset: 0, + limit: limit, + }, + }); + }); + + afterAll(() => { + scope.done(); + }); + + it('List Clients', async () => { + const clients = await api.listClients(); + expect(clients.data.length).toBe(1); + expect(clients.data[0].data.id).toBe(id); + expect(clients.pagination.limit).toBe(limit); + }); +}); diff --git a/tests/machineTranslation/api.test.ts b/tests/machineTranslation/api.test.ts index 0649a85fa..f2ecb9c65 100644 --- a/tests/machineTranslation/api.test.ts +++ b/tests/machineTranslation/api.test.ts @@ -13,6 +13,7 @@ describe('Machine Translation engines (MTs) API', () => { const name = 'test'; const type = 'type'; const lang = 'us'; + const apiKey = 'test'; const limit = 25; @@ -44,7 +45,7 @@ describe('Machine Translation engines (MTs) API', () => { { name: name, type: type, - credentials: [], + credentials: { apiKey }, }, { reqheaders: { @@ -127,7 +128,7 @@ describe('Machine Translation engines (MTs) API', () => { const mt = await api.createMt({ name: name, type: type, - credentials: [], + credentials: { apiKey }, }); expect(mt.data.id).toBe(mtId); }); diff --git a/tests/sourceStrings/api.test.ts b/tests/sourceStrings/api.test.ts index f320f4995..fc98db19d 100644 --- a/tests/sourceStrings/api.test.ts +++ b/tests/sourceStrings/api.test.ts @@ -12,11 +12,41 @@ describe('Source Strings API', () => { const stringIdentifier = '222'; const stringId = 123; const stringText = 'text. Sample text'; + const uploadId = '123-123'; + const branchId = 1212; + const storageId = 2332; const limit = 25; beforeAll(() => { scope = nock(api.url) + .get(`/projects/${projectId}/strings/uploads/${uploadId}`, undefined, { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }) + .reply(200, { + data: { + identifier: uploadId, + }, + }) + .post( + `/projects/${projectId}/strings/uploads`, + { + storageId, + branchId, + }, + { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }, + ) + .reply(200, { + data: { + identifier: uploadId, + }, + }) .get(`/projects/${projectId}/strings`, undefined, { reqheaders: { Authorization: `Bearer ${api.token}`, @@ -127,6 +157,19 @@ describe('Source Strings API', () => { scope.done(); }); + it('Upload strings status', async () => { + const status = await api.uploadStringsStatus(projectId, uploadId); + expect(status.data.identifier).toBe(uploadId); + }); + + it('Upload strings', async () => { + const status = await api.uploadStrings(projectId, { + branchId, + storageId, + }); + expect(status.data.identifier).toBe(uploadId); + }); + it('List project strings', async () => { const strings = await api.listProjectStrings(projectId); expect(strings.data.length).toBe(1); diff --git a/tests/stringTranslations/api.test.ts b/tests/stringTranslations/api.test.ts index f73fd7d13..973c900f2 100644 --- a/tests/stringTranslations/api.test.ts +++ b/tests/stringTranslations/api.test.ts @@ -170,7 +170,7 @@ describe('String Translations API', () => { }) .reply(200) .put( - `/projects/${projectId}/translations/${translationId}/restore`, + `/projects/${projectId}/translations/${translationId}`, {}, { reqheaders: { diff --git a/tests/translationMemory/api.test.ts b/tests/translationMemory/api.test.ts index 5e93c3291..3cc57d63a 100644 --- a/tests/translationMemory/api.test.ts +++ b/tests/translationMemory/api.test.ts @@ -163,7 +163,7 @@ describe('Translation Memory API', () => { targetLanguageId: languageId, autoSubstitution: true, minRelevant: 60, - expression: 'Welcome!', + expressions: ['Welcome!'], }, { reqheaders: { @@ -252,6 +252,26 @@ describe('Translation Memory API', () => { }, }) .reply(200) + .patch( + `/tms/${tmId}/segments/${segmentId}`, + [ + { + value: segmentRecordText, + op: 'replace', + path: `/records/${segmentRecordId}/text`, + }, + ], + { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }, + ) + .reply(200, { + data: { + id: segmentId, + }, + }) .delete(`/tms/${tmId}/segments/${segmentId}/records/${segmentRecordId}`, undefined, { reqheaders: { Authorization: `Bearer ${api.token}`, @@ -372,7 +392,7 @@ describe('Translation Memory API', () => { it('Concordance search in TMs', async () => { const res = await api.concordanceSearch(projectId, { autoSubstitution: true, - expression: 'Welcome!', + expressions: ['Welcome!'], minRelevant: 60, sourceLanguageId: languageId, targetLanguageId: languageId, @@ -412,6 +432,17 @@ describe('Translation Memory API', () => { await api.deleteTmSegment(tmId, segmentId); }); + it('Edit TM Segment', async () => { + const segment = await api.editTmSegment(tmId, segmentId, [ + { + value: segmentRecordText, + op: 'replace', + path: `/records/${segmentRecordId}/text`, + }, + ]); + expect(segment.data.id).toBe(segmentId); + }); + it('Delete TM Segment Record', async () => { await api.deleteTmSegmentRecord(tmId, segmentId, segmentRecordId); }); diff --git a/tests/translations/api.test.ts b/tests/translations/api.test.ts index 80830eadc..c5115482a 100644 --- a/tests/translations/api.test.ts +++ b/tests/translations/api.test.ts @@ -15,6 +15,7 @@ describe('Translations API', () => { const url = 'test.com'; const storageId = 5; const fileId = 51; + const branchId = 71; const directoryId = 61; const progress = 50; const languageId = 'uk'; @@ -145,8 +146,8 @@ describe('Translations API', () => { .post( `/projects/${projectId}/translations/${languageId}`, { - storageId: storageId, - fileId: fileId, + storageId, + fileId, }, { reqheaders: { @@ -162,6 +163,26 @@ describe('Translations API', () => { projectId, }, }) + .post( + `/projects/${projectId}/translations/${languageId}`, + { + storageId, + branchId, + }, + { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }, + ) + .reply(200, { + data: { + branchId, + storageId, + languageId, + projectId, + }, + }) .post( `/projects/${projectId}/translations/exports`, { @@ -274,8 +295,8 @@ describe('Translations API', () => { it('Upload Translation', async () => { const res = await api.uploadTranslation(projectId, languageId, { - storageId: storageId, - fileId: fileId, + storageId, + fileId, }); expect(res.data.fileId).toBe(fileId); expect(res.data.languageId).toBe(languageId); @@ -283,6 +304,17 @@ describe('Translations API', () => { expect(res.data.storageId).toBe(storageId); }); + it('Upload Translation String-based', async () => { + const res = await api.uploadTranslationStrings(projectId, languageId, { + storageId, + branchId, + }); + expect(res.data.branchId).toBe(branchId); + expect(res.data.languageId).toBe(languageId); + expect(res.data.projectId).toBe(projectId); + expect(res.data.storageId).toBe(storageId); + }); + it('Export Project Translation', async () => { const res = await api.exportProjectTranslation(projectId, { targetLanguageId: languageId, diff --git a/tests/users/api.test.ts b/tests/users/api.test.ts index b4e11f843..3fb69e738 100644 --- a/tests/users/api.test.ts +++ b/tests/users/api.test.ts @@ -39,6 +39,8 @@ describe('Users API', () => { `/projects/${projectId}/members`, { userIds: [id], + emails: [], + usernames: [], }, { reqheaders: { @@ -180,6 +182,8 @@ describe('Users API', () => { it('Add Project Member', async () => { const resp = await api.addProjectMember(projectId, { userIds: [id], + emails: [], + usernames: [], }); expect(resp.added.length).toBe(1); expect(resp.added[0].data.id).toBe(memberId);