Building a Claude API Multilingual Translation App
If you're building a Claude API multilingual translation app, the core workflow is simpler than most developers expect: send source text and a target language instruction to Claude's Messages API, get back natural, context-aware translations, and layer formatting, caching, and streaming on top for a production-ready experience.
Unlike rule-based machine translation systems, Claude handles idioms, tone, technical jargon, and ambiguous phrasing because it's reasoning over meaning rather than matching dictionary entries. This makes it a strong fit for apps that need accurate translation across dozens of languages without maintaining separate models or glossaries per language pair. The rest of this guide covers how to structure prompts, handle long documents, preserve formatting, and ship this reliably.
Why Claude Works Well for Translation
Traditional translation APIs (Google Translate, DeepL) are fast and cheap for short, literal text but struggle with:
- Context-dependent meaning — words that translate differently based on surrounding sentences
- Tone and register — formal vs. casual, technical vs. conversational
- Domain-specific terminology — legal, medical, or product-specific vocabulary
- Mixed content — text with embedded code, markdown, or placeholders that shouldn't be translated
Claude handles all of these because it's generating a response based on understanding, not pattern-matching against a translation table. You can also instruct it to preserve formatting, keep variable names untranslated, or match a specific tone — none of which traditional MT APIs support out of the box.
Core Translation Prompt Structure
The simplest reliable pattern is a system prompt that fixes the behavior, plus a user message containing the text to translate:
const response = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"x-api-key": process.env.ANTHROPIC_API_KEY,
"anthropic-version": "2023-06-01",
"content-type": "application/json",
},
body: JSON.stringify({
model: "claude-sonnet-4-5",
max_tokens: 1024,
system:
"You are a professional translator. Translate the user's text into French. " +
"Preserve formatting, line breaks, and any code blocks exactly as-is. " +
"Return only the translated text, no explanations.",
messages: [{ role: "user", content: "How are you doing today?" }],
}),
});
The key instructions in the system prompt are what separate a toy demo from a usable product:
- "Return only the translated text" — without this, Claude may add explanations or notes
- Explicit target language — don't let the model guess
- Formatting preservation rules — critical for UI strings, markdown, or HTML content
Handling Dynamic Target Languages
Most apps need to support many languages selected at runtime, not a hardcoded one. Build the system prompt dynamically and keep a controlled list of supported language codes to avoid ambiguous input:
function buildSystemPrompt(targetLang) {
return `You are a professional translator. Translate the user's text into ${targetLang}.
Match the tone and formality of the source text. Preserve any markdown, HTML tags,
or placeholder variables like {{name}} exactly as they appear. Return only the
translated text with no preamble.`;
}
Passing a full language name ("Brazilian Portuguese") rather than a raw ISO code tends to produce more accurate results, since the model doesn't need to resolve ambiguous codes internally.
Preserving Structure in Real Content
Real-world strings rarely come as plain sentences — they come as JSON locale files, UI copy with interpolation, or markdown documents. Tell Claude explicitly what not to touch:
Translate the "value" fields in this JSON into Spanish. Do not translate the
"key" fields. Do not translate anything inside {{curly braces}}. Return valid JSON only.
{
"welcome_message": "Hello, {{username}}!",
"cta_button": "Get started"
}
This pattern works reliably for locale files, email templates, and product UI strings, and it scales to batch requests where you send an array of strings and get back the same array translated.
Streaming for Long-Form Content
For document or article translation, streaming avoids making users stare at a blank screen while a multi-paragraph response is generated. Claude's API supports server-sent events for this — see /docs/streaming for the full event format. The practical pattern is the same regardless of provider: open a streaming connection, append text chunks to the UI as they arrive, and handle the final stop event to know when translation is complete.
Shipping It as a Product, Not a Script
A translation prompt that works in a notebook is not the same as a translation feature running in production. Things that break first:
- No retry/backoff logic when the upstream API is rate-limited mid-batch
- No usage visibility — you don't know which customer or endpoint is burning through tokens
- No separation between internal testing keys and live traffic
- Manual key rotation across every service that calls the translation endpoint
This is the gap SubToAPI is built for. It turns your existing Claude access into a standard HTTPS API with application-scoped keys (sub_live_...), so your translation service, your mobile app, and your internal tools each get their own key with its own usage metadata — without sharing one raw credential across your stack. You get streaming support out of the box (/docs/streaming), tool use if you want to combine translation with lookups or formatting logic (/docs/tools), and a dashboard that shows exactly which key is consuming tokens on which endpoint.
Getting started takes the same shape as the example above — see /docs/quickstart for the setup and /docs/messages for the full request format. Plans start at Solo €9/month, with Team (€19/seat) and Scale (€49/seat) tiers for multi-developer setups, and a free trial at /signup.
Practical Tips for Production Translation Apps
- Cache aggressively. Identical source strings translated to the same language don't need a new API call — hash the input + target language and cache the result.
- Batch small strings. Sending 50 UI strings in one request with a numbered list is cheaper and faster than 50 separate calls.
- Validate output format for structured content (JSON, markdown) before writing it back to your app — occasionally the model needs a retry with a stricter instruction.
- Log source/target pairs so you can spot systematic translation issues for a specific language over time.
Questions
Is Claude better than DeepL or Google Translate for app translation? Claude is stronger for context-aware, tone-sensitive, or structured content (JSON, markdown, UI strings with placeholders). For high-volume, purely literal short-string translation, dedicated MT APIs can be cheaper per call.
Can Claude translate and preserve code or HTML inside text? Yes, if you explicitly instruct it not to translate specific tags, variables, or code blocks in your system prompt. Without that instruction, it may translate everything indiscriminately.
How do I manage API keys across a translation service with multiple apps? Use scoped application keys instead of one shared credential. SubToAPI issues per-app sub_live_... keys with individual usage tracking, so you can monitor and rotate access without affecting other services — see /docs/quickstart.