इसे छोड़कर कंटेंट पर जाएं

अनुवाद प्रणाली

यह साइट 17 भाषाओं में प्रकाशित है। अनुवादकों की किसी टीम द्वारा नहीं, बल्कि एक Python स्क्रिप्ट, एक Claude Opus मॉडल, और एक ऐसी फ़ाइल संरचना द्वारा जो सब कुछ सही जगह बैठा देती है। यहाँ पूरी प्रक्रिया का विवरण है।

दस्तावेज़ीकरण src/content/docs/ में रहता है। अंग्रेज़ी मूल (root) है — बाकी हर भाषा इसका हूबहू दर्पण बनाती है:

src/content/docs/
├── index.mdx ← English (root)
├── getting-started.md
├── features/
│ ├── play-chess.md
│ ├── multiplayer.md
│ └── ...
├── setup/
│ ├── tts-overview.md
│ └── ...
├── under-the-hood/
│ ├── architecture.md
│ └── ...
├── fr/ ← French
│ ├── index.mdx
│ ├── getting-started.md
│ ├── features/
│ │ ├── play-chess.md
│ │ └── ...
│ └── ...
├── ja/ ← Japanese
│ ├── index.mdx
│ ├── getting-started.md
│ └── ...
└── ... (16 language directories total)

हर अनुवादित फ़ाइल अपनी अंग्रेज़ी स्रोत फ़ाइल का संरचनात्मक दर्पण है। वही फ़ाइल नाम, वही उप-निर्देशिका पथ, वही frontmatter कुंजियाँ। फ़र्क सिर्फ इतना है कि गद्य दूसरी भाषा में है।

दर्पण संरचना क्यों ज़रूरी है

Section titled “दर्पण संरचना क्यों ज़रूरी है”

Starlight (दस्तावेज़ीकरण फ़्रेमवर्क) इसी सममिति पर निर्भर करता है। जब कोई उपयोगकर्ता भाषा बदलता है, तो Starlight /docs/getting-started/ को /fr/docs/getting-started/ से बदल देता है — वही पथ, अलग locale उपसर्ग। अगर फ़्रेंच फ़ाइल ठीक fr/getting-started.md पर मौजूद नहीं है, तो स्विचर टूट जाता है या चुपचाप अंग्रेज़ी पर वापस लौट जाता है।

भाषाओं को वैश्विक शतरंज-खेलने वाली जनसंख्या के अनुसार क्रमबद्ध किया गया है, जो Lichess, Chess.com, और FIDE पंजीकरण के डेटा पर आधारित है। अंग्रेज़ी स्रोत भाषा के रूप में पहले आती है; बाकी सब शतरंज रैंकिंग का अनुसरण करती हैं:

क्रमकोडभाषाशैली
1enअंग्रेज़ीमूल स्रोत
2esस्पेनिशमानक औपचारिक
3hiहिन्दीदेवनागरी लिपि
4ruरूसीमानक औपचारिक
5deजर्मनमानक औपचारिक
6frफ़्रेंचमानक औपचारिक
7ptपुर्तगालीयूरोपीय पुर्तगाली
11plपोलिशमानक औपचारिक
12itइतालवीमानक औपचारिक
13ukयूक्रेनीमानक औपचारिक
14trतुर्कीमानक औपचारिक
17koकोरियाई합니다/습니다 रूप
18zhचीनी (सरलीकृत)सरलीकृत अक्षर
zh-twचीनी (पारंपरिक)पारंपरिक अक्षर
23nbनॉर्वेजियन बूकमॉलमानक बूकमॉल
beबेलारूसीमानक बेलारूसी
34jaजापानीです/ます रूप

“शैली” कॉलम महत्वपूर्ण है। जापानी और कोरियाई में औपचारिक रजिस्टर के विकल्प होते हैं जो हर वाक्य को प्रभावित करते हैं। अनुवाद प्रॉम्प्ट में ये निर्देश शामिल किए जाते हैं ताकि मॉडल स्वाभाविक, परिष्कृत गद्य उत्पन्न करे — न कि कठोर मशीनी आउटपुट।

यह क्रम साइट हेडर में भाषा ड्रॉपडाउन को भी नियंत्रित करता है। सबसे अधिक बोली जाने वाली शतरंज भाषाएँ पहले दिखती हैं, जिससे उपयोगकर्ताओं को स्क्रॉल किए बिना अपनी भाषा मिलने की संभावना बढ़ जाती है।

