-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial 5 Localization hi
लक्ष्य: समझें कि LockedIn CLI कैसे 33 भाषाएँ बोलती है — और एक एजेंट को एक और भाषा जोड़ने के लिए निर्देशित करने का अभ्यास करें। लोकलाइज़ेशन एक शानदार एजेंट टास्क है: यह delegate करने लायक पर्याप्त यांत्रिक है, पर इसमें असली constraints हैं (एक test गेट, layout नियम, व्याकरण review) जो आपको review करना सिखाते हैं।
← पिछला: ट्यूटोरियल 4 प्रॉम्प्टिंग और रिव्यू · होम पर वापस
CLI को स्पेनिश, हिन्दी, जापानी, सरलीकृत चीनी, या किसी भी shipped भाषा में चलाएँ और सब कुछ बदल जाता है — splash, help table, हर कमांड का output, chat session, यहाँ तक कि legal fine print भी। सिर्फ़ मज़ाक नहीं: पूरी दृश्यमान सतह।
lockedin --lang hi post
LOCKEDIN_LANG=hi lockedin
lockedin --lang zh auraभाषा startup पर autodetect होती है, प्राथमिकता क्रम में हल होती है:
-
--langflag (--lang hi,--lang=fr,-l ja) -
LOCKEDIN_LANGenvironment variable - आपका locale (
LC_ALL/LC_MESSAGES/LANG, फिर OS/runtime locale) - अंग्रेज़ी, fallback के रूप में
normalizeLang() सामान्यतः locale के primary subtag का उपयोग करता है। इसका मतलब
de-DE de चुनता है, पर tlh गलती से tl नहीं बन जाता; असली aliases fil और tgl
जानबूझकर Tagalog (tl) पर map होते हैं, नॉर्वेजियन nb और nn no पर map होते हैं,
legacy Indonesian in id पर map होता है, और legacy Hebrew iw he पर map होता है।
दो regional codes उनके primary subtag में मोड़ने के बजाय हूबहू संरक्षित रहते हैं:
pt-BR/pt_BR canonical regional code चुनते हैं जबकि generic pt backward-compatible
Brazilian Portuguese bundle रहता है (दोनों Brazilian Portuguese हैं और एक ही pools/UI
साझा करते हैं), और en-SG/en_SG Singlish रखते हैं (generic en अंग्रेज़ी रहता है)।
Hong Kong Traditional Chinese उसी तरह का अपवाद है: zh-HK, zh_HK.UTF-8, और
zh-Hant-HK zh-HK चुनते हैं, जबकि generic zh और mainland tags सरलीकृत चीनी (zh)
चुनते हैं।
बीच में switch — /language panel। CLI हमेशा किसी और भाषा में शुरू हो सकती थी
(--lang, LOCKEDIN_LANG); अब आप session के बीच में switch कर सकते हैं। /language
टाइप करें (aliases /lang और /languages) सभी 33 भाषाओं को code के हिसाब से सूचीबद्ध
करने के लिए, हर एक अपनी script में; /language el बाकी session के लिए switch कर देता
है। बात है escape hatch की: switch के बाद यह नई भाषा में फिर से draw करता है और फिर,
उसी भाषा में जिसे आपने अभी छोड़ा, ठीक वापसी का रास्ता print करता है — अभी
/language en, अगली बार lockedin --lang en — ताकि गलती से 日本語 या ಕನ್ನಡ में जा
पड़ने पर भी आप कभी न फँसें। (दो बार switch करें और आपका LOCKEDIN_LANG जिस भाषा का नाम
लेता है वह भी पेश की जाती है।) --lang और LOCKEDIN_LANG अपरिवर्तित हैं। /a11y की
तरह, यह एक सच्ची utility है, satire का हिस्सा नहीं।
सारा translatable text bundles में रहता है, प्रति भाषा एक, हर एक का आकार ऐसा:
{ meta: { lang: 'hi', name: 'हिन्दी', dir: 'ltr' },
pools: { HOOKS: [ /* ~25 */ ], LESSONS: [ /* ... */ ], /* ... */ },
ui: { buzzwordDensity: 'Buzzword घनत्व: ', /* labels, headings */ } }-
poolsवे content arrays (मज़ाक) हैं जिनसे आप अध्याय 2 में मिले। -
uichrome strings हैं: labels, headings, और छोटे templates।
अंग्रेज़ी src/lockedin.js के अंदर reference bundle है; बाकी 32 bundle modules
src/content/*.js में रहते हैं: ar, bn, bo, de, el, en-SG, es, eu,
fa, fi, fr, he, hi, id, is, it, ja, kn, ms, nl, no, pl,
pt, pt-BR, ru, sv, tl, tr, uk, ur, zh, और zh-HK (pt-BR pt के
pools/UI दोबारा इस्तेमाल करता है पर अलग से register होता है)। हर एक BUNDLES में
register है; SUPPORTED_LANGS उन keys से बनता है, और renderHelp() वह बनी हुई code
सूची print करता है। कोई UI bundle सूची को hard-code नहीं करता।
setLang('fr'); // active भाषा को French bundle की ओर इंगित करें
// L = सक्रिय pools, U = सक्रिय ui
pick(L.HOOKS) // एक French hook
U.buzzwordDensity // "Densité de jargon : "चूँकि हर renderer L और U पढ़ता है (कभी hardcoded string नहीं), अकेला setLang
पूरा अनुभव बदल देता है। यही पूरी तरकीब है।
यही वह invariant है जो एक भाषा जोड़ना सुरक्षित बनाता है:
हर bundle को अंग्रेज़ी जैसी ठीक वही
poolsऔरuikeys expose करनी चाहिए।
एक test इसे सभी 33 bundles में लागू करता है। अगर आप अंग्रेज़ी में एक नई UI string जोड़ते
हैं और यूक्रेनियन में अनुवाद करना भूल जाते हैं, npm test लाल हो जाता है और बताता है
कौन-सी key गायब है। आप चुपके से एक आधी-अनुवादित भाषा ship नहीं कर सकते।
भाषाएँ terminal layout पर अलग-अलग तरीकों से दबाव डालती हैं:
-
जापानी, सरलीकृत चीनी, और Hong Kong Traditional Chinese East Asian Wide /
Fullwidth characters इस्तेमाल करते हैं।
vw()उन्हें दो columns गिनता है, औरwrap()लंबे space-रहित tokens को hard-break करता है ताकि CJK text cards और boxes के अंदर रहे। -
हिन्दी और कन्नड़ nonspacing/enclosing combining marks (
Mn/Me) इस्तेमाल करते हैं, जैसे मात्राएँ और विराम।vw()उन्हें शून्य columns गिनता है ताकि वे मापी गई width को न फुलाएँ। -
box()हर body line को pad करने से पहले wrap करता है, ताकि एक लंबा अनुवादित banner अब border को न भेद सके। - हर bundle
sentenceEndऔरlistSepसेट करता है (उदाहरण के लिए./。,,/、) ताकि generator-रचित वाक्य स्वाभाविक रूप से पढ़ें।
जब आप एक भाषा जोड़ते हैं, card header strings (cardSubtitle, cardMeta,
cardFooter) को अब भी ≤ 60 visible columns में फिट होना चाहिए। अरबी, फ़ारसी,
हिब्रू, और उर्दू meta.dir: 'rtl' सेट करते हैं। Output में default रूप से कोई bidi
controls नहीं होते, क्योंकि कुछ terminals उन्हें boxed labels के रूप में render करते
हैं। LOCKEDIN_BIDI=on स्पष्ट रूप से wrapping के बाद balanced isolates सक्षम करता है
उन terminals के लिए जो उन्हें support करने के लिए जाने जाते हैं, ANSI, ASCII commands,
और logical copy/paste क्रम संरक्षित रखते हुए। Accessible output हमेशा उन controls को
हटा देता है। opt-in के बिना, मिश्रित RTL/LTR क्रम कम परिष्कृत हो सकता है; कभी support
probe या infer न करें।
कुछ UI templates {cap} जैसे placeholders के साथ raw user clauses splice करते हैं।
उन्हें slot-for-slot अनुवाद न करें। वाक्य को व्याकरणसम्मत रहना चाहिए जब placeholder एक
ऐसा phrase हो जिसे user ने type किया, न कि कोई साफ़-सुथरा noun।
एक असली सावधानी वाला bug: जापानी templates जो {cap} के ठीक बाद は लगाते हैं, गलत लग
सकते हैं जब {cap} एक पूरा clause हो। इलाज "और ज़ोर से अनुवाद करना" नहीं है; इलाज है
template को फिर से संरचित करना (उदाहरण के लिए, एक nominalizer जोड़ना या placeholder
हटाना) ताकि कोई भी user input अब भी फिट हो।
यह अभ्यास ठीक उसी तरह काम करता है। ऐसी भाषा चुनें जिसे आप sanity-check कर सकें (या एजेंट से करवाएँ), और उसे शुरू से अंत तक चलाएँ। पहले spec लिखें:
डैनिश (
da) जोड़ें। अंग्रेज़ी जैसी वही keys के साथsrc/content/da.jsको एक{ meta, pools, ui }bundle के रूप में बनाएँ, हर entry का अनुवाद करते हुए (content pools ~25 प्रत्येक, सारी UI strings)।src/lockedin.jsमेंBUNDLESमेंdaregister करें।--lang daऔर एकda-*locale को इसे चुनना चाहिए। card header strings को width सीमा के भीतर रखें।npm testहरा रहना चाहिए, और मौजूदा localized वालों को प्रतिबिंबित करते हुए डैनिश invariants + detection tests जोड़ें।
फिर अध्याय 3–4 का loop चलाएँ:
- पहले plan। "कोड लिखने से पहले, बताओ कौन-सी फ़ाइलें बदलोगे और अंग्रेज़ी के साथ key parity कैसे रखोगे।"
-
पहले tests। "failing tests जोड़ो:
dadetection,daके लिए key parity, और एक डैनिश reflect/connect invariant। bundle अभी मत बनाओ।" -
Implement। "अब एक मौजूदा bundle को key दर key अनुवाद करके
src/content/da.jsबनाओ, उसे register करो, और tests पास कराओ। randomness के लिए सिर्फ़pick/shuffle।" -
गेट + review।
npm test, फिरlockedin --lang da post— और diff को पढ़ो: क्या हर key का अनुवाद हुआ? क्या card borders अब भी line up होते हैं? क्या{cap}वाले templates raw user clauses में टिकते हैं?
अगर पूरी भाषा बहुत ज़्यादा है तो छोटे warm-up अभ्यास:
- "सभी 33 language bundles में एक और
TAGLINEजोड़ो, counts बराबर रखते हुए।" - "जाँचो कि कन्नड़
cardFooter≤ 60 visible columns है या नहीं और समझाओ कि combining marks कैसे मापी गईं।" - "वह test दिखाओ जो fail होगा अगर मैं
ja.jsसे एकuikey delete कर दूँ।"
-
src/content/es.jsस्किम करें — यह अब भी एक नए bundle के लिए एक friendly template है। -
docs/HANDOFF.md→ "Adding a language" फिर से पढ़ें। - कमांड रेफरेंस में बहुभाषी मज़ाक का आनंद लें।
यही पूरा ट्यूटोरियल है। अब आप एक AI एजेंट को features बनाने और उन्हें एक test गेट के पीछे localize करने के लिए निर्देशित कर सकते हैं — 33 भाषाओं में और और के लिए तैयार। Agree? 👇
Tutorial
- 1 · Orientation
- 2 · How the Code Works
- 3 · Your First Agent Task
- 4 · Prompting & Reviewing
- 5 · Localization
Reference
Satire · Sátira · 風刺. Not affiliated with LinkedIn. GPL-3.0-or-later.