Document Translation service SDK (#29916)
### Packages impacted by this PR ### Issues associated with this PR ### Describe the problem that is addressed by this PR ### What are the possible designs available to address the problem? If there are more than one possible design, why was the one in this PR chosen? ### Are there test cases added in this PR? _(If not, why?)_ ### Provide a list of related PRs _(if any)_ ### Command used to generate this PR:**_(Applicable only to SDK release request PRs)_ ### Checklists - [ ] Added impacted package name to the issue description - [ ] Does this PR needs any fixes in the SDK Generator?** _(If so, create an Issue in the [Autorest/typescript](https://github.com/Azure/autorest.typescript) repository and link it here)_ - [ ] Added a changelog (if necessary)
This commit is contained in:
Родитель
3f931789cd
Коммит
72f170abc7
|
@ -44,6 +44,9 @@ dependencies:
|
|||
'@rush-temp/ai-text-analytics':
|
||||
specifier: file:./projects/ai-text-analytics.tgz
|
||||
version: file:projects/ai-text-analytics.tgz
|
||||
'@rush-temp/ai-translation-document':
|
||||
specifier: file:./projects/ai-translation-document.tgz
|
||||
version: file:projects/ai-translation-document.tgz
|
||||
'@rush-temp/ai-translation-text':
|
||||
specifier: file:./projects/ai-translation-text.tgz
|
||||
version: file:projects/ai-translation-text.tgz
|
||||
|
@ -3923,7 +3926,7 @@ packages:
|
|||
dependencies:
|
||||
'@typescript-eslint/types': 7.10.0
|
||||
eslint-visitor-keys: 3.4.3
|
||||
dev: false
|
||||
dev: false
|
||||
|
||||
/@ungap/structured-clone@1.2.0:
|
||||
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
|
||||
|
@ -11729,6 +11732,55 @@ packages:
|
|||
- supports-color
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
file:projects/ai-translation-document.tgz:
|
||||
resolution: {integrity: sha512-1beNCHG8JIOTr4zb1uhu0VXnFd5n1zUiY038vRewBFO7IGkiztLe+5gN0qPh3/sliCKDKnIjDn87NK9H9+invw==, tarball: file:projects/ai-translation-document.tgz}
|
||||
name: '@rush-temp/ai-translation-document'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@azure-rest/core-client': 1.4.0
|
||||
'@azure-tools/test-credential': 1.2.0
|
||||
'@azure-tools/test-recorder': 3.5.2
|
||||
'@azure/core-lro': 3.0.0-beta.1
|
||||
'@azure/identity': 4.3.0
|
||||
'@azure/storage-blob': 12.23.0
|
||||
'@microsoft/api-extractor': 7.47.0(@types/node@18.19.37)
|
||||
'@types/chai': 4.3.16
|
||||
'@types/mocha': 10.0.6
|
||||
'@types/node': 18.19.37
|
||||
autorest: 3.7.1
|
||||
chai: 4.3.10
|
||||
cross-env: 7.0.3
|
||||
dotenv: 16.4.5
|
||||
eslint: 8.57.0
|
||||
karma: 6.4.3(debug@4.3.5)
|
||||
karma-chrome-launcher: 3.2.0
|
||||
karma-coverage: 2.2.1
|
||||
karma-env-preprocessor: 0.1.1
|
||||
karma-firefox-launcher: 1.3.0
|
||||
karma-junit-reporter: 2.0.1(karma@6.4.3)
|
||||
karma-mocha: 2.0.1
|
||||
karma-mocha-reporter: 2.2.5(karma@6.4.3)
|
||||
karma-source-map-support: 1.4.0
|
||||
karma-sourcemap-loader: 0.3.8
|
||||
mkdirp: 3.0.1
|
||||
mocha: 10.4.0
|
||||
nyc: 15.1.0
|
||||
prettier: 3.3.2
|
||||
rimraf: 5.0.7
|
||||
source-map-support: 0.5.21
|
||||
ts-node: 10.9.2(@types/node@18.19.37)(typescript@5.4.5)
|
||||
tshy: 1.15.1
|
||||
tslib: 2.6.3
|
||||
typescript: 5.4.5
|
||||
transitivePeerDependencies:
|
||||
- '@swc/core'
|
||||
- '@swc/wasm'
|
||||
- bufferutil
|
||||
- debug
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
file:projects/ai-translation-text.tgz:
|
||||
resolution: {integrity: sha512-tjMi1e0jZ6A/L5v5CB+XLrR5UF8JkDmro+8nEygRHxCbxErYgbt+NG+TRGRq/ZoBBn5Q+DCRjkKvWKfCoJrDow==, tarball: file:projects/ai-translation-text.tgz}
|
||||
|
@ -23997,4 +24049,4 @@ packages:
|
|||
- debug
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
dev: false
|
|
@ -325,6 +325,11 @@
|
|||
"projectFolder": "sdk/translation/ai-translation-text-rest",
|
||||
"versionPolicyName": "client"
|
||||
},
|
||||
{
|
||||
"packageName": "@azure-rest/ai-translation-document",
|
||||
"projectFolder": "sdk/translation/ai-translation-document-rest",
|
||||
"versionPolicyName": "client"
|
||||
},
|
||||
{
|
||||
"packageName": "@azure-rest/defender-easm",
|
||||
"projectFolder": "sdk/easm/defender-easm-rest",
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"plugins": ["@azure/azure-sdk"],
|
||||
"extends": ["plugin:@azure/azure-sdk/azure-sdk-base"],
|
||||
"rules": {
|
||||
"@azure/azure-sdk/ts-modules-only-named": "warn",
|
||||
"@azure/azure-sdk/ts-apiextractor-json-types": "warn",
|
||||
"@azure/azure-sdk/ts-package-json-types": "warn",
|
||||
"@azure/azure-sdk/ts-package-json-engine-is-present": "warn",
|
||||
"tsdoc/syntax": "warn"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
# Release History
|
||||
## 1.0.0-beta.1 (2024-06-27)
|
||||
- Initial release. Please see the README and wiki for information on the new design.
|
||||
|
||||
Version 1.0.0-beta.1 is preview of our efforts in creating a client library that is developer-friendly, idiomatic
|
||||
to the JS/TS ecosystem, and as consistent across different languages and platforms as possible.
|
||||
|
||||
This package's
|
||||
[documentation](https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/README.md)
|
||||
and
|
||||
[samples](https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples)
|
||||
demonstrate the new API.
|
||||
|
||||
### Features Added
|
||||
- Added support for Synchronous document translation - [translate-document API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/translate-document)
|
||||
- Added support for Batch Translation - [start Translation API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/start-batch-translation)
|
||||
- Added support for Get Translations Status - [get translations status API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/get-translations-status)
|
||||
- Added support for Get Translation Status - [get translation status API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/get-translation-status)
|
||||
- Added support for Get Documents Status - [get documents status API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/get-documents-status)
|
||||
- Added support for Get Document Status - [get document status API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/get-document-status)
|
||||
- Added support for Cancel Translation - [cancel translation API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/cancel-translation)
|
||||
- Added support for Get Supported Document Formats - [get supported document formats API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/get-supported-document-formats)
|
||||
- Added support for Get Supported Glossary Formats - [get supported glossary formats API](https://learn.microsoft.com/azure/ai-services/translator/document-translation/reference/get-supported-glossary-formats)
|
|
@ -0,0 +1,346 @@
|
|||
# DocumentTranslation REST client library for JavaScript
|
||||
|
||||
Document Translation is a cloud-based machine translation feature of the Azure AI Translator service. You can translate multiple and complex documents across all supported languages and dialects while preserving original document structure and data format. The Document translation API supports two translation processes:
|
||||
|
||||
Asynchronous batch translation supports the processing of multiple documents and large files. The batch translation process requires an Azure Blob storage account with storage containers for your source and translated documents.
|
||||
|
||||
Synchronous single file supports the processing of single file translations. The file translation process doesn't require an Azure Blob storage account. The final response contains the translated document and is returned directly to the calling client.
|
||||
|
||||
The following operations are supported by the Document Translation feature:
|
||||
|
||||
- **Synchronous document translation**: Used to synchronously translate a single document. The method doesn't require an Azure Blob storage account.
|
||||
|
||||
- **Start batch translation**: Used to execute an asynchronous batch translation request. The method requires an Azure Blob storage account with storage containers for your source and translated documents.
|
||||
|
||||
- **Get status for all translation jobs**: Used to request a list and the status of all translation jobs submitted by the user (associated with the resource).
|
||||
|
||||
- **Get status for a specific translation job**: Used to request the status of a specific translation job. The response includes the overall job status and the status for documents that are being translated as part of that job.
|
||||
|
||||
- **Get status for all documents**: Used to request the status for all documents in a translation job.
|
||||
|
||||
- **Get status for a specific document**: This returns the status for a specific document in a job as indicated in the request by the id and documentId query parameters.
|
||||
|
||||
- **Cancel translation**: This cancels a translation job that is currently processing or queued (pending) as indicated in the request by the id query parameter. An operation isn't canceled if already completed, failed, or still canceling. In those instances, a bad request is returned. Completed translations can't be canceled and are charged.
|
||||
|
||||
- **Get supported formats**: This returns a list of document or glossary formats supported by the Document Translation feature. The list includes common file extensions and content-type if using the upload API.
|
||||
|
||||
Key links:
|
||||
|
||||
- [Source code](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/translation/ai-translation-document-rest)
|
||||
- [Package (NPM)](https://www.npmjs.com/package/@azure-rest/ai-translation-document)
|
||||
- [Samples](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/translation/ai-translation-document-rest/samples)
|
||||
|
||||
## Getting started
|
||||
|
||||
### Currently supported environments
|
||||
|
||||
- LTS versions of Node.js
|
||||
- Latest versions of Edge, Chrome, Safar and Firefox
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- An existing Translator service or Cognitive Services resource. More info on [Pre-requisites][pre_requisities].
|
||||
|
||||
### Install the `@azure-rest/ai-translation-document` package
|
||||
|
||||
Install the Document Translation REST client library for JavaScript with `npm`:
|
||||
|
||||
```bash
|
||||
npm install @azure-rest/ai-translation-document
|
||||
```
|
||||
|
||||
#### Create a Translator service resource
|
||||
|
||||
You can create Translator resource following [Create a Translator resource][translator_resource_create].
|
||||
|
||||
### Create a `DocumentTranslationClient` using an endpoint URL and API key `KeyCredential`
|
||||
|
||||
Once you have the value for API key, create a credential
|
||||
```typescript
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
```
|
||||
|
||||
With the value of the `KeyCredential` you can create the `DocumentTranslationClient` using the `createClient` method of [documentTranslationClient_class]:
|
||||
|
||||
```typescript
|
||||
const client = createClient(endpoint, credentials);
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
The following section provides several code snippets using the `client`, and covers the main features present in this client library.
|
||||
|
||||
### Synchronous Document Translation
|
||||
|
||||
Used to synchronously translate a single document. The method doesn't require an Azure Blob storage account.
|
||||
|
||||
```typescript
|
||||
console.log("== Synchronous Document Translation ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
const options: DocumentTranslateParameters = {
|
||||
queryParameters: {
|
||||
targetLanguage: "hi",
|
||||
},
|
||||
contentType: "multipart/form-data",
|
||||
body: [
|
||||
{
|
||||
name: "document",
|
||||
body: "This is a test.",
|
||||
filename: "test-input.txt",
|
||||
contentType: "text/html",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const response = await client.path("/document:translate").post(options);
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
console.log('Response code: ' + response.status + ', Response body: ' + response.body);
|
||||
```
|
||||
|
||||
### Batch Document Translation
|
||||
Used to execute an asynchronous batch translation request. The method requires an Azure Blob storage account with storage containers for your source and translated documents.
|
||||
|
||||
```typescript
|
||||
console.log("== Batch Document Translation ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = {inputs: [batchRequest]};
|
||||
const poller = await client.path("/document/batches").post({
|
||||
body: batchRequests
|
||||
});
|
||||
const id = getTranslationOperationID(poller.headers["operation-location"]);
|
||||
console.log('Translation started and the operationID is: ' + id);
|
||||
```
|
||||
|
||||
### Cancel Document Translation
|
||||
This cancels a translation job that is currently processing or queued (pending) as indicated in the request by the id query parameter. An operation isn't canceled if already completed, failed, or still canceling. In those instances, a bad request is returned. Completed translations can't be canceled and are charged.
|
||||
|
||||
```typescript
|
||||
console.log("== Cancel Translation ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = {inputs: [batchRequest]};
|
||||
const poller = await client.path("/document/batches").post({
|
||||
body: batchRequests
|
||||
});
|
||||
const id = getTranslationOperationID(poller.headers["operation-location"]);
|
||||
|
||||
//Cancel translation
|
||||
await client.path("/document/batches/{id}", id).delete();
|
||||
|
||||
//get translation status and verify the job is cancelled, cancelling or notStarted
|
||||
const response = await client.path("/document/batches/{id}", id).get();
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
console.log("The status after cancelling the batch operation is:" + response.body.status);
|
||||
```
|
||||
|
||||
### Get Documents Status
|
||||
Used to request the status for all documents in a translation job.
|
||||
|
||||
```typescript
|
||||
console.log("== Gets Documents Status ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = {inputs: [batchRequest]};
|
||||
const response = await StartTranslationAndWait(client, batchRequests);
|
||||
|
||||
const operationLocationUrl = response.headers["operation-location"]
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
//get Documents Status
|
||||
const documentResponse = await client.path("/document/batches/{id}/documents", operationId).get();
|
||||
if (isUnexpected(documentResponse)) {
|
||||
throw documentResponse.body;
|
||||
}
|
||||
|
||||
const responseBody = documentResponse.body;
|
||||
for (const documentStatus of responseBody.value) {
|
||||
console.log("Document Status is: " + documentStatus.status);
|
||||
console.log("Characters charged is: " + documentStatus.characterCharged);
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
### Get Document Status
|
||||
This returns the status for a specific document in a job as indicated in the request by the id and documentId query parameters.
|
||||
|
||||
```typescript
|
||||
console.log("== Get Document Status ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = {inputs: [batchRequest]};
|
||||
const response = await StartTranslationAndWait(client, batchRequests);
|
||||
const operationLocationUrl = response.headers["operation-location"]
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
//get Documents Status
|
||||
const documentResponse = await client.path("/document/batches/{id}/documents", operationId).get();
|
||||
if (isUnexpected(documentResponse)) {
|
||||
throw documentResponse.body;
|
||||
}
|
||||
|
||||
const responseBody = documentResponse.body;
|
||||
for (const document of responseBody.value) {
|
||||
//get document status
|
||||
const documentStatus = await client.path("/document/batches/{id}/documents/{documentId}", operationId, document.id).get();
|
||||
console.log("Document Status = " + documentStatus.status);
|
||||
const documentStatusOutput = documentStatus.body as DocumentStatusOutput;
|
||||
console.log("Document ID = " +documentStatusOutput.id);
|
||||
console.log("Document source path = " + documentStatusOutput.sourcePath);
|
||||
console.log("Document path = " + documentStatusOutput.path);
|
||||
console.log("Target language = " + documentStatusOutput.to);
|
||||
console.log("Document created dateTime = " + documentStatusOutput.createdDateTimeUtc);
|
||||
console.log("Document last action date time = " + documentStatusOutput.lastActionDateTimeUtc);
|
||||
}
|
||||
```
|
||||
|
||||
### Get Translations Status
|
||||
Used to request a list and the status of all translation jobs submitted by the user (associated with the resource).
|
||||
|
||||
```typescript
|
||||
console.log("== Get Translations Status ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = {inputs: [batchRequest]};
|
||||
const translationResponse = await StartTranslationAndWait(client, batchRequests);
|
||||
const operationLocationUrl = translationResponse.headers["operation-location"]
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
//get Translation Statusby ID filter
|
||||
const queryParams = {
|
||||
ids: [operationId]
|
||||
};
|
||||
const response = await client.path("/document/batches").get({
|
||||
queryParameters: queryParams
|
||||
});
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
const responseBody = response.body;
|
||||
for (const translationStatus of responseBody.value) {
|
||||
console.log("Translation ID = " + translationStatus.id);
|
||||
console.log("Translation Status = " + translationStatus.status);
|
||||
console.log("Translation createdDateTimeUtc = " + translationStatus.createdDateTimeUtc);
|
||||
console.log("Translation lastActionDateTimeUtc = " + translationStatus.lastActionDateTimeUtc);
|
||||
console.log("Total documents submitted for translation = " + translationStatus.summary.total);
|
||||
console.log("Total characters charged = " + translationStatus.summary.totalCharacterCharged);
|
||||
}
|
||||
```
|
||||
|
||||
### Get Translation Status
|
||||
Used to request the status of a specific translation job. The response includes the overall job status and the status for documents that are being translated as part of that job.
|
||||
|
||||
```typescript
|
||||
console.log("== Get Translation Status ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = {inputs: [batchRequest]};
|
||||
const translationResponse = await StartTranslationAndWait(client, batchRequests);
|
||||
|
||||
const operationLocationUrl = translationResponse.headers["operation-location"]
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
//get Translation Status
|
||||
const response = await client.path("/document/batches/{id}",operationId).get() as GetTranslationStatus200Response;
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
|
||||
console.log("Translation ID = " + response.body.id);
|
||||
console.log("Translation Status = " + response.body.status);
|
||||
console.log("Translation createdDateTimeUtc = " + response.body.createdDateTimeUtc);
|
||||
console.log("Translation lastActionDateTimeUtc = " + response.body.lastActionDateTimeUtc);
|
||||
console.log("Total documents submitted for translation = " + response.body.summary.total);
|
||||
console.log("Total characters charged = " + response.body.summary.totalCharacterCharged);
|
||||
```
|
||||
|
||||
|
||||
### Get Supported Formats
|
||||
|
||||
This returns a list of document or glossary formats supported by the Document Translation feature. The list includes common file extensions and content-type if using the upload API.
|
||||
|
||||
```typescript
|
||||
console.log("== List Supported Format Types ==");
|
||||
|
||||
const documentTranslationClient = DocumentTranslationClient(endpoint);
|
||||
const response = await documentTranslationClient.path("/document/formats").get();
|
||||
|
||||
const fileFormatTypes = response.body;
|
||||
fileFormatTypes.value.forEach((fileFormatType: { format: any; contentTypes: any; fileExtensions: any; }) => {
|
||||
console.log(fileFormatType.format);
|
||||
console.log(fileFormatType.contentTypes);
|
||||
console.log(fileFormatType.fileExtensions);
|
||||
});
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
When you interact with the Translator Service using the DocumentTranslator client library, errors returned by the Translator service correspond to the same HTTP status codes returned for REST API requests.
|
||||
|
||||
For example, if you submit a translation request without a target translate language, a `400` error is returned, indicating "Bad Request".
|
||||
|
||||
You can find the different error codes returned by the service in the [Service Documentation][service_errors].
|
||||
|
||||
### Logging
|
||||
|
||||
Enabling logging may help uncover useful information about failures. In order to see a log of HTTP requests and responses, set the `AZURE_LOG_LEVEL` environment variable to `info`. Alternatively, logging can be enabled at runtime by calling `setLogLevel` in the `@azure/logger`:
|
||||
|
||||
```javascript
|
||||
const { setLogLevel } = require("@azure/logger");
|
||||
|
||||
setLogLevel("info");
|
||||
```
|
||||
|
||||
For more detailed instructions on how to enable logs, you can look at the [@azure/logger package docs](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger).
|
||||
Please refer to the service documentation for a conceptual discussion of [languages][languages_doc].
|
||||
|
||||
[service_errors]: https://learn.microsoft.com/azure/ai-services/translator/document-translation/how-to-guides/use-rest-api-programmatically?tabs=csharp#common-http-status-codes
|
||||
[translator_resource_create]: https://learn.microsoft.com/azure/cognitive-services/Translator/create-translator-resource
|
||||
[documentTranslationClient_class]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/src/documentTranslationClient.ts
|
||||
[pre_requisities]: https://learn.microsoft.com/azure/ai-services/translator/document-translation/how-to-guides/use-rest-api-programmatically?tabs=csharp#prerequisites
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
||||
"mainEntryPointFilePath": "./types/src/index.d.ts",
|
||||
"docModel": {
|
||||
"enabled": true
|
||||
},
|
||||
"apiReport": {
|
||||
"enabled": true,
|
||||
"reportFolder": "./review"
|
||||
},
|
||||
"dtsRollup": {
|
||||
"enabled": true,
|
||||
"untrimmedFilePath": "",
|
||||
"publicTrimmedFilePath": "./types/ai-translation-document-rest.d.ts"
|
||||
},
|
||||
"messages": {
|
||||
"tsdocMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "none"
|
||||
}
|
||||
},
|
||||
"extractorMessageReporting": {
|
||||
"ae-missing-release-tag": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"ae-unresolved-link": {
|
||||
"logLevel": "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"AssetsRepo": "Azure/azure-sdk-assets",
|
||||
"AssetsRepoPrefixPath": "js",
|
||||
"TagPrefix": "js/translation/ai-translation-document-rest",
|
||||
"Tag": "js/translation/ai-translation-document-rest_2ddbd57773"
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
// https://github.com/karma-runner/karma-chrome-launcher
|
||||
process.env.CHROME_BIN = require("puppeteer").executablePath();
|
||||
require("dotenv").config();
|
||||
|
||||
process.env.RECORDINGS_RELATIVE_PATH =
|
||||
require("@azure-tools/test-recorder").relativeRecordingsPath();
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
// base path that will be used to resolve all patterns (eg. files, exclude)
|
||||
basePath: "./",
|
||||
|
||||
// frameworks to use
|
||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||
frameworks: ["source-map-support", "mocha"],
|
||||
|
||||
plugins: [
|
||||
"karma-mocha",
|
||||
"karma-mocha-reporter",
|
||||
"karma-chrome-launcher",
|
||||
"karma-firefox-launcher",
|
||||
"karma-env-preprocessor",
|
||||
"karma-coverage",
|
||||
"karma-sourcemap-loader",
|
||||
"karma-junit-reporter",
|
||||
"karma-source-map-support",
|
||||
],
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: [
|
||||
"dist-test/index.browser.js",
|
||||
{
|
||||
pattern: "dist-test/index.browser.js.map",
|
||||
type: "html",
|
||||
included: false,
|
||||
served: true,
|
||||
},
|
||||
],
|
||||
|
||||
// list of files / patterns to exclude
|
||||
exclude: [],
|
||||
|
||||
// preprocess matching files before serving them to the browser
|
||||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
||||
preprocessors: {
|
||||
"**/*.js": ["sourcemap", "env"],
|
||||
// IMPORTANT: COMMENT following line if you want to debug in your browsers!!
|
||||
// Preprocess source file to calculate code coverage, however this will make source file unreadable
|
||||
// "dist-test/index.js": ["coverage"]
|
||||
},
|
||||
|
||||
envPreprocessor: [
|
||||
"TEST_MODE",
|
||||
"DOCUMENT_TRANSLATION_API_KEY",
|
||||
"DOCUMENT_TRANSLATION_ENDPOINT",
|
||||
"DOCUMENT_TRANSLATION_STORAGE_NAME",
|
||||
"DOCUMENT_TRANSLATION_CONNECTION_STRING",
|
||||
"RECORDINGS_RELATIVE_PATH",
|
||||
],
|
||||
|
||||
// test results reporter to use
|
||||
// possible values: 'dots', 'progress'
|
||||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||
reporters: ["mocha", "coverage", "junit"],
|
||||
|
||||
coverageReporter: {
|
||||
// specify a common output directory
|
||||
dir: "coverage-browser/",
|
||||
reporters: [
|
||||
{ type: "json", subdir: ".", file: "coverage.json" },
|
||||
{ type: "lcovonly", subdir: ".", file: "lcov.info" },
|
||||
{ type: "html", subdir: "html" },
|
||||
{ type: "cobertura", subdir: ".", file: "cobertura-coverage.xml" },
|
||||
],
|
||||
},
|
||||
|
||||
junitReporter: {
|
||||
outputDir: "", // results will be saved as $outputDir/$browserName.xml
|
||||
outputFile: "test-results.browser.xml", // if included, results will be saved as $outputDir/$browserName/$outputFile
|
||||
suite: "", // suite will become the package name attribute in xml testsuite element
|
||||
useBrowserName: false, // add browser name to report and classes names
|
||||
nameFormatter: undefined, // function (browser, result) to customize the name attribute in xml testcase element
|
||||
classNameFormatter: undefined, // function (browser, result) to customize the classname attribute in xml testcase element
|
||||
properties: {}, // key value pair of properties to add to the <properties> section of the report
|
||||
},
|
||||
|
||||
// web server port
|
||||
port: 9876,
|
||||
|
||||
// enable / disable colors in the output (reporters and logs)
|
||||
colors: true,
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
|
||||
// enable / disable watching file and executing tests whenever any file changes
|
||||
autoWatch: false,
|
||||
|
||||
// --no-sandbox allows our tests to run in Linux without having to change the system.
|
||||
// --disable-web-security allows us to authenticate from the browser without having to write tests using interactive auth, which would be far more complex.
|
||||
browsers: ["ChromeHeadlessNoSandbox"],
|
||||
customLaunchers: {
|
||||
ChromeHeadlessNoSandbox: {
|
||||
base: "ChromeHeadless",
|
||||
flags: ["--no-sandbox", "--disable-web-security"],
|
||||
},
|
||||
},
|
||||
|
||||
// Continuous Integration mode
|
||||
// if true, Karma captures browsers, runs the tests and exits
|
||||
singleRun: false,
|
||||
|
||||
// Concurrency level
|
||||
// how many browser should be started simultaneous
|
||||
concurrency: 1,
|
||||
|
||||
browserNoActivityTimeout: 60000000,
|
||||
browserDisconnectTimeout: 10000,
|
||||
browserDisconnectTolerance: 3,
|
||||
|
||||
client: {
|
||||
mocha: {
|
||||
// change Karma's debug.html to the mocha web reporter
|
||||
reporter: "html",
|
||||
timeout: "600000",
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
|
@ -0,0 +1,123 @@
|
|||
{
|
||||
"name": "@azure-rest/ai-translation-document",
|
||||
"sdk-type": "client",
|
||||
"author": "Microsoft Corporation",
|
||||
"description": "A generated SDK for DocumentTranslationClient.",
|
||||
"version": "1.0.0-beta.1",
|
||||
"keywords": [
|
||||
"node",
|
||||
"azure",
|
||||
"cloud",
|
||||
"typescript",
|
||||
"browser",
|
||||
"isomorphic",
|
||||
"translate",
|
||||
"translation"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "dist/index.js",
|
||||
"module": "./dist-esm/src/index.js",
|
||||
"types": "./types/ai-translation-document-rest.d.ts",
|
||||
"homepage": "https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/translation/ai-translation-document-rest/README.md",
|
||||
"repository": "github:Azure/azure-sdk-for-js",
|
||||
"bugs": {
|
||||
"url": "https://github.com/Azure/azure-sdk-for-js/issues"
|
||||
},
|
||||
"files": [
|
||||
"dist/",
|
||||
"dist-esm/src/",
|
||||
"types/ai-translation-document.d.ts",
|
||||
"README.md",
|
||||
"CHANGELOG.md",
|
||||
"LICENSE"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"//sampleConfiguration": {
|
||||
"productName": "Azure Document Translation Service",
|
||||
"productSlugs": [
|
||||
"azure",
|
||||
"azure-cognitive-services",
|
||||
"azure-translator"
|
||||
],
|
||||
"requiredResources": {
|
||||
"Azure Cognitive Services instance": "https://docs.microsoft.com/azure/cognitive-services/cognitive-services-apis-create-account"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure/core-rest-pipeline": "^1.8.0",
|
||||
"@azure/logger": "^1.0.0",
|
||||
"@azure/core-paging": "^1.2.0",
|
||||
"@azure-rest/core-client": "^2.0.0",
|
||||
"@azure/core-auth": "^1.6.0",
|
||||
"tslib": "^2.6.2",
|
||||
"@azure/core-lro": "3.0.0-beta.1",
|
||||
"@azure/abort-controller": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@azure/storage-blob": "^12.23.0",
|
||||
"@microsoft/api-extractor": "^7.47.0",
|
||||
"rimraf": "^5.0.5",
|
||||
"autorest": "latest",
|
||||
"@types/node": "^18.0.0",
|
||||
"dotenv": "^16.0.0",
|
||||
"eslint": "^8.55.0",
|
||||
"mkdirp": "^3.0.1",
|
||||
"source-map-support": "^0.5.9",
|
||||
"typescript": "~5.4.5",
|
||||
"@azure/dev-tool": "^1.0.0",
|
||||
"@azure/eslint-plugin-azure-sdk": "^3.0.0",
|
||||
"@azure-tools/test-credential": "^1.0.0",
|
||||
"@azure/identity": "^4.0.1",
|
||||
"@azure-tools/test-recorder": "^3.5.2",
|
||||
"mocha": "^10.0.0",
|
||||
"@types/mocha": "^10.0.0",
|
||||
"cross-env": "^7.0.2",
|
||||
"@types/chai": "^4.2.8",
|
||||
"chai": "^4.2.0",
|
||||
"karma-chrome-launcher": "^3.0.0",
|
||||
"karma-coverage": "^2.0.0",
|
||||
"karma-env-preprocessor": "^0.1.1",
|
||||
"karma-firefox-launcher": "^1.1.0",
|
||||
"karma-junit-reporter": "^2.0.1",
|
||||
"karma-mocha-reporter": "^2.2.5",
|
||||
"karma-mocha": "^2.0.1",
|
||||
"karma-source-map-support": "~1.4.0",
|
||||
"karma-sourcemap-loader": "^0.3.8",
|
||||
"karma": "^6.2.0",
|
||||
"nyc": "^15.1.0",
|
||||
"ts-node": "^10.0.0",
|
||||
"prettier": "^3.2.5",
|
||||
"tshy": "1.15.1"
|
||||
},
|
||||
"scripts": {
|
||||
"audit": "node ../../../common/scripts/rush-audit.js && rimraf node_modules package-lock.json && npm i --package-lock-only 2>&1 && npm audit",
|
||||
"build:browser": "tsc -p . && dev-tool run bundle",
|
||||
"build:node": "tsc -p . && dev-tool run bundle --browser-test false",
|
||||
"build:samples": "echo Obsolete.",
|
||||
"build:test": "tsc -p . && dev-tool run bundle",
|
||||
"build:debug": "tsc -p . && dev-tool run bundle && dev-tool run extract-api",
|
||||
"check-format": "dev-tool run vendored prettier --list-different --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"test/**/*.ts\" \"samples-dev/**/*.ts\" \"*.{js,json}\"",
|
||||
"clean": "rimraf --glob dist dist-browser dist-esm test-dist temp types *.tgz *.log",
|
||||
"execute:samples": "dev-tool samples run samples-dev",
|
||||
"extract-api": "rimraf review && mkdirp ./review && dev-tool run extract-api",
|
||||
"format": "dev-tool run vendored prettier --write --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"test/**/*.ts\" \"samples-dev/**/*.ts\" \"*.{js,json}\"",
|
||||
"generate:client": "echo skipped",
|
||||
"integration-test:browser": "dev-tool run test:browser",
|
||||
"integration-test:node": "dev-tool run test:node-js-input -- --timeout 5000000 'dist-esm/test/**/*.spec.js'",
|
||||
"integration-test": "npm run integration-test:node && npm run integration-test:browser",
|
||||
"lint:fix": "eslint package.json api-extractor.json src test --ext .ts --fix --fix-type [problem,suggestion]",
|
||||
"lint": "eslint package.json api-extractor.json src test --ext .ts",
|
||||
"pack": "npm pack 2>&1",
|
||||
"test:browser": "npm run clean && npm run build:test && npm run unit-test:browser",
|
||||
"test:node": "npm run clean && npm run build:test && npm run unit-test:node",
|
||||
"test": "npm run clean && npm run build:test && npm run unit-test",
|
||||
"unit-test": "npm run unit-test:node && npm run unit-test:browser",
|
||||
"unit-test:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/*.spec.ts'",
|
||||
"unit-test:browser": "dev-tool run test:browser",
|
||||
"build": "npm run clean && tsc -p . && dev-tool run bundle && mkdirp ./review && dev-tool run extract-api"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"autoPublish": false
|
||||
}
|
|
@ -0,0 +1,640 @@
|
|||
## API Report File for "@azure-rest/ai-translation-document"
|
||||
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
|
||||
/// <reference types="node" />
|
||||
|
||||
import { AbortSignalLike } from '@azure/abort-controller';
|
||||
import { CancelOnProgress } from '@azure/core-lro';
|
||||
import { Client } from '@azure-rest/core-client';
|
||||
import { ClientOptions } from '@azure-rest/core-client';
|
||||
import { createFile } from '@azure/core-rest-pipeline';
|
||||
import { createFileFromStream } from '@azure/core-rest-pipeline';
|
||||
import { CreateFileFromStreamOptions } from '@azure/core-rest-pipeline';
|
||||
import { CreateFileOptions } from '@azure/core-rest-pipeline';
|
||||
import { CreateHttpPollerOptions } from '@azure/core-lro';
|
||||
import { ErrorResponse } from '@azure-rest/core-client';
|
||||
import { HttpResponse } from '@azure-rest/core-client';
|
||||
import { KeyCredential } from '@azure/core-auth';
|
||||
import { OperationState } from '@azure/core-lro';
|
||||
import { PagedAsyncIterableIterator } from '@azure/core-paging';
|
||||
import { PathUncheckedResponse } from '@azure-rest/core-client';
|
||||
import { RawHttpHeaders } from '@azure/core-rest-pipeline';
|
||||
import { RawHttpHeadersInput } from '@azure/core-rest-pipeline';
|
||||
import { RequestParameters } from '@azure-rest/core-client';
|
||||
import { StreamableMethod } from '@azure-rest/core-client';
|
||||
import { TokenCredential } from '@azure/core-auth';
|
||||
|
||||
// @public
|
||||
export interface BatchRequest {
|
||||
source: SourceInput;
|
||||
storageType?: StorageInputType;
|
||||
targets: Array<TargetInput>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface CancelTranslation200Response extends HttpResponse {
|
||||
// (undocumented)
|
||||
body: TranslationStatusOutput;
|
||||
// (undocumented)
|
||||
status: "200";
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface CancelTranslationDefaultHeaders {
|
||||
"x-ms-error-code"?: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface CancelTranslationDefaultResponse extends HttpResponse {
|
||||
// (undocumented)
|
||||
body: ErrorResponse;
|
||||
// (undocumented)
|
||||
headers: RawHttpHeaders & CancelTranslationDefaultHeaders;
|
||||
// (undocumented)
|
||||
status: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type CancelTranslationParameters = RequestParameters;
|
||||
|
||||
// @public
|
||||
function createClient(endpointParam: string, credentials: TokenCredential | KeyCredential, options?: ClientOptions): DocumentTranslationClient;
|
||||
export default createClient;
|
||||
|
||||
export { createFile }
|
||||
|
||||
export { createFileFromStream }
|
||||
|
||||
export { CreateFileFromStreamOptions }
|
||||
|
||||
export { CreateFileOptions }
|
||||
|
||||
// @public
|
||||
export interface DocumentFilter {
|
||||
prefix?: string;
|
||||
suffix?: string;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface DocumentsStatusOutput {
|
||||
nextLink?: string;
|
||||
value: Array<DocumentStatusOutput>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface DocumentStatusOutput {
|
||||
characterCharged?: number;
|
||||
createdDateTimeUtc: string;
|
||||
error?: TranslationErrorOutput;
|
||||
id: string;
|
||||
lastActionDateTimeUtc: string;
|
||||
path?: string;
|
||||
progress: number;
|
||||
sourcePath: string;
|
||||
status: StatusOutput;
|
||||
to: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DocumentTranslate {
|
||||
post(options: DocumentTranslateParameters): StreamableMethod<DocumentTranslate200Response | DocumentTranslateDefaultResponse>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DocumentTranslate200Headers {
|
||||
"x-ms-client-request-id"?: string;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface DocumentTranslate200Response extends HttpResponse {
|
||||
body: Uint8Array;
|
||||
// (undocumented)
|
||||
headers: RawHttpHeaders & DocumentTranslate200Headers;
|
||||
// (undocumented)
|
||||
status: "200";
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DocumentTranslateBodyParam {
|
||||
// (undocumented)
|
||||
body?: DocumentTranslateContent;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type DocumentTranslateContent = FormData | Array<DocumentTranslateContentDocumentPartDescriptor | DocumentTranslateContentGlossaryPartDescriptor>;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DocumentTranslateContentDocumentPartDescriptor {
|
||||
// (undocumented)
|
||||
body: string | Uint8Array | ReadableStream<Uint8Array> | NodeJS.ReadableStream | File;
|
||||
// (undocumented)
|
||||
contentType?: string;
|
||||
// (undocumented)
|
||||
filename?: string;
|
||||
// (undocumented)
|
||||
name: "document";
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DocumentTranslateContentGlossaryPartDescriptor {
|
||||
// (undocumented)
|
||||
body: string | Uint8Array | ReadableStream<Uint8Array> | NodeJS.ReadableStream | File;
|
||||
// (undocumented)
|
||||
contentType?: string;
|
||||
// (undocumented)
|
||||
filename?: string;
|
||||
// (undocumented)
|
||||
name: "glossary";
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DocumentTranslateDefaultHeaders {
|
||||
"x-ms-error-code"?: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DocumentTranslateDefaultResponse extends HttpResponse {
|
||||
// (undocumented)
|
||||
body: ErrorResponse;
|
||||
// (undocumented)
|
||||
headers: RawHttpHeaders & DocumentTranslateDefaultHeaders;
|
||||
// (undocumented)
|
||||
status: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DocumentTranslateHeaderParam {
|
||||
// (undocumented)
|
||||
headers?: RawHttpHeadersInput & DocumentTranslateHeaders;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DocumentTranslateHeaders {
|
||||
"x-ms-client-request-id"?: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DocumentTranslateMediaTypesParam {
|
||||
contentType: "multipart/form-data";
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type DocumentTranslateParameters = DocumentTranslateQueryParam & DocumentTranslateHeaderParam & DocumentTranslateMediaTypesParam & DocumentTranslateBodyParam & RequestParameters;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DocumentTranslateQueryParam {
|
||||
// (undocumented)
|
||||
queryParameters: DocumentTranslateQueryParamProperties;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DocumentTranslateQueryParamProperties {
|
||||
allowFallback?: boolean;
|
||||
category?: string;
|
||||
sourceLanguage?: string;
|
||||
targetLanguage: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type DocumentTranslationClient = Client & {
|
||||
path: Routes;
|
||||
};
|
||||
|
||||
// @public
|
||||
export interface FileFormatOutput {
|
||||
contentTypes: string[];
|
||||
defaultVersion?: string;
|
||||
fileExtensions: string[];
|
||||
format: string;
|
||||
type?: string;
|
||||
versions?: string[];
|
||||
}
|
||||
|
||||
// @public
|
||||
export type FileFormatType = "document" | "glossary" | string;
|
||||
|
||||
// @public
|
||||
export type GetArrayType<T> = T extends Array<infer TData> ? TData : never;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetDocumentsStatus {
|
||||
get(options?: GetDocumentsStatusParameters): StreamableMethod<GetDocumentsStatus200Response | GetDocumentsStatusDefaultResponse>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface GetDocumentsStatus200Response extends HttpResponse {
|
||||
// (undocumented)
|
||||
body: DocumentsStatusOutput;
|
||||
// (undocumented)
|
||||
status: "200";
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetDocumentsStatusDefaultHeaders {
|
||||
"x-ms-error-code"?: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetDocumentsStatusDefaultResponse extends HttpResponse {
|
||||
// (undocumented)
|
||||
body: ErrorResponse;
|
||||
// (undocumented)
|
||||
headers: RawHttpHeaders & GetDocumentsStatusDefaultHeaders;
|
||||
// (undocumented)
|
||||
status: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type GetDocumentsStatusParameters = GetDocumentsStatusQueryParam & RequestParameters;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetDocumentsStatusQueryParam {
|
||||
// (undocumented)
|
||||
queryParameters?: GetDocumentsStatusQueryParamProperties;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetDocumentsStatusQueryParamProperties {
|
||||
createdDateTimeUtcEnd?: Date | string;
|
||||
createdDateTimeUtcStart?: Date | string;
|
||||
ids?: string[];
|
||||
maxpagesize?: number;
|
||||
orderby?: string[];
|
||||
skip?: number;
|
||||
statuses?: string[];
|
||||
top?: number;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetDocumentStatus {
|
||||
get(options?: GetDocumentStatusParameters): StreamableMethod<GetDocumentStatus200Response | GetDocumentStatusDefaultResponse>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface GetDocumentStatus200Response extends HttpResponse {
|
||||
// (undocumented)
|
||||
body: DocumentStatusOutput;
|
||||
// (undocumented)
|
||||
status: "200";
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetDocumentStatusDefaultHeaders {
|
||||
"x-ms-error-code"?: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetDocumentStatusDefaultResponse extends HttpResponse {
|
||||
// (undocumented)
|
||||
body: ErrorResponse;
|
||||
// (undocumented)
|
||||
headers: RawHttpHeaders & GetDocumentStatusDefaultHeaders;
|
||||
// (undocumented)
|
||||
status: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type GetDocumentStatusParameters = RequestParameters;
|
||||
|
||||
// @public
|
||||
export function getLongRunningPoller<TResult extends StartTranslationLogicalResponse | StartTranslationDefaultResponse>(client: Client, initialResponse: StartTranslation202Response | StartTranslationDefaultResponse, options?: CreateHttpPollerOptions<TResult, OperationState<TResult>>): Promise<SimplePollerLike<OperationState<TResult>, TResult>>;
|
||||
|
||||
// @public
|
||||
export type GetPage<TPage> = (pageLink: string, maxPageSize?: number) => Promise<{
|
||||
page: TPage;
|
||||
nextPageLink?: string;
|
||||
}>;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetSupportedFormats {
|
||||
get(options?: GetSupportedFormatsParameters): StreamableMethod<GetSupportedFormats200Response | GetSupportedFormatsDefaultResponse>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface GetSupportedFormats200Response extends HttpResponse {
|
||||
// (undocumented)
|
||||
body: SupportedFileFormatsOutput;
|
||||
// (undocumented)
|
||||
status: "200";
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetSupportedFormatsDefaultHeaders {
|
||||
"x-ms-error-code"?: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetSupportedFormatsDefaultResponse extends HttpResponse {
|
||||
// (undocumented)
|
||||
body: ErrorResponse;
|
||||
// (undocumented)
|
||||
headers: RawHttpHeaders & GetSupportedFormatsDefaultHeaders;
|
||||
// (undocumented)
|
||||
status: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type GetSupportedFormatsParameters = GetSupportedFormatsQueryParam & RequestParameters;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetSupportedFormatsQueryParam {
|
||||
// (undocumented)
|
||||
queryParameters?: GetSupportedFormatsQueryParamProperties;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetSupportedFormatsQueryParamProperties {
|
||||
type?: FileFormatType;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface GetTranslationsStatus200Response extends HttpResponse {
|
||||
// (undocumented)
|
||||
body: TranslationsStatusOutput;
|
||||
// (undocumented)
|
||||
status: "200";
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetTranslationsStatusDefaultHeaders {
|
||||
"x-ms-error-code"?: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetTranslationsStatusDefaultResponse extends HttpResponse {
|
||||
// (undocumented)
|
||||
body: ErrorResponse;
|
||||
// (undocumented)
|
||||
headers: RawHttpHeaders & GetTranslationsStatusDefaultHeaders;
|
||||
// (undocumented)
|
||||
status: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type GetTranslationsStatusParameters = GetTranslationsStatusQueryParam & RequestParameters;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetTranslationsStatusQueryParam {
|
||||
// (undocumented)
|
||||
queryParameters?: GetTranslationsStatusQueryParamProperties;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetTranslationsStatusQueryParamProperties {
|
||||
createdDateTimeUtcEnd?: Date | string;
|
||||
createdDateTimeUtcStart?: Date | string;
|
||||
ids?: string[];
|
||||
maxpagesize?: number;
|
||||
orderby?: string[];
|
||||
skip?: number;
|
||||
statuses?: string[];
|
||||
top?: number;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetTranslationStatus {
|
||||
delete(options?: CancelTranslationParameters): StreamableMethod<CancelTranslation200Response | CancelTranslationDefaultResponse>;
|
||||
get(options?: GetTranslationStatusParameters): StreamableMethod<GetTranslationStatus200Response | GetTranslationStatusDefaultResponse>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface GetTranslationStatus200Response extends HttpResponse {
|
||||
// (undocumented)
|
||||
body: TranslationStatusOutput;
|
||||
// (undocumented)
|
||||
status: "200";
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetTranslationStatusDefaultHeaders {
|
||||
"x-ms-error-code"?: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GetTranslationStatusDefaultResponse extends HttpResponse {
|
||||
// (undocumented)
|
||||
body: ErrorResponse;
|
||||
// (undocumented)
|
||||
headers: RawHttpHeaders & GetTranslationStatusDefaultHeaders;
|
||||
// (undocumented)
|
||||
status: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type GetTranslationStatusParameters = RequestParameters;
|
||||
|
||||
// @public
|
||||
export interface Glossary {
|
||||
format: string;
|
||||
glossaryUrl: string;
|
||||
storageSource?: StorageSource;
|
||||
version?: string;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface InnerTranslationErrorOutput {
|
||||
code: string;
|
||||
innerError?: InnerTranslationErrorOutput;
|
||||
message: string;
|
||||
readonly target?: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export function isUnexpected(response: DocumentTranslate200Response | DocumentTranslateDefaultResponse): response is DocumentTranslateDefaultResponse;
|
||||
|
||||
// @public (undocumented)
|
||||
export function isUnexpected(response: StartTranslation202Response | StartTranslationLogicalResponse | StartTranslationDefaultResponse): response is StartTranslationDefaultResponse;
|
||||
|
||||
// @public (undocumented)
|
||||
export function isUnexpected(response: GetTranslationsStatus200Response | GetTranslationsStatusDefaultResponse): response is GetTranslationsStatusDefaultResponse;
|
||||
|
||||
// @public (undocumented)
|
||||
export function isUnexpected(response: GetDocumentStatus200Response | GetDocumentStatusDefaultResponse): response is GetDocumentStatusDefaultResponse;
|
||||
|
||||
// @public (undocumented)
|
||||
export function isUnexpected(response: GetTranslationStatus200Response | GetTranslationStatusDefaultResponse): response is GetTranslationStatusDefaultResponse;
|
||||
|
||||
// @public (undocumented)
|
||||
export function isUnexpected(response: CancelTranslation200Response | CancelTranslationDefaultResponse): response is CancelTranslationDefaultResponse;
|
||||
|
||||
// @public (undocumented)
|
||||
export function isUnexpected(response: GetDocumentsStatus200Response | GetDocumentsStatusDefaultResponse): response is GetDocumentsStatusDefaultResponse;
|
||||
|
||||
// @public (undocumented)
|
||||
export function isUnexpected(response: GetSupportedFormats200Response | GetSupportedFormatsDefaultResponse): response is GetSupportedFormatsDefaultResponse;
|
||||
|
||||
// @public
|
||||
export function paginate<TResponse extends PathUncheckedResponse>(client: Client, initialResponse: TResponse, options?: PagingOptions<TResponse>): PagedAsyncIterableIterator<PaginateReturn<TResponse>>;
|
||||
|
||||
// @public
|
||||
export type PaginateReturn<TResult> = TResult extends {
|
||||
body: {
|
||||
value?: infer TPage;
|
||||
};
|
||||
} ? GetArrayType<TPage> : Array<unknown>;
|
||||
|
||||
// @public
|
||||
export interface PagingOptions<TResponse> {
|
||||
customGetPage?: GetPage<PaginateReturn<TResponse>[]>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface Routes {
|
||||
(path: "/document:translate"): DocumentTranslate;
|
||||
(path: "/document/batches"): StartTranslation;
|
||||
(path: "/document/batches/{id}/documents/{documentId}", id: string, documentId: string): GetDocumentStatus;
|
||||
(path: "/document/batches/{id}", id: string): GetTranslationStatus;
|
||||
(path: "/document/batches/{id}/documents", id: string): GetDocumentsStatus;
|
||||
(path: "/document/formats"): GetSupportedFormats;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface SimplePollerLike<TState extends OperationState<TResult>, TResult> {
|
||||
getOperationState(): TState;
|
||||
getResult(): TResult | undefined;
|
||||
isDone(): boolean;
|
||||
isStopped(): boolean;
|
||||
onProgress(callback: (state: TState) => void): CancelOnProgress;
|
||||
poll(options?: {
|
||||
abortSignal?: AbortSignalLike;
|
||||
}): Promise<TState>;
|
||||
pollUntilDone(pollOptions?: {
|
||||
abortSignal?: AbortSignalLike;
|
||||
}): Promise<TResult>;
|
||||
serialize(): Promise<string>;
|
||||
// @deprecated
|
||||
stopPolling(): void;
|
||||
submitted(): Promise<void>;
|
||||
// @deprecated
|
||||
toString(): string;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface SourceInput {
|
||||
filter?: DocumentFilter;
|
||||
language?: string;
|
||||
sourceUrl: string;
|
||||
storageSource?: StorageSource;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface StartTranslation {
|
||||
get(options?: GetTranslationsStatusParameters): StreamableMethod<GetTranslationsStatus200Response | GetTranslationsStatusDefaultResponse>;
|
||||
post(options?: StartTranslationParameters): StreamableMethod<StartTranslation202Response | StartTranslationDefaultResponse>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface StartTranslation202Headers {
|
||||
"operation-location": string;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface StartTranslation202Response extends HttpResponse {
|
||||
// (undocumented)
|
||||
headers: RawHttpHeaders & StartTranslation202Headers;
|
||||
// (undocumented)
|
||||
status: "202";
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface StartTranslationBodyParam {
|
||||
// (undocumented)
|
||||
body?: StartTranslationDetails;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface StartTranslationDefaultHeaders {
|
||||
"x-ms-error-code"?: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface StartTranslationDefaultResponse extends HttpResponse {
|
||||
// (undocumented)
|
||||
body: ErrorResponse;
|
||||
// (undocumented)
|
||||
headers: RawHttpHeaders & StartTranslationDefaultHeaders;
|
||||
// (undocumented)
|
||||
status: string;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface StartTranslationDetails {
|
||||
inputs: Array<BatchRequest>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface StartTranslationLogicalResponse extends HttpResponse {
|
||||
// (undocumented)
|
||||
status: "200";
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type StartTranslationParameters = StartTranslationBodyParam & RequestParameters;
|
||||
|
||||
// @public
|
||||
export type StatusOutput = "NotStarted" | "Running" | "Succeeded" | "Failed" | "Cancelled" | "Cancelling" | "ValidationFailed" | string;
|
||||
|
||||
// @public
|
||||
export interface StatusSummaryOutput {
|
||||
cancelled: number;
|
||||
failed: number;
|
||||
inProgress: number;
|
||||
notYetStarted: number;
|
||||
success: number;
|
||||
total: number;
|
||||
totalCharacterCharged: number;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type StorageInputType = "Folder" | "File" | string;
|
||||
|
||||
// @public
|
||||
export type StorageSource = "AzureBlob" | string;
|
||||
|
||||
// @public
|
||||
export interface SupportedFileFormatsOutput {
|
||||
value: Array<FileFormatOutput>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface TargetInput {
|
||||
category?: string;
|
||||
glossaries?: Array<Glossary>;
|
||||
language: string;
|
||||
storageSource?: StorageSource;
|
||||
targetUrl: string;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type TranslationErrorCodeOutput = "InvalidRequest" | "InvalidArgument" | "InternalServerError" | "ServiceUnavailable" | "ResourceNotFound" | "Unauthorized" | "RequestRateTooHigh" | string;
|
||||
|
||||
// @public
|
||||
export interface TranslationErrorOutput {
|
||||
code: TranslationErrorCodeOutput;
|
||||
innerError?: InnerTranslationErrorOutput;
|
||||
message: string;
|
||||
readonly target?: string;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface TranslationsStatusOutput {
|
||||
nextLink?: string;
|
||||
value: Array<TranslationStatusOutput>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface TranslationStatusOutput {
|
||||
createdDateTimeUtc: string;
|
||||
error?: TranslationErrorOutput;
|
||||
id: string;
|
||||
lastActionDateTimeUtc: string;
|
||||
status: StatusOutput;
|
||||
summary: StatusSummaryOutput;
|
||||
}
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
|
||||
```
|
|
@ -0,0 +1,6 @@
|
|||
# Used in most samples.
|
||||
# Get the key and region - https://learn.microsoft.com/azure/ai-services/translator/document-translation/how-to-guides/use-rest-api-programmatically?tabs=csharp#retrieve-your-key-and-custom-domain-endpoint
|
||||
|
||||
ENDPOINT="https://<your-translator-instance>.cognitiveservices.azure.com"
|
||||
TEXT_TRANSLATOR_API_KEY="<key>"
|
||||
TEXT_TRANSLATOR_REGION="<region>"
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to make a simple call to the Azure Document Translator service to start a batch translation
|
||||
*/
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import createClient from "../src/documentTranslationClient";
|
||||
import {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} from "../test/public/utils/samplesHelper";
|
||||
import {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} from "../test/public/utils/testHelper";
|
||||
import { isUnexpected } from "../src/isUnexpected";
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
export async function main() {
|
||||
console.log("== Batch Document Translation ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const poller = await client.path("/document/batches").post({
|
||||
body: batchRequests,
|
||||
});
|
||||
if (isUnexpected(poller)) {
|
||||
throw poller.body;
|
||||
}
|
||||
const id = getTranslationOperationID(poller.headers["operation-location"]);
|
||||
console.log("Translation started and the operationID is: " + id);
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to cancel a batch translation request
|
||||
*/
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import createClient from "../src/documentTranslationClient";
|
||||
import {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} from "../test/public/utils/samplesHelper";
|
||||
import {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} from "../test/public/utils/testHelper";
|
||||
import { isUnexpected } from "../src/isUnexpected";
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
export async function main() {
|
||||
console.log("== Cancel Translation ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const poller = await client.path("/document/batches").post({
|
||||
body: batchRequests,
|
||||
});
|
||||
const id = getTranslationOperationID(poller.headers["operation-location"]);
|
||||
|
||||
//Cancel translation
|
||||
await client.path("/document/batches/{id}", id).delete();
|
||||
|
||||
//get translation status and verify the job is cancelled, cancelling or notStarted
|
||||
const response = await client.path("/document/batches/{id}", id).get();
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
console.log("The status after cancelling the batch operation is:" + response.body.status);
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to get the Document status for a given document of a batch translation operation
|
||||
*/
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import createClient from "../src/documentTranslationClient";
|
||||
import {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
StartTranslationAndWait,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} from "../test/public/utils/samplesHelper";
|
||||
import {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} from "../test/public/utils/testHelper";
|
||||
import { isUnexpected } from "../src";
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
export async function main() {
|
||||
console.log("== Get Document Status ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await StartTranslationAndWait(client, batchRequests);
|
||||
const operationLocationUrl = response.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
//get Documents Status
|
||||
const documentResponse = await client.path("/document/batches/{id}/documents", operationId).get();
|
||||
if (isUnexpected(documentResponse)) {
|
||||
throw documentResponse.body;
|
||||
}
|
||||
|
||||
const responseBody = documentResponse.body;
|
||||
for (const document of responseBody.value) {
|
||||
//get document status
|
||||
const documentStatus = await client
|
||||
.path("/document/batches/{id}/documents/{documentId}", operationId, document.id)
|
||||
.get();
|
||||
if (isUnexpected(documentStatus)) {
|
||||
throw documentStatus.body;
|
||||
}
|
||||
console.log("Document Status = " + documentStatus.status);
|
||||
const documentStatusOutput = documentStatus.body;
|
||||
console.log("Document ID = " + documentStatusOutput.id);
|
||||
console.log("Document source path = " + documentStatusOutput.sourcePath);
|
||||
console.log("Document path = " + documentStatusOutput.path);
|
||||
console.log("Target language = " + documentStatusOutput.to);
|
||||
console.log("Document created dateTime = " + documentStatusOutput.createdDateTimeUtc);
|
||||
console.log("Document last action date time = " + documentStatusOutput.lastActionDateTimeUtc);
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to get the Documents status of a batch translation operation initiated by a user
|
||||
*/
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import createClient from "../src/documentTranslationClient";
|
||||
import {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
StartTranslationAndWait,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} from "../test/public/utils/samplesHelper";
|
||||
import {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} from "../test/public/utils/testHelper";
|
||||
import { isUnexpected } from "../src/isUnexpected";
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
export async function main() {
|
||||
console.log("== Gets Documents Status ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await StartTranslationAndWait(client, batchRequests);
|
||||
const operationLocationUrl = response.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
//get Documents Status
|
||||
const documentResponse = await client.path("/document/batches/{id}/documents", operationId).get();
|
||||
if (isUnexpected(documentResponse)) {
|
||||
throw documentResponse.body;
|
||||
}
|
||||
const responseBody = documentResponse.body;
|
||||
for (const documentStatus of responseBody.value) {
|
||||
console.log("Document Status is: " + documentStatus.status);
|
||||
console.log("Characters charged is: " + documentStatus.characterCharged);
|
||||
break;
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to make a simple call to the Azure Document Translator service to get a list of supported languages
|
||||
*/
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import createClient from "../src/documentTranslationClient";
|
||||
import { isUnexpected } from "../src/isUnexpected";
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
export async function main() {
|
||||
console.log("== List Supported Format Types ==");
|
||||
|
||||
const client = createClient(endpoint, credentials);
|
||||
const response = await client.path("/document/formats").get();
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
|
||||
const fileFormatTypes = response.body;
|
||||
fileFormatTypes.value.forEach(
|
||||
(fileFormatType: { format: any; contentTypes: any; fileExtensions: any }) => {
|
||||
console.log(fileFormatType.format);
|
||||
console.log(fileFormatType.contentTypes);
|
||||
console.log(fileFormatType.fileExtensions);
|
||||
},
|
||||
);
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to get the Translations Status of a batch translation operation initiated by a user
|
||||
*/
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import createClient from "../src/documentTranslationClient";
|
||||
import {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
StartTranslationAndWait,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} from "../test/public/utils/samplesHelper";
|
||||
import {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} from "../test/public/utils/testHelper";
|
||||
import { GetTranslationStatus200Response } from "../src/responses";
|
||||
import { isUnexpected } from "../src";
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
export async function main() {
|
||||
console.log("== Get Translation Status ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const translationResponse = await StartTranslationAndWait(client, batchRequests);
|
||||
const operationLocationUrl = translationResponse.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
//get Translation Status
|
||||
const response = (await client
|
||||
.path("/document/batches/{id}", operationId)
|
||||
.get()) as GetTranslationStatus200Response;
|
||||
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
const responseBody = response.body;
|
||||
console.log("Translation ID = " + responseBody.id);
|
||||
console.log("Translation Status = " + responseBody.status);
|
||||
console.log("Translation createdDateTimeUtc = " + responseBody.createdDateTimeUtc);
|
||||
console.log("Translation lastActionDateTimeUtc = " + responseBody.lastActionDateTimeUtc);
|
||||
console.log("Total documents submitted for translation = " + responseBody.summary.total);
|
||||
console.log("Total characters charged = " + responseBody.summary.totalCharacterCharged);
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to get the Translations Status of a batch translation operation initiated by a user
|
||||
*/
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import createClient from "../src/documentTranslationClient";
|
||||
import {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
StartTranslationAndWait,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} from "../test/public/utils/samplesHelper";
|
||||
import {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} from "../test/public/utils/testHelper";
|
||||
import { isUnexpected } from "../src/isUnexpected";
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
export async function main() {
|
||||
console.log("== Get Translations Status ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const translationResponse = await StartTranslationAndWait(client, batchRequests);
|
||||
const operationLocationUrl = translationResponse.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
//get Translation Statusby ID filter
|
||||
const queryParams = {
|
||||
ids: [operationId],
|
||||
};
|
||||
const response = await client.path("/document/batches").get({
|
||||
queryParameters: queryParams,
|
||||
});
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
const responseBody = response.body;
|
||||
for (const translationStatus of responseBody.value) {
|
||||
console.log("Translation ID = " + translationStatus.id);
|
||||
console.log("Translation Status = " + translationStatus.status);
|
||||
console.log("Translation createdDateTimeUtc = " + translationStatus.createdDateTimeUtc);
|
||||
console.log("Translation lastActionDateTimeUtc = " + translationStatus.lastActionDateTimeUtc);
|
||||
console.log("Total documents submitted for translation = " + translationStatus.summary.total);
|
||||
console.log("Total characters charged = " + translationStatus.summary.totalCharacterCharged);
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to make a simple call to the Azure Document Translator service to synchronously start a single file translation
|
||||
*/
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import { DocumentTranslateParameters, isUnexpected } from "../src";
|
||||
import createClient from "../src/documentTranslationClient";
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
export async function main() {
|
||||
console.log("== Synchronous Document Translation ==");
|
||||
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const options: DocumentTranslateParameters = {
|
||||
queryParameters: {
|
||||
targetLanguage: "hi",
|
||||
},
|
||||
contentType: "multipart/form-data",
|
||||
body: [
|
||||
{
|
||||
name: "document",
|
||||
body: "This is a test.",
|
||||
filename: "test-input.txt",
|
||||
contentType: "text/html",
|
||||
},
|
||||
{
|
||||
name: "glossary",
|
||||
body: "test,test",
|
||||
filename: "test-glossary.csv",
|
||||
contentType: "text/csv",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const response = await client.path("/document:translate").post(options);
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
console.log("Response code: " + response.status + ", Response body: " + response.body);
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
page_type: sample
|
||||
languages:
|
||||
- javascript
|
||||
products:
|
||||
- azure
|
||||
- azure-cognitive-services
|
||||
- azure-translator
|
||||
urlFragment: ai-translation-document-javascript-beta
|
||||
---
|
||||
|
||||
# Azure Document Translation Service client library samples for JavaScript (Beta)
|
||||
|
||||
These sample programs show how to use the JavaScript client libraries for Azure Document Translation Service in some common scenarios.
|
||||
|
||||
| **File Name** | **Description** |
|
||||
| ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [batchDocumentTranslation.js][batchdocumenttranslation] | This sample demonstrates how to make a simple call to the Azure Document Translator service to start a batch translation |
|
||||
| [cancelTranslation.js][canceltranslation] | This sample demonstrates how to cancel a batch translation request |
|
||||
| [getDocumentStatus.js][getdocumentstatus] | This sample demonstrates how to get the Document status for a given document of a batch translation operation |
|
||||
| [getDocumentsStatus.js][getdocumentsstatus] | This sample demonstrates how to get the Documents status of a batch translation operation initiated by a user |
|
||||
| [getSupportedFormats.js][getsupportedformats] | This sample demonstrates how to make a simple call to the Azure Document Translator service to get a list of supported languages |
|
||||
| [getTranslationStatus.js][gettranslationstatus] | This sample demonstrates how to get the Translations Status of a batch translation operation initiated by a user |
|
||||
| [getTranslationsStatus.js][gettranslationsstatus] | This sample demonstrates how to get the Translations Status of a batch translation operation initiated by a user |
|
||||
| [synchronousDocumentTranslation.js][synchronousdocumenttranslation] | This sample demonstrates how to make a simple call to the Azure Document Translator service to synchronously start a single file translation |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
The sample programs are compatible with [LTS versions of Node.js](https://github.com/nodejs/release#release-schedule).
|
||||
|
||||
You need [an Azure subscription][freesub] and the following Azure resources to run these sample programs:
|
||||
|
||||
- [Azure Cognitive Services instance][createinstance_azurecognitiveservicesinstance]
|
||||
|
||||
Samples retrieve credentials to access the service endpoint from environment variables. Alternatively, edit the source code to include the appropriate credentials. See each individual sample for details on which environment variables/credentials it requires to function.
|
||||
|
||||
Adapting the samples to run in the browser may require some additional consideration. For details, please see the [package README][package].
|
||||
|
||||
## Setup
|
||||
|
||||
To run the samples using the published version of the package:
|
||||
|
||||
1. Install the dependencies using `npm`:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
2. Edit the file `sample.env`, adding the correct credentials to access the Azure service and run the samples. Then rename the file from `sample.env` to just `.env`. The sample programs will read this file automatically.
|
||||
|
||||
3. Run whichever samples you like (note that some samples may require additional setup, see the table above):
|
||||
|
||||
```bash
|
||||
node batchDocumentTranslation.js
|
||||
```
|
||||
|
||||
Alternatively, run a single sample with the correct environment variables set (setting up the `.env` file is not required if you do this), for example (cross-platform):
|
||||
|
||||
```bash
|
||||
npx cross-env ENDPOINT="<endpoint>" DOCUMENT_TRANSLATION_API_KEY="<document translation api key>" node batchDocumentTranslation.js
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
Take a look at our [API Documentation][apiref] for more information about the APIs that are available in the clients.
|
||||
|
||||
[batchdocumenttranslation]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples/v1-beta/javascript/batchDocumentTranslation.js
|
||||
[canceltranslation]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples/v1-beta/javascript/cancelTranslation.js
|
||||
[getdocumentstatus]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples/v1-beta/javascript/getDocumentStatus.js
|
||||
[getdocumentsstatus]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples/v1-beta/javascript/getDocumentsStatus.js
|
||||
[getsupportedformats]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples/v1-beta/javascript/getSupportedFormats.js
|
||||
[gettranslationstatus]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples/v1-beta/javascript/getTranslationStatus.js
|
||||
[gettranslationsstatus]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples/v1-beta/javascript/getTranslationsStatus.js
|
||||
[synchronousdocumenttranslation]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples/v1-beta/javascript/synchronousDocumentTranslation.js
|
||||
[apiref]: https://learn.microsoft.com/azure/ai-services/translator/document-translation/overview
|
||||
[freesub]: https://azure.microsoft.com/free/
|
||||
[createinstance_azurecognitiveservicesinstance]: https://docs.microsoft.com/azure/cognitive-services/cognitive-services-apis-create-account
|
||||
[package]: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/translation/ai-translation-document-rest/README.md
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to make a simple call to the Azure Document Translator service to start a batch translation
|
||||
*/
|
||||
|
||||
const dotenv = require("dotenv");
|
||||
const createClient = require("../src/documentTranslationClient").default;
|
||||
const {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} = require("../test/public/utils/samplesHelper");
|
||||
const {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} = require("../test/public/utils/testHelper");
|
||||
const { isUnexpected } = require("../src/isUnexpected");
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
async function main() {
|
||||
console.log("== Batch Document Translation ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const poller = await client.path("/document/batches").post({
|
||||
body: batchRequests,
|
||||
});
|
||||
if (isUnexpected(poller)) {
|
||||
throw poller.body;
|
||||
}
|
||||
const id = getTranslationOperationID(poller.headers["operation-location"]);
|
||||
console.log("Translation started and the operationID is: " + id);
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { main };
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to cancel a batch translation request
|
||||
*/
|
||||
|
||||
const dotenv = require("dotenv");
|
||||
const createClient = require("../src/documentTranslationClient").default;
|
||||
const {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} = require("../test/public/utils/samplesHelper");
|
||||
const {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} = require("../test/public/utils/testHelper");
|
||||
const { isUnexpected } = require("../src/isUnexpected");
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
async function main() {
|
||||
console.log("== Cancel Translation ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const poller = await client.path("/document/batches").post({
|
||||
body: batchRequests,
|
||||
});
|
||||
const id = getTranslationOperationID(poller.headers["operation-location"]);
|
||||
|
||||
//Cancel translation
|
||||
await client.path("/document/batches/{id}", id).delete();
|
||||
|
||||
//get translation status and verify the job is cancelled, cancelling or notStarted
|
||||
const response = await client.path("/document/batches/{id}", id).get();
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
console.log("The status after cancelling the batch operation is:" + response.body.status);
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { main };
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to get the Document status for a given document of a batch translation operation
|
||||
*/
|
||||
|
||||
const dotenv = require("dotenv");
|
||||
const createClient = require("../src/documentTranslationClient").default;
|
||||
const {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
StartTranslationAndWait,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} = require("../test/public/utils/samplesHelper");
|
||||
const {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} = require("../test/public/utils/testHelper");
|
||||
const { isUnexpected } = require("../src");
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
async function main() {
|
||||
console.log("== Get Document Status ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await StartTranslationAndWait(client, batchRequests);
|
||||
const operationLocationUrl = response.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
//get Documents Status
|
||||
const documentResponse = await client.path("/document/batches/{id}/documents", operationId).get();
|
||||
if (isUnexpected(documentResponse)) {
|
||||
throw documentResponse.body;
|
||||
}
|
||||
|
||||
const responseBody = documentResponse.body;
|
||||
for (const document of responseBody.value) {
|
||||
//get document status
|
||||
const documentStatus = await client
|
||||
.path("/document/batches/{id}/documents/{documentId}", operationId, document.id)
|
||||
.get();
|
||||
if (isUnexpected(documentStatus)) {
|
||||
throw documentStatus.body;
|
||||
}
|
||||
console.log("Document Status = " + documentStatus.status);
|
||||
const documentStatusOutput = documentStatus.body;
|
||||
console.log("Document ID = " + documentStatusOutput.id);
|
||||
console.log("Document source path = " + documentStatusOutput.sourcePath);
|
||||
console.log("Document path = " + documentStatusOutput.path);
|
||||
console.log("Target language = " + documentStatusOutput.to);
|
||||
console.log("Document created dateTime = " + documentStatusOutput.createdDateTimeUtc);
|
||||
console.log("Document last action date time = " + documentStatusOutput.lastActionDateTimeUtc);
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { main };
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to get the Documents status of a batch translation operation initiated by a user
|
||||
*/
|
||||
|
||||
const dotenv = require("dotenv");
|
||||
const createClient = require("../src/documentTranslationClient").default;
|
||||
const {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
StartTranslationAndWait,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} = require("../test/public/utils/samplesHelper");
|
||||
const {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} = require("../test/public/utils/testHelper");
|
||||
const { isUnexpected } = require("../src/isUnexpected");
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
async function main() {
|
||||
console.log("== Gets Documents Status ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await StartTranslationAndWait(client, batchRequests);
|
||||
const operationLocationUrl = response.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
//get Documents Status
|
||||
const documentResponse = await client.path("/document/batches/{id}/documents", operationId).get();
|
||||
if (isUnexpected(documentResponse)) {
|
||||
throw documentResponse.body;
|
||||
}
|
||||
const responseBody = documentResponse.body;
|
||||
for (const documentStatus of responseBody.value) {
|
||||
console.log("Document Status is: " + documentStatus.status);
|
||||
console.log("Characters charged is: " + documentStatus.characterCharged);
|
||||
break;
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { main };
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to make a simple call to the Azure Document Translator service to get a list of supported languages
|
||||
*/
|
||||
|
||||
const dotenv = require("dotenv");
|
||||
const createClient = require("../src/documentTranslationClient").default;
|
||||
const { isUnexpected } = require("../src/isUnexpected");
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
async function main() {
|
||||
console.log("== List Supported Format Types ==");
|
||||
|
||||
const client = createClient(endpoint, credentials);
|
||||
const response = await client.path("/document/formats").get();
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
|
||||
const fileFormatTypes = response.body;
|
||||
fileFormatTypes.value.forEach((fileFormatType) => {
|
||||
console.log(fileFormatType.format);
|
||||
console.log(fileFormatType.contentTypes);
|
||||
console.log(fileFormatType.fileExtensions);
|
||||
});
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
module.exports = { main };
|
|
@ -0,0 +1,66 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to get the Translations Status of a batch translation operation initiated by a user
|
||||
*/
|
||||
|
||||
const dotenv = require("dotenv");
|
||||
const createClient = require("../src/documentTranslationClient").default;
|
||||
const {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
StartTranslationAndWait,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} = require("../test/public/utils/samplesHelper");
|
||||
const {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} = require("../test/public/utils/testHelper");
|
||||
const { isUnexpected } = require("../src");
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
async function main() {
|
||||
console.log("== Get Translation Status ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const translationResponse = await StartTranslationAndWait(client, batchRequests);
|
||||
const operationLocationUrl = translationResponse.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
//get Translation Status
|
||||
const response = await client.path("/document/batches/{id}", operationId).get();
|
||||
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
const responseBody = response.body;
|
||||
console.log("Translation ID = " + responseBody.id);
|
||||
console.log("Translation Status = " + responseBody.status);
|
||||
console.log("Translation createdDateTimeUtc = " + responseBody.createdDateTimeUtc);
|
||||
console.log("Translation lastActionDateTimeUtc = " + responseBody.lastActionDateTimeUtc);
|
||||
console.log("Total documents submitted for translation = " + responseBody.summary.total);
|
||||
console.log("Total characters charged = " + responseBody.summary.totalCharacterCharged);
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { main };
|
|
@ -0,0 +1,72 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to get the Translations Status of a batch translation operation initiated by a user
|
||||
*/
|
||||
|
||||
const dotenv = require("dotenv");
|
||||
const createClient = require("../src/documentTranslationClient").default;
|
||||
const {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
StartTranslationAndWait,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} = require("../test/public/utils/samplesHelper");
|
||||
const {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} = require("../test/public/utils/testHelper");
|
||||
const { isUnexpected } = require("../src/isUnexpected");
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
async function main() {
|
||||
console.log("== Get Translations Status ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const translationResponse = await StartTranslationAndWait(client, batchRequests);
|
||||
const operationLocationUrl = translationResponse.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
//get Translation Statusby ID filter
|
||||
const queryParams = {
|
||||
ids: [operationId],
|
||||
};
|
||||
const response = await client.path("/document/batches").get({
|
||||
queryParameters: queryParams,
|
||||
});
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
const responseBody = response.body;
|
||||
for (const translationStatus of responseBody.value) {
|
||||
console.log("Translation ID = " + translationStatus.id);
|
||||
console.log("Translation Status = " + translationStatus.status);
|
||||
console.log("Translation createdDateTimeUtc = " + translationStatus.createdDateTimeUtc);
|
||||
console.log("Translation lastActionDateTimeUtc = " + translationStatus.lastActionDateTimeUtc);
|
||||
console.log("Total documents submitted for translation = " + translationStatus.summary.total);
|
||||
console.log("Total characters charged = " + translationStatus.summary.totalCharacterCharged);
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { main };
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "@azure-samples/ai-translation-document-js-beta",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"description": "Azure Document Translation Service client library samples for JavaScript (Beta)",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Azure/azure-sdk-for-js.git",
|
||||
"directory": "sdk/translation/ai-translation-document-rest"
|
||||
},
|
||||
"keywords": [
|
||||
"node",
|
||||
"azure",
|
||||
"cloud",
|
||||
"typescript",
|
||||
"browser",
|
||||
"isomorphic",
|
||||
"translate",
|
||||
"translation"
|
||||
],
|
||||
"author": "Microsoft Corporation",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/Azure/azure-sdk-for-js/issues"
|
||||
},
|
||||
"homepage": "https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/translation/ai-translation-document-rest",
|
||||
"dependencies": {
|
||||
"@azure-rest/ai-translation-document": "next",
|
||||
"dotenv": "latest"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
# Used in most samples.
|
||||
# Get the key and region - https://learn.microsoft.com/azure/ai-services/translator/document-translation/how-to-guides/use-rest-api-programmatically?tabs=csharp#retrieve-your-key-and-custom-domain-endpoint
|
||||
|
||||
ENDPOINT="https://<your-translator-instance>.cognitiveservices.azure.com"
|
||||
TEXT_TRANSLATOR_API_KEY="<key>"
|
||||
TEXT_TRANSLATOR_REGION="<region>"
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to make a simple call to the Azure Document Translator service to synchronously start a single file translation
|
||||
*/
|
||||
|
||||
const dotenv = require("dotenv");
|
||||
const { isUnexpected } = require("../src");
|
||||
const createClient = require("../src/documentTranslationClient").default;
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
async function main() {
|
||||
console.log("== Synchronous Document Translation ==");
|
||||
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const options = {
|
||||
queryParameters: {
|
||||
targetLanguage: "hi",
|
||||
},
|
||||
contentType: "multipart/form-data",
|
||||
body: [
|
||||
{
|
||||
name: "document",
|
||||
body: "This is a test.",
|
||||
filename: "test-input.txt",
|
||||
contentType: "text/html",
|
||||
},
|
||||
{
|
||||
name: "glossary",
|
||||
body: "test,test",
|
||||
filename: "test-glossary.csv",
|
||||
contentType: "text/csv",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const response = await client.path("/document:translate").post(options);
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
console.log("Response code: " + response.status + ", Response body: " + response.body);
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { main };
|
|
@ -0,0 +1,91 @@
|
|||
---
|
||||
page_type: sample
|
||||
languages:
|
||||
- typescript
|
||||
products:
|
||||
- azure
|
||||
- azure-cognitive-services
|
||||
- azure-translator
|
||||
urlFragment: ai-translation-document-typescript-beta
|
||||
---
|
||||
|
||||
# Azure Document Translation Service client library samples for TypeScript (Beta)
|
||||
|
||||
These sample programs show how to use the TypeScript client libraries for Azure Document Translation Service in some common scenarios.
|
||||
|
||||
| **File Name** | **Description** |
|
||||
| ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [batchDocumentTranslation.ts][batchdocumenttranslation] | This sample demonstrates how to make a simple call to the Azure Document Translator service to start a batch translation |
|
||||
| [cancelTranslation.ts][canceltranslation] | This sample demonstrates how to cancel a batch translation request |
|
||||
| [getDocumentStatus.ts][getdocumentstatus] | This sample demonstrates how to get the Document status for a given document of a batch translation operation |
|
||||
| [getDocumentsStatus.ts][getdocumentsstatus] | This sample demonstrates how to get the Documents status of a batch translation operation initiated by a user |
|
||||
| [getSupportedFormats.ts][getsupportedformats] | This sample demonstrates how to make a simple call to the Azure Document Translator service to get a list of supported languages |
|
||||
| [getTranslationStatus.ts][gettranslationstatus] | This sample demonstrates how to get the Translations Status of a batch translation operation initiated by a user |
|
||||
| [getTranslationsStatus.ts][gettranslationsstatus] | This sample demonstrates how to get the Translations Status of a batch translation operation initiated by a user |
|
||||
| [synchronousDocumentTranslation.ts][synchronousdocumenttranslation] | This sample demonstrates how to make a simple call to the Azure Document Translator service to synchronously start a single file translation |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
The sample programs are compatible with [LTS versions of Node.js](https://github.com/nodejs/release#release-schedule).
|
||||
|
||||
Before running the samples in Node, they must be compiled to JavaScript using the TypeScript compiler. For more information on TypeScript, see the [TypeScript documentation][typescript]. Install the TypeScript compiler using:
|
||||
|
||||
```bash
|
||||
npm install -g typescript
|
||||
```
|
||||
|
||||
You need [an Azure subscription][freesub] and the following Azure resources to run these sample programs:
|
||||
|
||||
- [Azure Cognitive Services instance][createinstance_azurecognitiveservicesinstance]
|
||||
|
||||
Samples retrieve credentials to access the service endpoint from environment variables. Alternatively, edit the source code to include the appropriate credentials. See each individual sample for details on which environment variables/credentials it requires to function.
|
||||
|
||||
Adapting the samples to run in the browser may require some additional consideration. For details, please see the [package README][package].
|
||||
|
||||
## Setup
|
||||
|
||||
To run the samples using the published version of the package:
|
||||
|
||||
1. Install the dependencies using `npm`:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
2. Compile the samples:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
3. Edit the file `sample.env`, adding the correct credentials to access the Azure service and run the samples. Then rename the file from `sample.env` to just `.env`. The sample programs will read this file automatically.
|
||||
|
||||
4. Run whichever samples you like (note that some samples may require additional setup, see the table above):
|
||||
|
||||
```bash
|
||||
node dist/batchDocumentTranslation.js
|
||||
```
|
||||
|
||||
Alternatively, run a single sample with the correct environment variables set (setting up the `.env` file is not required if you do this), for example (cross-platform):
|
||||
|
||||
```bash
|
||||
npx cross-env ENDPOINT="<endpoint>" DOCUMENT_TRANSLATION_API_KEY="<document translation api key>" node dist/batchDocumentTranslation.js
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
Take a look at our [API Documentation][apiref] for more information about the APIs that are available in the clients.
|
||||
|
||||
[batchdocumenttranslation]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples/v1-beta/typescript/src/batchDocumentTranslation.ts
|
||||
[canceltranslation]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples/v1-beta/typescript/src/cancelTranslation.ts
|
||||
[getdocumentstatus]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples/v1-beta/typescript/src/getDocumentStatus.ts
|
||||
[getdocumentsstatus]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples/v1-beta/typescript/src/getDocumentsStatus.ts
|
||||
[getsupportedformats]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples/v1-beta/typescript/src/getSupportedFormats.ts
|
||||
[gettranslationstatus]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples/v1-beta/typescript/src/getTranslationStatus.ts
|
||||
[gettranslationsstatus]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples/v1-beta/typescript/src/getTranslationsStatus.ts
|
||||
[synchronousdocumenttranslation]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/translation/ai-translation-document-rest/samples/v1-beta/typescript/src/synchronousDocumentTranslation.ts
|
||||
[apiref]: https://learn.microsoft.com/azure/ai-services/translator/document-translation/overview
|
||||
[freesub]: https://azure.microsoft.com/free/
|
||||
[createinstance_azurecognitiveservicesinstance]: https://docs.microsoft.com/azure/cognitive-services/cognitive-services-apis-create-account
|
||||
[package]: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/translation/ai-translation-document-rest/README.md
|
||||
[typescript]: https://www.typescriptlang.org/docs/home.html
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"name": "@azure-samples/ai-translation-document-ts-beta",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"description": "Azure Document Translation Service client library samples for TypeScript (Beta)",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"prebuild": "rimraf dist/"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Azure/azure-sdk-for-js.git",
|
||||
"directory": "sdk/translation/ai-translation-document-rest"
|
||||
},
|
||||
"keywords": [
|
||||
"node",
|
||||
"azure",
|
||||
"cloud",
|
||||
"typescript",
|
||||
"browser",
|
||||
"isomorphic",
|
||||
"translate",
|
||||
"translation"
|
||||
],
|
||||
"author": "Microsoft Corporation",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/Azure/azure-sdk-for-js/issues"
|
||||
},
|
||||
"homepage": "https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/translation/ai-translation-document-rest",
|
||||
"dependencies": {
|
||||
"@azure-rest/ai-translation-document": "next",
|
||||
"dotenv": "latest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.0.0",
|
||||
"typescript": "~5.4.5",
|
||||
"rimraf": "latest"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
# Used in most samples.
|
||||
# Get the key and region - https://learn.microsoft.com/azure/ai-services/translator/document-translation/how-to-guides/use-rest-api-programmatically?tabs=csharp#retrieve-your-key-and-custom-domain-endpoint
|
||||
|
||||
ENDPOINT="https://<your-translator-instance>.cognitiveservices.azure.com"
|
||||
TEXT_TRANSLATOR_API_KEY="<key>"
|
||||
TEXT_TRANSLATOR_REGION="<region>"
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to make a simple call to the Azure Document Translator service to start a batch translation
|
||||
*/
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import createClient from "../src/documentTranslationClient";
|
||||
import {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} from "../test/public/utils/samplesHelper";
|
||||
import {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} from "../test/public/utils/testHelper";
|
||||
import { isUnexpected } from "../src/isUnexpected";
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
export async function main() {
|
||||
console.log("== Batch Document Translation ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const poller = await client.path("/document/batches").post({
|
||||
body: batchRequests,
|
||||
});
|
||||
if (isUnexpected(poller)) {
|
||||
throw poller.body;
|
||||
}
|
||||
const id = getTranslationOperationID(poller.headers["operation-location"]);
|
||||
console.log("Translation started and the operationID is: " + id);
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to cancel a batch translation request
|
||||
*/
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import createClient from "../src/documentTranslationClient";
|
||||
import {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} from "../test/public/utils/samplesHelper";
|
||||
import {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} from "../test/public/utils/testHelper";
|
||||
import { isUnexpected } from "../src/isUnexpected";
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
export async function main() {
|
||||
console.log("== Cancel Translation ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const poller = await client.path("/document/batches").post({
|
||||
body: batchRequests,
|
||||
});
|
||||
const id = getTranslationOperationID(poller.headers["operation-location"]);
|
||||
|
||||
//Cancel translation
|
||||
await client.path("/document/batches/{id}", id).delete();
|
||||
|
||||
//get translation status and verify the job is cancelled, cancelling or notStarted
|
||||
const response = await client.path("/document/batches/{id}", id).get();
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
console.log("The status after cancelling the batch operation is:" + response.body.status);
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to get the Document status for a given document of a batch translation operation
|
||||
*/
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import createClient from "../src/documentTranslationClient";
|
||||
import {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
StartTranslationAndWait,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} from "../test/public/utils/samplesHelper";
|
||||
import {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} from "../test/public/utils/testHelper";
|
||||
import { isUnexpected } from "../src";
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
export async function main() {
|
||||
console.log("== Get Document Status ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await StartTranslationAndWait(client, batchRequests);
|
||||
const operationLocationUrl = response.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
//get Documents Status
|
||||
const documentResponse = await client.path("/document/batches/{id}/documents", operationId).get();
|
||||
if (isUnexpected(documentResponse)) {
|
||||
throw documentResponse.body;
|
||||
}
|
||||
|
||||
const responseBody = documentResponse.body;
|
||||
for (const document of responseBody.value) {
|
||||
//get document status
|
||||
const documentStatus = await client
|
||||
.path("/document/batches/{id}/documents/{documentId}", operationId, document.id)
|
||||
.get();
|
||||
if (isUnexpected(documentStatus)) {
|
||||
throw documentStatus.body;
|
||||
}
|
||||
console.log("Document Status = " + documentStatus.status);
|
||||
const documentStatusOutput = documentStatus.body;
|
||||
console.log("Document ID = " + documentStatusOutput.id);
|
||||
console.log("Document source path = " + documentStatusOutput.sourcePath);
|
||||
console.log("Document path = " + documentStatusOutput.path);
|
||||
console.log("Target language = " + documentStatusOutput.to);
|
||||
console.log("Document created dateTime = " + documentStatusOutput.createdDateTimeUtc);
|
||||
console.log("Document last action date time = " + documentStatusOutput.lastActionDateTimeUtc);
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to get the Documents status of a batch translation operation initiated by a user
|
||||
*/
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import createClient from "../src/documentTranslationClient";
|
||||
import {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
StartTranslationAndWait,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} from "../test/public/utils/samplesHelper";
|
||||
import {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} from "../test/public/utils/testHelper";
|
||||
import { isUnexpected } from "../src/isUnexpected";
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
export async function main() {
|
||||
console.log("== Gets Documents Status ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await StartTranslationAndWait(client, batchRequests);
|
||||
const operationLocationUrl = response.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
//get Documents Status
|
||||
const documentResponse = await client.path("/document/batches/{id}/documents", operationId).get();
|
||||
if (isUnexpected(documentResponse)) {
|
||||
throw documentResponse.body;
|
||||
}
|
||||
const responseBody = documentResponse.body;
|
||||
for (const documentStatus of responseBody.value) {
|
||||
console.log("Document Status is: " + documentStatus.status);
|
||||
console.log("Characters charged is: " + documentStatus.characterCharged);
|
||||
break;
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to make a simple call to the Azure Document Translator service to get a list of supported languages
|
||||
*/
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import createClient from "../src/documentTranslationClient";
|
||||
import { isUnexpected } from "../src/isUnexpected";
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
export async function main() {
|
||||
console.log("== List Supported Format Types ==");
|
||||
|
||||
const client = createClient(endpoint, credentials);
|
||||
const response = await client.path("/document/formats").get();
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
|
||||
const fileFormatTypes = response.body;
|
||||
fileFormatTypes.value.forEach(
|
||||
(fileFormatType: { format: any; contentTypes: any; fileExtensions: any }) => {
|
||||
console.log(fileFormatType.format);
|
||||
console.log(fileFormatType.contentTypes);
|
||||
console.log(fileFormatType.fileExtensions);
|
||||
},
|
||||
);
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to get the Translations Status of a batch translation operation initiated by a user
|
||||
*/
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import createClient from "../src/documentTranslationClient";
|
||||
import {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
StartTranslationAndWait,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} from "../test/public/utils/samplesHelper";
|
||||
import {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} from "../test/public/utils/testHelper";
|
||||
import { GetTranslationStatus200Response } from "../src/responses";
|
||||
import { isUnexpected } from "../src";
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
export async function main() {
|
||||
console.log("== Get Translation Status ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const translationResponse = await StartTranslationAndWait(client, batchRequests);
|
||||
const operationLocationUrl = translationResponse.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
//get Translation Status
|
||||
const response = (await client
|
||||
.path("/document/batches/{id}", operationId)
|
||||
.get()) as GetTranslationStatus200Response;
|
||||
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
const responseBody = response.body;
|
||||
console.log("Translation ID = " + responseBody.id);
|
||||
console.log("Translation Status = " + responseBody.status);
|
||||
console.log("Translation createdDateTimeUtc = " + responseBody.createdDateTimeUtc);
|
||||
console.log("Translation lastActionDateTimeUtc = " + responseBody.lastActionDateTimeUtc);
|
||||
console.log("Total documents submitted for translation = " + responseBody.summary.total);
|
||||
console.log("Total characters charged = " + responseBody.summary.totalCharacterCharged);
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to get the Translations Status of a batch translation operation initiated by a user
|
||||
*/
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import createClient from "../src/documentTranslationClient";
|
||||
import {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
StartTranslationAndWait,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} from "../test/public/utils/samplesHelper";
|
||||
import {
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
createBatchRequest,
|
||||
getTranslationOperationID,
|
||||
} from "../test/public/utils/testHelper";
|
||||
import { isUnexpected } from "../src/isUnexpected";
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
export async function main() {
|
||||
console.log("== Get Translations Status ==");
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const sourceUrl = await createSourceContainer(ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer();
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
//Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const translationResponse = await StartTranslationAndWait(client, batchRequests);
|
||||
const operationLocationUrl = translationResponse.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
//get Translation Statusby ID filter
|
||||
const queryParams = {
|
||||
ids: [operationId],
|
||||
};
|
||||
const response = await client.path("/document/batches").get({
|
||||
queryParameters: queryParams,
|
||||
});
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
const responseBody = response.body;
|
||||
for (const translationStatus of responseBody.value) {
|
||||
console.log("Translation ID = " + translationStatus.id);
|
||||
console.log("Translation Status = " + translationStatus.status);
|
||||
console.log("Translation createdDateTimeUtc = " + translationStatus.createdDateTimeUtc);
|
||||
console.log("Translation lastActionDateTimeUtc = " + translationStatus.lastActionDateTimeUtc);
|
||||
console.log("Total documents submitted for translation = " + translationStatus.summary.total);
|
||||
console.log("Total characters charged = " + translationStatus.summary.totalCharacterCharged);
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @summary This sample demonstrates how to make a simple call to the Azure Document Translator service to synchronously start a single file translation
|
||||
*/
|
||||
|
||||
import * as dotenv from "dotenv";
|
||||
import { DocumentTranslateParameters, isUnexpected } from "../src";
|
||||
import createClient from "../src/documentTranslationClient";
|
||||
dotenv.config();
|
||||
|
||||
const endpoint =
|
||||
process.env["ENDPOINT"] ||
|
||||
"https://<translator-instance>-doctranslation.cognitiveservices.azure.com";
|
||||
const apiKey = process.env["DOCUMENT_TRANSLATION_API_KEY"] || "<API_Key>";
|
||||
const credentials = { key: apiKey ?? "" };
|
||||
|
||||
export async function main() {
|
||||
console.log("== Synchronous Document Translation ==");
|
||||
|
||||
const client = createClient(endpoint, credentials);
|
||||
|
||||
const options: DocumentTranslateParameters = {
|
||||
queryParameters: {
|
||||
targetLanguage: "hi",
|
||||
},
|
||||
contentType: "multipart/form-data",
|
||||
body: [
|
||||
{
|
||||
name: "document",
|
||||
body: "This is a test.",
|
||||
filename: "test-input.txt",
|
||||
contentType: "text/html",
|
||||
},
|
||||
{
|
||||
name: "glossary",
|
||||
body: "test,test",
|
||||
filename: "test-glossary.csv",
|
||||
contentType: "text/csv",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const response = await client.path("/document:translate").post(options);
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
console.log("Response code: " + response.status + ", Response body: " + response.body);
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"alwaysStrict": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,247 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
DocumentTranslateParameters,
|
||||
StartTranslationParameters,
|
||||
GetTranslationsStatusParameters,
|
||||
GetDocumentStatusParameters,
|
||||
GetTranslationStatusParameters,
|
||||
CancelTranslationParameters,
|
||||
GetDocumentsStatusParameters,
|
||||
GetSupportedFormatsParameters,
|
||||
} from "./parameters.js";
|
||||
import {
|
||||
DocumentTranslate200Response,
|
||||
DocumentTranslateDefaultResponse,
|
||||
StartTranslation202Response,
|
||||
StartTranslationDefaultResponse,
|
||||
GetTranslationsStatus200Response,
|
||||
GetTranslationsStatusDefaultResponse,
|
||||
GetDocumentStatus200Response,
|
||||
GetDocumentStatusDefaultResponse,
|
||||
GetTranslationStatus200Response,
|
||||
GetTranslationStatusDefaultResponse,
|
||||
CancelTranslation200Response,
|
||||
CancelTranslationDefaultResponse,
|
||||
GetDocumentsStatus200Response,
|
||||
GetDocumentsStatusDefaultResponse,
|
||||
GetSupportedFormats200Response,
|
||||
GetSupportedFormatsDefaultResponse,
|
||||
} from "./responses.js";
|
||||
import { Client, StreamableMethod } from "@azure-rest/core-client";
|
||||
|
||||
export interface DocumentTranslate {
|
||||
/** Use this API to submit a single translation request to the Document Translation Service. */
|
||||
post(
|
||||
options: DocumentTranslateParameters,
|
||||
): StreamableMethod<DocumentTranslate200Response | DocumentTranslateDefaultResponse>;
|
||||
}
|
||||
|
||||
export interface StartTranslation {
|
||||
/**
|
||||
* Use this API to submit a bulk (batch) translation request to the Document
|
||||
* Translation service.
|
||||
* Each request can contain multiple documents and must
|
||||
* contain a source and destination container for each document.
|
||||
*
|
||||
* The
|
||||
* prefix and suffix filter (if supplied) are used to filter folders. The prefix
|
||||
* is applied to the subpath after the container name.
|
||||
*
|
||||
* Glossaries /
|
||||
* Translation memory can be included in the request and are applied by the
|
||||
* service when the document is translated.
|
||||
*
|
||||
* If the glossary is
|
||||
* invalid or unreachable during translation, an error is indicated in the
|
||||
* document status.
|
||||
* If a file with the same name already exists at the
|
||||
* destination, it will be overwritten. The targetUrl for each target language
|
||||
* must be unique.
|
||||
*/
|
||||
post(
|
||||
options?: StartTranslationParameters,
|
||||
): StreamableMethod<StartTranslation202Response | StartTranslationDefaultResponse>;
|
||||
/**
|
||||
* Returns a list of batch requests submitted and the status for each
|
||||
* request.
|
||||
* This list only contains batch requests submitted by the user (based on
|
||||
* the resource).
|
||||
*
|
||||
* If the number of requests exceeds our paging limit,
|
||||
* server-side paging is used. Paginated responses indicate a partial result and
|
||||
* include a continuation token in the response.
|
||||
* The absence of a continuation
|
||||
* token means that no additional pages are available.
|
||||
*
|
||||
* top, skip
|
||||
* and maxpagesize query parameters can be used to specify a number of results to
|
||||
* return and an offset for the collection.
|
||||
*
|
||||
* top indicates the total
|
||||
* number of records the user wants to be returned across all pages.
|
||||
* skip
|
||||
* indicates the number of records to skip from the list of batches based on the
|
||||
* sorting method specified. By default, we sort by descending start
|
||||
* time.
|
||||
* maxpagesize is the maximum items returned in a page. If more items are
|
||||
* requested via top (or top is not specified and there are more items to be
|
||||
* returned), @nextLink will contain the link to the next page.
|
||||
*
|
||||
*
|
||||
* orderby query parameter can be used to sort the returned list (ex
|
||||
* "orderby=createdDateTimeUtc asc" or "orderby=createdDateTimeUtc
|
||||
* desc").
|
||||
* The default sorting is descending by createdDateTimeUtc.
|
||||
* Some query
|
||||
* parameters can be used to filter the returned list (ex:
|
||||
* "status=Succeeded,Cancelled") will only return succeeded and cancelled
|
||||
* operations.
|
||||
* createdDateTimeUtcStart and createdDateTimeUtcEnd can be used
|
||||
* combined or separately to specify a range of datetime to filter the returned
|
||||
* list by.
|
||||
* The supported filtering query parameters are (status, ids,
|
||||
* createdDateTimeUtcStart, createdDateTimeUtcEnd).
|
||||
*
|
||||
* The server honors
|
||||
* the values specified by the client. However, clients must be prepared to handle
|
||||
* responses that contain a different page size or contain a continuation token.
|
||||
*
|
||||
*
|
||||
* When both top and skip are included, the server should first apply
|
||||
* skip and then top on the collection.
|
||||
* Note: If the server can't honor top
|
||||
* and/or skip, the server must return an error to the client informing about it
|
||||
* instead of just ignoring the query options.
|
||||
* This reduces the risk of the client
|
||||
* making assumptions about the data returned.
|
||||
*/
|
||||
get(
|
||||
options?: GetTranslationsStatusParameters,
|
||||
): StreamableMethod<GetTranslationsStatus200Response | GetTranslationsStatusDefaultResponse>;
|
||||
}
|
||||
|
||||
export interface GetDocumentStatus {
|
||||
/**
|
||||
* Returns the translation status for a specific document based on the request Id
|
||||
* and document Id.
|
||||
*/
|
||||
get(
|
||||
options?: GetDocumentStatusParameters,
|
||||
): StreamableMethod<GetDocumentStatus200Response | GetDocumentStatusDefaultResponse>;
|
||||
}
|
||||
|
||||
export interface GetTranslationStatus {
|
||||
/**
|
||||
* Returns the status for a document translation request.
|
||||
* The status includes the
|
||||
* overall request status, as well as the status for documents that are being
|
||||
* translated as part of that request.
|
||||
*/
|
||||
get(
|
||||
options?: GetTranslationStatusParameters,
|
||||
): StreamableMethod<GetTranslationStatus200Response | GetTranslationStatusDefaultResponse>;
|
||||
/**
|
||||
* Cancel a currently processing or queued translation.
|
||||
* A translation will not be
|
||||
* cancelled if it is already completed or failed or cancelling. A bad request
|
||||
* will be returned.
|
||||
* All documents that have completed translation will not be
|
||||
* cancelled and will be charged.
|
||||
* All pending documents will be cancelled if
|
||||
* possible.
|
||||
*/
|
||||
delete(
|
||||
options?: CancelTranslationParameters,
|
||||
): StreamableMethod<CancelTranslation200Response | CancelTranslationDefaultResponse>;
|
||||
}
|
||||
|
||||
export interface GetDocumentsStatus {
|
||||
/**
|
||||
* Returns the status for all documents in a batch document translation request.
|
||||
*
|
||||
*
|
||||
* If the number of documents in the response exceeds our paging limit,
|
||||
* server-side paging is used.
|
||||
* Paginated responses indicate a partial result and
|
||||
* include a continuation token in the response. The absence of a continuation
|
||||
* token means that no additional pages are available.
|
||||
*
|
||||
* top, skip
|
||||
* and maxpagesize query parameters can be used to specify a number of results to
|
||||
* return and an offset for the collection.
|
||||
*
|
||||
* top indicates the total
|
||||
* number of records the user wants to be returned across all pages.
|
||||
* skip
|
||||
* indicates the number of records to skip from the list of document status held
|
||||
* by the server based on the sorting method specified. By default, we sort by
|
||||
* descending start time.
|
||||
* maxpagesize is the maximum items returned in a page.
|
||||
* If more items are requested via top (or top is not specified and there are
|
||||
* more items to be returned), @nextLink will contain the link to the next page.
|
||||
*
|
||||
*
|
||||
* orderby query parameter can be used to sort the returned list (ex
|
||||
* "orderby=createdDateTimeUtc asc" or "orderby=createdDateTimeUtc
|
||||
* desc").
|
||||
* The default sorting is descending by createdDateTimeUtc.
|
||||
* Some query
|
||||
* parameters can be used to filter the returned list (ex:
|
||||
* "status=Succeeded,Cancelled") will only return succeeded and cancelled
|
||||
* documents.
|
||||
* createdDateTimeUtcStart and createdDateTimeUtcEnd can be used
|
||||
* combined or separately to specify a range of datetime to filter the returned
|
||||
* list by.
|
||||
* The supported filtering query parameters are (status, ids,
|
||||
* createdDateTimeUtcStart, createdDateTimeUtcEnd).
|
||||
*
|
||||
* When both top
|
||||
* and skip are included, the server should first apply skip and then top on
|
||||
* the collection.
|
||||
* Note: If the server can't honor top and/or skip, the server
|
||||
* must return an error to the client informing about it instead of just ignoring
|
||||
* the query options.
|
||||
* This reduces the risk of the client making assumptions about
|
||||
* the data returned.
|
||||
*/
|
||||
get(
|
||||
options?: GetDocumentsStatusParameters,
|
||||
): StreamableMethod<GetDocumentsStatus200Response | GetDocumentsStatusDefaultResponse>;
|
||||
}
|
||||
|
||||
export interface GetSupportedFormats {
|
||||
/**
|
||||
* The list of supported formats supported by the Document Translation
|
||||
* service.
|
||||
* The list includes the common file extension, as well as the
|
||||
* content-type if using the upload API.
|
||||
*/
|
||||
get(
|
||||
options?: GetSupportedFormatsParameters,
|
||||
): StreamableMethod<GetSupportedFormats200Response | GetSupportedFormatsDefaultResponse>;
|
||||
}
|
||||
|
||||
export interface Routes {
|
||||
/** Resource for '/document:translate' has methods for the following verbs: post */
|
||||
(path: "/document:translate"): DocumentTranslate;
|
||||
/** Resource for '/document/batches' has methods for the following verbs: post, get */
|
||||
(path: "/document/batches"): StartTranslation;
|
||||
/** Resource for '/document/batches/\{id\}/documents/\{documentId\}' has methods for the following verbs: get */
|
||||
(
|
||||
path: "/document/batches/{id}/documents/{documentId}",
|
||||
id: string,
|
||||
documentId: string,
|
||||
): GetDocumentStatus;
|
||||
/** Resource for '/document/batches/\{id\}' has methods for the following verbs: get, delete */
|
||||
(path: "/document/batches/{id}", id: string): GetTranslationStatus;
|
||||
/** Resource for '/document/batches/\{id\}/documents' has methods for the following verbs: get */
|
||||
(path: "/document/batches/{id}/documents", id: string): GetDocumentsStatus;
|
||||
/** Resource for '/document/formats' has methods for the following verbs: get */
|
||||
(path: "/document/formats"): GetSupportedFormats;
|
||||
}
|
||||
|
||||
export type DocumentTranslationClient = Client & {
|
||||
path: Routes;
|
||||
};
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { getClient, ClientOptions } from "@azure-rest/core-client";
|
||||
import { logger } from "./logger";
|
||||
import { TokenCredential, KeyCredential } from "@azure/core-auth";
|
||||
import { DocumentTranslationClient } from "./clientDefinitions";
|
||||
|
||||
/**
|
||||
* Initialize a new instance of `DocumentTranslationClient`
|
||||
* @param endpointParam - Supported document Translation endpoint, protocol and hostname, for example: https://{TranslatorResourceName}.cognitiveservices.azure.com/translator.
|
||||
* @param credentials - uniquely identify client credential
|
||||
* @param options - the parameter for all optional parameters
|
||||
*/
|
||||
export default function createClient(
|
||||
endpointParam: string,
|
||||
credentials: TokenCredential | KeyCredential,
|
||||
options: ClientOptions = {},
|
||||
): DocumentTranslationClient {
|
||||
const endpointUrl = options.endpoint ?? options.baseUrl ?? `${endpointParam}/translator`;
|
||||
options.apiVersion = options.apiVersion ?? "2024-05-01";
|
||||
const userAgentInfo = `azsdk-js-ai-translation-document-rest/1.0.0-beta.1`;
|
||||
const userAgentPrefix =
|
||||
options.userAgentOptions && options.userAgentOptions.userAgentPrefix
|
||||
? `${options.userAgentOptions.userAgentPrefix} ${userAgentInfo}`
|
||||
: `${userAgentInfo}`;
|
||||
options = {
|
||||
...options,
|
||||
userAgentOptions: {
|
||||
userAgentPrefix,
|
||||
},
|
||||
loggingOptions: {
|
||||
logger: options.loggingOptions?.logger ?? logger.info,
|
||||
},
|
||||
credentials: {
|
||||
scopes: options.credentials?.scopes ?? ["https://cognitiveservices.azure.com/.default"],
|
||||
apiKeyHeaderName: options.credentials?.apiKeyHeaderName ?? "Ocp-Apim-Subscription-Key",
|
||||
},
|
||||
};
|
||||
|
||||
const client = getClient(endpointUrl, credentials, options) as DocumentTranslationClient;
|
||||
|
||||
return client;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import DocumentTranslationClient from "./documentTranslationClient";
|
||||
|
||||
export * from "./documentTranslationClient";
|
||||
export * from "./parameters";
|
||||
export * from "./responses";
|
||||
export * from "./clientDefinitions";
|
||||
export * from "./isUnexpected";
|
||||
export * from "./models";
|
||||
export * from "./outputModels";
|
||||
export * from "./paginateHelper";
|
||||
export * from "./pollingHelper";
|
||||
export {
|
||||
createFile,
|
||||
createFileFromStream,
|
||||
type CreateFileOptions,
|
||||
type CreateFileFromStreamOptions,
|
||||
} from "@azure/core-rest-pipeline";
|
||||
|
||||
export default DocumentTranslationClient;
|
|
@ -0,0 +1,164 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
DocumentTranslate200Response,
|
||||
DocumentTranslateDefaultResponse,
|
||||
StartTranslation202Response,
|
||||
StartTranslationLogicalResponse,
|
||||
StartTranslationDefaultResponse,
|
||||
GetTranslationsStatus200Response,
|
||||
GetTranslationsStatusDefaultResponse,
|
||||
GetDocumentStatus200Response,
|
||||
GetDocumentStatusDefaultResponse,
|
||||
GetTranslationStatus200Response,
|
||||
GetTranslationStatusDefaultResponse,
|
||||
CancelTranslation200Response,
|
||||
CancelTranslationDefaultResponse,
|
||||
GetDocumentsStatus200Response,
|
||||
GetDocumentsStatusDefaultResponse,
|
||||
GetSupportedFormats200Response,
|
||||
GetSupportedFormatsDefaultResponse,
|
||||
} from "./responses.js";
|
||||
|
||||
const responseMap: Record<string, string[]> = {
|
||||
"POST /document:translate": ["200"],
|
||||
"GET /document/batches": ["200"],
|
||||
"POST /document/batches": ["202"],
|
||||
"GET /document/batches/{id}/documents/{documentId}": ["200"],
|
||||
"GET /document/batches/{id}": ["200"],
|
||||
"DELETE /document/batches/{id}": ["200"],
|
||||
"GET /document/batches/{id}/documents": ["200"],
|
||||
"GET /document/formats": ["200"],
|
||||
};
|
||||
|
||||
export function isUnexpected(
|
||||
response: DocumentTranslate200Response | DocumentTranslateDefaultResponse,
|
||||
): response is DocumentTranslateDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| StartTranslation202Response
|
||||
| StartTranslationLogicalResponse
|
||||
| StartTranslationDefaultResponse,
|
||||
): response is StartTranslationDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: GetTranslationsStatus200Response | GetTranslationsStatusDefaultResponse,
|
||||
): response is GetTranslationsStatusDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: GetDocumentStatus200Response | GetDocumentStatusDefaultResponse,
|
||||
): response is GetDocumentStatusDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: GetTranslationStatus200Response | GetTranslationStatusDefaultResponse,
|
||||
): response is GetTranslationStatusDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: CancelTranslation200Response | CancelTranslationDefaultResponse,
|
||||
): response is CancelTranslationDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: GetDocumentsStatus200Response | GetDocumentsStatusDefaultResponse,
|
||||
): response is GetDocumentsStatusDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response: GetSupportedFormats200Response | GetSupportedFormatsDefaultResponse,
|
||||
): response is GetSupportedFormatsDefaultResponse;
|
||||
export function isUnexpected(
|
||||
response:
|
||||
| DocumentTranslate200Response
|
||||
| DocumentTranslateDefaultResponse
|
||||
| StartTranslation202Response
|
||||
| StartTranslationLogicalResponse
|
||||
| StartTranslationDefaultResponse
|
||||
| GetTranslationsStatus200Response
|
||||
| GetTranslationsStatusDefaultResponse
|
||||
| GetDocumentStatus200Response
|
||||
| GetDocumentStatusDefaultResponse
|
||||
| GetTranslationStatus200Response
|
||||
| GetTranslationStatusDefaultResponse
|
||||
| CancelTranslation200Response
|
||||
| CancelTranslationDefaultResponse
|
||||
| GetDocumentsStatus200Response
|
||||
| GetDocumentsStatusDefaultResponse
|
||||
| GetSupportedFormats200Response
|
||||
| GetSupportedFormatsDefaultResponse,
|
||||
): response is
|
||||
| DocumentTranslateDefaultResponse
|
||||
| StartTranslationDefaultResponse
|
||||
| GetTranslationsStatusDefaultResponse
|
||||
| GetDocumentStatusDefaultResponse
|
||||
| GetTranslationStatusDefaultResponse
|
||||
| CancelTranslationDefaultResponse
|
||||
| GetDocumentsStatusDefaultResponse
|
||||
| GetSupportedFormatsDefaultResponse {
|
||||
const lroOriginal = response.headers["x-ms-original-url"];
|
||||
const url = new URL(lroOriginal ?? response.request.url);
|
||||
const method = response.request.method;
|
||||
let pathDetails = responseMap[`${method} ${url.pathname}`];
|
||||
if (!pathDetails) {
|
||||
pathDetails = getParametrizedPathSuccess(method, url.pathname);
|
||||
}
|
||||
return !pathDetails.includes(response.status);
|
||||
}
|
||||
|
||||
function getParametrizedPathSuccess(method: string, path: string): string[] {
|
||||
const pathParts = path.split("/");
|
||||
|
||||
// Traverse list to match the longest candidate
|
||||
// matchedLen: the length of candidate path
|
||||
// matchedValue: the matched status code array
|
||||
let matchedLen = -1,
|
||||
matchedValue: string[] = [];
|
||||
|
||||
// Iterate the responseMap to find a match
|
||||
for (const [key, value] of Object.entries(responseMap)) {
|
||||
// Extracting the path from the map key which is in format
|
||||
// GET /path/foo
|
||||
if (!key.startsWith(method)) {
|
||||
continue;
|
||||
}
|
||||
const candidatePath = getPathFromMapKey(key);
|
||||
// Get each part of the url path
|
||||
const candidateParts = candidatePath.split("/");
|
||||
|
||||
// track if we have found a match to return the values found.
|
||||
let found = true;
|
||||
for (let i = candidateParts.length - 1, j = pathParts.length - 1; i >= 1 && j >= 1; i--, j--) {
|
||||
if (candidateParts[i]?.startsWith("{") && candidateParts[i]?.indexOf("}") !== -1) {
|
||||
const start = candidateParts[i]!.indexOf("}") + 1,
|
||||
end = candidateParts[i]?.length;
|
||||
// If the current part of the candidate is a "template" part
|
||||
// Try to use the suffix of pattern to match the path
|
||||
// {guid} ==> $
|
||||
// {guid}:export ==> :export$
|
||||
const isMatched = new RegExp(`${candidateParts[i]?.slice(start, end)}`).test(
|
||||
pathParts[j] || "",
|
||||
);
|
||||
|
||||
if (!isMatched) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the candidate part is not a template and
|
||||
// the parts don't match mark the candidate as not found
|
||||
// to move on with the next candidate path.
|
||||
if (candidateParts[i] !== pathParts[j]) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We finished evaluating the current candidate parts
|
||||
// Update the matched value if and only if we found the longer pattern
|
||||
if (found && candidatePath.length > matchedLen) {
|
||||
matchedLen = candidatePath.length;
|
||||
matchedValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
return matchedValue;
|
||||
}
|
||||
|
||||
function getPathFromMapKey(mapKey: string): string {
|
||||
const pathStart = mapKey.indexOf("/");
|
||||
return mapKey.slice(pathStart);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { createClientLogger } from "@azure/logger";
|
||||
export const logger = createClientLogger("ai-translation-document");
|
|
@ -0,0 +1,111 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export interface DocumentTranslateContentDocumentPartDescriptor {
|
||||
name: "document";
|
||||
body: string | Uint8Array | ReadableStream<Uint8Array> | NodeJS.ReadableStream | File;
|
||||
filename?: string;
|
||||
contentType?: string;
|
||||
}
|
||||
|
||||
export interface DocumentTranslateContentGlossaryPartDescriptor {
|
||||
name: "glossary";
|
||||
body: string | Uint8Array | ReadableStream<Uint8Array> | NodeJS.ReadableStream | File;
|
||||
filename?: string;
|
||||
contentType?: string;
|
||||
}
|
||||
|
||||
/** Translation job submission batch request */
|
||||
export interface StartTranslationDetails {
|
||||
/** The input list of documents or folders containing documents */
|
||||
inputs: Array<BatchRequest>;
|
||||
}
|
||||
|
||||
/** Definition for the input batch translation request */
|
||||
export interface BatchRequest {
|
||||
/** Source of the input documents */
|
||||
source: SourceInput;
|
||||
/** Location of the destination for the output */
|
||||
targets: Array<TargetInput>;
|
||||
/** Storage type of the input documents source string */
|
||||
storageType?: StorageInputType;
|
||||
}
|
||||
|
||||
/** Source of the input documents */
|
||||
export interface SourceInput {
|
||||
/** Location of the folder / container or single file with your documents */
|
||||
sourceUrl: string;
|
||||
/** Document filter */
|
||||
filter?: DocumentFilter;
|
||||
/**
|
||||
* Language code
|
||||
* If none is specified, we will perform auto detect on the document
|
||||
*/
|
||||
language?: string;
|
||||
/** Storage Source */
|
||||
storageSource?: StorageSource;
|
||||
}
|
||||
|
||||
/** Document filter */
|
||||
export interface DocumentFilter {
|
||||
/**
|
||||
* A case-sensitive prefix string to filter documents in the source path for
|
||||
* translation.
|
||||
* For example, when using a Azure storage blob Uri, use the prefix
|
||||
* to restrict sub folders for translation.
|
||||
*/
|
||||
prefix?: string;
|
||||
/**
|
||||
* A case-sensitive suffix string to filter documents in the source path for
|
||||
* translation.
|
||||
* This is most often use for file extensions
|
||||
*/
|
||||
suffix?: string;
|
||||
}
|
||||
|
||||
/** Destination for the finished translated documents */
|
||||
export interface TargetInput {
|
||||
/** Location of the folder / container with your documents */
|
||||
targetUrl: string;
|
||||
/** Category / custom system for translation request */
|
||||
category?: string;
|
||||
/** Target Language */
|
||||
language: string;
|
||||
/** List of Glossary */
|
||||
glossaries?: Array<Glossary>;
|
||||
/** Storage Source */
|
||||
storageSource?: StorageSource;
|
||||
}
|
||||
|
||||
/** Glossary / translation memory for the request */
|
||||
export interface Glossary {
|
||||
/**
|
||||
* Location of the glossary.
|
||||
* We will use the file extension to extract the
|
||||
* formatting if the format parameter is not supplied.
|
||||
*
|
||||
* If the translation
|
||||
* language pair is not present in the glossary, it will not be applied
|
||||
*/
|
||||
glossaryUrl: string;
|
||||
/** Format */
|
||||
format: string;
|
||||
/** Optional Version. If not specified, default is used. */
|
||||
version?: string;
|
||||
/** Storage Source */
|
||||
storageSource?: StorageSource;
|
||||
}
|
||||
|
||||
/** Document Translate Request Content */
|
||||
export type DocumentTranslateContent =
|
||||
| FormData
|
||||
| Array<
|
||||
| DocumentTranslateContentDocumentPartDescriptor
|
||||
| DocumentTranslateContentGlossaryPartDescriptor
|
||||
>;
|
||||
/** Alias for StorageSource */
|
||||
export type StorageSource = "AzureBlob" | string;
|
||||
/** Alias for StorageInputType */
|
||||
export type StorageInputType = "Folder" | "File" | string;
|
||||
/** Alias for FileFormatType */
|
||||
export type FileFormatType = "document" | "glossary" | string;
|
|
@ -0,0 +1,181 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
/** Translation job Status Response */
|
||||
export interface TranslationsStatusOutput {
|
||||
/** The summary status of individual operation */
|
||||
value: Array<TranslationStatusOutput>;
|
||||
/** Url for the next page. Null if no more pages available */
|
||||
nextLink?: string;
|
||||
}
|
||||
|
||||
/** Translation job status response */
|
||||
export interface TranslationStatusOutput {
|
||||
/** Id of the operation. */
|
||||
id: string;
|
||||
/** Operation created date time */
|
||||
createdDateTimeUtc: string;
|
||||
/** Date time in which the operation's status has been updated */
|
||||
lastActionDateTimeUtc: string;
|
||||
/** List of possible statuses for job or document */
|
||||
status: StatusOutput;
|
||||
/**
|
||||
* This contains an outer error with error code, message, details, target and an
|
||||
* inner error with more descriptive details.
|
||||
*/
|
||||
error?: TranslationErrorOutput;
|
||||
/** Status Summary */
|
||||
summary: StatusSummaryOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* This contains an outer error with error code, message, details, target and an
|
||||
* inner error with more descriptive details.
|
||||
*/
|
||||
export interface TranslationErrorOutput {
|
||||
/** Enums containing high level error codes. */
|
||||
code: TranslationErrorCodeOutput;
|
||||
/** Gets high level error message. */
|
||||
message: string;
|
||||
/**
|
||||
* Gets the source of the error.
|
||||
* For example it would be "documents" or
|
||||
* "document id" in case of invalid document.
|
||||
*/
|
||||
readonly target?: string;
|
||||
/**
|
||||
* New Inner Error format which conforms to Cognitive Services API Guidelines
|
||||
* which is available at
|
||||
* https://microsoft.sharepoint.com/%3Aw%3A/t/CognitiveServicesPMO/EUoytcrjuJdKpeOKIK_QRC8BPtUYQpKBi8JsWyeDMRsWlQ?e=CPq8ow.
|
||||
* This
|
||||
* contains required properties ErrorCode, message and optional properties target,
|
||||
* details(key value pair), inner error(this can be nested).
|
||||
*/
|
||||
innerError?: InnerTranslationErrorOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* New Inner Error format which conforms to Cognitive Services API Guidelines
|
||||
* which is available at
|
||||
* https://microsoft.sharepoint.com/%3Aw%3A/t/CognitiveServicesPMO/EUoytcrjuJdKpeOKIK_QRC8BPtUYQpKBi8JsWyeDMRsWlQ?e=CPq8ow.
|
||||
* This
|
||||
* contains required properties ErrorCode, message and optional properties target,
|
||||
* details(key value pair), inner error(this can be nested).
|
||||
*/
|
||||
export interface InnerTranslationErrorOutput {
|
||||
/** Gets code error string. */
|
||||
code: string;
|
||||
/** Gets high level error message. */
|
||||
message: string;
|
||||
/**
|
||||
* Gets the source of the error.
|
||||
* For example it would be "documents" or
|
||||
* "document id" in case of invalid document.
|
||||
*/
|
||||
readonly target?: string;
|
||||
/**
|
||||
* New Inner Error format which conforms to Cognitive Services API Guidelines
|
||||
* which is available at
|
||||
* https://microsoft.sharepoint.com/%3Aw%3A/t/CognitiveServicesPMO/EUoytcrjuJdKpeOKIK_QRC8BPtUYQpKBi8JsWyeDMRsWlQ?e=CPq8ow.
|
||||
* This
|
||||
* contains required properties ErrorCode, message and optional properties target,
|
||||
* details(key value pair), inner error(this can be nested).
|
||||
*/
|
||||
innerError?: InnerTranslationErrorOutput;
|
||||
}
|
||||
|
||||
/** Status Summary */
|
||||
export interface StatusSummaryOutput {
|
||||
/** Total count */
|
||||
total: number;
|
||||
/** Failed count */
|
||||
failed: number;
|
||||
/** Number of Success */
|
||||
success: number;
|
||||
/** Number of in progress */
|
||||
inProgress: number;
|
||||
/** Count of not yet started */
|
||||
notYetStarted: number;
|
||||
/** Number of cancelled */
|
||||
cancelled: number;
|
||||
/** Total characters charged by the API */
|
||||
totalCharacterCharged: number;
|
||||
}
|
||||
|
||||
/** Document Status Response */
|
||||
export interface DocumentStatusOutput {
|
||||
/** Location of the document or folder */
|
||||
path?: string;
|
||||
/** Location of the source document */
|
||||
sourcePath: string;
|
||||
/** Operation created date time */
|
||||
createdDateTimeUtc: string;
|
||||
/** Date time in which the operation's status has been updated */
|
||||
lastActionDateTimeUtc: string;
|
||||
/** List of possible statuses for job or document */
|
||||
status: StatusOutput;
|
||||
/** To language */
|
||||
to: string;
|
||||
/**
|
||||
* This contains an outer error with error code, message, details, target and an
|
||||
* inner error with more descriptive details.
|
||||
*/
|
||||
error?: TranslationErrorOutput;
|
||||
/** Progress of the translation if available */
|
||||
progress: number;
|
||||
/** Document Id */
|
||||
id: string;
|
||||
/** Character charged by the API */
|
||||
characterCharged?: number;
|
||||
}
|
||||
|
||||
/** Documents Status Response */
|
||||
export interface DocumentsStatusOutput {
|
||||
/** The detail status of individual documents */
|
||||
value: Array<DocumentStatusOutput>;
|
||||
/** Url for the next page. Null if no more pages available */
|
||||
nextLink?: string;
|
||||
}
|
||||
|
||||
/** List of supported file formats */
|
||||
export interface SupportedFileFormatsOutput {
|
||||
/** list of objects */
|
||||
value: Array<FileFormatOutput>;
|
||||
}
|
||||
|
||||
/** File Format */
|
||||
export interface FileFormatOutput {
|
||||
/** Name of the format */
|
||||
format: string;
|
||||
/** Supported file extension for this format */
|
||||
fileExtensions: string[];
|
||||
/** Supported Content-Types for this format */
|
||||
contentTypes: string[];
|
||||
/** Default version if none is specified */
|
||||
defaultVersion?: string;
|
||||
/** Supported Version */
|
||||
versions?: string[];
|
||||
/** Supported Type for this format */
|
||||
type?: string;
|
||||
}
|
||||
|
||||
/** Alias for StatusOutput */
|
||||
export type StatusOutput =
|
||||
| "NotStarted"
|
||||
| "Running"
|
||||
| "Succeeded"
|
||||
| "Failed"
|
||||
| "Cancelled"
|
||||
| "Cancelling"
|
||||
| "ValidationFailed"
|
||||
| string;
|
||||
/** Alias for TranslationErrorCodeOutput */
|
||||
export type TranslationErrorCodeOutput =
|
||||
| "InvalidRequest"
|
||||
| "InvalidArgument"
|
||||
| "InternalServerError"
|
||||
| "ServiceUnavailable"
|
||||
| "ResourceNotFound"
|
||||
| "Unauthorized"
|
||||
| "RequestRateTooHigh"
|
||||
| string;
|
|
@ -0,0 +1,131 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { getPagedAsyncIterator, PagedAsyncIterableIterator, PagedResult } from "@azure/core-paging";
|
||||
import { Client, createRestError, PathUncheckedResponse } from "@azure-rest/core-client";
|
||||
|
||||
/**
|
||||
* Helper type to extract the type of an array
|
||||
*/
|
||||
export type GetArrayType<T> = T extends Array<infer TData> ? TData : never;
|
||||
|
||||
/**
|
||||
* The type of a custom function that defines how to get a page and a link to the next one if any.
|
||||
*/
|
||||
export type GetPage<TPage> = (
|
||||
pageLink: string,
|
||||
maxPageSize?: number,
|
||||
) => Promise<{
|
||||
page: TPage;
|
||||
nextPageLink?: string;
|
||||
}>;
|
||||
|
||||
/**
|
||||
* Options for the paging helper
|
||||
*/
|
||||
export interface PagingOptions<TResponse> {
|
||||
/**
|
||||
* Custom function to extract pagination details for crating the PagedAsyncIterableIterator
|
||||
*/
|
||||
customGetPage?: GetPage<PaginateReturn<TResponse>[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper type to infer the Type of the paged elements from the response type
|
||||
* This type is generated based on the swagger information for x-ms-pageable
|
||||
* specifically on the itemName property which indicates the property of the response
|
||||
* where the page items are found. The default value is `value`.
|
||||
* This type will allow us to provide strongly typed Iterator based on the response we get as second parameter
|
||||
*/
|
||||
export type PaginateReturn<TResult> = TResult extends {
|
||||
body: { value?: infer TPage };
|
||||
}
|
||||
? GetArrayType<TPage>
|
||||
: Array<unknown>;
|
||||
|
||||
/**
|
||||
* Helper to paginate results from an initial response that follows the specification of Autorest `x-ms-pageable` extension
|
||||
* @param client - Client to use for sending the next page requests
|
||||
* @param initialResponse - Initial response containing the nextLink and current page of elements
|
||||
* @param customGetPage - Optional - Function to define how to extract the page and next link to be used to paginate the results
|
||||
* @returns - PagedAsyncIterableIterator to iterate the elements
|
||||
*/
|
||||
export function paginate<TResponse extends PathUncheckedResponse>(
|
||||
client: Client,
|
||||
initialResponse: TResponse,
|
||||
options: PagingOptions<TResponse> = {},
|
||||
): PagedAsyncIterableIterator<PaginateReturn<TResponse>> {
|
||||
// Extract element type from initial response
|
||||
type TElement = PaginateReturn<TResponse>;
|
||||
let firstRun = true;
|
||||
const itemName = "value";
|
||||
const nextLinkName = "nextLink";
|
||||
const { customGetPage } = options;
|
||||
const pagedResult: PagedResult<TElement[]> = {
|
||||
firstPageLink: "",
|
||||
getPage:
|
||||
typeof customGetPage === "function"
|
||||
? customGetPage
|
||||
: async (pageLink: string) => {
|
||||
const result = firstRun ? initialResponse : await client.pathUnchecked(pageLink).get();
|
||||
firstRun = false;
|
||||
checkPagingRequest(result);
|
||||
const nextLink = getNextLink(result.body, nextLinkName);
|
||||
const values = getElements<TElement>(result.body, itemName);
|
||||
return {
|
||||
page: values,
|
||||
nextPageLink: nextLink,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
return getPagedAsyncIterator(pagedResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets for the value of nextLink in the body
|
||||
*/
|
||||
function getNextLink(body: unknown, nextLinkName?: string): string | undefined {
|
||||
if (!nextLinkName) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const nextLink = (body as Record<string, unknown>)[nextLinkName];
|
||||
|
||||
if (typeof nextLink !== "string" && typeof nextLink !== "undefined") {
|
||||
throw new Error(`Body Property ${nextLinkName} should be a string or undefined`);
|
||||
}
|
||||
|
||||
return nextLink;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the elements of the current request in the body.
|
||||
*/
|
||||
function getElements<T = unknown>(body: unknown, itemName: string): T[] {
|
||||
const value = (body as Record<string, unknown>)[itemName] as T[];
|
||||
|
||||
// value has to be an array according to the x-ms-pageable extension.
|
||||
// The fact that this must be an array is used above to calculate the
|
||||
// type of elements in the page in PaginateReturn
|
||||
if (!Array.isArray(value)) {
|
||||
throw new Error(
|
||||
`Couldn't paginate response\n Body doesn't contain an array property with name: ${itemName}`,
|
||||
);
|
||||
}
|
||||
|
||||
return value ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a request failed
|
||||
*/
|
||||
function checkPagingRequest(response: PathUncheckedResponse): void {
|
||||
const Http2xxStatusCodes = ["200", "201", "202", "203", "204", "205", "206", "207", "208", "226"];
|
||||
if (!Http2xxStatusCodes.includes(response.status)) {
|
||||
throw createRestError(
|
||||
`Pagination failed with unexpected statusCode ${response.status}`,
|
||||
response,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,202 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { RawHttpHeadersInput } from "@azure/core-rest-pipeline";
|
||||
import { RequestParameters } from "@azure-rest/core-client";
|
||||
import { DocumentTranslateContent, StartTranslationDetails, FileFormatType } from "./models.js";
|
||||
|
||||
export interface DocumentTranslateHeaders {
|
||||
/** An opaque, globally-unique, client-generated string identifier for the request. */
|
||||
"x-ms-client-request-id"?: string;
|
||||
}
|
||||
|
||||
export interface DocumentTranslateBodyParam {
|
||||
body?: DocumentTranslateContent;
|
||||
}
|
||||
|
||||
export interface DocumentTranslateQueryParamProperties {
|
||||
/**
|
||||
* Specifies source language of the input document.
|
||||
* If this parameter isn't specified, automatic language detection is applied to determine the source language.
|
||||
* For example if the source document is written in English, then use sourceLanguage=en
|
||||
*/
|
||||
sourceLanguage?: string;
|
||||
/**
|
||||
* Specifies the language of the output document.
|
||||
* The target language must be one of the supported languages included in the translation scope.
|
||||
* For example if you want to translate the document in German language, then use targetLanguage=de
|
||||
*/
|
||||
targetLanguage: string;
|
||||
/**
|
||||
* A string specifying the category (domain) of the translation. This parameter is used to get translations
|
||||
* from a customized system built with Custom Translator. Add the Category ID from your Custom Translator
|
||||
* project details to this parameter to use your deployed customized system. Default value is: general.
|
||||
*/
|
||||
category?: string;
|
||||
/**
|
||||
* Specifies that the service is allowed to fall back to a general system when a custom system doesn't exist.
|
||||
* Possible values are: true (default) or false.
|
||||
*/
|
||||
allowFallback?: boolean;
|
||||
}
|
||||
|
||||
export interface DocumentTranslateQueryParam {
|
||||
queryParameters: DocumentTranslateQueryParamProperties;
|
||||
}
|
||||
|
||||
export interface DocumentTranslateHeaderParam {
|
||||
headers?: RawHttpHeadersInput & DocumentTranslateHeaders;
|
||||
}
|
||||
|
||||
export interface DocumentTranslateMediaTypesParam {
|
||||
/** Content Type as multipart/form-data */
|
||||
contentType: "multipart/form-data";
|
||||
}
|
||||
|
||||
export type DocumentTranslateParameters = DocumentTranslateQueryParam &
|
||||
DocumentTranslateHeaderParam &
|
||||
DocumentTranslateMediaTypesParam &
|
||||
DocumentTranslateBodyParam &
|
||||
RequestParameters;
|
||||
|
||||
export interface StartTranslationBodyParam {
|
||||
body?: StartTranslationDetails;
|
||||
}
|
||||
|
||||
export type StartTranslationParameters = StartTranslationBodyParam & RequestParameters;
|
||||
|
||||
export interface GetTranslationsStatusQueryParamProperties {
|
||||
/**
|
||||
* top indicates the total number of records the user wants to be returned across
|
||||
* all pages.
|
||||
*
|
||||
* Clients MAY use top and skip query parameters to
|
||||
* specify a number of results to return and an offset into the collection.
|
||||
* When
|
||||
* both top and skip are given by a client, the server SHOULD first apply skip
|
||||
* and then top on the collection.
|
||||
*
|
||||
* Note: If the server can't honor
|
||||
* top and/or skip, the server MUST return an error to the client informing
|
||||
* about it instead of just ignoring the query options.
|
||||
*/
|
||||
top?: number;
|
||||
/**
|
||||
* skip indicates the number of records to skip from the list of records held by
|
||||
* the server based on the sorting method specified. By default, we sort by
|
||||
* descending start time.
|
||||
*
|
||||
* Clients MAY use top and skip query
|
||||
* parameters to specify a number of results to return and an offset into the
|
||||
* collection.
|
||||
* When both top and skip are given by a client, the server SHOULD
|
||||
* first apply skip and then top on the collection.
|
||||
*
|
||||
* Note: If the
|
||||
* server can't honor top and/or skip, the server MUST return an error to the
|
||||
* client informing about it instead of just ignoring the query options.
|
||||
*/
|
||||
skip?: number;
|
||||
/**
|
||||
* maxpagesize is the maximum items returned in a page. If more items are
|
||||
* requested via top (or top is not specified and there are more items to be
|
||||
* returned), @nextLink will contain the link to the next page.
|
||||
*
|
||||
*
|
||||
* Clients MAY request server-driven paging with a specific page size by
|
||||
* specifying a maxpagesize preference. The server SHOULD honor this preference
|
||||
* if the specified page size is smaller than the server's default page size.
|
||||
*/
|
||||
maxpagesize?: number;
|
||||
/** Ids to use in filtering */
|
||||
ids?: string[];
|
||||
/** Statuses to use in filtering */
|
||||
statuses?: string[];
|
||||
/** the start datetime to get items after */
|
||||
createdDateTimeUtcStart?: Date | string;
|
||||
/** the end datetime to get items before */
|
||||
createdDateTimeUtcEnd?: Date | string;
|
||||
/** the sorting query for the collection (ex: 'CreatedDateTimeUtc asc','CreatedDateTimeUtc desc') */
|
||||
orderby?: string[];
|
||||
}
|
||||
|
||||
export interface GetTranslationsStatusQueryParam {
|
||||
queryParameters?: GetTranslationsStatusQueryParamProperties;
|
||||
}
|
||||
|
||||
export type GetTranslationsStatusParameters = GetTranslationsStatusQueryParam & RequestParameters;
|
||||
export type GetDocumentStatusParameters = RequestParameters;
|
||||
export type GetTranslationStatusParameters = RequestParameters;
|
||||
export type CancelTranslationParameters = RequestParameters;
|
||||
|
||||
export interface GetDocumentsStatusQueryParamProperties {
|
||||
/**
|
||||
* top indicates the total number of records the user wants to be returned across
|
||||
* all pages.
|
||||
*
|
||||
* Clients MAY use top and skip query parameters to
|
||||
* specify a number of results to return and an offset into the collection.
|
||||
* When
|
||||
* both top and skip are given by a client, the server SHOULD first apply skip
|
||||
* and then top on the collection.
|
||||
*
|
||||
* Note: If the server can't honor
|
||||
* top and/or skip, the server MUST return an error to the client informing
|
||||
* about it instead of just ignoring the query options.
|
||||
*/
|
||||
top?: number;
|
||||
/**
|
||||
* skip indicates the number of records to skip from the list of records held by
|
||||
* the server based on the sorting method specified. By default, we sort by
|
||||
* descending start time.
|
||||
*
|
||||
* Clients MAY use top and skip query
|
||||
* parameters to specify a number of results to return and an offset into the
|
||||
* collection.
|
||||
* When both top and skip are given by a client, the server SHOULD
|
||||
* first apply skip and then top on the collection.
|
||||
*
|
||||
* Note: If the
|
||||
* server can't honor top and/or skip, the server MUST return an error to the
|
||||
* client informing about it instead of just ignoring the query options.
|
||||
*/
|
||||
skip?: number;
|
||||
/**
|
||||
* maxpagesize is the maximum items returned in a page. If more items are
|
||||
* requested via top (or top is not specified and there are more items to be
|
||||
* returned), @nextLink will contain the link to the next page.
|
||||
*
|
||||
*
|
||||
* Clients MAY request server-driven paging with a specific page size by
|
||||
* specifying a maxpagesize preference. The server SHOULD honor this preference
|
||||
* if the specified page size is smaller than the server's default page size.
|
||||
*/
|
||||
maxpagesize?: number;
|
||||
/** Ids to use in filtering */
|
||||
ids?: string[];
|
||||
/** Statuses to use in filtering */
|
||||
statuses?: string[];
|
||||
/** the start datetime to get items after */
|
||||
createdDateTimeUtcStart?: Date | string;
|
||||
/** the end datetime to get items before */
|
||||
createdDateTimeUtcEnd?: Date | string;
|
||||
/** the sorting query for the collection (ex: 'CreatedDateTimeUtc asc','CreatedDateTimeUtc desc') */
|
||||
orderby?: string[];
|
||||
}
|
||||
|
||||
export interface GetDocumentsStatusQueryParam {
|
||||
queryParameters?: GetDocumentsStatusQueryParamProperties;
|
||||
}
|
||||
|
||||
export type GetDocumentsStatusParameters = GetDocumentsStatusQueryParam & RequestParameters;
|
||||
|
||||
export interface GetSupportedFormatsQueryParamProperties {
|
||||
/** the type of format like document or glossary */
|
||||
type?: FileFormatType;
|
||||
}
|
||||
|
||||
export interface GetSupportedFormatsQueryParam {
|
||||
queryParameters?: GetSupportedFormatsQueryParamProperties;
|
||||
}
|
||||
|
||||
export type GetSupportedFormatsParameters = GetSupportedFormatsQueryParam & RequestParameters;
|
|
@ -0,0 +1,204 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Client, HttpResponse } from "@azure-rest/core-client";
|
||||
import { AbortSignalLike } from "@azure/abort-controller";
|
||||
import {
|
||||
CancelOnProgress,
|
||||
CreateHttpPollerOptions,
|
||||
LongRunningOperation,
|
||||
OperationResponse,
|
||||
OperationState,
|
||||
createHttpPoller,
|
||||
} from "@azure/core-lro";
|
||||
import {
|
||||
StartTranslation202Response,
|
||||
StartTranslationDefaultResponse,
|
||||
StartTranslationLogicalResponse,
|
||||
} from "./responses.js";
|
||||
|
||||
/**
|
||||
* A simple poller that can be used to poll a long running operation.
|
||||
*/
|
||||
export interface SimplePollerLike<TState extends OperationState<TResult>, TResult> {
|
||||
/**
|
||||
* Returns true if the poller has finished polling.
|
||||
*/
|
||||
isDone(): boolean;
|
||||
/**
|
||||
* Returns true if the poller is stopped.
|
||||
*/
|
||||
isStopped(): boolean;
|
||||
/**
|
||||
* Returns the state of the operation.
|
||||
*/
|
||||
getOperationState(): TState;
|
||||
/**
|
||||
* Returns the result value of the operation,
|
||||
* regardless of the state of the poller.
|
||||
* It can return undefined or an incomplete form of the final TResult value
|
||||
* depending on the implementation.
|
||||
*/
|
||||
getResult(): TResult | undefined;
|
||||
/**
|
||||
* Returns a promise that will resolve once a single polling request finishes.
|
||||
* It does this by calling the update method of the Poller's operation.
|
||||
*/
|
||||
poll(options?: { abortSignal?: AbortSignalLike }): Promise<TState>;
|
||||
/**
|
||||
* Returns a promise that will resolve once the underlying operation is completed.
|
||||
*/
|
||||
pollUntilDone(pollOptions?: { abortSignal?: AbortSignalLike }): Promise<TResult>;
|
||||
/**
|
||||
* Invokes the provided callback after each polling is completed,
|
||||
* sending the current state of the poller's operation.
|
||||
*
|
||||
* It returns a method that can be used to stop receiving updates on the given callback function.
|
||||
*/
|
||||
onProgress(callback: (state: TState) => void): CancelOnProgress;
|
||||
|
||||
/**
|
||||
* Returns a promise that could be used for serialized version of the poller's operation
|
||||
* by invoking the operation's serialize method.
|
||||
*/
|
||||
serialize(): Promise<string>;
|
||||
|
||||
/**
|
||||
* Wait the poller to be submitted.
|
||||
*/
|
||||
submitted(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Returns a string representation of the poller's operation. Similar to serialize but returns a string.
|
||||
* @deprecated Use serialize() instead.
|
||||
*/
|
||||
toString(): string;
|
||||
|
||||
/**
|
||||
* Stops the poller from continuing to poll. Please note this will only stop the client-side polling
|
||||
* @deprecated Use abortSignal to stop polling instead.
|
||||
*/
|
||||
stopPolling(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that builds a Poller object to help polling a long running operation.
|
||||
* @param client - Client to use for sending the request to get additional pages.
|
||||
* @param initialResponse - The initial response.
|
||||
* @param options - Options to set a resume state or custom polling interval.
|
||||
* @returns - A poller object to poll for operation state updates and eventually get the final response.
|
||||
*/
|
||||
export async function getLongRunningPoller<
|
||||
TResult extends StartTranslationLogicalResponse | StartTranslationDefaultResponse,
|
||||
>(
|
||||
client: Client,
|
||||
initialResponse: StartTranslation202Response | StartTranslationDefaultResponse,
|
||||
options?: CreateHttpPollerOptions<TResult, OperationState<TResult>>,
|
||||
): Promise<SimplePollerLike<OperationState<TResult>, TResult>>;
|
||||
export async function getLongRunningPoller<TResult extends HttpResponse>(
|
||||
client: Client,
|
||||
initialResponse: TResult,
|
||||
options: CreateHttpPollerOptions<TResult, OperationState<TResult>> = {},
|
||||
): Promise<SimplePollerLike<OperationState<TResult>, TResult>> {
|
||||
const abortController = new AbortController();
|
||||
const poller: LongRunningOperation<TResult> = {
|
||||
sendInitialRequest: async () => {
|
||||
// In the case of Rest Clients we are building the LRO poller object from a response that's the reason
|
||||
// we are not triggering the initial request here, just extracting the information from the
|
||||
// response we were provided.
|
||||
return getLroResponse(initialResponse);
|
||||
},
|
||||
sendPollRequest: async (path, sendPollRequestOptions?: { abortSignal?: AbortSignalLike }) => {
|
||||
// This is the callback that is going to be called to poll the service
|
||||
// to get the latest status. We use the client provided and the polling path
|
||||
// which is an opaque URL provided by caller, the service sends this in one of the following headers: operation-location, azure-asyncoperation or location
|
||||
// depending on the lro pattern that the service implements. If non is provided we default to the initial path.
|
||||
function abortListener(): void {
|
||||
abortController.abort();
|
||||
}
|
||||
const inputAbortSignal = sendPollRequestOptions?.abortSignal;
|
||||
const abortSignal = abortController.signal;
|
||||
if (inputAbortSignal?.aborted) {
|
||||
abortController.abort();
|
||||
} else if (!abortSignal.aborted) {
|
||||
inputAbortSignal?.addEventListener("abort", abortListener, {
|
||||
once: true,
|
||||
});
|
||||
}
|
||||
let response;
|
||||
try {
|
||||
response = await client
|
||||
.pathUnchecked(path ?? initialResponse.request.url)
|
||||
.get({ abortSignal });
|
||||
} finally {
|
||||
inputAbortSignal?.removeEventListener("abort", abortListener);
|
||||
}
|
||||
const lroResponse = getLroResponse(response as TResult);
|
||||
lroResponse.rawResponse.headers["x-ms-original-url"] = initialResponse.request.url;
|
||||
return lroResponse;
|
||||
},
|
||||
};
|
||||
|
||||
options.resolveOnUnsuccessful = options.resolveOnUnsuccessful ?? true;
|
||||
const httpPoller = createHttpPoller(poller, options);
|
||||
const simplePoller: SimplePollerLike<OperationState<TResult>, TResult> = {
|
||||
isDone() {
|
||||
return httpPoller.isDone;
|
||||
},
|
||||
isStopped() {
|
||||
return httpPoller.isStopped;
|
||||
},
|
||||
getOperationState() {
|
||||
if (!httpPoller.operationState) {
|
||||
throw new Error(
|
||||
"Operation state is not available. The poller may not have been started and you could await submitted() before calling getOperationState().",
|
||||
);
|
||||
}
|
||||
return httpPoller.operationState;
|
||||
},
|
||||
getResult() {
|
||||
return httpPoller.result;
|
||||
},
|
||||
toString() {
|
||||
if (!httpPoller.operationState) {
|
||||
throw new Error(
|
||||
"Operation state is not available. The poller may not have been started and you could await submitted() before calling getOperationState().",
|
||||
);
|
||||
}
|
||||
return JSON.stringify({
|
||||
state: httpPoller.operationState,
|
||||
});
|
||||
},
|
||||
stopPolling() {
|
||||
abortController.abort();
|
||||
},
|
||||
onProgress: httpPoller.onProgress,
|
||||
poll: httpPoller.poll,
|
||||
pollUntilDone: httpPoller.pollUntilDone,
|
||||
serialize: httpPoller.serialize,
|
||||
submitted: httpPoller.submitted,
|
||||
};
|
||||
return simplePoller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Rest Client response to a response that the LRO implementation understands
|
||||
* @param response - a rest client http response
|
||||
* @returns - An LRO response that the LRO implementation understands
|
||||
*/
|
||||
function getLroResponse<TResult extends HttpResponse>(
|
||||
response: TResult,
|
||||
): OperationResponse<TResult> {
|
||||
if (Number.isNaN(response.status)) {
|
||||
throw new TypeError(`Status code of the response is not a number. Value: ${response.status}`);
|
||||
}
|
||||
|
||||
return {
|
||||
flatResponse: response,
|
||||
rawResponse: {
|
||||
...response,
|
||||
statusCode: Number.parseInt(response.status),
|
||||
body: response.body,
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { RawHttpHeaders } from "@azure/core-rest-pipeline";
|
||||
import { HttpResponse, ErrorResponse } from "@azure-rest/core-client";
|
||||
import {
|
||||
TranslationsStatusOutput,
|
||||
DocumentStatusOutput,
|
||||
TranslationStatusOutput,
|
||||
DocumentsStatusOutput,
|
||||
SupportedFileFormatsOutput,
|
||||
} from "./outputModels.js";
|
||||
|
||||
export interface DocumentTranslate200Headers {
|
||||
/** An opaque, globally-unique, client-generated string identifier for the request. */
|
||||
"x-ms-client-request-id"?: string;
|
||||
}
|
||||
|
||||
/** The request has succeeded. */
|
||||
export interface DocumentTranslate200Response extends HttpResponse {
|
||||
status: "200";
|
||||
/** Value may contain any sequence of octets */
|
||||
body: Uint8Array;
|
||||
headers: RawHttpHeaders & DocumentTranslate200Headers;
|
||||
}
|
||||
|
||||
export interface DocumentTranslateDefaultHeaders {
|
||||
/** String error code indicating what went wrong. */
|
||||
"x-ms-error-code"?: string;
|
||||
}
|
||||
|
||||
export interface DocumentTranslateDefaultResponse extends HttpResponse {
|
||||
status: string;
|
||||
body: ErrorResponse;
|
||||
headers: RawHttpHeaders & DocumentTranslateDefaultHeaders;
|
||||
}
|
||||
|
||||
export interface StartTranslation202Headers {
|
||||
/** Link to the translation operation status */
|
||||
"operation-location": string;
|
||||
}
|
||||
|
||||
/** The request has been accepted for processing, but processing has not yet completed. */
|
||||
export interface StartTranslation202Response extends HttpResponse {
|
||||
status: "202";
|
||||
headers: RawHttpHeaders & StartTranslation202Headers;
|
||||
}
|
||||
|
||||
export interface StartTranslationDefaultHeaders {
|
||||
/** String error code indicating what went wrong. */
|
||||
"x-ms-error-code"?: string;
|
||||
}
|
||||
|
||||
export interface StartTranslationDefaultResponse extends HttpResponse {
|
||||
status: string;
|
||||
body: ErrorResponse;
|
||||
headers: RawHttpHeaders & StartTranslationDefaultHeaders;
|
||||
}
|
||||
|
||||
/** The final response for long-running startTranslation operation */
|
||||
export interface StartTranslationLogicalResponse extends HttpResponse {
|
||||
status: "200";
|
||||
}
|
||||
|
||||
/** The request has succeeded. */
|
||||
export interface GetTranslationsStatus200Response extends HttpResponse {
|
||||
status: "200";
|
||||
body: TranslationsStatusOutput;
|
||||
}
|
||||
|
||||
export interface GetTranslationsStatusDefaultHeaders {
|
||||
/** String error code indicating what went wrong. */
|
||||
"x-ms-error-code"?: string;
|
||||
}
|
||||
|
||||
export interface GetTranslationsStatusDefaultResponse extends HttpResponse {
|
||||
status: string;
|
||||
body: ErrorResponse;
|
||||
headers: RawHttpHeaders & GetTranslationsStatusDefaultHeaders;
|
||||
}
|
||||
|
||||
/** The request has succeeded. */
|
||||
export interface GetDocumentStatus200Response extends HttpResponse {
|
||||
status: "200";
|
||||
body: DocumentStatusOutput;
|
||||
}
|
||||
|
||||
export interface GetDocumentStatusDefaultHeaders {
|
||||
/** String error code indicating what went wrong. */
|
||||
"x-ms-error-code"?: string;
|
||||
}
|
||||
|
||||
export interface GetDocumentStatusDefaultResponse extends HttpResponse {
|
||||
status: string;
|
||||
body: ErrorResponse;
|
||||
headers: RawHttpHeaders & GetDocumentStatusDefaultHeaders;
|
||||
}
|
||||
|
||||
/** The request has succeeded. */
|
||||
export interface GetTranslationStatus200Response extends HttpResponse {
|
||||
status: "200";
|
||||
body: TranslationStatusOutput;
|
||||
}
|
||||
|
||||
export interface GetTranslationStatusDefaultHeaders {
|
||||
/** String error code indicating what went wrong. */
|
||||
"x-ms-error-code"?: string;
|
||||
}
|
||||
|
||||
export interface GetTranslationStatusDefaultResponse extends HttpResponse {
|
||||
status: string;
|
||||
body: ErrorResponse;
|
||||
headers: RawHttpHeaders & GetTranslationStatusDefaultHeaders;
|
||||
}
|
||||
|
||||
/** The request has succeeded. */
|
||||
export interface CancelTranslation200Response extends HttpResponse {
|
||||
status: "200";
|
||||
body: TranslationStatusOutput;
|
||||
}
|
||||
|
||||
export interface CancelTranslationDefaultHeaders {
|
||||
/** String error code indicating what went wrong. */
|
||||
"x-ms-error-code"?: string;
|
||||
}
|
||||
|
||||
export interface CancelTranslationDefaultResponse extends HttpResponse {
|
||||
status: string;
|
||||
body: ErrorResponse;
|
||||
headers: RawHttpHeaders & CancelTranslationDefaultHeaders;
|
||||
}
|
||||
|
||||
/** The request has succeeded. */
|
||||
export interface GetDocumentsStatus200Response extends HttpResponse {
|
||||
status: "200";
|
||||
body: DocumentsStatusOutput;
|
||||
}
|
||||
|
||||
export interface GetDocumentsStatusDefaultHeaders {
|
||||
/** String error code indicating what went wrong. */
|
||||
"x-ms-error-code"?: string;
|
||||
}
|
||||
|
||||
export interface GetDocumentsStatusDefaultResponse extends HttpResponse {
|
||||
status: string;
|
||||
body: ErrorResponse;
|
||||
headers: RawHttpHeaders & GetDocumentsStatusDefaultHeaders;
|
||||
}
|
||||
|
||||
/** The request has succeeded. */
|
||||
export interface GetSupportedFormats200Response extends HttpResponse {
|
||||
status: "200";
|
||||
body: SupportedFileFormatsOutput;
|
||||
}
|
||||
|
||||
export interface GetSupportedFormatsDefaultHeaders {
|
||||
/** String error code indicating what went wrong. */
|
||||
"x-ms-error-code"?: string;
|
||||
}
|
||||
|
||||
export interface GetSupportedFormatsDefaultResponse extends HttpResponse {
|
||||
status: string;
|
||||
body: ErrorResponse;
|
||||
headers: RawHttpHeaders & GetSupportedFormatsDefaultHeaders;
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Recorder } from "@azure-tools/test-recorder";
|
||||
import { assert } from "chai";
|
||||
import { DocumentTranslationClient, isUnexpected } from "../../src";
|
||||
import { createDocumentTranslationClient, startRecorder } from "./utils/recordedClient";
|
||||
import { Context } from "mocha";
|
||||
|
||||
describe("GetSupportedFormats tests", () => {
|
||||
let recorder: Recorder;
|
||||
let client: DocumentTranslationClient;
|
||||
|
||||
beforeEach(async function (this: Context) {
|
||||
recorder = await startRecorder(this);
|
||||
client = await createDocumentTranslationClient({ recorder });
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
await recorder.stop();
|
||||
});
|
||||
|
||||
it("all formats", async () => {
|
||||
const response = await client.path("/document/formats").get();
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
|
||||
const fileFormatTypes = response.body;
|
||||
fileFormatTypes.value.forEach((fileFormatType) => {
|
||||
assert.isTrue(fileFormatType.format !== null);
|
||||
assert.isTrue(fileFormatType.contentTypes !== null);
|
||||
assert.isTrue(fileFormatType.fileExtensions !== null);
|
||||
});
|
||||
});
|
||||
|
||||
it("document formats", async () => {
|
||||
// Define the query parameters with the specified type
|
||||
const options = {
|
||||
queryParameters: {
|
||||
type: "document",
|
||||
},
|
||||
};
|
||||
|
||||
const response = await client.path("/document/formats").get(options);
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
|
||||
const fileFormatTypes = response.body;
|
||||
fileFormatTypes.value.forEach((fileFormatType) => {
|
||||
assert.isTrue(fileFormatType.format !== null);
|
||||
assert.isTrue(fileFormatType.contentTypes !== null);
|
||||
assert.isTrue(fileFormatType.fileExtensions !== null);
|
||||
assert.isTrue(fileFormatType.type === "Document");
|
||||
if (fileFormatType.format === "XLIFF") {
|
||||
assert.isTrue(fileFormatType.defaultVersion !== null);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("glossary formats", async () => {
|
||||
// Define the query parameters with the specified type
|
||||
const options = {
|
||||
queryParameters: {
|
||||
type: "glossary",
|
||||
},
|
||||
};
|
||||
|
||||
const response = await client.path("/document/formats").get(options);
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
|
||||
const fileFormatTypes = response.body;
|
||||
fileFormatTypes.value.forEach((fileFormatType) => {
|
||||
assert.isTrue(fileFormatType.format !== null);
|
||||
assert.isTrue(fileFormatType.contentTypes !== null);
|
||||
assert.isTrue(fileFormatType.fileExtensions !== null);
|
||||
assert.isTrue(fileFormatType.type === "Glossary");
|
||||
if (fileFormatType.format === "XLIFF") {
|
||||
assert.isTrue(fileFormatType.defaultVersion !== null);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Recorder } from "@azure-tools/test-recorder";
|
||||
import { assert } from "chai";
|
||||
import { DocumentTranslationClient, isUnexpected } from "../.././../src";
|
||||
import { createDocumentTranslationClient, startRecorder } from "../utils/recordedClient";
|
||||
import {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
} from "./containerHelper";
|
||||
import { Context } from "mocha";
|
||||
import {
|
||||
createBatchRequest,
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
getTranslationOperationID,
|
||||
} from "../utils/testHelper";
|
||||
|
||||
describe("CancelTranslation tests", () => {
|
||||
let recorder: Recorder;
|
||||
let client: DocumentTranslationClient;
|
||||
|
||||
beforeEach(async function (this: Context) {
|
||||
recorder = await startRecorder(this);
|
||||
client = await createDocumentTranslationClient({ recorder });
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
await recorder.stop();
|
||||
});
|
||||
|
||||
it("cancel translation", async () => {
|
||||
const sourceUrl = await createSourceContainer(recorder, ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer(recorder);
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const poller = await client.path("/document/batches").post({
|
||||
body: batchRequests,
|
||||
});
|
||||
const id = getTranslationOperationID(poller.headers["operation-location"]);
|
||||
|
||||
// Cancel translation
|
||||
await client.path("/document/batches/{id}", id).delete();
|
||||
|
||||
// get translation status and verify
|
||||
const response = await client.path("/document/batches/{id}", id).get();
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
|
||||
const idOutput = response.body.id;
|
||||
assert.isTrue(idOutput === id, "IDOutput is:" + idOutput);
|
||||
const statusOutput = response.body.status;
|
||||
assert.isTrue(
|
||||
statusOutput === "Cancelled" ||
|
||||
statusOutput === "Cancelling" ||
|
||||
statusOutput === "NotStarted",
|
||||
"Status output is: " + statusOutput,
|
||||
);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,179 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Recorder, env } from "@azure-tools/test-recorder";
|
||||
import { ContainerClient, ContainerSASPermissions, BlobServiceClient } from "@azure/storage-blob";
|
||||
import { TestDocument, createTestDocument } from "../utils/TestDocument";
|
||||
import { Pipeline } from "@azure/core-rest-pipeline";
|
||||
|
||||
export const ONE_TEST_DOCUMENTS = [
|
||||
createTestDocument("Document1.txt", "First english test document"),
|
||||
];
|
||||
|
||||
export const TWO_TEST_DOCUMENTS = [
|
||||
createTestDocument("Document1.txt", "First english test file"),
|
||||
createTestDocument("File2.txt", "Second english test file"),
|
||||
];
|
||||
|
||||
export async function createSourceContainer(
|
||||
recorder: Recorder,
|
||||
documents: TestDocument[],
|
||||
containerName?: string | undefined,
|
||||
): Promise<string> {
|
||||
if (containerName === undefined) {
|
||||
containerName = recorder.variable("sourceContainer", `source-${getUniqueName()}`);
|
||||
}
|
||||
const containerClient = await createContainer(recorder, containerName, documents);
|
||||
|
||||
const sasUrl = await containerClient.generateSasUrl({
|
||||
permissions: ContainerSASPermissions.parse("rwl"),
|
||||
expiresOn: getDateOneDayAfter(),
|
||||
});
|
||||
return `${sasUrl}`;
|
||||
}
|
||||
|
||||
export async function createTargetContainer(
|
||||
recorder: Recorder,
|
||||
containerName?: string | undefined,
|
||||
documents?: TestDocument[],
|
||||
): Promise<string> {
|
||||
if (containerName === undefined) {
|
||||
containerName = recorder.variable("targetContainer", `target-${getUniqueName()}`);
|
||||
}
|
||||
const containerClient = await createContainer(recorder, containerName, documents);
|
||||
|
||||
const sasUrl = await containerClient.generateSasUrl({
|
||||
permissions: ContainerSASPermissions.parse("rwl"),
|
||||
expiresOn: getDateOneDayAfter(),
|
||||
});
|
||||
return `${sasUrl}`;
|
||||
}
|
||||
|
||||
export async function createGlossaryContainer(recorder: Recorder): Promise<string> {
|
||||
const glossaryName = "validGlossary.csv";
|
||||
const glossaryContent = "test, glossaryTest";
|
||||
const documents = [createTestDocument(glossaryName, glossaryContent)];
|
||||
const containerName = recorder.variable("glossaryContainer", `glossary-${getUniqueName()}`);
|
||||
const containerClient = await createContainer(recorder, containerName, documents);
|
||||
|
||||
const sasUrl = await containerClient.generateSasUrl({
|
||||
permissions: ContainerSASPermissions.parse("rwl"),
|
||||
expiresOn: getDateOneDayAfter(),
|
||||
});
|
||||
|
||||
// Extract the base URL and query parameters
|
||||
const urlParts = `${sasUrl}`.split("?");
|
||||
const baseUrl = urlParts[0];
|
||||
const queryParams = urlParts[1];
|
||||
|
||||
// Add the document name to the base URL
|
||||
const newUrl = `${baseUrl}/${glossaryName}?${queryParams}`;
|
||||
return `${newUrl}`;
|
||||
}
|
||||
|
||||
export async function createTargetContainerWithInfo(
|
||||
recorder: Recorder,
|
||||
documents?: TestDocument[],
|
||||
): Promise<Map<string, string>> {
|
||||
const containerName = recorder.variable("targetContainer", `target-${getUniqueName()}`);
|
||||
const containerClient = await createContainer(recorder, containerName, documents);
|
||||
|
||||
const sasUrl = await containerClient.generateSasUrl({
|
||||
permissions: ContainerSASPermissions.parse("rwl"),
|
||||
expiresOn: getDateOneDayAfter(),
|
||||
});
|
||||
|
||||
const sasUrlTest = recorder.variable("sasUrl", `${sasUrl}`);
|
||||
const containerValuesMap: Map<string, string> = new Map();
|
||||
containerValuesMap.set("sasUrl", sasUrlTest);
|
||||
containerValuesMap.set("containerName", containerName);
|
||||
return containerValuesMap;
|
||||
}
|
||||
|
||||
async function createContainer(
|
||||
recorder: Recorder,
|
||||
containerName: string,
|
||||
documents?: TestDocument[],
|
||||
): Promise<ContainerClient> {
|
||||
const blobServiceClient: BlobServiceClient = BlobServiceClient.fromConnectionString(
|
||||
env.DOCUMENT_TRANSLATION_CONNECTION_STRING as string,
|
||||
);
|
||||
configureBlobStorageClient(recorder, blobServiceClient);
|
||||
|
||||
const containerClient = blobServiceClient.getContainerClient(containerName);
|
||||
await containerClient.createIfNotExists();
|
||||
|
||||
if (documents && documents.length > 0) {
|
||||
await uploadDocuments(containerClient, documents);
|
||||
}
|
||||
return containerClient;
|
||||
}
|
||||
|
||||
function configureBlobStorageClient(
|
||||
recorder: Recorder,
|
||||
serviceClient: ContainerClient | BlobServiceClient,
|
||||
): void {
|
||||
const options = recorder.configureClientOptions({});
|
||||
|
||||
const pipeline: Pipeline = (serviceClient as any).storageClientContext.pipeline;
|
||||
for (const { policy } of options.additionalPolicies ?? []) {
|
||||
pipeline.addPolicy(policy, { afterPhase: "Sign", afterPolicies: ["injectorPolicy"] });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
async function uploadDocuments(containerClient: ContainerClient, documents: TestDocument[]) {
|
||||
for (const document of documents) {
|
||||
const blobClient = containerClient.getBlobClient(document.name);
|
||||
const blockBlobClient = blobClient.getBlockBlobClient();
|
||||
await blockBlobClient.upload(document.content, document.content.length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
export async function downloadDocument(
|
||||
recorder: Recorder,
|
||||
containerName: string,
|
||||
documentName: string,
|
||||
): Promise<string> {
|
||||
const blobServiceClient: BlobServiceClient = BlobServiceClient.fromConnectionString(
|
||||
env.DOCUMENT_TRANSLATION_CONNECTION_STRING as string,
|
||||
);
|
||||
configureBlobStorageClient(recorder, blobServiceClient);
|
||||
const containerClient = blobServiceClient.getContainerClient(containerName);
|
||||
const blobClient = containerClient.getBlobClient(documentName);
|
||||
const blockBlobClient = blobClient.getBlockBlobClient();
|
||||
|
||||
const downloadBlockBlobResponse = await blockBlobClient.download();
|
||||
const downloaded = (
|
||||
await streamToBuffer(downloadBlockBlobResponse.readableStreamBody)
|
||||
).toString();
|
||||
console.log("Downloaded Stream = " + downloaded);
|
||||
return downloaded;
|
||||
}
|
||||
|
||||
export function getUniqueName(): string {
|
||||
const randomNumber = Math.floor(Math.random() * 1e10);
|
||||
return randomNumber.toString().padStart(10, "0");
|
||||
}
|
||||
|
||||
function getDateOneDayAfter(): Date {
|
||||
const currentDate = new Date();
|
||||
const nextDayDate = new Date(currentDate);
|
||||
nextDayDate.setDate(currentDate.getDate() + 1);
|
||||
return nextDayDate;
|
||||
}
|
||||
|
||||
// A helper method used to read a Node.js readable stream into a Buffer
|
||||
async function streamToBuffer(readableStream: NodeJS.ReadableStream | undefined): Promise<Buffer> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const chunks: Buffer[] = [];
|
||||
readableStream?.on("data", (data: Buffer | string) => {
|
||||
chunks.push(data instanceof Buffer ? data : Buffer.from(data));
|
||||
});
|
||||
readableStream?.on("end", () => {
|
||||
resolve(Buffer.concat(chunks));
|
||||
});
|
||||
readableStream?.on("error", reject);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,264 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Recorder, isPlaybackMode } from "@azure-tools/test-recorder";
|
||||
import { assert } from "chai";
|
||||
import {
|
||||
DocumentTranslationClient,
|
||||
isUnexpected,
|
||||
getLongRunningPoller,
|
||||
StartTranslation202Response,
|
||||
} from "../.././../src";
|
||||
import { createDocumentTranslationClient, startRecorder } from "../utils/recordedClient";
|
||||
import { createSourceContainer, createTargetContainer } from "./containerHelper";
|
||||
import { Context } from "mocha";
|
||||
import {
|
||||
createBatchRequest,
|
||||
createDummyTestDocuments,
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
getTranslationOperationID,
|
||||
} from "../utils/testHelper";
|
||||
|
||||
export const testPollingOptions = {
|
||||
intervalInMs: isPlaybackMode() ? 0 : undefined,
|
||||
};
|
||||
|
||||
describe("DocumentFilter tests", () => {
|
||||
let recorder: Recorder;
|
||||
let client: DocumentTranslationClient;
|
||||
|
||||
beforeEach(async function (this: Context) {
|
||||
recorder = await startRecorder(this);
|
||||
client = await createDocumentTranslationClient({ recorder });
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
await recorder.stop();
|
||||
});
|
||||
|
||||
it("Document Statuses Filter By Status", async () => {
|
||||
const result = createSingleTranslationJob(5);
|
||||
const operationLocationUrl = (await result).headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
// Add Status filter
|
||||
const succeededStatusList = ["Succeeded"];
|
||||
const queryParams = {
|
||||
statuses: succeededStatusList,
|
||||
};
|
||||
|
||||
// get DocumentsStatus
|
||||
const response = await client.path("/document/batches/{id}/documents", operationId).get({
|
||||
queryParameters: queryParams,
|
||||
});
|
||||
if (isUnexpected(response)) {
|
||||
throw "get documents status job error:" + response.body;
|
||||
}
|
||||
const responseBody = response.body;
|
||||
for (const documentStatus of responseBody.value) {
|
||||
assert.isTrue(succeededStatusList.includes(documentStatus.status));
|
||||
}
|
||||
});
|
||||
|
||||
it("Document Statuses Filter By ID", async () => {
|
||||
const result = createSingleTranslationJob(2);
|
||||
const operationLocationUrl = (await result).headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
// get Documents Status with operationID
|
||||
const testIds = [];
|
||||
const response = await client.path("/document/batches/{id}/documents", operationId).get();
|
||||
if (isUnexpected(response)) {
|
||||
throw "get documents status job error:" + response.body;
|
||||
}
|
||||
let responseBody = response.body;
|
||||
for (const documentStatus of responseBody.value) {
|
||||
testIds.push(documentStatus.id);
|
||||
}
|
||||
|
||||
// Add id filter
|
||||
const queryParams = {
|
||||
ids: testIds,
|
||||
};
|
||||
|
||||
// get Documents Status with testIds option
|
||||
const documentStatusResponse = await client
|
||||
.path("/document/batches/{id}/documents", operationId)
|
||||
.get({
|
||||
queryParameters: queryParams,
|
||||
});
|
||||
if (isUnexpected(documentStatusResponse)) {
|
||||
throw "get documents status job error:" + documentStatusResponse.body;
|
||||
}
|
||||
|
||||
responseBody = documentStatusResponse.body;
|
||||
for (const documentStatus of responseBody.value) {
|
||||
assert.isTrue(testIds.includes(documentStatus.id));
|
||||
}
|
||||
});
|
||||
|
||||
it("Document Statuses Filter By Created After", async () => {
|
||||
const result = createSingleTranslationJob(5);
|
||||
const operationLocationUrl = (await result).headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
// Add orderBy filter
|
||||
const orderByList = ["createdDateTimeUtc asc"];
|
||||
const queryParams = {
|
||||
orderby: orderByList,
|
||||
};
|
||||
|
||||
// get Documents Status w.r.t orderby
|
||||
const testCreatedOnDateTimes = [];
|
||||
const response = await client.path("/document/batches/{id}/documents", operationId).get({
|
||||
queryParameters: queryParams,
|
||||
});
|
||||
if (isUnexpected(response)) {
|
||||
throw "get documents status job error:" + response.body;
|
||||
}
|
||||
let responseBody = response.body;
|
||||
for (const documentStatus of responseBody.value) {
|
||||
testCreatedOnDateTimes.push(documentStatus.createdDateTimeUtc);
|
||||
}
|
||||
|
||||
// Asserting that only the last document is returned
|
||||
let itemCount = 0;
|
||||
const queryParams2 = {
|
||||
createdDateTimeUtcStart: testCreatedOnDateTimes[4],
|
||||
};
|
||||
|
||||
const response2 = await client.path("/document/batches/{id}/documents", operationId).get({
|
||||
queryParameters: queryParams2,
|
||||
});
|
||||
if (isUnexpected(response2)) {
|
||||
throw "get documents status job error:" + response2.body;
|
||||
}
|
||||
responseBody = response2.body;
|
||||
for (const documentStatus of responseBody.value) {
|
||||
assert.isNotNull(documentStatus);
|
||||
itemCount += 1;
|
||||
}
|
||||
|
||||
assert.equal(itemCount, 1);
|
||||
});
|
||||
|
||||
it("Document Statuses Filter By Created Before", async () => {
|
||||
const result = createSingleTranslationJob(5);
|
||||
const operationLocationUrl = (await result).headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
// Add orderBy filter
|
||||
const orderByList = ["createdDateTimeUtc asc"];
|
||||
const queryParams = {
|
||||
orderby: orderByList,
|
||||
};
|
||||
|
||||
// get Documents Status w.r.t orderby
|
||||
const testCreatedOnDateTimes = [];
|
||||
const response = await client.path("/document/batches/{id}/documents", operationId).get({
|
||||
queryParameters: queryParams,
|
||||
});
|
||||
if (isUnexpected(response)) {
|
||||
throw "get documents status job error:" + response.body;
|
||||
}
|
||||
let responseBody = response.body;
|
||||
for (const documentStatus of responseBody.value) {
|
||||
testCreatedOnDateTimes.push(documentStatus.createdDateTimeUtc);
|
||||
}
|
||||
|
||||
// Asserting that only the first document is returned
|
||||
let itemCount2 = 0;
|
||||
const queryParams2 = {
|
||||
createdDateTimeUtcEnd: testCreatedOnDateTimes[0],
|
||||
};
|
||||
|
||||
const response2 = await client.path("/document/batches/{id}/documents", operationId).get({
|
||||
queryParameters: queryParams2,
|
||||
});
|
||||
if (isUnexpected(response2)) {
|
||||
throw "get documents status job error:" + response2.body;
|
||||
}
|
||||
|
||||
responseBody = response2.body;
|
||||
for (const documentStatus of responseBody.value) {
|
||||
assert.isNotNull(documentStatus);
|
||||
itemCount2 += 1;
|
||||
}
|
||||
|
||||
assert.equal(itemCount2, 1);
|
||||
|
||||
// Asserting that the first 4/5 docs are returned
|
||||
let itemCount3 = 0;
|
||||
const queryParams3 = {
|
||||
createdDateTimeUtcEnd: testCreatedOnDateTimes[3],
|
||||
};
|
||||
|
||||
const response3 = await client.path("/document/batches/{id}/documents", operationId).get({
|
||||
queryParameters: queryParams3,
|
||||
});
|
||||
if (isUnexpected(response3)) {
|
||||
throw "get documents status job error:" + response3.body;
|
||||
}
|
||||
responseBody = response3.body;
|
||||
for (const documentStatus of responseBody.value) {
|
||||
assert.isNotNull(documentStatus);
|
||||
itemCount3 += 1;
|
||||
}
|
||||
|
||||
assert.equal(itemCount3, 4);
|
||||
});
|
||||
|
||||
it("Document Statuses Filter By Created On", async () => {
|
||||
const result = createSingleTranslationJob(3);
|
||||
const operationLocationUrl = (await result).headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
|
||||
// Add OrderBy filter
|
||||
const orderByList = ["createdDateTimeUtc desc"];
|
||||
const queryParams = {
|
||||
statuses: orderByList,
|
||||
};
|
||||
|
||||
// get Documents Status
|
||||
const response = await client.path("/document/batches/{id}/documents", operationId).get({
|
||||
queryParameters: queryParams,
|
||||
});
|
||||
if (isUnexpected(response)) {
|
||||
throw "get documents status job error:" + response.body;
|
||||
}
|
||||
const timestamp = new Date();
|
||||
|
||||
const responseBody = response.body;
|
||||
for (const documentStatus of responseBody.value) {
|
||||
const createdDateTime = new Date(documentStatus.createdDateTimeUtc);
|
||||
assert.isTrue(createdDateTime < timestamp || createdDateTime === timestamp);
|
||||
}
|
||||
});
|
||||
|
||||
async function createSingleTranslationJob(count: number) {
|
||||
const testDocs = createDummyTestDocuments(count);
|
||||
const sourceUrl = await createSourceContainer(recorder, testDocs);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
|
||||
const targetUrl = await createTargetContainer(recorder);
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await client.path("/document/batches").post({
|
||||
body: batchRequests,
|
||||
});
|
||||
if (isUnexpected(response)) {
|
||||
throw "start translation job error:" + response.body;
|
||||
}
|
||||
|
||||
// Wait until the operation completes
|
||||
const poller = getLongRunningPoller(client, response, testPollingOptions);
|
||||
const result = await (await poller).pollUntilDone();
|
||||
assert.equal(result.status, "200");
|
||||
|
||||
return response as StartTranslation202Response;
|
||||
}
|
||||
});
|
|
@ -0,0 +1,575 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Recorder, isLiveMode, isPlaybackMode } from "@azure-tools/test-recorder";
|
||||
import { assert } from "chai";
|
||||
import {
|
||||
DocumentStatusOutput,
|
||||
DocumentTranslationClient,
|
||||
GetDocumentStatus200Response,
|
||||
GetTranslationStatus200Response,
|
||||
StartTranslationDefaultResponse,
|
||||
TranslationStatusOutput,
|
||||
getLongRunningPoller,
|
||||
isUnexpected,
|
||||
} from "../.././../src";
|
||||
import {
|
||||
createDocumentTranslationClient,
|
||||
createDocumentTranslationClientWithEndpointAndCredentials,
|
||||
startRecorder,
|
||||
} from "../utils/recordedClient";
|
||||
|
||||
import { Context } from "mocha";
|
||||
import {
|
||||
ONE_TEST_DOCUMENTS,
|
||||
TWO_TEST_DOCUMENTS,
|
||||
createGlossaryContainer,
|
||||
createSourceContainer,
|
||||
createTargetContainer,
|
||||
createTargetContainerWithInfo,
|
||||
downloadDocument,
|
||||
getUniqueName,
|
||||
} from "./containerHelper";
|
||||
import {
|
||||
createBatchRequest,
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
getTranslationOperationID,
|
||||
sleep,
|
||||
} from "../utils/testHelper";
|
||||
import { createTestDocument } from "../utils/TestDocument";
|
||||
import { BatchRequest } from "../../../src/models";
|
||||
|
||||
export const testPollingOptions = {
|
||||
intervalInMs: isPlaybackMode() ? 0 : undefined,
|
||||
};
|
||||
|
||||
describe("DocumentTranslation tests", () => {
|
||||
const retryCount = 10;
|
||||
let recorder: Recorder;
|
||||
let client: DocumentTranslationClient;
|
||||
|
||||
beforeEach(async function (this: Context) {
|
||||
recorder = await startRecorder(this);
|
||||
client = await createDocumentTranslationClient({ recorder });
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
await recorder.stop();
|
||||
});
|
||||
|
||||
it("Client Cannot Authenticate With FakeApiKey", async () => {
|
||||
const testEndpoint = "https://t7d8641d8f25ec940-doctranslation.cognitiveservices.azure.com";
|
||||
const testApiKey = "fakeApiKey";
|
||||
const testClient = await createDocumentTranslationClientWithEndpointAndCredentials({
|
||||
endpointParam: testEndpoint,
|
||||
credentials: { key: testApiKey },
|
||||
});
|
||||
|
||||
const response = await testClient.path("/document/formats").get();
|
||||
if (isUnexpected(response)) {
|
||||
assert.equal(response.status, "401");
|
||||
}
|
||||
});
|
||||
|
||||
it("Single Source Single Target", async () => {
|
||||
const sourceUrl = await createSourceContainer(recorder, ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer(recorder);
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await StartTranslationAndWait(batchRequests);
|
||||
|
||||
// Validate the response
|
||||
validateTranslationStatus(response as StartTranslationDefaultResponse, 1);
|
||||
});
|
||||
|
||||
it("Single Source Multiple Targets", async () => {
|
||||
const sourceUrl = await createSourceContainer(recorder, ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
|
||||
const containerName1 = recorder.variable("targetContainer1", `target-${getUniqueName()}`);
|
||||
const targetUrl1 = await createTargetContainer(recorder, containerName1);
|
||||
const targetInput1 = createTargetInput(targetUrl1, "fr");
|
||||
|
||||
const containerName2 = recorder.variable("targetContainer2", `target-${getUniqueName()}`);
|
||||
const targetUrl2 = await createTargetContainer(recorder, containerName2);
|
||||
const targetInput2 = createTargetInput(targetUrl2, "es");
|
||||
|
||||
const containerName3 = recorder.variable("targetContainer3", `target-${getUniqueName()}`);
|
||||
const targetUrl3 = await createTargetContainer(recorder, containerName3);
|
||||
const targetInput3 = createTargetInput(targetUrl3, "ar");
|
||||
|
||||
const batchRequest = createBatchRequest(sourceInput, [
|
||||
targetInput1,
|
||||
targetInput2,
|
||||
targetInput3,
|
||||
]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await StartTranslationAndWait(batchRequests);
|
||||
|
||||
// Validate the response
|
||||
validateTranslationStatus(response as StartTranslationDefaultResponse, 3);
|
||||
});
|
||||
|
||||
it("Multiple Sources Single Target", async () => {
|
||||
const srcContainerName1 = recorder.variable("sourceContainer1", `source-${getUniqueName()}`);
|
||||
const sourceUrl1 = await createSourceContainer(recorder, ONE_TEST_DOCUMENTS, srcContainerName1);
|
||||
const sourceInput1 = createSourceInput(sourceUrl1);
|
||||
|
||||
const tgtContainerName1 = recorder.variable("targetContainer1", `target-${getUniqueName()}`);
|
||||
const targetUrl1 = await createTargetContainer(recorder, tgtContainerName1);
|
||||
const targetInput1 = createTargetInput(targetUrl1, "fr");
|
||||
const batchRequest1 = createBatchRequest(sourceInput1, [targetInput1]);
|
||||
|
||||
const srcContainerName2 = recorder.variable("sourceContainer2", `source-${getUniqueName()}`);
|
||||
const sourceInput2 = createSourceInput(
|
||||
await createSourceContainer(recorder, ONE_TEST_DOCUMENTS, srcContainerName2),
|
||||
);
|
||||
|
||||
const tgtContainerName2 = recorder.variable("targetContainer2", `target-${getUniqueName()}`);
|
||||
const targetUrl2 = await createTargetContainer(recorder, tgtContainerName2);
|
||||
const targetInput2 = createTargetInput(targetUrl2, "es");
|
||||
const batchRequest2 = createBatchRequest(sourceInput2, [targetInput2]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest1, batchRequest2] };
|
||||
const response = await StartTranslationAndWait(batchRequests);
|
||||
|
||||
// Validate the response
|
||||
validateTranslationStatus(response, 2);
|
||||
});
|
||||
|
||||
it("Single Source Single Target With Prefix", async () => {
|
||||
const documentFilter = {
|
||||
prefix: "File",
|
||||
};
|
||||
const sourceUrl = await createSourceContainer(recorder, TWO_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl, undefined, undefined, documentFilter);
|
||||
|
||||
const targetUrl = await createTargetContainer(recorder);
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await StartTranslationAndWait(batchRequests);
|
||||
|
||||
// Validate the response
|
||||
validateTranslationStatus(response as StartTranslationDefaultResponse, 1);
|
||||
});
|
||||
|
||||
it("Single Source Single Target With Suffix", async () => {
|
||||
const documentFilter = {
|
||||
suffix: "txt",
|
||||
};
|
||||
const sourceInput = createSourceInput(
|
||||
await createSourceContainer(recorder, ONE_TEST_DOCUMENTS),
|
||||
undefined,
|
||||
undefined,
|
||||
documentFilter,
|
||||
);
|
||||
const targetInput = createTargetInput(await createTargetContainer(recorder), "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await StartTranslationAndWait(batchRequests);
|
||||
|
||||
// Validate the response
|
||||
validateTranslationStatus(response as StartTranslationDefaultResponse, 1);
|
||||
});
|
||||
|
||||
it("Single Source Single Target List Documents", async () => {
|
||||
const sourceInput = createSourceInput(
|
||||
await createSourceContainer(recorder, ONE_TEST_DOCUMENTS),
|
||||
);
|
||||
const targetInput = createTargetInput(await createTargetContainer(recorder), "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await StartTranslationAndWait(batchRequests);
|
||||
|
||||
const operationLocationUrl = response.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
assert.isNotNull(operationId);
|
||||
|
||||
// get translations status
|
||||
let translationStatus = null;
|
||||
let retriesLeft = retryCount;
|
||||
do {
|
||||
try {
|
||||
await sleep(10000);
|
||||
retriesLeft--;
|
||||
translationStatus = (await client
|
||||
.path("/document/batches/{id}", operationId)
|
||||
.get()) as GetTranslationStatus200Response;
|
||||
} catch (error) {
|
||||
console.error("Error during translation status retrieval:", error);
|
||||
}
|
||||
} while (
|
||||
translationStatus &&
|
||||
(translationStatus.body as TranslationStatusOutput).status === "Succeeded" &&
|
||||
retriesLeft > 0
|
||||
);
|
||||
const translationStatusOutput = translationStatus?.body as TranslationStatusOutput;
|
||||
|
||||
if (translationStatusOutput.status === "Succeeded") {
|
||||
// get Documents Status
|
||||
const documentResponse = await client
|
||||
.path("/document/batches/{id}/documents", operationId)
|
||||
.get();
|
||||
if (isUnexpected(documentResponse)) {
|
||||
throw "get documents status job error:" + documentResponse.body;
|
||||
}
|
||||
const responseBody = documentResponse.body;
|
||||
for (const documentStatus of responseBody.value) {
|
||||
console.log("documentStatus.status" + documentStatus.status);
|
||||
console.log("translationStatusOutput.status" + translationStatusOutput.status);
|
||||
assert.equal(documentStatus.status, translationStatusOutput.status);
|
||||
assert.equal(
|
||||
documentStatus.characterCharged,
|
||||
translationStatusOutput.summary.totalCharacterCharged,
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("Get Document Status", async () => {
|
||||
const sourceInput = createSourceInput(
|
||||
await createSourceContainer(recorder, ONE_TEST_DOCUMENTS),
|
||||
);
|
||||
const targetInput = createTargetInput(await createTargetContainer(recorder), "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await StartTranslationAndWait(batchRequests);
|
||||
|
||||
const operationLocationUrl = response.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
assert.isNotNull(operationId);
|
||||
|
||||
// get Documents Status
|
||||
const documentResponse = await client
|
||||
.path("/document/batches/{id}/documents", operationId)
|
||||
.get();
|
||||
|
||||
if (isUnexpected(documentResponse)) {
|
||||
throw "get documents status job error:" + documentResponse.body;
|
||||
}
|
||||
const responseBody = documentResponse.body;
|
||||
for (const document of responseBody.value) {
|
||||
const documentStatus = await client
|
||||
.path("/document/batches/{id}/documents/{documentId}", operationId, document.id)
|
||||
.get();
|
||||
if (isUnexpected(documentStatus)) {
|
||||
throw "get documents status job error:" + documentStatus.body;
|
||||
}
|
||||
validateDocumentStatus(documentStatus as GetDocumentStatus200Response, document.to);
|
||||
}
|
||||
});
|
||||
|
||||
it("Wrong Source Right Target", async () => {
|
||||
const sourceInput = createSourceInput("https://idont.ex.ist");
|
||||
const targetInput = createTargetInput(await createTargetContainer(recorder), "es");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await client.path("/document/batches").post({
|
||||
body: batchRequests,
|
||||
});
|
||||
const operationLocationUrl = response.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
assert.isNotNull(operationId);
|
||||
|
||||
// get translations status
|
||||
let translationStatus = null;
|
||||
let retriesLeft = retryCount;
|
||||
do {
|
||||
try {
|
||||
await sleep(10000);
|
||||
retriesLeft--;
|
||||
translationStatus = (await client
|
||||
.path("/document/batches/{id}", operationId)
|
||||
.get()) as GetTranslationStatus200Response;
|
||||
} catch (error) {
|
||||
console.error("Error during translation status retrieval:", error);
|
||||
}
|
||||
} while (
|
||||
translationStatus &&
|
||||
(translationStatus.body as TranslationStatusOutput).status === "NotStarted" &&
|
||||
retriesLeft > 0
|
||||
);
|
||||
assert.equal((translationStatus?.body as TranslationStatusOutput).status, "ValidationFailed");
|
||||
assert.equal(
|
||||
(translationStatus?.body as TranslationStatusOutput).error?.innerError?.code,
|
||||
"InvalidDocumentAccessLevel",
|
||||
);
|
||||
});
|
||||
|
||||
it("Right Source Wrong Target", async () => {
|
||||
const sourceUrl = await createSourceContainer(recorder, ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetInput = createTargetInput("https://idont.ex.ist", "es");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await client.path("/document/batches").post({
|
||||
body: batchRequests,
|
||||
});
|
||||
const operationLocationUrl = response.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
assert.isNotNull(operationId);
|
||||
|
||||
// get translations status
|
||||
let translationStatus = null;
|
||||
let retriesLeft = retryCount;
|
||||
do {
|
||||
try {
|
||||
await sleep(10000);
|
||||
retriesLeft--;
|
||||
translationStatus = (await client
|
||||
.path("/document/batches/{id}", operationId)
|
||||
.get()) as GetTranslationStatus200Response;
|
||||
} catch (error) {
|
||||
console.error("Error during translation status retrieval:", error);
|
||||
}
|
||||
} while (
|
||||
translationStatus &&
|
||||
(translationStatus.body as TranslationStatusOutput).status === "NotStarted" &&
|
||||
retriesLeft > 0
|
||||
);
|
||||
|
||||
assert.equal((translationStatus?.body as TranslationStatusOutput).status, "ValidationFailed");
|
||||
assert.equal(
|
||||
(translationStatus?.body as TranslationStatusOutput).error?.innerError?.code,
|
||||
"InvalidTargetDocumentAccessLevel",
|
||||
);
|
||||
});
|
||||
|
||||
it("Supported And UnSupported Files", async () => {
|
||||
const documents = [
|
||||
createTestDocument("Document1.txt", "First english test file"),
|
||||
createTestDocument("File2.jpg", "jpg"),
|
||||
];
|
||||
const sourceUrl = await createSourceContainer(recorder, documents);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer(recorder);
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await StartTranslationAndWait(batchRequests);
|
||||
if (isUnexpected(response)) {
|
||||
throw "get documents status job error:" + response.body;
|
||||
}
|
||||
|
||||
// Validate the response
|
||||
validateTranslationStatus(response as StartTranslationDefaultResponse, 1);
|
||||
});
|
||||
|
||||
it("Empty Document Error", async () => {
|
||||
const documents = [createTestDocument("Document1.txt", "")];
|
||||
const sourceUrl = await createSourceContainer(recorder, documents);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer(recorder);
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await StartTranslationAndWait(batchRequests);
|
||||
// Validate the response
|
||||
const operationLocationUrl = response.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
assert.isNotNull(operationId);
|
||||
|
||||
const translationStatus = (await client
|
||||
.path("/document/batches/{id}", operationId)
|
||||
.get()) as GetTranslationStatus200Response;
|
||||
if (isUnexpected(translationStatus)) {
|
||||
throw "get documents status job error:" + translationStatus.body;
|
||||
}
|
||||
const translationStatusOutput = translationStatus.body as TranslationStatusOutput;
|
||||
assert.equal(translationStatusOutput.status, "Failed");
|
||||
assert.equal(translationStatusOutput.summary.total, 1);
|
||||
assert.equal(translationStatusOutput.summary.success, 0);
|
||||
assert.equal(translationStatusOutput.summary.failed, 1);
|
||||
assert.equal(translationStatusOutput.error?.code, "InvalidRequest");
|
||||
assert.equal(translationStatusOutput.error?.innerError?.code, "NoTranslatableText");
|
||||
});
|
||||
|
||||
it("Existing File In Target Container", async () => {
|
||||
const sourceUrl = await createSourceContainer(recorder, ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer(recorder, undefined, ONE_TEST_DOCUMENTS);
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await client.path("/document/batches").post({
|
||||
body: batchRequests,
|
||||
});
|
||||
const operationLocationUrl = response.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
assert.isNotNull(operationId);
|
||||
|
||||
// get translations status
|
||||
let translationStatus = null;
|
||||
let retriesLeft = retryCount;
|
||||
do {
|
||||
try {
|
||||
await sleep(10000);
|
||||
retriesLeft--;
|
||||
translationStatus = (await client
|
||||
.path("/document/batches/{id}", operationId)
|
||||
.get()) as GetTranslationStatus200Response;
|
||||
} catch (error) {
|
||||
console.error("Error during translation status retrieval:", error);
|
||||
}
|
||||
} while (
|
||||
translationStatus &&
|
||||
(translationStatus.body as TranslationStatusOutput).status === "NotStarted" &&
|
||||
retriesLeft > 0
|
||||
);
|
||||
assert.equal((translationStatus?.body as TranslationStatusOutput).status, "ValidationFailed");
|
||||
assert.equal(
|
||||
(translationStatus?.body as TranslationStatusOutput).error?.innerError?.code,
|
||||
"TargetFileAlreadyExists",
|
||||
);
|
||||
});
|
||||
|
||||
it("Invalid Document GUID", async () => {
|
||||
const sourceUrl = await createSourceContainer(recorder, ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
const targetUrl = await createTargetContainer(recorder);
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await client.path("/document/batches").post({
|
||||
body: batchRequests,
|
||||
});
|
||||
const operationLocationUrl = response.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
assert.isNotNull(operationId);
|
||||
|
||||
// get document status
|
||||
let documentResponse = await client
|
||||
.path("/document/batches/{id}/documents/{documentId}", operationId, "Foo Bar")
|
||||
.get();
|
||||
assert.equal(documentResponse.status, "404");
|
||||
|
||||
documentResponse = await client
|
||||
.path("/document/batches/{id}/documents/{documentId}", operationId, " ")
|
||||
.get();
|
||||
assert.equal(documentResponse.status, "404");
|
||||
});
|
||||
|
||||
it("Document Translation With Glossary", async () => {
|
||||
const sourceUrl = await createSourceContainer(recorder, ONE_TEST_DOCUMENTS);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
|
||||
const targetContainer = await createTargetContainerWithInfo(recorder);
|
||||
const targetUrl = targetContainer.get("sasUrl") as string;
|
||||
const targetContainerName = targetContainer.get("containerName") as string;
|
||||
const glossaryUrl = await createGlossaryContainer(recorder);
|
||||
|
||||
const glossaries = [
|
||||
{
|
||||
glossaryUrl: glossaryUrl,
|
||||
format: "csv",
|
||||
},
|
||||
];
|
||||
const targetInput = createTargetInput(targetUrl, "fr", undefined, glossaries);
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await StartTranslationAndWait(batchRequests);
|
||||
|
||||
// Validate the response
|
||||
const operationLocationUrl = response.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
assert.isNotNull(operationId);
|
||||
|
||||
const result = downloadDocument(recorder, targetContainerName, "Document1.txt");
|
||||
assert.isTrue((await result).includes("glossaryTest"));
|
||||
});
|
||||
|
||||
async function validateTranslationStatus(
|
||||
translationResponse: StartTranslationDefaultResponse,
|
||||
translationCount: number,
|
||||
) {
|
||||
const operationLocationUrl = translationResponse.headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
assert.isNotNull(operationId);
|
||||
assert.equal(translationResponse.status, "Succeeded");
|
||||
|
||||
const translationStatus = (await client
|
||||
.path("/document/batches/{id}", operationId)
|
||||
.get()) as GetTranslationStatus200Response;
|
||||
if (isUnexpected(translationStatus)) {
|
||||
throw "get documents status job error:" + translationStatus.body;
|
||||
}
|
||||
const translationStatusOutput = translationStatus.body as TranslationStatusOutput;
|
||||
assert.equal(translationStatusOutput.summary.total, translationCount);
|
||||
assert.equal(translationStatusOutput.summary.success, translationCount);
|
||||
assert.equal(translationStatusOutput.summary.failed, 0);
|
||||
assert.equal(translationStatusOutput.summary.cancelled, 0);
|
||||
assert.equal(translationStatusOutput.summary.inProgress, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
function validateDocumentStatus(
|
||||
documentStatus: GetDocumentStatus200Response,
|
||||
targetLanguage: string,
|
||||
) {
|
||||
assert.equal(documentStatus.status, "200");
|
||||
const documentStatusOutput = documentStatus.body as DocumentStatusOutput;
|
||||
assert.isNotNull(documentStatusOutput.id);
|
||||
assert.isNotNull(documentStatusOutput.sourcePath);
|
||||
assert.isNotNull(documentStatusOutput.path);
|
||||
if (isLiveMode()) {
|
||||
assert.equal(targetLanguage, documentStatusOutput.to);
|
||||
}
|
||||
assert.notEqual(new Date(), new Date(documentStatusOutput.createdDateTimeUtc));
|
||||
assert.notEqual(new Date(), new Date(documentStatusOutput.lastActionDateTimeUtc));
|
||||
assert.equal(1, documentStatusOutput.progress);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
async function StartTranslationAndWait(batchRequests: {
|
||||
inputs: BatchRequest[];
|
||||
}): Promise<StartTranslationDefaultResponse> {
|
||||
// Start translation
|
||||
const response = await client.path("/document/batches").post({
|
||||
body: batchRequests,
|
||||
});
|
||||
if (isUnexpected(response)) {
|
||||
throw "start translation job error:" + response.body;
|
||||
}
|
||||
|
||||
// Wait until the operation completes
|
||||
const poller = getLongRunningPoller(client, response, testPollingOptions);
|
||||
const result = await (await poller).pollUntilDone();
|
||||
assert.equal(result.status, "200");
|
||||
|
||||
return response as StartTranslationDefaultResponse;
|
||||
}
|
||||
});
|
|
@ -0,0 +1,251 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Recorder, isPlaybackMode } from "@azure-tools/test-recorder";
|
||||
import { assert } from "chai";
|
||||
import {
|
||||
DocumentTranslationClient,
|
||||
isUnexpected,
|
||||
getLongRunningPoller,
|
||||
GetTranslationStatus200Response,
|
||||
TranslationStatusOutput,
|
||||
} from "../.././../src";
|
||||
import { createDocumentTranslationClient, startRecorder } from "../utils/recordedClient";
|
||||
import { createSourceContainer, createTargetContainer } from "./containerHelper";
|
||||
import { Context } from "mocha";
|
||||
import {
|
||||
createBatchRequest,
|
||||
createDummyTestDocuments,
|
||||
createSourceInput,
|
||||
createTargetInput,
|
||||
getTranslationOperationID,
|
||||
sleep,
|
||||
} from "../utils/testHelper";
|
||||
|
||||
export const testPollingOptions = {
|
||||
intervalInMs: isPlaybackMode() ? 0 : undefined,
|
||||
};
|
||||
|
||||
describe("TranslationFilter tests", () => {
|
||||
let recorder: Recorder;
|
||||
let client: DocumentTranslationClient;
|
||||
|
||||
beforeEach(async function (this: Context) {
|
||||
recorder = await startRecorder(this);
|
||||
client = await createDocumentTranslationClient({ recorder });
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
await recorder.stop();
|
||||
});
|
||||
|
||||
it("Translation Statuses Filter By Status", async () => {
|
||||
createTranslationJobs(1, 1, "Succeeded");
|
||||
const cancelledIds = createTranslationJobs(1, 1, "Cancelled");
|
||||
|
||||
// list translations with filter
|
||||
const cancelledStatusList = ["Cancelled", "Cancelling"];
|
||||
const testStartTime = recorder.variable("testStartTime", new Date().toISOString());
|
||||
|
||||
const queryParams = {
|
||||
statuses: cancelledStatusList,
|
||||
createdDateTimeUtcStart: testStartTime,
|
||||
};
|
||||
|
||||
// get Translation Status
|
||||
const response = await client.path("/document/batches").get({
|
||||
queryParameters: queryParams,
|
||||
});
|
||||
|
||||
if (isUnexpected(response)) {
|
||||
throw "get translation status job error:" + response.body;
|
||||
}
|
||||
const responseBody = response.body;
|
||||
for (const translationStatus of responseBody.value) {
|
||||
assert.isTrue(cancelledStatusList.includes(translationStatus.status));
|
||||
assert.isTrue((await cancelledIds).includes(translationStatus.id));
|
||||
}
|
||||
});
|
||||
|
||||
it("Translation Statuses Filter By Id", async () => {
|
||||
const allIds = createTranslationJobs(2, 1, "Succeeded");
|
||||
const targetIds = [];
|
||||
targetIds.push((await allIds)[0]);
|
||||
|
||||
// get Translation Status
|
||||
const queryParams = {
|
||||
ids: targetIds,
|
||||
};
|
||||
const response = await client.path("/document/batches").get({
|
||||
queryParameters: queryParams,
|
||||
});
|
||||
|
||||
if (isUnexpected(response)) {
|
||||
throw "get translation status job error:" + response.body;
|
||||
}
|
||||
|
||||
const responseBody = response.body;
|
||||
for (const translationStatus of responseBody.value) {
|
||||
assert.isTrue(targetIds.includes(translationStatus.id));
|
||||
}
|
||||
});
|
||||
|
||||
it("Translation Statuses Filter By Created After", async () => {
|
||||
const testStartTime = recorder.variable("testStartTime", new Date().toISOString());
|
||||
const targetIds = createTranslationJobs(1, 1, "Succeeded");
|
||||
|
||||
// get Translation Status
|
||||
const queryParams = {
|
||||
createdDateTimeUtcStart: testStartTime,
|
||||
};
|
||||
const response = await client.path("/document/batches").get({
|
||||
queryParameters: queryParams,
|
||||
});
|
||||
if (isUnexpected(response)) {
|
||||
throw "get translation status job error:" + response.body;
|
||||
}
|
||||
const responseBody = response.body;
|
||||
for (const translationStatus of responseBody.value) {
|
||||
assert.isTrue((await targetIds).includes(translationStatus.id));
|
||||
assert.isTrue(new Date(translationStatus.createdDateTimeUtc).toISOString() > testStartTime);
|
||||
}
|
||||
});
|
||||
|
||||
it("Translation Statuses Filter By Created Before", async () => {
|
||||
const targetIds = createTranslationJobs(1, 1, "Succeeded");
|
||||
for (let i = 0; i < (await targetIds).length; i++) {
|
||||
console.log(`targetIds[${i}]:`, (await targetIds)[i]);
|
||||
}
|
||||
|
||||
const endDateTime = recorder.variable("endDateTime", new Date().toISOString());
|
||||
createTranslationJobs(1, 1, "Succeeded");
|
||||
|
||||
// getting only translations from the last hour
|
||||
const testDateTime = new Date();
|
||||
testDateTime.setHours(testDateTime.getHours() - 1);
|
||||
const startDateTime = recorder.variable("startDateTime", testDateTime.toISOString());
|
||||
|
||||
// get Translation Status
|
||||
const queryParams = {
|
||||
createdDateTimeUtcStart: startDateTime,
|
||||
createdDateTimeUtcEnd: endDateTime,
|
||||
};
|
||||
const response = await client.path("/document/batches").get({
|
||||
queryParameters: queryParams,
|
||||
});
|
||||
if (isUnexpected(response)) {
|
||||
throw "get translation status job error:" + response.body;
|
||||
}
|
||||
|
||||
const responseBody = response.body;
|
||||
let idExists = false;
|
||||
for (const translationStatus of responseBody.value) {
|
||||
if ((await targetIds).includes(translationStatus.id)) {
|
||||
idExists = true;
|
||||
}
|
||||
assert.isTrue(new Date(translationStatus.createdDateTimeUtc).toISOString() < endDateTime);
|
||||
}
|
||||
assert.isTrue(idExists);
|
||||
});
|
||||
|
||||
it("Translation Statuses Filter By Created On", async () => {
|
||||
createTranslationJobs(3, 1, "Succeeded");
|
||||
|
||||
// Add filter
|
||||
const startDateTime = recorder.variable("startDateTime", new Date().toISOString());
|
||||
const orderByList = ["createdDateTimeUtc asc"];
|
||||
const queryParams = {
|
||||
createdDateTimeUtcStart: startDateTime,
|
||||
orderby: orderByList,
|
||||
};
|
||||
|
||||
const response = await client.path("/document/batches").get({
|
||||
queryParameters: queryParams,
|
||||
});
|
||||
if (isUnexpected(response)) {
|
||||
throw "get translation status job error:" + response.body;
|
||||
}
|
||||
let timestamp = new Date(-8640000000000000); // Minimum valid Date value in JavaScript
|
||||
|
||||
const responseBody = response.body;
|
||||
for (const translationStatus of responseBody.value) {
|
||||
assert.isTrue(new Date(translationStatus.createdDateTimeUtc) > timestamp);
|
||||
timestamp = new Date(translationStatus.createdDateTimeUtc);
|
||||
}
|
||||
});
|
||||
|
||||
async function createTranslationJobs(
|
||||
jobsCount: number,
|
||||
docsPerJob: number,
|
||||
jobTerminalStatus: string,
|
||||
) {
|
||||
// create source container
|
||||
if (jobTerminalStatus.includes("cancelled")) {
|
||||
docsPerJob = 20; // in order to avoid job completing before canceling
|
||||
}
|
||||
const testDocuments = createDummyTestDocuments(docsPerJob);
|
||||
const sourceUrl = await createSourceContainer(recorder, testDocuments);
|
||||
const sourceInput = createSourceInput(sourceUrl);
|
||||
|
||||
// create a translation job
|
||||
const translationIds = [];
|
||||
for (let i = 1; i <= jobsCount; i++) {
|
||||
const targetUrl = await createTargetContainer(recorder);
|
||||
const targetInput = createTargetInput(targetUrl, "fr");
|
||||
const batchRequest = createBatchRequest(sourceInput, [targetInput]);
|
||||
|
||||
// Start translation
|
||||
const batchRequests = { inputs: [batchRequest] };
|
||||
const response = await client.path("/document/batches").post({
|
||||
body: batchRequests,
|
||||
});
|
||||
if (isUnexpected(response)) {
|
||||
throw "start translation job error:" + response.body;
|
||||
}
|
||||
|
||||
const operationLocationUrl = (await response).headers["operation-location"];
|
||||
const operationId = getTranslationOperationID(operationLocationUrl);
|
||||
translationIds.push(operationId);
|
||||
|
||||
if (jobTerminalStatus.includes("succeeded")) {
|
||||
// Wait until the operation completes
|
||||
const poller = getLongRunningPoller(client, response, testPollingOptions);
|
||||
const result = await (await poller).pollUntilDone();
|
||||
assert.equal(result.status, "200");
|
||||
} else if (jobTerminalStatus.includes("cancelled")) {
|
||||
await client.path("/document/batches/{id}", operationId).delete();
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that cancel status has propagated before returning
|
||||
if (jobTerminalStatus.includes("cancelled")) {
|
||||
waitForJobCancellation(translationIds);
|
||||
}
|
||||
return translationIds;
|
||||
}
|
||||
|
||||
async function waitForJobCancellation(translationIds: string[]): Promise<void> {
|
||||
const retryCount = 10;
|
||||
|
||||
for (const translationId of translationIds) {
|
||||
let translationStatus = null;
|
||||
let retriesLeft = retryCount;
|
||||
do {
|
||||
try {
|
||||
await sleep(10000);
|
||||
retriesLeft--;
|
||||
translationStatus = (await client
|
||||
.path("/document/batches/{id}", translationId)
|
||||
.get()) as GetTranslationStatus200Response;
|
||||
} catch (error) {
|
||||
console.error("Error during translation status retrieval:", error);
|
||||
}
|
||||
} while (
|
||||
translationStatus &&
|
||||
(translationStatus.body as TranslationStatusOutput).summary.cancelled > 0 &&
|
||||
retriesLeft > 0
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
|
@ -0,0 +1,126 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Recorder } from "@azure-tools/test-recorder";
|
||||
import { assert } from "chai";
|
||||
import {
|
||||
DocumentTranslateDefaultResponse,
|
||||
DocumentTranslateParameters,
|
||||
DocumentTranslationClient,
|
||||
isUnexpected,
|
||||
} from "../../src";
|
||||
import { createDocumentTranslationClient, startRecorder } from "./utils/recordedClient";
|
||||
import { Context } from "mocha";
|
||||
|
||||
describe("SingleDocumentTranslate tests", () => {
|
||||
let recorder: Recorder;
|
||||
let client: DocumentTranslationClient;
|
||||
|
||||
beforeEach(async function (this: Context) {
|
||||
recorder = await startRecorder(this);
|
||||
client = await createDocumentTranslationClient({ recorder });
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
await recorder.stop();
|
||||
});
|
||||
|
||||
it("document translate", async () => {
|
||||
const options = {
|
||||
queryParameters: {
|
||||
targetLanguage: "hi",
|
||||
},
|
||||
contentType: "multipart/form-data",
|
||||
body: [
|
||||
{
|
||||
name: "document",
|
||||
body: "This is a test.",
|
||||
filename: "test-input.txt",
|
||||
contentType: "text/html",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const response = await client
|
||||
.path("/document:translate")
|
||||
.post(options as DocumentTranslateParameters);
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
});
|
||||
|
||||
it("single CSV glossary", async () => {
|
||||
const options = {
|
||||
queryParameters: {
|
||||
targetLanguage: "hi",
|
||||
},
|
||||
contentType: "multipart/form-data",
|
||||
body: [
|
||||
{
|
||||
name: "document",
|
||||
body: "This is a test.",
|
||||
filename: "test-input.txt",
|
||||
contentType: "text/html",
|
||||
},
|
||||
{
|
||||
name: "glossary",
|
||||
body: "test,test",
|
||||
filename: "test-glossary.csv",
|
||||
contentType: "text/csv",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const response = await client
|
||||
.path("/document:translate")
|
||||
.post(options as DocumentTranslateParameters);
|
||||
if (isUnexpected(response)) {
|
||||
throw response.body;
|
||||
}
|
||||
assert.isTrue(response.body.toString().includes("test"));
|
||||
});
|
||||
|
||||
it("Multiple CSV glossary", async () => {
|
||||
const options = {
|
||||
queryParameters: {
|
||||
targetLanguage: "hi",
|
||||
},
|
||||
contentType: "multipart/form-data",
|
||||
body: [
|
||||
{
|
||||
name: "document",
|
||||
body: "This is a test.",
|
||||
filename: "test-input.txt",
|
||||
contentType: "text/html",
|
||||
},
|
||||
{
|
||||
name: "glossary",
|
||||
body: "test,test",
|
||||
filename: "test-glossary.csv",
|
||||
contentType: "text/csv",
|
||||
},
|
||||
{
|
||||
name: "glossary",
|
||||
body: "test,test",
|
||||
filename: "test-glossary.csv",
|
||||
contentType: "text/csv",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const response = (await client
|
||||
.path("/document:translate")
|
||||
.post(options as DocumentTranslateParameters)) as DocumentTranslateDefaultResponse;
|
||||
|
||||
if (isUnexpected(response)) {
|
||||
assert.equal(response.status, "400");
|
||||
assert.isTrue(
|
||||
response.body.error.message.includes(
|
||||
"The maximum number of glossary files has been exceeded",
|
||||
),
|
||||
);
|
||||
} else {
|
||||
assert.isFalse(true);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { TokenCredential, AccessToken } from "@azure/core-auth";
|
||||
|
||||
export class StaticAccessTokenCredential implements TokenCredential {
|
||||
// AccessToken is an object with two properties:
|
||||
// - A "token" property with a string value.
|
||||
// - And an "expiresOnTimestamp" property with a numeric unix timestamp as its value.
|
||||
constructor(private accessToken: string) {}
|
||||
async getToken(): Promise<AccessToken> {
|
||||
return {
|
||||
expiresOnTimestamp: Date.now() + 10000,
|
||||
token: this.accessToken,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
export interface TestDocument {
|
||||
name: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export function createTestDocument(name: string, content: string): TestDocument {
|
||||
return {
|
||||
name,
|
||||
content,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { Context } from "mocha";
|
||||
import { Recorder, env } from "@azure-tools/test-recorder";
|
||||
import { ClientOptions } from "@azure-rest/core-client";
|
||||
import { DocumentTranslationClient } from "../../../src";
|
||||
import createClient from "../../../src/documentTranslationClient";
|
||||
import { KeyCredential, TokenCredential } from "@azure/core-auth";
|
||||
|
||||
export async function startRecorder(context: Context): Promise<Recorder> {
|
||||
const recorder = new Recorder(context.currentTest);
|
||||
await recorder.start({
|
||||
envSetupForPlayback: {
|
||||
DOCUMENT_TRANSLATION_API_KEY: "fakeApiKey",
|
||||
DOCUMENT_TRANSLATION_ENDPOINT:
|
||||
"https://fakeEndpoint-doctranslation.cognitiveservices.azure.com",
|
||||
DOCUMENT_TRANSLATION_STORAGE_NAME: "fakestoragename",
|
||||
DOCUMENT_TRANSLATION_CONNECTION_STRING:
|
||||
"DefaultEndpointsProtocol=https;AccountName=fakeStorageName;AccountKey=fakeKey;EndpointSuffix=core.windows.net",
|
||||
},
|
||||
removeCentralSanitizers: ["AZSDK2030", "AZSDK3430"],
|
||||
});
|
||||
// SAS token may contain sensitive information
|
||||
await recorder.addSanitizers(
|
||||
{
|
||||
bodyKeySanitizers: [
|
||||
{
|
||||
value: "Sanitized",
|
||||
jsonPath: "$..sourceUrl",
|
||||
},
|
||||
{
|
||||
value: "Sanitized",
|
||||
jsonPath: "$..targetUrl",
|
||||
},
|
||||
{
|
||||
value: "Sanitized",
|
||||
jsonPath: "$..glossaryUrl",
|
||||
},
|
||||
],
|
||||
},
|
||||
["record", "playback"],
|
||||
);
|
||||
return recorder;
|
||||
}
|
||||
|
||||
export async function createDocumentTranslationClient(options: {
|
||||
recorder?: Recorder;
|
||||
clientOptions?: ClientOptions;
|
||||
}): Promise<DocumentTranslationClient> {
|
||||
const { recorder, clientOptions = {} } = options;
|
||||
const updatedOptions = recorder ? recorder.configureClientOptions(clientOptions) : clientOptions;
|
||||
const endpoint = env.DOCUMENT_TRANSLATION_ENDPOINT ?? "";
|
||||
const credentials = { key: env.DOCUMENT_TRANSLATION_API_KEY ?? "" };
|
||||
|
||||
const client = createClient(endpoint, credentials, updatedOptions);
|
||||
return client;
|
||||
}
|
||||
|
||||
export async function createDocumentTranslationClientWithEndpointAndCredentials(options: {
|
||||
recorder?: Recorder;
|
||||
endpointParam: string;
|
||||
credentials: TokenCredential | KeyCredential;
|
||||
clientOptions?: ClientOptions;
|
||||
}): Promise<DocumentTranslationClient> {
|
||||
const { recorder, clientOptions = {} } = options;
|
||||
const updatedOptions = recorder ? recorder.configureClientOptions(clientOptions) : clientOptions;
|
||||
const client = createClient(options.endpointParam, options.credentials, updatedOptions);
|
||||
return client;
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import { ContainerClient, ContainerSASPermissions, BlobServiceClient } from "@azure/storage-blob";
|
||||
import { TestDocument, createTestDocument } from "../utils/TestDocument";
|
||||
import {
|
||||
BatchRequest,
|
||||
DocumentTranslationClient,
|
||||
StartTranslationDefaultResponse,
|
||||
getLongRunningPoller,
|
||||
} from "../../../src";
|
||||
|
||||
const connectionString =
|
||||
process.env["DOCUMENT_TRANSLATION_CONNECTION_STRING"] || "ConnectionString";
|
||||
|
||||
export async function StartTranslationAndWait(
|
||||
client: DocumentTranslationClient,
|
||||
batchRequests: { inputs: BatchRequest[] },
|
||||
): Promise<StartTranslationDefaultResponse> {
|
||||
// Start translation
|
||||
const response = await client.path("/document/batches").post({
|
||||
body: batchRequests,
|
||||
});
|
||||
|
||||
// Wait until the operation completes
|
||||
const poller = getLongRunningPoller(client, response, undefined);
|
||||
await (await poller).pollUntilDone();
|
||||
|
||||
return response as StartTranslationDefaultResponse;
|
||||
}
|
||||
|
||||
export const ONE_TEST_DOCUMENTS: TestDocument[] = [
|
||||
createTestDocument("Document1.txt", "First english test document"),
|
||||
];
|
||||
|
||||
export const TWO_TEST_DOCUMENTS: TestDocument[] = [
|
||||
createTestDocument("Document1.txt", "First english test file"),
|
||||
createTestDocument("File2.txt", "Second english test file"),
|
||||
];
|
||||
|
||||
export async function createSourceContainer(
|
||||
documents: TestDocument[],
|
||||
containerName?: string | undefined,
|
||||
): Promise<string> {
|
||||
if (containerName === undefined) {
|
||||
containerName = `source-${getUniqueName()}`;
|
||||
}
|
||||
const containerClient = await createContainer(containerName, documents);
|
||||
|
||||
const sasUrl = await containerClient.generateSasUrl({
|
||||
permissions: ContainerSASPermissions.parse("rwl"),
|
||||
expiresOn: getDateOneDayAfter(),
|
||||
});
|
||||
return `${sasUrl}`;
|
||||
}
|
||||
|
||||
export async function createTargetContainer(
|
||||
containerName?: string | undefined,
|
||||
documents?: TestDocument[],
|
||||
): Promise<string> {
|
||||
if (containerName === undefined) {
|
||||
containerName = `target-${getUniqueName()}`;
|
||||
}
|
||||
const containerClient = await createContainer(containerName, documents);
|
||||
|
||||
const sasUrl = await containerClient.generateSasUrl({
|
||||
permissions: ContainerSASPermissions.parse("rwl"),
|
||||
expiresOn: getDateOneDayAfter(),
|
||||
});
|
||||
return `${sasUrl}`;
|
||||
}
|
||||
|
||||
async function createContainer(
|
||||
containerName: string,
|
||||
documents?: TestDocument[],
|
||||
): Promise<ContainerClient> {
|
||||
const blobServiceClient: BlobServiceClient =
|
||||
BlobServiceClient.fromConnectionString(connectionString);
|
||||
const containerClient = blobServiceClient.getContainerClient(containerName);
|
||||
await containerClient.createIfNotExists();
|
||||
|
||||
if (documents && documents.length > 0) {
|
||||
await uploadDocuments(containerClient, documents);
|
||||
}
|
||||
return containerClient;
|
||||
}
|
||||
|
||||
export function getUniqueName(): string {
|
||||
const randomNumber = Math.floor(Math.random() * 1e10);
|
||||
return randomNumber.toString().padStart(10, "0");
|
||||
}
|
||||
|
||||
async function uploadDocuments(containerClient: ContainerClient, documents: TestDocument[]) {
|
||||
for (const document of documents) {
|
||||
const blobClient = containerClient.getBlobClient(document.name);
|
||||
const blockBlobClient = blobClient.getBlockBlobClient();
|
||||
await blockBlobClient.upload(document.content, document.content.length);
|
||||
}
|
||||
}
|
||||
|
||||
function getDateOneDayAfter(): Date {
|
||||
const currentDate = new Date();
|
||||
const nextDayDate = new Date(currentDate);
|
||||
nextDayDate.setDate(currentDate.getDate() + 1);
|
||||
return nextDayDate;
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
BatchRequest,
|
||||
DocumentFilter,
|
||||
Glossary,
|
||||
SourceInput,
|
||||
StorageInputType,
|
||||
StorageSource,
|
||||
TargetInput,
|
||||
} from "../../../src/models";
|
||||
import { TestDocument, createTestDocument } from "./TestDocument";
|
||||
|
||||
export function createSourceInput(
|
||||
sourceUrl: string,
|
||||
language?: string,
|
||||
storageSource?: StorageSource,
|
||||
filter?: DocumentFilter,
|
||||
): SourceInput {
|
||||
return {
|
||||
sourceUrl,
|
||||
language,
|
||||
storageSource,
|
||||
filter,
|
||||
};
|
||||
}
|
||||
|
||||
export function createTargetInput(
|
||||
targetUrl: string,
|
||||
language: string,
|
||||
storageSource?: StorageSource,
|
||||
glossaries?: Glossary[],
|
||||
category?: string,
|
||||
): TargetInput {
|
||||
return {
|
||||
targetUrl,
|
||||
language,
|
||||
storageSource,
|
||||
glossaries,
|
||||
category,
|
||||
};
|
||||
}
|
||||
|
||||
export function createBatchRequest(
|
||||
source: SourceInput,
|
||||
targets: Array<TargetInput>,
|
||||
storageType?: StorageInputType,
|
||||
): BatchRequest {
|
||||
return {
|
||||
source,
|
||||
targets,
|
||||
storageType,
|
||||
};
|
||||
}
|
||||
|
||||
export function getTranslationOperationID(url: string): string {
|
||||
try {
|
||||
const parsedUrl = new URL(url);
|
||||
const pathSegments = parsedUrl.pathname.split("/");
|
||||
const lastSegment = pathSegments[pathSegments.length - 1];
|
||||
return typeof lastSegment === "string" ? lastSegment : "";
|
||||
} catch (error) {
|
||||
console.error("Invalid Operation-location URL:", error);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
export function sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
export function createDummyTestDocuments(count: number): TestDocument[] {
|
||||
const result: TestDocument[] = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
const fileName: string = `File_${i}.txt`;
|
||||
const text: string = "some random text";
|
||||
result.push(createTestDocument(fileName, text));
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
parameters:
|
||||
- name: Location
|
||||
displayName: Location
|
||||
type: string
|
||||
default: eastus
|
||||
|
||||
trigger: none
|
||||
|
||||
extends:
|
||||
template: /eng/pipelines/templates/stages/archetype-sdk-tests.yml
|
||||
parameters:
|
||||
PackageName: "@azure-rest/ai-translation-document"
|
||||
ServiceDirectory: translation
|
||||
Location: "${{ parameters.Location }}"
|
||||
SupportedClouds: 'Public'
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.package",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist-esm",
|
||||
"declarationDir": "./types",
|
||||
"paths": {
|
||||
"@azure-rest/ai-translation-document": ["./src/index"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*.ts",
|
||||
"./src/**/*.mts",
|
||||
"./src/**/*.cts",
|
||||
"test/**/*.ts",
|
||||
"samples-dev/**/*.ts"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
commit: c27f2af6b7ffa0e2d966fc0926b9d19242f9f774
|
||||
repo: Azure/azure-rest-api-specs
|
||||
directory: specification/translation/Azure.AI.DocumentTranslation
|
||||
|
|
@ -11,6 +11,7 @@ trigger:
|
|||
include:
|
||||
- sdk/translation/ci.yml
|
||||
- sdk/translation/ai-translation-text-rest/
|
||||
- sdk/translation/ai-translation-document-rest/
|
||||
|
||||
pr:
|
||||
branches:
|
||||
|
@ -24,6 +25,7 @@ pr:
|
|||
include:
|
||||
- sdk/translation/ci.yml
|
||||
- sdk/translation/ai-translation-text-rest/
|
||||
- sdk/translation/ai-translation-document-rest/
|
||||
|
||||
extends:
|
||||
template: ../../eng/pipelines/templates/stages/archetype-sdk-client.yml
|
||||
|
@ -32,3 +34,5 @@ extends:
|
|||
Artifacts:
|
||||
- name: azure-rest-ai-translation-text
|
||||
safeName: azurerestaitranslationtext
|
||||
- name: azure-rest-ai-translation-document
|
||||
safeName: azurerestaitranslationdocument
|
||||
|
|
|
@ -41,13 +41,40 @@
|
|||
"customEndpointSuffix": {
|
||||
"defaultValue": ".cognitiveservices.azure.com/translator/text/v3.0",
|
||||
"type": "string"
|
||||
},
|
||||
"dtEndpointPrefix": {
|
||||
"defaultValue": "doctranslation",
|
||||
"type": "string"
|
||||
},
|
||||
"dtEndpointSuffix": {
|
||||
"defaultValue": ".cognitiveservices.azure.com",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"uniqueSubDomainName": "[format('{0}', parameters('baseName'))]",
|
||||
"endpointValue": "[format('https://{0}{1}', parameters('endpointPrefix'), parameters('endpointSuffix'))]",
|
||||
"customEndpointValue": "[format('https://{0}{1}', parameters('baseName'),parameters('customEndpointSuffix'))]",
|
||||
"regionValue": "[format('{0}', parameters('location'))]"
|
||||
"regionValue": "[format('{0}', parameters('location'))]",
|
||||
"tokenURLValue": "[format('https://{0}.api.cognitive.microsoft.com', parameters('location'))]",
|
||||
"roleDefinitionId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908')]",
|
||||
"dtUniqueSubDomainName": "[format('{0}-{1}', parameters('baseName'), parameters('dtEndpointPrefix'))]",
|
||||
"dtEndpointValue": "[format('https://{0}-{1}{2}', parameters('baseName'), parameters('dtEndpointPrefix'), parameters('dtEndpointSuffix'))]",
|
||||
"storageAccountName": "[concat(parameters('baseName'), 'prim')]",
|
||||
"encryption": {
|
||||
"services": {
|
||||
"blob": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"keySource": "Microsoft.Storage"
|
||||
},
|
||||
"networkAcls": {
|
||||
"bypass": "AzureServices",
|
||||
"virtualNetworkRules": [],
|
||||
"ipRules": [],
|
||||
"defaultAction": "Allow"
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
|
@ -62,6 +89,33 @@
|
|||
"properties": {
|
||||
"customSubDomainName": "[variables('uniqueSubDomainName')]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Authorization/roleAssignments",
|
||||
"apiVersion": "2018-09-01-preview",
|
||||
"name": "[guid(resourceGroup().id)]",
|
||||
"properties": {
|
||||
"roleDefinitionId": "[variables('roleDefinitionId')]",
|
||||
"principalId": "[parameters('testApplicationOid')]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Storage/storageAccounts",
|
||||
"apiVersion": "2022-05-01",
|
||||
"name": "[variables('storageAccountName')]",
|
||||
"location": "[parameters('location')]",
|
||||
"sku": {
|
||||
"name": "Standard_RAGRS",
|
||||
"tier": "Standard"
|
||||
},
|
||||
"kind": "StorageV2",
|
||||
"properties": {
|
||||
"networkAcls": "[variables('networkAcls')]",
|
||||
"supportsHttpsTrafficOnly": true,
|
||||
"encryption": "[variables('encryption')]",
|
||||
"accessTier": "Cool",
|
||||
"minimumTlsVersion": "TLS1_2"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": {
|
||||
|
@ -80,6 +134,22 @@
|
|||
"TEXT_TRANSLATION_REGION": {
|
||||
"type": "string",
|
||||
"value": "[variables('regionValue')]"
|
||||
}
|
||||
},
|
||||
"DOCUMENT_TRANSLATION_API_KEY": {
|
||||
"type": "string",
|
||||
"value": "[listKeys(resourceId('Microsoft.CognitiveServices/accounts', variables('dtUniqueSubDomainName')), '2017-04-18').key1]"
|
||||
},
|
||||
"DOCUMENT_TRANSLATION_ENDPOINT": {
|
||||
"type": "string",
|
||||
"value": "[variables('dtEndpointValue')]"
|
||||
},
|
||||
"DOCUMENT_TRANSLATION_STORAGE_NAME": {
|
||||
"type": "string",
|
||||
"value": "[variables('storageAccountName')]"
|
||||
},
|
||||
"DOCUMENT_TRANSLATION_CONNECTION_STRING": {
|
||||
"type": "string",
|
||||
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-04-01').keys[0].value,';EndpointSuffix=core.windows.net')]"
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче