Skip to content

Tutorial 5 Localization fa

James Morris edited this page Jul 29, 2026 · 1 revision

آموزش ۵ · بومی‌سازی (i18n)

🌎 زبان: فارسیمشاهدهٔ هر ۳۳ زبان

هدف: درک اینکه LockedIn CLI چگونه به ۳۳ زبان صحبت می‌کند — و تمرینِ هدایتِ یک عامل برای افزودنِ زبانی دیگر. بومی‌سازی یک کارِ عاملیِ فوق‌العاده است: به‌قدرِ کافی مکانیکی است که واگذار شود، اما محدودیت‌های واقعی دارد (یک دروازهٔ آزمون، قواعدِ چیدمان، بازبینیِ دستور زبان) که به شما بازبینی را می‌آموزد.

← قبلی: آموزش ۴ اعلان‌نویسی و بازبینی · بازگشت به خانه


«بومی‌سازی‌شده» این‌جا یعنی چه

CLI را به اسپانیایی، هندی، ژاپنی، چینیِ ساده‌شده یا هر زبانِ عرضه‌شده‌ای اجرا کنید و همه‌چیز تغییر می‌کند — صفحه‌ی آغازین، جدولِ راهنما، خروجیِ هر فرمان، نشستِ گفت‌وگو، حتی ریزنوشته‌ی حقوقی. نه فقط شوخی‌ها: کلِ سطحِ قابل‌مشاهده.

lockedin --lang fa post
LOCKEDIN_LANG=hi lockedin
lockedin --lang zh aura

زبان در هنگام راه‌اندازی خودکار تشخیص داده می‌شود و به‌ترتیبِ اولویت حل می‌شود:

  1. پرچمِ --lang (--lang fa، --lang=fr، -l ja)
  2. متغیرِ محیطیِ LOCKEDIN_LANG
  3. محلیِ شما (LC_ALL / LC_MESSAGES / LANG، سپس محلیِ سیستم‌عامل/زمانِ‌اجرا)
  4. انگلیسی، به‌عنوان بازگشت‌گاه

normalizeLang() معمولاً از زیربرچسبِ اصلیِ محلی استفاده می‌کند. یعنی de-DE به‌سراغِ de می‌رود، اما tlh به‌طور تصادفی tl نمی‌شود؛ نام‌های بدیلِ واقعیِ fil و tgl عمداً به تاگالوگ (tl) نگاشته می‌شوند، نروژیِ nb و nn به no نگاشته می‌شوند، اندونزیاییِ قدیمیِ in به id نگاشته می‌شود، و عبریِ قدیمیِ iw به he نگاشته می‌شود. دو کدِ منطقه‌ای به‌جای تاشدن به زیربرچسبِ اصلیِ خود، عیناً حفظ می‌شوند: pt-BR/pt_BR کدِ منطقه‌ایِ متعارف را انتخاب می‌کنند در حالی که ptِ عمومی همان بسته‌ی سازگارِ پرتغالیِ برزیل می‌ماند (هر دو پرتغالیِ برزیل‌اند و همان pools/UI را به اشتراک می‌گذارند)، و en-SG/en_SG سینگلیش را نگه می‌دارند (enِ عمومی همان انگلیسی می‌ماند). چینیِ سنتیِ هنگ‌کنگ همان نوع استثناست: zh-HK، zh_HK.UTF-8 و zh-Hant-HK به‌سراغِ zh-HK می‌روند، در حالی که zhِ عمومی و برچسب‌های سرزمینِ اصلی چینیِ ساده‌شده (zh) را انتخاب می‌کنند.

تعویض در میانه‌ی راه — تابلوی /language. CLI همیشه می‌توانست در زبانی دیگر شروع کند (--lang، LOCKEDIN_LANG)؛ اکنون می‌توانید در میانه‌ی نشست تعویض کنید. /language را تایپ کنید (نام‌های بدیلِ /lang و /languages) تا همه‌ی ۳۳ زبان را با کد فهرست کنید، هرکدام در خطِ خودش؛ /language el برای باقیِ نشست تعویض می‌کند. نکته همان دریچه‌ی فرار است: پس از تعویض در زبانِ جدید بازترسیم می‌کند و سپس، در زبانی که همین حالا ترک کردید، راهِ دقیقِ بازگشت را چاپ می‌کند — همین حالا /language en، دفعه‌ی بعد lockedin --lang en — تا فرودِ تصادفی در 日本語 یا ಕನ್ನಡ هرگز شما را در بن‌بست نگذارد. (دو بار تعویض کنید و زبانی که LOCKEDIN_LANG شما نام می‌برد هم پیشنهاد می‌شود.) --lang و LOCKEDIN_LANG بدون تغییرند. مانند /a11y، این یک ابزارِ صادقانه است، نه بخشی از طنز.

ایده: بسته‌های زبانی

