Azure Cognitive Services Document Translation client library for .NET - version 2.0.0-beta.2
Azure Cognitive Services Document Translation is a cloud service that translates documents to and from 90 languages and dialects while preserving document structure and data format. Use the client library for Document Translation to:
- Translate numerous, large files from an Azure Blob Storage container to a target container in your language of choice.
- Check the translation status and progress of each document in the translation operation.
- Apply a custom translation model or glossaries to tailor translation to your specific case.
Source code | Package (NuGet) | API reference documentation | Product documentation | Samples
Getting started
Install the package
Install the Azure Document Translation client library for .NET with NuGet:
dotnet add package Azure.AI.Translation.Document
Note: This version of the client library defaults to the
v1.0
version of the service.
Prerequisites
- An Azure subscription.
- An existing Translator resource.
Create a Translator resource
Document Translation supports single-service access only. To access the service, create a Translator resource.
You can create either resource using:
Option 1: Azure Portal.
Option 2: Azure CLI.
Below is an example of how you can create a Translator resource using the CLI:
# Create a new resource group to hold the Translator resource -
# if using an existing resource group, skip this step
az group create --name <your-resource-name> --location <location>
# Create Translator
az cognitiveservices account create \
--name <your-resource-name> \
--custom-domain <your-resource-name> \
--resource-group <your-resource-group-name> \
--kind TextTranslation \
--sku S1 \
--location <location> \
--yes
For more information about creating the resource or how to get the location information see here.
Authenticate the client
In order to interact with the Document Translation service, you'll need to create an instance of the DocumentTranslationClient class. You will need an endpoint, and either an API key or TokenCredential
to instantiate a client object. For more information regarding authenticating with cognitive services, see Authenticate requests to Azure Cognitive Services.
Looking up the endpoint
For Document Translation you will need to use a Custom Domain Endpoint using the name of you Translator resource.
Get API Key
You can get the API key
from the Translator resource information in the Azure Portal.
Alternatively, use the Azure CLI snippet below to get the API key from the Translator resource.
az cognitiveservices account keys list --resource-group <your-resource-group-name> --name <your-resource-name>
Create DocumentTranslationClient with API Key Credential
Once you have the value for the API key, create an AzureKeyCredential
. This will allow you to
update the API key without creating a new client.
With the value of the endpoint and an AzureKeyCredential
, you can create the DocumentTranslationClient:
string endpoint = "<Document Translator Resource Endpoint>";
string apiKey = "<Document Translator Resource API Key>";
var client = new DocumentTranslationClient(new Uri(endpoint), new AzureKeyCredential(apiKey));
Create DocumentTranslationClient with Azure Active Directory Credential
Client API key authentication is used in most of the examples in this getting started guide, but you can also authenticate with Azure Active Directory using the Azure Identity library. Note that regional endpoints do not support AAD authentication.
Create a custom subdomain for your resource in order to use this type of authentication.
To use the DefaultAzureCredential provider shown below, or other credential providers provided with the Azure SDK, please install the Azure.Identity package:
dotnet add package Azure.Identity
You will also need to register a new AAD application and grant access to your Translator resource by assigning the "Cognitive Services User"
role to your service principal.
Set the values of the client ID
, tenant ID
, and client secret
of the AAD application as environment variables: AZURE_CLIENT_ID
, AZURE_TENANT_ID
, AZURE_CLIENT_SECRET
.
string endpoint = "<Document Translator Resource Endpoint>";
var client = new DocumentTranslationClient(new Uri(endpoint), new DefaultAzureCredential());
Key concepts
The Document Translation service requires that you upload your files to an Azure Blob Storage source container and provide a target container where the translated documents can be written. SAS tokens to the containers (or files) are used to access the documents and create the translated documents in the target container. Additional information about setting this up can be found in the service documentation:
- Set up Azure Blob Storage containers with your documents.
- Optionally apply glossaries or a custom model for translation.
- Generate SAS tokens to your containers (or files) with the appropriate permissions.
DocumentTranslationClient
A DocumentTranslationClient
is the primary interface for developers using the Document Translation client library. It provides both synchronous and asynchronous methods to perform the following operations:
- Creating a translation operation to translate documents in your source container(s) and write results to you target container(s).
- Enumerating all past and current translation operations.
- Identifying supported glossary and document formats.
Translation Input
To start a translation operation you need to create one instance or a list of DocumentTranslationInput
.
A single source URL to documents can be translated to many different languages:
Uri sourceSasUri = new Uri("<source SAS URI>");
Uri frenchTargetSasUri = new Uri("<french target SAS URI>");
var input = new DocumentTranslationInput(sourceSasUri, frenchTargetSasUri, "fr");
Or multiple different sources can be provided each with their own targets.
Uri arabicTargetSasUri = new Uri("<arabic target SAS URI>");
Uri spanishTargetSasUri = new Uri("<spanish target SAS URI>");
Uri source1SasUri = new Uri("<source1 SAS URI>");
Uri source2SasUri = new Uri("<source2 SAS URI>");
var inputs = new List<DocumentTranslationInput>
{
new DocumentTranslationInput(source1SasUri, spanishTargetSasUri, "es"),
new DocumentTranslationInput(
source: new TranslationSource(source2SasUri),
targets: new List<TranslationTarget>
{
new TranslationTarget(frenchTargetSasUri, "fr"),
new TranslationTarget(arabicTargetSasUri, "ar")
}),
};
Note that documents written to a target container must have unique names. So you can't translate a source container into a target container twice or have sources with the same documents translated into the same target container.
Long-Running Operations
Document Translation is implemented as a long-running operation. Long-running operations consist of an initial request sent to the service to start an operation, followed by polling the service at intervals to determine whether the operation has completed successfully or failed.
For long running operations in the Azure SDK, the client exposes a Start<operation-name>
method that returns a PageableOperation<T>
. You can use the extension method WaitForCompletionAsync()
to wait for the operation to complete and obtain its result. A sample code snippet is provided to illustrate using long-running operations below.
Thread safety
We guarantee that all client instance methods are thread-safe and independent of each other (guideline). This ensures that the recommendation of reusing client instances is always safe, even across threads.
Additional concepts
Client options | Accessing the response | Handling failures | Diagnostics | Mocking | Client lifetime
Examples
The following section provides several code snippets using the client
created above, and covers the main functions of Document Translation.
Note: our DocumentTranslationClient
provides both synchronous and asynchronous methods.
Async Examples
Sync Examples
Note: our DocumentTranslationClient
provides both synchronous and asynchronous methods.
Start Translation Asynchronously
Start a translation operation to translate documents in the source container and write the translated files to the target container. DocumentTranslationOperation
allows you to poll the status of the translation operation and get the status of the individual documents.
Uri sourceUri = new Uri("<source SAS URI>");
Uri targetUri = new Uri("<target SAS URI>");
var input = new DocumentTranslationInput(sourceUri, targetUri, "es");
DocumentTranslationOperation operation = await client.StartTranslationAsync(input);
await operation.WaitForCompletionAsync();
Console.WriteLine($" Status: {operation.Status}");
Console.WriteLine($" Created on: {operation.CreatedOn}");
Console.WriteLine($" Last modified: {operation.LastModified}");
Console.WriteLine($" Total documents: {operation.DocumentsTotal}");
Console.WriteLine($" Succeeded: {operation.DocumentsSucceeded}");
Console.WriteLine($" Failed: {operation.DocumentsFailed}");
Console.WriteLine($" In Progress: {operation.DocumentsInProgress}");
Console.WriteLine($" Not started: {operation.DocumentsNotStarted}");
await foreach (DocumentStatusResult document in operation.Value)
{
Console.WriteLine($"Document with Id: {document.Id}");
Console.WriteLine($" Status:{document.Status}");
if (document.Status == DocumentTranslationStatus.Succeeded)
{
Console.WriteLine($" Translated Document Uri: {document.TranslatedDocumentUri}");
Console.WriteLine($" Translated to language code: {document.TranslatedToLanguageCode}.");
Console.WriteLine($" Document source Uri: {document.SourceDocumentUri}");
}
else
{
Console.WriteLine($" Error Code: {document.Error.Code}");
Console.WriteLine($" Message: {document.Error.Message}");
}
}
Get Operations History Asynchronously
Get History of submitted translation operations from the last 7 days. The options parameter can be ommitted if the user would like to return all submitted operations.
int operationsCount = 0;
int totalDocs = 0;
int docsCanceled = 0;
int docsSucceeded = 0;
int docsFailed = 0;
DateTimeOffset lastWeekTimestamp = DateTimeOffset.Now.AddDays(-7);
var options = new GetTranslationStatusesOptions
{
CreatedAfter = lastWeekTimestamp
};
await foreach (TranslationStatusResult translationStatus in client.GetTranslationStatusesAsync(options))
{
if (translationStatus.Status == DocumentTranslationStatus.NotStarted ||
translationStatus.Status == DocumentTranslationStatus.Running)
{
DocumentTranslationOperation operation = new DocumentTranslationOperation(translationStatus.Id, client);
await operation.WaitForCompletionAsync();
}
operationsCount++;
totalDocs += translationStatus.DocumentsTotal;
docsCanceled += translationStatus.DocumentsCanceled;
docsSucceeded += translationStatus.DocumentsSucceeded;
docsFailed += translationStatus.DocumentsFailed;
}
Console.WriteLine($"# of operations: {operationsCount}");
Console.WriteLine($"Total Documents: {totalDocs}");
Console.WriteLine($"Succeeded Document: {docsSucceeded}");
Console.WriteLine($"Failed Document: {docsFailed}");
Console.WriteLine($"Canceled Documents: {docsCanceled}");
Start Translation with Multiple Inputs Asynchronously
Start a translation operation to translate documents in multiple source containers to multiple target containers in different languages. DocumentTranslationOperation
allows you to poll the status of the translation operation and get the status of the individual documents.
Uri source1SasUri = new Uri("<source1 SAS URI>");
Uri source2SasUri = new Uri("<source2 SAS URI>");
Uri frenchTargetSasUri = new Uri("<french target SAS URI>");
Uri arabicTargetSasUri = new Uri("<arabic target SAS URI>");
Uri spanishTargetSasUri = new Uri("<spanish target SAS URI>");
Uri frenchGlossarySasUri = new Uri("<french glossary SAS URI>");
var glossaryFormat = "TSV";
var input1 = new DocumentTranslationInput(source1SasUri, frenchTargetSasUri, "fr", new TranslationGlossary(frenchGlossarySasUri, glossaryFormat));
input1.AddTarget(spanishTargetSasUri, "es");
var input2 = new DocumentTranslationInput(source2SasUri, arabicTargetSasUri, "ar");
input2.AddTarget(frenchTargetSasUri, "fr", new TranslationGlossary(frenchGlossarySasUri, glossaryFormat));
var inputs = new List<DocumentTranslationInput>()
{
input1,
input2
};
DocumentTranslationOperation operation = await client.StartTranslationAsync(inputs);
await operation.WaitForCompletionAsync();
await foreach (DocumentStatusResult document in operation.GetValuesAsync())
{
Console.WriteLine($"Document with Id: {document.Id}");
Console.WriteLine($" Status:{document.Status}");
if (document.Status == DocumentTranslationStatus.Succeeded)
{
Console.WriteLine($" Translated Document Uri: {document.TranslatedDocumentUri}");
Console.WriteLine($" Translated to language code: {document.TranslatedToLanguageCode}.");
Console.WriteLine($" Document source Uri: {document.SourceDocumentUri}");
}
else
{
Console.WriteLine($" Document source Uri: {document.SourceDocumentUri}");
Console.WriteLine($" Error Code: {document.Error.Code}");
Console.WriteLine($" Message: {document.Error.Message}");
}
}
Start Translation
Start a translation operation to translate documents in the source container and write the translated files to the target container. DocumentTranslationOperation
allows you to poll the status of the translation operation and get the status of the individual documents.
Uri sourceUri = new Uri("<source SAS URI>");
Uri targetUri = new Uri("<target SAS URI>");
var input = new DocumentTranslationInput(sourceUri, targetUri, "es");
DocumentTranslationOperation operation = client.StartTranslation(input);
TimeSpan pollingInterval = new(1000);
while (true)
{
operation.UpdateStatus();
Console.WriteLine($" Status: {operation.Status}");
Console.WriteLine($" Created on: {operation.CreatedOn}");
Console.WriteLine($" Last modified: {operation.LastModified}");
Console.WriteLine($" Total documents: {operation.DocumentsTotal}");
Console.WriteLine($" Succeeded: {operation.DocumentsSucceeded}");
Console.WriteLine($" Failed: {operation.DocumentsFailed}");
Console.WriteLine($" In Progress: {operation.DocumentsInProgress}");
Console.WriteLine($" Not started: {operation.DocumentsNotStarted}");
if (operation.HasCompleted)
{
break;
}
else
{
if (operation.GetRawResponse().Headers.TryGetValue("Retry-After", out string value))
{
pollingInterval = TimeSpan.FromSeconds(Convert.ToInt32(value));
}
Thread.Sleep(pollingInterval);
}
}
foreach (DocumentStatusResult document in operation.GetValues())
{
Console.WriteLine($"Document with Id: {document.Id}");
Console.WriteLine($" Status:{document.Status}");
if (document.Status == DocumentTranslationStatus.Succeeded)
{
Console.WriteLine($" Translated Document Uri: {document.TranslatedDocumentUri}");
Console.WriteLine($" Translated to language code: {document.TranslatedToLanguageCode}.");
Console.WriteLine($" Document source Uri: {document.SourceDocumentUri}");
}
else
{
Console.WriteLine($" Document source Uri: {document.SourceDocumentUri}");
Console.WriteLine($" Error Code: {document.Error.Code}");
Console.WriteLine($" Message: {document.Error.Message}");
}
}
Create SingleDocumentTranslationClient with API Key Credential
Once you have the value for the API key, create an AzureKeyCredential
. This will allow you to
update the API key without creating a new client.
With the value of the endpoint and an AzureKeyCredential
, you can create the SingleDocumentTranslationClient:
string endpoint = "<Document Translator Resource Endpoint>";
string apiKey = "<Document Translator Resource API Key>";
SingleDocumentTranslationClient client = new SingleDocumentTranslationClient(new Uri(endpoint), new AzureKeyCredential(apiKey));
Single Document Translation
Start a single document translation.
try
{
string filePath = Path.Combine("TestData", "test-input.txt");
using Stream fileStream = File.OpenRead(filePath);
var sourceDocument = new MultipartFormFileData(Path.GetFileName(filePath), fileStream, "text/html");
DocumentTranslateContent content = new DocumentTranslateContent(sourceDocument);
var response = client.DocumentTranslate("hi", content);
var requestString = File.ReadAllText(filePath);
var responseString = Encoding.UTF8.GetString(response.Value.ToArray());
Console.WriteLine($"Request string for translation: {requestString}");
Console.WriteLine($"Response string after translation: {responseString}");
}
catch (RequestFailedException exception)
{
Console.WriteLine($"Error Code: {exception.ErrorCode}");
Console.WriteLine($"Message: {exception.Message}");
}
Troubleshooting
General
When you interact with the Cognitive Services Document Translation client library using the .NET SDK, errors returned by the service correspond to the same HTTP status codes returned for REST API requests.
For example, if you submit a request with an empty targets list, a 400
error is returned, indicating "Bad Request".
var invalidInput = new DocumentTranslationInput(new TranslationSource(new Uri(endpoint)), new List<TranslationTarget>());
try
{
DocumentTranslationOperation operation = client.StartTranslation(invalidInput);
}
catch (RequestFailedException e)
{
Console.WriteLine(e.ToString());
}
You will notice that additional information is logged, like the client request ID of the operation.
Message:
Azure.RequestFailedException: Service request failed.
Status: 400 (Bad Request)
Content:
{"error":{"code":"InvalidRequest","message":"No translation target found.","target":"TargetInput","innerError":{"code":"NoTranslationTargetFound","message":"No translation target found."}}}
Headers:
Transfer-Encoding: chunked
X-RequestId: REDACTED
Content-Type: application/json; charset=utf-8
Set-Cookie: REDACTED
X-Powered-By: REDACTED
apim-request-id: REDACTED
Strict-Transport-Security: REDACTED
x-content-type-options: REDACTED
Date: Mon, 22 Mar 2021 11:54:58 GMT
Setting up console logging
The simplest way to see the logs is to enable the console logging. To create an Azure SDK log listener that outputs messages to console use AzureEventSourceListener.CreateConsoleLogger method.
// Setup a listener to monitor logged events.
using AzureEventSourceListener listener = AzureEventSourceListener.CreateConsoleLogger();
To learn more about other logging mechanisms see here.
Next steps
Samples showing how to use the Cognitive Services Document Translation library are available in this GitHub repository.
Advanced samples
Contributing
See the CONTRIBUTING.md for details on building, testing, and contributing to this library.
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit cla.microsoft.com.
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.