अनुवाद पाइपलाइन

Section titled “अनुवाद पाइपलाइन”

चरण 1: अंग्रेज़ी में लिखें

Section titled “चरण 1: अंग्रेज़ी में लिखें”

सारा दस्तावेज़ीकरण src/content/docs/ में अंग्रेज़ी मार्कडाउन के रूप में शुरू होता है। Frontmatter में title और description होता है:

---
title: "Getting Started"
description: "Install En Parlant~ and play your first game."
---
Download the latest release...

चरण 2: स्क्रिप्ट चलाएँ

Section titled “चरण 2: स्क्रिप्ट चलाएँ”

एक Python स्क्रिप्ट (scripts/translate-docs.py) हर अंग्रेज़ी स्रोत फ़ाइल पढ़ती है, उसे Claude API को भेजती है, और अनुवादित मार्कडाउन लिखती है:

Terminal window
python3 scripts/translate-docs.py \
--anthropic-key $ANTHROPIC_API_KEY \
--model claude-opus-4-6 \
--workers 5

सभी 28 स्रोत फ़ाइलों को 16 लक्ष्य भाषाओं में अनुवाद करने में स्क्रिप्ट को लगभग 60–70 मिनट लगते हैं (कुल 448 फ़ाइलें)। यह रेट लिमिट के भीतर रहने के लिए 5 समानांतर API कॉल चलाती है।

किसी एकल नई भाषा के लिए, लगभग 4 मिनट लगते हैं।

Terminal window
pnpm build

Astro स्रोत मार्कडाउन पढ़ता है, Starlight के टेम्पलेट्स से रेंडर करता है, और dist/ में स्टैटिक HTML आउटपुट करता है। सभी ~500 पृष्ठों के लिए बिल्ड में लगभग 30 सेकंड लगते हैं।

चरण 4: डिप्लॉय करें

Section titled “चरण 4: डिप्लॉय करें”
Terminal window
pnpm run deploy

बिल्ड की गई साइट को Cloudflare Workers पर पुश करता है।

स्क्रिप्ट कैसे काम करती है

Section titled “स्क्रिप्ट कैसे काम करती है”

अनुवाद स्क्रिप्ट जानबूझकर सरल है — लगभग 300 लाइन Python कोड। यहाँ प्रवाह है:

┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Read English │────▶│ Claude API │────▶│ Write target │
│ source file │ │ (Opus 4.6) │ │ language file │
│ │ │ │ │ │
│ getting- │ │ "Translate into │ │ fr/getting- │
│ started.md │ │ French..." │ │ started.md │
└─────────────────┘ └──────────────────┘ └─────────────────┘
× 5 parallel
× 16 languages
× 28 files

प्रॉम्प्ट Claude को ठीक-ठीक बताता है कि क्या अनुवाद करना है और क्या वैसा ही छोड़ना है:

  • अनुवाद करें: गद्य, शीर्षक, तालिका लेबल, frontmatter title और description
  • अंग्रेज़ी में रखें: कोड ब्लॉक, इनलाइन कोड, कमांड उदाहरण, फ़ाइल पथ, URL, उत्पाद नाम, व्यक्तियों के नाम, ASCII डायग्राम

यह अलगाव अत्यंत महत्वपूर्ण है। pnpm build जैसी कमांड को हर भाषा में pnpm build ही रहना चाहिए। “En Parlant~” या “Stockfish” जैसे उत्पाद नाम अनुवादित नहीं होते। लेकिन “Getting Started” जापानी में “はじめに” और रूसी में “Начало работы” बन जाता है।

Claude Opus 4.6 तेज़ मॉडलों की तुलना में काफ़ी बेहतर अनुवाद उत्पन्न करता है। अंतर इनमें दिखता है:

  • स्वाभाविक वाक्य-रचना — Opus एक मूल वक्ता की तरह लिखता है, अनुवादक की तरह नहीं। जब अंग्रेज़ी शब्द-क्रम लक्ष्य भाषा में अटपटा लगे, तो यह वाक्यों की पुनर्संरचना करता है।
  • तकनीकी सटीकता — शतरंज की शब्दावली, TTS जार्गन, और सॉफ़्टवेयर अवधारणाएँ सही डोमेन-विशिष्ट शब्दों का उपयोग करके अनुवादित होती हैं।
  • एकरूपता — औपचारिक रजिस्टर पूरे दस्तावेज़ में सुसंगत रहता है। जापानी हर जगह です/ます रूप का उपयोग करती है, पैराग्राफ़ के बीच में अनौपचारिक और विनम्र के बीच स्विच नहीं करती।
  • MDX हैंडलिंग — Opus, .mdx फ़ाइलों में JSX कंपोनेंट टैग (<Card>, <CardGrid>) और import स्टेटमेंट को बिना बिगाड़े सही ढंग से सुरक्षित रखता है।