همه‌ی متنِ قابل‌ترجمه در بسته‌ها زندگی می‌کند، یکی برای هر زبان، هرکدام با این شکل:

{ meta: { lang: 'fa', name: 'فارسی', dir: 'rtl' },
  pools: { HOOKS: [ /* ~25 */ ], LESSONS: [ /* ... */ ], /* ... */ },
  ui:    { buzzwordDensity: 'چگالی کلمات پرطمطراق: ', /* برچسب‌ها، عنوان‌ها */ } }
  • pools آرایه‌های محتوا (شوخی‌ها) هستند که در فصل ۲ با آن‌ها آشنا شدید.
  • ui رشته‌های آرایه‌ای هستند: برچسب‌ها، سرنویس‌ها و الگوهای کوچک.

انگلیسی بسته‌ی مرجع درونِ src/lockedin.js است؛ ۳۲ ماژولِ بسته‌ی دیگر در 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 از pools/UIِ pt استفاده‌ی دوباره می‌کند اما جداگانه ثبت می‌شود). هرکدام در BUNDLES ثبت می‌شود؛ SUPPORTED_LANGS از آن کلیدها تولید می‌شود، و renderHelp() آن فهرستِ کدِ تولیدشده را چاپ می‌کند. هیچ بسته‌ی UIای فهرست را کدسخت نمی‌کند.

setLang('fr');       // زبان فعال را به بستهٔ فرانسوی اشاره بده
// L = مخزن‌های فعال، U = رابط کاربری فعال
pick(L.HOOKS)        // یک قلاب فرانسوی
U.buzzwordDensity    // "Densité de jargon : "

چون هر رندرگر L و U را می‌خواند (هرگز یک رشته‌ی کدسخت)، تنها setLang کلِ تجربه را تغییر می‌دهد. کلِ ترفند همین است.

تورِ ایمنی: برابری کلیدها

این ناوردایی است که افزودنِ یک زبان را امن می‌کند:

هر بسته باید دقیقاً همان کلیدهای pools و ui انگلیسی را در معرض بگذارد.

یک آزمون آن را در سراسرِ هر ۳۳ بسته اجرا می‌کند. اگر یک رشته‌ی UIِ جدید به انگلیسی اضافه کنید و فراموش کنید آن را به اوکراینی ترجمه کنید، npm test قرمز می‌شود و به شما می‌گوید کدام کلید گم است. نمی‌توانید بی‌سروصدا یک زبانِ نیمه‌ترجمه‌شده عرضه کنید.

بخشِ سخت: چیدمانِ ترمینال

زبان‌ها چیدمانِ ترمینال را به شیوه‌های گوناگون تحت فشار می‌گذارند:

  • ژاپنی، چینیِ ساده‌شده و چینیِ سنتیِ هنگ‌کنگ از نویسه‌های عریضِ آسیای شرقی / تمام‌عرض استفاده می‌کنند. vw() آن‌ها را دو ستون می‌شمارد، و wrap() توکن‌های بلندِ بدون‌فاصله را به‌سختی می‌شکند تا متنِ CJK درونِ کارت‌ها و جعبه‌ها بماند.
  • هندی و کانادا از علامت‌های ترکیبیِ بدون‌فاصله/محصورکننده (Mn / Me) استفاده می‌کنند، مانند ماتراها و ویراماها. vw() آن‌ها را صفر ستون می‌شمارد تا عرضِ اندازه‌گیری‌شده را باد نکنند.
  • box() پیش از لایه‌گذاریِ هر خطِ بدنه آن را می‌پیچد، تا یک بنرِ ترجمه‌شده‌ی بلند دیگر نتواند از حاشیه بیرون بزند.
  • هر بسته sentenceEnd و listSep را تنظیم می‌کند (برای مثال . / ، , / ) تا جملاتِ ساخته‌ی تولیدکننده طبیعی خوانده شوند.

وقتی یک زبان اضافه می‌کنید، رشته‌های سرنویسِ کارت (cardSubtitle، cardMeta، cardFooter) همچنان باید در ≤ ۶۰ ستونِ مرئی جا شوند. عربی، فارسی، عبری و اردو meta.dir: 'rtl' را تنظیم می‌کنند. خروجی به‌طور پیش‌فرض هیچ کنترلِ دوجهته‌ای ندارد، چون برخی ترمینال‌ها آن‌ها را به‌صورتِ برچسب‌های جعبه‌ای رندر می‌کنند. LOCKEDIN_BIDI=on جداسازهای متوازن را پس از پیچش برای ترمینال‌هایی که پشتیبانی‌شان شناخته‌شده است صراحتاً فعال می‌کند، در حالی که ANSI، فرمان‌های ASCII و ترتیبِ منطقیِ کپی/چسباندن را حفظ می‌کند. خروجیِ دسترس‌پذیر همیشه آن کنترل‌ها را حذف می‌کند. بدون این انتخابِ ارادی، ترتیبِ آمیخته‌ی RTL/LTR ممکن است کمتر پیچیده باشد؛ هرگز پشتیبانی را کاوش یا استنتاج نکنید.

