Document Translation, Custom Translator and Adaptive Translation

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

See the section bibliography for the reference material consulted while preparing these pages.

This page targets Azure CLI 2.90.0 and the Document Translation REST API 2026-03-01, with the client libraries azure-ai-translation-document 2.0.0 (Python), Azure.AI.Translation.Document 3.0.0 (.NET), com.azure:azure-ai-translation-document 2.0.1 (Java) and @azure-rest/ai-translation-document 1.0.0 (JavaScript), checked on 2026-10-06.

Text translation handles strings. Document translation handles whole files (Word, PowerPoint, Excel, PDF, HTML, Markdown and more) and keeps their layout: fonts, tables, headers and images stay where they were. It also covers how you customize translations with Custom Translator (NMT) and adaptive custom translation (LLM).

Asynchronous batch translation

Batch translation reads every document in a source Blob container (or a single blob, or a prefix filter) and writes translated copies to one target container per language.

  • Access: give the Translator resource’s system-assigned managed identity Storage Blob Data Reader on the source and Storage Blob Data Contributor on the targets, and pass plain container URLs. Alternatively pass SAS URLs (read/list on source, write/list on target). Managed identity is preferred: no tokens to expire.

  • Glossaries: a CSV, TSV or XLF file of term pairs, applied to every document in the job (for example series names and character names that must not be translated).

  • Limits: 40 MB per document, 1,000 files per batch, 250 MB per batch total. Results are written to Blob, so nothing is kept in the service.

  • Images and scans: with translateTextWithinImage the service translates text inside images embedded in DOCX and PPTX files (billed as image scans). Scanned PDFs are OCRed and translated.

sequenceDiagram participant Job as press-kit job participant DT as Document translation participant Src as stbookshelf press-kits container participant Dst as stbookshelf press-kits-es container Job->>DT: POST document/batches with source and target URLs DT-->>Job: 202 Accepted, Operation-Location DT->>Src: Read documents with managed identity DT->>DT: Translate, apply glossary, keep layout DT->>Dst: Write translated documents loop Until Succeeded Job->>DT: GET batch status DT-->>Job: Running, then Succeeded with document counts end Job->>Dst: Publish translated press kit
TOKEN=$(az account get-access-token --resource https://cognitiveservices.azure.com --query accessToken -o tsv)

curl -s -i -X POST \
  "https://$FOUNDRY.cognitiveservices.azure.com/translator/document/batches?api-version=2026-03-01" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "inputs": [{
      "source": {"sourceUrl": "https://stbookshelf.blob.core.windows.net/press-kits", "language": "en"},
      "targets": [
        {"targetUrl": "https://stbookshelf.blob.core.windows.net/press-kits-es", "language": "es",
         "glossaries": [{"glossaryUrl": "https://stbookshelf.blob.core.windows.net/glossaries/series-es.tsv", "format": "tsv"}]},
        {"targetUrl": "https://stbookshelf.blob.core.windows.net/press-kits-fr", "language": "fr"}
      ]
    }],
    "options": {"translateTextWithinImage": true}
  }'
# Poll the Operation-Location header URL until "status" is "Succeeded"
from azure.ai.translation.document import DocumentTranslationClient
from azure.ai.translation.document.models import TranslationGlossary
from azure.identity import DefaultAzureCredential

client = DocumentTranslationClient(
    "https://foundry-bookshelf.cognitiveservices.azure.com/", DefaultAzureCredential()
)
poller = client.begin_translation(
    "https://stbookshelf.blob.core.windows.net/press-kits",
    "https://stbookshelf.blob.core.windows.net/press-kits-es",
    "es",
    glossaries=[TranslationGlossary(
        "https://stbookshelf.blob.core.windows.net/glossaries/series-es.tsv", file_format="tsv")],
)
for doc in poller.result():
    print(doc.status, doc.translated_document_url)
using Azure.AI.Translation.Document;
using Azure.Identity;

var client = new DocumentTranslationClient(
    new Uri("https://foundry-bookshelf.cognitiveservices.azure.com/"), new DefaultAzureCredential());

var input = new DocumentTranslationInput(
    new Uri("https://stbookshelf.blob.core.windows.net/press-kits"),
    new Uri("https://stbookshelf.blob.core.windows.net/press-kits-fr"),
    "fr");

DocumentTranslationOperation operation = await client.StartTranslationAsync(input);
await operation.WaitForCompletionAsync();
await foreach (DocumentStatusResult doc in operation.Value)
    Console.WriteLine($"{doc.Status} {doc.TranslatedDocumentUri}");
import com.azure.ai.translation.document.DocumentTranslationClient;
import com.azure.ai.translation.document.DocumentTranslationClientBuilder;
import com.azure.ai.translation.document.models.*;
import com.azure.identity.DefaultAzureCredentialBuilder;
import java.util.List;