लागत का अंतर वास्तविक है — Opus के साथ पूरी साइट के अनुवाद के लिए लगभग $28 बनाम Sonnet के साथ $5 — लेकिन 448 ऐसी फ़ाइलों के लिए जिन्हें उपयोगकर्ता वास्तव में पढ़ेंगे, गुणवत्ता इसके लायक है।

Locale रूटिंग आर्किटेक्चर

Section titled “Locale रूटिंग आर्किटेक्चर”

यह वह हिस्सा है जिसे सही करने में सबसे ज़्यादा समय लगा।

Starlight किसी पृष्ठ की भाषा का पता उसके content slug के पहले खंड की जाँच करके लगाता है। जब यह fr/docs/getting-started देखता है, तो समझ जाता है कि यह फ़्रेंच है क्योंकि fr पहला खंड है। लेकिन प्रारंभिक कार्यान्वयन ने docs/fr/getting-started जैसे slug बनाए — locale, docs/ के नीचे दबा हुआ। Starlight ने docs को पहला खंड माना, सब कुछ अंग्रेज़ी मान लिया, और ~500 के बजाय 7,000+ डुप्लिकेट पृष्ठ बना दिए।

src/content.config.ts में एक कस्टम generateId फ़ंक्शन नियंत्रित करता है कि फ़ाइल पथ कैसे content slug बनते हैं:

generateId({ entry }) {
const slug = entry.replace(/\.[^.]+$/, "");
const firstSeg = slug.split("/")[0];
if (firstSeg && localeKeys.includes(firstSeg)) {
return `${firstSeg}/docs/${slug.slice(firstSeg.length + 1)}`;
}
return `docs/${slug}`;
}

यह locale उपसर्ग को docs/ से पहले रखता है:

फ़ाइल पथSlugURL
getting-started.mddocs/getting-started/docs/getting-started/
fr/getting-started.mdfr/docs/getting-started/fr/docs/getting-started/
ja/features/puzzles.mdja/docs/features/puzzles/ja/docs/features/puzzles/

अंग्रेज़ी defaultLocale: "root" का उपयोग करती है, जिसका अर्थ है कोई उपसर्ग नहीं — यह /en/docs/ पर नहीं, बल्कि सीधे /docs/ पर रहती है।

उसी फ़ाइल में एक localeKeys ऐरे में हर गैर-अंग्रेज़ी locale सूचीबद्ध होना चाहिए। अगर कोई locale Astro के config में मौजूद है लेकिन इस ऐरे में नहीं, तो उसकी अनुवादित सामग्री अंग्रेज़ी सामग्री मान ली जाती है — भाषा स्विचर टूट जाता है और पृष्ठ संख्या बेतहाशा बढ़ जाती है।

Astro slug मैपिंग को .astro/data-store.json में कैश करता है। किसी भी locale कॉन्फ़िगरेशन परिवर्तन के बाद, रीबिल्ड करने से पहले इस फ़ाइल को हटाना अनिवार्य है, अन्यथा बिल्ड पुरानी (ग़लत) रूटिंग के साथ सफल हो जाता है।

साइडबार astro.config.mjs में परिभाषित है। जो आइटम किसी पृष्ठ की ओर इशारा करते हैं (slug प्रॉपर्टी), वे स्वचालित रूप से अनुवादित पृष्ठ के frontmatter शीर्षक का उपयोग करते हैं — कोई मैनुअल अनुवाद ज़रूरी नहीं:

{ slug: "docs/getting-started" }
// English: "Getting Started" (from English frontmatter)
// French: "Premiers pas" (from French frontmatter)
// Japanese: "はじめに" (from Japanese frontmatter)

लेकिन ग्रुप लेबल और बाहरी लिंक के लिए स्पष्ट अनुवाद ज़रूरी हैं:

{
label: "Features",
translations: {
fr: "Fonctionnalités",
es: "Características",
de: "Funktionen",
ja: "機能",
// ... all 16 languages
},
items: [
{ slug: "docs/features/play-chess" },
{ slug: "docs/features/multiplayer" },
// ...
],
}

सात साइडबार तत्वों को मैनुअल अनुवाद की आवश्यकता होती है: Welcome, Features, App Menus, Setup Guides, Under the Hood, Credits, और Accessibility। कोई नई भाषा जोड़ने का मतलब है इन सातों ब्लॉक में एक-एक प्रविष्टि जोड़ना।

En Parlant~ अपने Help मेनू से इस दस्तावेज़ीकरण को लिंक करता है। यह लिंक locale-aware है — अगर आप ऐप फ़्रेंच में उपयोग कर रहे हैं, तो यह फ़्रेंच दस्तावेज़ खोलता है:

const docsLocalePrefix = useMemo(() => {
const lang = i18n.language; // e.g. "fr_FR", "zh_TW"
if (!lang || lang.startsWith("en")) return "";
if (lang === "zh_TW") return "/zh-tw";
return `/${lang.slice(0, 2)}`;
}, [i18n.language]);

ऐप में उपलब्ध हर भाषा का साइट पर एक मिलता-जुलता अनुवाद है। मैपिंग स्वचालित है — fr_FR /fr/docs/ पर मैप होता है, ja_JP /ja/docs/ पर मैप होता है। एकमात्र विशेष मामला पारंपरिक चीनी है: zh_TW /zh-tw/docs/ (हाइफ़नेटेड) पर मैप होता है।

अब यह आसान क्यों है

Section titled “अब यह आसान क्यों है”

कठिन हिस्से पूरे हो चुके हैं:

  1. रूटिंग आर्किटेक्चर हल हो चुका है। generateId फ़ंक्शन, localeKeys ऐरे, और defaultLocale: "root" कॉन्फ़िग मिलकर काम करते हैं ताकि Starlight सही URL संरचना बनाए। यह सबसे बड़ी परेशानी थी — इसे खोजने और ठीक करने के लिए Starlight और Astro की 6+ स्रोत फ़ाइलों को ट्रेस करना पड़ा।

  2. अनुवाद स्क्रिप्ट सब कुछ संभालती है। पूरी साइट का पुनः अनुवाद, एकल भाषा जोड़ना, व्यक्तिगत फ़ाइल अपडेट — सब एक ही स्क्रिप्ट, अलग-अलग फ़्लैग के साथ। यह रेट लिमिट पर पुनः प्रयास करती है, वर्कर्स में समानांतर चलती है, और त्रुटियाँ स्पष्ट रूप से रिपोर्ट करती है।

  3. नई भाषा जोड़ना चार config संपादन और एक कमांड है। astro.config.mjs, content.config.ts, और translate-docs.py में locale जोड़ें, साइडबार अनुवाद जोड़ें, स्क्रिप्ट चलाएँ। लगभग 10 मिनट का काम और 4 मिनट का अनुवाद समय।

  4. सामग्री अपडेट करना और भी सरल है। अंग्रेज़ी स्रोत संपादित करें, केवल बदली हुई फ़ाइलों के लिए --files और --overwrite के साथ स्क्रिप्ट चलाएँ, रीबिल्ड करें। या छोटे गद्य सुधारों के लिए, अनुवादित फ़ाइलें सीधे संपादित करें।

  5. पूरी पाइपलाइन एक skill में दर्ज है। /translate_docs चलाने पर पूरी प्रक्रिया का मार्गदर्शन मिलता है — कौन सा मोड उपयोग करें, कौन से फ़्लैग पास करें, प्री-फ़्लाइट जाँच, अनुवाद-पश्चात सत्यापन। किसी संस्थागत ज्ञान की आवश्यकता नहीं।

16 भाषाओं में 448 फ़ाइलों के कुल अनुवाद की लागत लगभग $28 रही और इसमें लगभग 70 मिनट लगे। एक नई भाषा की लागत लगभग $1.70 है। सभी भाषाओं में एक फ़ाइल के पुनः अनुवाद की लागत लगभग $1 है। दस्तावेज़ीकरण को 17 भाषाओं में अद्यतित रखने की निरंतर लागत यही है।