بخشِ فریبنده: دستور زبان پیرامونِ ورودیِ خامِ کاربر

برخی الگوهای UI بندهای خامِ کاربر را با جای‌گیرهایی مانند {cap} درج می‌کنند. آن‌ها را شکاف‌به‌شکاف ترجمه نکنید. جمله باید هنگامی که جای‌گیر عبارتی است که کاربر تایپ کرده، نه یک اسمِ مرتب، دستوری بماند.

یک باگِ هشداردهنده‌ی واقعی: الگوهای ژاپنی که را مستقیماً پس از {cap} می‌گذارند می‌توانند وقتی {cap} یک بندِ کامل است نادرست به گوش برسند. راه‌حل «سخت‌تر ترجمه کن» نیست؛ این است که الگو را بازساختاردهی کنید (برای مثال، یک اسم‌ساز اضافه کنید یا جای‌گیر را جابه‌جا کنید) تا هر ورودیِ دلخواهِ کاربر همچنان جا شود.

✅ با عامل خود امتحان کن — یک زبان اضافه کن

این تمرین همچنان دقیقاً به همان شیوه کار می‌کند. زبانی را که می‌توانید صحت‌سنجی کنید انتخاب کنید (یا از عامل بخواهید) و آن را سرتاسری هدایت کنید. نخست مشخصات را بنویسید:

دانمارکی (da) را اضافه کن. src/content/da.js را به‌عنوان یک بسته‌ی { meta, pools, ui } با همان کلیدهای انگلیسی بساز، با ترجمه‌ی هر ورودی (مخزن‌های محتوا هرکدام حدود ۲۵، همه‌ی رشته‌های UI). da را در BUNDLES در src/lockedin.js ثبت کن. --lang da و یک محلیِ da-* باید آن را انتخاب کنند. رشته‌های سرنویسِ کارت را در محدوده‌ی عرض نگه دار. npm test باید سبز بماند، و ناوردا‌ها + آزمون‌های تشخیصِ دانمارکی را بیفزا که آینه‌ی موجودِ بومی‌سازی‌شده باشند.

سپس حلقه‌ی فصل‌های ۳ تا ۴ را اجرا کنید:

  1. نخست برنامه. «پیش از نوشتن کد، فایل‌هایی که تغییر می‌دهی و اینکه چگونه برابریِ کلید با انگلیسی را نگه می‌داری به من بگو.»
  2. نخست آزمون‌ها. «آزمون‌های شکست‌خورده اضافه کن: تشخیصِ da، برابریِ کلید برای da، و یک ناوردای reflect/connect دانمارکی. هنوز بسته را نساز.»
  3. پیاده‌سازی. «حالا src/content/da.js را با ترجمه‌ی یک بسته‌ی موجود کلید‌به‌کلید بساز، ثبتش کن، و آزمون‌ها را سبز کن. برای تصادفی‌سازی فقط pick/shuffle
  4. دروازه + بازبینی. npm test، سپس lockedin --lang da post — و diff را بخوانید: آیا هر کلید ترجمه شد؟ آیا حاشیه‌های کارت هنوز هم‌تراز می‌شوند؟ آیا الگوهای دارای {cap} از بندهای خامِ کاربر جانِ سالم به در می‌برند؟

اگر یک زبانِ کامل زیادی بود، تمرین‌های گرم‌کردنِ کوچک‌تر:

  • «یک TAGLINE دیگر به هر ۳۳ بسته‌ی زبانی اضافه کن، با نگه‌داشتنِ برابریِ شمارش‌ها.»
  • «بررسی کن آیا cardFooterِ کانادا ≤ ۶۰ ستونِ مرئی است و توضیح بده علامت‌های ترکیبی چگونه اندازه‌گیری شدند.»
  • «آزمونی را نشانم بده که اگر یک کلیدِ ui را از ja.js حذف کنم شکست می‌خورد.»

به کجا برویم

  • src/content/es.js را مرور کنید — هنوز یک الگوی دوستانه برای یک بسته‌ی جدید است.
  • docs/HANDOFF.md → «Adding a language» را دوباره بخوانید.
  • از شوخی‌های چندزبانه در مرجع فرمان‌ها لذت ببرید.

آموزشِ کامل همین است. اکنون می‌توانید یک عامل هوش مصنوعی را هدایت کنید تا ویژگی‌ها را بسازد و آن‌ها را پشتِ یک دروازهٔ آزمون بومی‌سازی کند — به ۳۳ زبان و آماده‌ی بیشتر. موافقید؟ 👇

📘 LockedIn CLI wiki

Tutorial

Reference


Satire · Sátira · 風刺. Not affiliated with LinkedIn. GPL-3.0-or-later.

Clone this wiki locally