Alejandro Rioja.
AI Agents SEO

एक Agent से एक Blog Post को 13 भाषाओं में कैसे Translate करें

Alejandro Rioja
Alejandro Rioja
7 मिनट पढ़ें
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 मिला।

मुफ़्त न्यूज़लेटर

हर बुधवार। 28,400+ पाठक। बिना फालतू बात।

विषय सूची

मई 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 करता है।

code
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 builder

Orchestrator (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 होता है):

typescript
// 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 होता है):

typescript
  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 पर लिखता है।

typescript
// 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

typescript
// 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 करें:

sh
# एक नई 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.ts

Cost Breakdown: Haiku बनाम Sonnet

मेरे usage के आधार पर per post का actual cost:

ModelInput tokens (avg)Output tokens (avg)Cost per localeCost × 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 कर सकते हैं:

sh
TRANSLATE_MODEL=claude-sonnet-4-5 npx ts-node scripts/agent/translate-all.ts src/content/posts/en/flagship-post.md

Real Results: मेरे Traffic पर क्या हुआ

मैंने दिसंबर 2025 में full backlog translation (341 posts) ship किया। 60 दिनों में:

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 करें।

पढ़ते रहें

AI प्लेबुक अपने इनबॉक्स में पाएं

हर बुधवार। 28,400+ पाठक। बिना फालतू बात।

↵ सभी परिणाम देखें esc esc बंद करें