Guide · Amazon Translate · Custom Terminology

MCP Server AWS Translate Custom Terminology — ImportTerminologyCommand, directionality

Amazon Translate custom terminologies let you enforce exact translations for domain-specific words — product names, technical terms, brand vocabulary — that the neural translation model would otherwise paraphrase. You import a terminology file (CSV or TMX format) with ImportTerminologyCommand, then reference it by name in TranslateTextCommand via TerminologyNames. When a source term from the file appears in the input, Translate substitutes your pre-approved translation verbatim rather than generating one. The two directionality modes are UNI (one-way: source language → one target language) and MULTI (source language → any supported target language using per-language target columns in the CSV). Get the directionality wrong and either Translate silently ignores the terminology or raises a ValidationException at import time.

TL;DR

Create a CSV file with columns en, es, fr (etc.) — first column is source language, remaining columns are target languages. Import with ImportTerminologyCommand({ Name, MergeStrategy: 'OVERWRITE', TerminologyData: { File: csvBuffer, Format: 'CSV', Directionality: 'MULTI' } }). Apply by passing TerminologyNames: ['my-terminology'] to TranslateTextCommand. Check response.AppliedTerminologies to confirm terms were matched and substituted. Up to 100 terminologies per account; each file up to 10MB; up to 256 entries in the file for MULTI directionality.

Terminology file format: CSV vs TMX

Amazon Translate accepts two file formats: CSV (comma-separated values, easiest to maintain in a spreadsheet) and TMX (Translation Memory eXchange, the standard used by professional translation tools). For MCP server use cases, CSV is simpler to generate programmatically from a configuration object or database query.

A MULTI-directionality CSV has a header row listing language codes, followed by one row per term. The first column is the source language. Each subsequent column is a target language. Leave a cell blank if you have no approved translation for that language yet.

# terminology-multi.csv — MULTI directionality (source → many targets)
en,es,fr,de,ja
MCP server,servidor MCP,serveur MCP,MCP-Server,MCPサーバー
uptime monitoring,monitoreo de tiempo de actividad,surveillance de disponibilité,Verfügbarkeitsüberwachung,稼働時間監視
health check,verificación de estado,vérification de l'état,Integritätsprüfung,ヘルスチェック
AliveMCP,AliveMCP,AliveMCP,AliveMCP,AliveMCP

A UNI-directionality CSV has exactly two columns: source term and target term. It maps one source language to exactly one target language — the target language must match the TargetLanguageCode at translation time.

# terminology-uni.csv — UNI directionality (source → single target only)
en,es
MCP server,servidor MCP
uptime monitoring,monitoreo de tiempo de actividad
health check,verificación de estado

Case sensitivity: matches are case-sensitive by default. The term MCP server will match in source text that contains exactly MCP server but not mcp server or MCP Server. Import a separate entry for each casing variant you want to protect, or use the AppliedTerminologies response field to verify at runtime which terms were actually matched.

Importing a terminology with ImportTerminologyCommand

Terminologies are account-and-region-scoped — a terminology imported in us-east-1 is not visible in eu-west-1. Import once and reference by name. MergeStrategy: 'OVERWRITE' replaces the existing terminology if a file with the same name already exists.

import {
  TranslateClient,
  ImportTerminologyCommand,
  type ImportTerminologyCommandInput,
} from '@aws-sdk/client-translate';
import { readFileSync } from 'fs';

const translate = new TranslateClient({ region: process.env.AWS_REGION ?? 'us-east-1' });

export async function importTerminology(
  name: string,
  csvPath: string,
  directionality: 'UNI' | 'MULTI' = 'MULTI',
): Promise<void> {
  const csvBuffer = readFileSync(csvPath); // Buffer / Uint8Array

  const input: ImportTerminologyCommandInput = {
    Name: name,                    // unique identifier within the account+region
    MergeStrategy: 'OVERWRITE',    // 'OVERWRITE' (replace) | 'FAIL_ON_CONFLICT' (error if exists)
    TerminologyData: {
      File: csvBuffer,             // raw bytes of the CSV or TMX file
      Format: 'CSV',               // 'CSV' | 'TMX'
      Directionality: directionality,  // 'UNI' | 'MULTI'
    },
    Description: 'MCP server domain terminology — MCP-specific vocabulary',
  };

  const response = await translate.send(new ImportTerminologyCommand(input));

  console.log('Terminology imported:', {
    name: response.TerminologyProperties?.Name,
    sourceLanguage: response.TerminologyProperties?.SourceLanguageCode,
    targetLanguages: response.TerminologyProperties?.TargetLanguageCodes,
    termCount: response.TerminologyProperties?.TermCount,
    createdAt: response.TerminologyProperties?.CreatedAt,
  });
}

The TerminologyProperties in the response includes TermCount — the number of entries Translate parsed from your file. If TermCount is lower than expected, the file has formatting errors (extra commas, missing language header, BOM at the start of the file). UTF-8 without BOM is required for CSV files.

Applying a terminology in TranslateTextCommand

Pass the terminology name in the TerminologyNames array when calling TranslateTextCommand. Up to 1 custom terminology can be applied per call. The applied terminology must match the SourceLanguageCode and TargetLanguageCode of the translation request — mismatches cause a ResourceNotFoundException at call time (not at import time).