DocumentTranslationClient client = new DocumentTranslationClientBuilder()
    .endpoint("https://foundry-bookshelf.cognitiveservices.azure.com/")
    .credential(new DefaultAzureCredentialBuilder().build())
    .buildClient();

TranslationSource source = new TranslationSource("https://stbookshelf.blob.core.windows.net/press-kits");
TranslationTarget target = new TranslationTarget("https://stbookshelf.blob.core.windows.net/press-kits-de", "de");
BatchRequest batch = new BatchRequest(source, List.of(target));

TranslationStatus status = client.beginTranslation(
    new StartTranslationDetails(List.of(batch))).getFinalResult();
System.out.println(status.getStatus());

Synchronous single-document translation

For one small document that a user waits for (for example a contract preview), call the synchronous endpoint. It returns the translated file in the response body, with no Blob storage involved:

curl -s -X POST \
  "https://$FOUNDRY.cognitiveservices.azure.com/translator/document:translate?targetLanguage=es&api-version=2026-03-01" \
  -H "Authorization: Bearer $TOKEN" \
  -F "document=@sample-chapter.docx;type=application/vnd.openxmlformats-officedocument.wordprocessingml.document" \
  -F "glossary=@series-es.tsv;type=text/tab-separated-values" \
  -o sample-chapter.es.docx

Synchronous translation has smaller limits than batch (one document, around 10 MB). Check the service limits page.

Custom Translator

Custom Translator (https://portal.customtranslator.azure.ai) trains an NMT model on your own data:

  1. Create a workspace connected to the Translator resource, and a project for a language pair and domain.

  2. Upload parallel documents (aligned source and target sentences, at least 10,000 pairs for good results) and optionally phrase and sentence dictionaries that force exact translations.

  3. Train, review the BLEU score against the baseline, and publish the model to one or more regions.

  4. Call text or document translation with the model’s category ID.

curl -s -X POST \
  "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&to=es&category=$CATEGORY_ID" \
  -H "Ocp-Apim-Subscription-Key: $TRANSLATOR_KEY" -H "Ocp-Apim-Subscription-Region: eastus2" \
  -H "Content-Type: application/json" -d '[{"Text":"The Archivist returns in book three."}]'

Adaptive custom translation

Adaptive custom translation is the LLM-era alternative. Instead of training a model, you give the LLM examples: a handful of reference pairs in each request, or a dataset index of translation pairs uploaded once in the Foundry portal and referenced by ID. The model follows your terminology and style without a training run. It works with LLM targets in text translation, and with document translation that uses an LLM deployment.

Containers

Translator text and document translation containers run on your own infrastructure. They are gated: you request access with an application form, and they must be billed against a single-service TextTranslation resource, optionally with a commitment tier for disconnected use. See Pricing, Quotas, Containers and Monitoring.

Provisioning

In the Azure portal

  1. Use the Foundry resource foundry-bookshelf and turn on its System assigned managed identity.

  2. On storage account stbookshelf, open Access control (IAM) and assign Storage Blob Data Reader (source) and Storage Blob Data Contributor (targets) to the managed identity of foundry-bookshelf.

  3. Create the containers press-kits, press-kits-es, press-kits-fr, press-kits-de and glossaries.

  4. In the Foundry portal, Playgrounds → Translator playground → Document translation translates a single file interactively.

With the Azure CLI

PRINCIPAL=$(az cognitiveservices account show --name "$FOUNDRY" --resource-group "$RG" --query identity.principalId -o tsv)
SCOPE=$(az storage account show --name stbookshelf --resource-group "$RG" --query id -o tsv)

az role assignment create --assignee-object-id "$PRINCIPAL" --assignee-principal-type ServicePrincipal \
  --role "Storage Blob Data Contributor" --scope "$SCOPE"

for c in press-kits press-kits-es press-kits-fr press-kits-de glossaries; do
  az storage container create --account-name stbookshelf --name "$c" --auth-mode login
done

Use cases

Scenario Feature Why this feature Example input → output

Bookshelf: translate publisher press kits and sample chapters

Batch translation with a glossary of series and character names

Layout must survive; names must not be translated.

press-kits/*.docx → press-kits-es/*.docx and press-kits-fr/*.docx

Legal and contract translation

Synchronous single-document translation

Preserves numbering, tables and signatures; reviewer gets the file at once.

Contract.pdf → Contrato.pdf

Manuals in a technical domain

Custom Translator category

Consistent terminology across thousands of pages.

Service manual DOCX → localized DOCX with approved terms

Slide decks with screenshots

translateTextWithinImage

Text inside images is translated too.

Sales deck PPTX → Japanese PPTX

When not to use it

Clean up

for c in press-kits press-kits-es press-kits-fr press-kits-de glossaries; do
  az storage container delete --account-name stbookshelf --name "$c" --auth-mode login
done