एक Agent से एक Blog Post को 13 भाषाओं में कैसे Translate करें
एक TypeScript agent Claude API को parallel में call करता है और 90 सेकंड से कम में एक EN post को 12 भाषाओं में translate करता है। Voice preserve करने के लिए two-part system prompt जरूरी है: पहले style constraints, फिर locale-specific notes। Haiku पर cost लगभग $0.004–$0.02 per post है। मेरी site को 60 दिनों में 34% international traffic increase मिला।
हर बुधवार। 28,400+ पाठक। बिना फालतू बात।
✓ Check your inbox — click the confirmation link to complete sign-up.
✓ You're subscribed!
✓ You're already on the list.
विषय सूची
मई 2026 में अपडेट किया गया।
TL;DR: एक TypeScript agent Claude API को parallel में call करता है और 90 सेकंड से कम में एक EN post को 12 भाषाओं में translate करता है। Voice preserve करने के लिए two-part system prompt जरूरी है: पहले style constraints, फिर locale-specific notes। Haiku पर cost लगभग $0.004–$0.02 per post है। मेरी site को 60 दिनों में 34% international traffic increase मिला।
[Operator का नज़रिया] मैं हर बार जब नई post publish करता हूं तो यह agent चलाता हूं। इसने 341 posts को 12 भाषाओं में process किया है बिना मैंने किसी भी translation को manually touch किए। यहां बिल्कुल सही तरीके से बताता हूं कि यह कैसे काम करता है।
Translators hire करने की बजाय Translation Agent क्यों बनाया
Multilingual SEO के argument को skip करता हूं — आप जानते हैं कि यह important है। मेरी problem workflow थी। हर post के लिए translators hire करना expensive है ($40–$120/post × 12 languages = $480–$1,440 per article), slow है (3–7 दिन का turnaround), और impossible है batch में process करना जब 341 existing posts को catch up करना हो।
दूसरा option जो लोग suggest करते हैं वो है Google Translate या DeepL। दोनों accuracy के लिए ठीक हैं लेकिन voice को destroy कर देते हैं। मेरी writing style direct, first-person और slightly contrarian है। Machine translation सब कुछ formal और passive बना देता है। यह problem है जब voice consistency आपके brand का हिस्सा हो।
इसलिए मैंने Claude-backed TypeScript agent बनाया। यह main में हर merge पर CI में run होता है, translations को parallel में fan out करता है, files को disk पर वापस लिखता है, और किसी भी locale को skip करता है जिसके पास पहले से file है। नई post के लिए पूरी process 90 सेकंड से कम लेती है।
Project Structure
Agent scripts/agent/translate-worker.ts में रहता है। इसे एक top-level orchestrator call करता है जो EN post read करता है, frontmatter extract करता है, और हर locale के लिए एक translation job dispatch करता है।
scripts/
agent/
translate-worker.ts # per-locale translation logic
translate-all.ts # orchestrator: EN पढ़ता है, 12 locales में fan out करता है
lib/
frontmatter.ts # gray-matter frontmatter parse/serialize करता है
voice-prompt.ts # shared system prompt builderOrchestrator (translate-all.ts) Promise.allSettled use करता है ताकि एक failed locale बाकी को block न करे।
System Prompt Engineering
यहीं पर ज़्यादातर लोग गलती करते हैं। वे एक liner लिखते हैं जैसे “इसे French में translate करो, author की voice रखो।” इससे mediocre output आता है।
मेरे system prompt में दो mandatory sections हैं:
Section 1 — Style constraints (universal, हर call में prepend होता है):
// scripts/agent/lib/voice-prompt.ts
export function buildSystemPrompt(targetLocale: string): string {
const styleConstraints = `
You are a professional translator working on blog posts written by Alejandro Rioja.
STYLE RULES — apply to every locale:
- Short paragraphs (1–3 sentences max). Do not merge them.
- First-person, direct voice. Never passive if active is natural.
- No filler phrases: no "In today's world", no "It is worth noting that".
- Preserve all markdown: headings, bold, italics, code blocks, links.
- Translate heading text but keep the ## / ### prefix exactly.
- Code blocks: translate comments only. Keep all variable names, strings, and syntax in English.
- Preserve frontmatter keys exactly. Only translate the VALUES for: title, ogTitle, description, tldr, imageAlt.
- Keep these frontmatter values UNCHANGED: pubDate, updatedDate, translation_key, tags, image, author, draft, lang (set lang to: ${targetLocale}).
`.trim();Section 2 — Locale-specific notes (हर call में append होता है):
const localeNotes: Record<string, string> = {
ar: "Arabic: use Modern Standard Arabic (MSA). RTL layout is handled by the CMS — do not add any RTL markup. Avoid overly formal Classical Arabic registers.",
de: "German: use informal 'du' not formal 'Sie'. Compound nouns are fine; don't over-hyphenate. Keep tech terms in English when that's the industry standard (e.g. 'Content Marketing', 'SEO').",
es: "Spanish: use neutral Latin American Spanish, not Castilian. Tuteo ('tú') over 'usted'. Keep anglicisms that are standard in tech (SEO, agente, prompt).",
fr: "French: use informal 'tu'. Avoid over-formalizing. Tech anglicisms are acceptable when widely used (SEO, agent, prompt).",
hi: "Hindi: use Devanagari script. Mix Hindi and English naturally for tech terms — this is standard in Indian tech writing. Don't force Hindi equivalents for words like 'agent', 'prompt', 'SEO'.",
it: "Italian: use 'tu' form. Keep English tech terms where they're standard in Italian digital marketing.",
ja: "Japanese: use です/ます (polite) style, not casual or keigo. Keep technical English terms in katakana where standard (e.g. エージェント, プロンプト, SEO).",
ko: "Korean: use 합쇼체 (formal polite). Tech terms in English or standard Korean loanwords. Keep SEO, agent, prompt as-is or standard loanwords.",
nl: "Dutch: use 'je/jij' (informal). Keep English tech terms standard in Dutch digital marketing.",
pt: "Portuguese: use Brazilian Portuguese (pt-BR). Informal 'você'. Keep tech anglicisms standard in Brazilian digital marketing.",
ru: "Russian: use modern, accessible Russian. Avoid overly bureaucratic phrasing. Tech terms can stay in English where that's the norm in Russian tech writing.",
zh: "Chinese: use Simplified Chinese (zh-CN). Modern, accessible tone. Tech terms can use standard Chinese equivalents or keep English where that's industry norm.",
};
return `${styleConstraints}\n\nLOCALE-SPECIFIC NOTES for ${targetLocale}:\n${localeNotes[targetLocale]}`;
}Translate Worker
यहां पूरा worker है। यह EN file read करता है, Claude call करता है, output को disk पर लिखता है।
// scripts/agent/translate-worker.ts
import Anthropic from "@anthropic-ai/sdk";
import * as fs from "fs";
import * as path from "path";
import { buildSystemPrompt } from "./lib/voice-prompt";
const client = new Anthropic();
export interface TranslateJob {
enFilePath: string;
locale: string;
outputDir: string;
model?: "claude-haiku-4-5" | "claude-sonnet-4-5";
dryRun?: boolean;
}
export async function translatePost(job: TranslateJob): Promise<string> {
const { enFilePath, locale, outputDir, model = "claude-haiku-4-5", dryRun = false } = job;
// Idempotency: अगर translation पहले से exist करता है तो skip करें
const filename = path.basename(enFilePath);
const outPath = path.join(outputDir, locale, filename);
if (fs.existsSync(outPath)) {
console.log(`[${locale}] पहले से exist करता है — skip: ${outPath}`);
return outPath;
}
const enContent = fs.readFileSync(enFilePath, "utf-8");
const systemPrompt = buildSystemPrompt(locale);
const message = await client.messages.create({
model,
max_tokens: 8192,
system: systemPrompt,
messages: [
{
role: "user",
content: `Translate the following blog post to ${locale}. Return ONLY the translated markdown file content — no explanation, no preamble, no code fences around the whole file.\n\n${enContent}`,
},
],
});
const translated = (message.content[0] as { type: string; text: string }).text;
if (!dryRun) {
fs.mkdirSync(path.join(outputDir, locale), { recursive: true });
fs.writeFileSync(outPath, translated, "utf-8");
console.log(`[${locale}] लिखा गया: ${outPath}`);
}
return outPath;
}Orchestrator
// scripts/agent/translate-all.ts
import * as path from "path";
import * as fs from "fs";
import { translatePost } from "./translate-worker";
const LOCALES = ["ar", "de", "es", "fr", "hi", "it", "ja", "ko", "nl", "pt", "ru", "zh"];
const POSTS_DIR = path.resolve("src/content/posts");
const MODEL = (process.env.TRANSLATE_MODEL as "claude-haiku-4-5" | "claude-sonnet-4-5") ?? "claude-haiku-4-5";
async function main() {
// Specific file accept करें या सभी EN posts translate करें
const targetFile = process.argv[2];
const enFiles = targetFile
? [path.resolve(targetFile)]
: fs.readdirSync(path.join(POSTS_DIR, "en")).map((f) => path.join(POSTS_DIR, "en", f));
console.log(`${enFiles.length} post(s) × ${LOCALES.length} locales translate कर रहे हैं। Model: ${MODEL}`);
for (const enFile of enFiles) {
const results = await Promise.allSettled(
LOCALES.map((locale) =>
translatePost({
enFilePath: enFile,
locale,
outputDir: POSTS_DIR,
model: MODEL,
})
)
);
results.forEach((r, i) => {
if (r.status === "rejected") {
console.error(`[${LOCALES[i]}] FAILED:`, r.reason);
}
});
}
console.log("हो गया।");
}
main();इसे run करें:
# एक नई post translate करें
npx ts-node scripts/agent/translate-all.ts src/content/posts/en/my-new-post.md
# सब कुछ translate करें (idempotent — existing skip करता है)
npx ts-node scripts/agent/translate-all.tsCost Breakdown: Haiku बनाम Sonnet
मेरे usage के आधार पर per post का actual cost:
| Model | Input tokens (avg) | Output tokens (avg) | Cost per locale | Cost × 12 locales |
|---|---|---|---|---|
| claude-haiku-4-5 | ~2,400 | ~2,600 | ~$0.0004 | ~$0.005 |
| claude-sonnet-4-5 | ~2,400 | ~2,600 | ~$0.015 | ~$0.18 |
Haiku पर 341 posts × 12 locales: लगभग $1.70 total। यह पूरा backlog है।
Sonnet marginally बेहतर idiomatic phrasing produce करता है लेकिन ज़्यादातर posts के लिए difference 36× price justify नहीं करता। मैं Sonnet सिर्फ उन posts के लिए use करता हूं जहां nuanced persuasive tone matter करता है — जैसे sales pages या high-traffic cornerstone content।
TRANSLATE_MODEL env var के साथ per-run model switch कर सकते हैं:
TRANSLATE_MODEL=claude-sonnet-4-5 npx ts-node scripts/agent/translate-all.ts src/content/posts/en/flagship-post.mdReal Results: मेरे Traffic पर क्या हुआ
मैंने दिसंबर 2025 में full backlog translation (341 posts) ship किया। 60 दिनों में:
- +34% organic sessions site-wide (Google Search Console, Jan–Feb 2026 बनाम Oct–Nov 2025)
- Sessions में top नई language: Brazilian Portuguese (pt) — 11% new international traffic
- Conversion rate में top नई language: German (de) — 2.1% consultation booking rate बनाम 1.8% global average
- Worst performer: Arabic (ar) — traffic आया लेकिन zero conversions। मुझे लगता है booking flow post content से आगे localized नहीं है।
- Japanese (ja) और Korean (ko): meaningful traffic lift (international sessions का क्रमशः 8% और 6%) above-average engagement के साथ (time-on-page EN baseline से 40% ऊपर)
Japanese और Korean results ने मुझे surprise किया। दोनों locales में high-quality AI communities हैं और practical operator content के लिए apparently अच्छी demand है।
Operator का Bottom Line
एक agent, setup का एक घंटा, $1.70 API costs। बस इतना ही चाहिए था 341 posts को 12 additional languages में discoverable बनाने के लिए। SEO lift alone ने पहले हफ्ते में compute cost recover कर लिया। अगर आप content-heavy site चला रहे हैं और अभी तक यह नहीं बनाया है, तो आप international traffic छोड़ रहे हैं। ऊपर का code full implementation है — इसे fork करें, अपने voice-prompt notes swap करें, और आज रात अपने backlog पर run करें।
हर बुधवार। 28,400+ पाठक। बिना फालतू बात।
✓ Check your inbox — click the confirmation link to complete sign-up.
✓ You're subscribed!
✓ You're already on the list.
AI प्लेबुक अपने इनबॉक्स में पाएं
हर बुधवार। 28,400+ पाठक। बिना फालतू बात।
Check your inbox.
We sent you a confirmation email — click the link inside to complete your subscription. Check spam if you don't see it within a minute.
You're subscribed.
Welcome — the next edition lands in your inbox soon.
You're already on the list — look for it every Wednesday.