import { TranslateClient, TranslateTextCommand } from '@aws-sdk/client-translate';

const translate = new TranslateClient({ region: process.env.AWS_REGION ?? 'us-east-1' });

export async function translateWithTerminology(
  text: string,
  targetLang: string,
  terminologyName: string,
): Promise<{ translated: string; appliedTerms: string[] }> {
  const response = await translate.send(new TranslateTextCommand({
    Text: text,
    SourceLanguageCode: 'en',
    TargetLanguageCode: targetLang,
    TerminologyNames: [terminologyName],  // array; currently max 1 custom terminology per call
  }));

  // AppliedTerminologies lists terms from the file that were actually found and substituted
  const appliedTerms = (response.AppliedTerminologies ?? []).flatMap(t =>
    (t.Terms ?? []).map(term => `${term.SourceText} → ${term.TargetText}`)
  );

  return {
    translated: response.TranslatedText ?? '',
    appliedTerms,
  };
}

// Usage:
// const result = await translateWithTerminology(
//   'The MCP server health check endpoint returned a timeout.',
//   'es',
//   'mcp-domain-terms',
// );
// result.appliedTerms → ['MCP server → servidor MCP', 'health check → verificación de estado']

AppliedTerminologies[].Terms is a list of { SourceText, TargetText } pairs that were matched. If this array is empty when you expected matches, the most common causes are: (1) case mismatch in the source text vs the terminology entry, (2) the terminology was imported with UNI directionality but the target language in the call is different from the one configured at import, or (3) the term appears inside a larger compound word or phrase that the tokenizer treats as a single unit.

Listing and retrieving terminologies

Use ListTerminologiesCommand to enumerate all terminologies in the account+region, and GetTerminologyCommand to retrieve a terminology's metadata and download its contents as a presigned S3 URL.

import {
  TranslateClient,
  ListTerminologiesCommand,
  GetTerminologyCommand,
} from '@aws-sdk/client-translate';

const translate = new TranslateClient({ region: process.env.AWS_REGION ?? 'us-east-1' });

// List all terminologies
export async function listTerminologies(): Promise<string[]> {
  const response = await translate.send(new ListTerminologiesCommand({}));
  return (response.TerminologyPropertiesList ?? []).map(t => t.Name ?? '');
}

// Get metadata + download URL for a specific terminology
export async function getTerminology(name: string) {
  const response = await translate.send(new GetTerminologyCommand({
    Name: name,
    TerminologyDataFormat: 'CSV',  // 'CSV' | 'TMX' — format for the download URL
  }));

  return {
    name: response.TerminologyProperties?.Name,
    termCount: response.TerminologyProperties?.TermCount,
    sourceLanguage: response.TerminologyProperties?.SourceLanguageCode,
    targetLanguages: response.TerminologyProperties?.TargetLanguageCodes,
    directionality: response.TerminologyProperties?.Directionality,
    downloadUrl: response.TerminologyDataLocation?.Location,  // presigned S3 URL, 300s expiry
    createdAt: response.TerminologyProperties?.CreatedAt,
    lastUpdatedAt: response.TerminologyProperties?.LastUpdatedAt,
  };
}

The TerminologyDataLocation.Location is a presigned S3 URL valid for 300 seconds. Download it promptly if you need to inspect or edit the file — after expiry you must call GetTerminologyCommand again to get a fresh URL.

UNI vs MULTI directionality decision table

Use caseDirectionalityCSV structureConstraint
Single target language (e.g. English → Spanish only)UNI2 columns: source, targetTarget language fixed at import — cannot reuse for other targets
Multiple target languages from one sourceMULTIN+1 columns: source + one per target languageMax 10 target language columns; max 256 terms per file
Bidirectional (en↔es, es↔en)MULTIBoth en and es as columns — Translate infers direction at call timeMULTI with both source and target as columns enables both directions
Large term list (>256 entries)UNISplit into multiple UNI filesMULTI cap is 256; UNI has no published limit beyond 10MB file size

The 10MB file size limit applies to the raw bytes sent to ImportTerminologyCommand. For large domain vocabularies exceeding 256 MULTI entries, split into multiple UNI files and apply the right one at call time based on the target language. Each TranslateTextCommand call can reference only one terminology.

Error handling reference

ErrorCauseFix
ValidationException at importWrong directionality for the CSV structure, missing language code header, or BOM in UTF-8 fileEnsure CSV header matches Directionality; save as UTF-8 without BOM
ResourceNotFoundException at translateTerminology name not found in this region, or target language not in the terminology's TargetLanguageCodesVerify name with ListTerminologiesCommand; check that MULTI file includes the target language column
LimitExceededExceptionMore than 100 terminologies per account+region, or file exceeds 10MBDelete unused terminologies; split large files
AccessDeniedExceptionMissing translate:ImportTerminology or translate:GetTerminology IAM actionAdd translate:ImportTerminology, translate:GetTerminology, translate:ListTerminologies to the role
AppliedTerminologies is empty (no error)Terms not matched — case mismatch, tokenization boundary, or wrong directionalityLog the exact source text; check for leading/trailing spaces; verify casing in the CSV