مواد پر جائیں
بلاگ پر واپس جائیں
TypeScript

غائب ترجمے کو رن ٹائم حیرت نہیں، کمپائل ایرر بنانا

شائع شدہ 27 اپریل، 20265 منٹ پڑھنے کا وقت

ہر ملٹی-لینگویج سائٹ بالآخر ایک ایسا صفحہ شپ کر دیتی ہے جہاں ترجمہ ہونا چاہیے تھا مگر خالی جگہ ہے۔ عام طور پر یہ ترجمے کی غلطی نہیں ہوتی — یہ ایک ایسی کلید ہوتی ہے جو بنیادی زبان کی فائل میں شامل کی گئی مگر باقی تین میں کبھی کاپی نہیں ہوئی، اور ٹول چین میں کسی نے اسے تب تک نہیں دیکھا جب تک ایک صارف نے نہ دیکھ لیا۔

معمول کے حل، اور ہم نے انہیں کیوں چھوڑا

عام حل ہیں ایک linter اسکرپٹ جو JSON فائلوں کے درمیان کلیدوں کے سیٹ کا فرق نکالتا ہے (CI میں چلتا ہے، ایک کمٹ دیر سے انحراف پکڑتا ہے)، یا ایک رن ٹائم فال بیک جو غائب ترجمے پر خاموشی سے انگریزی سٹرنگ دکھا دیتا ہے (بگ کو ٹھیک کرنے کے بجائے چھپا دیتا ہے، اور "عارضی طور پر" غائب سٹرنگ اکثر غائب ہی رہتی ہے)۔ دونوں ڈکشنری کی ساخت کو ایسا ڈیٹا سمجھتے ہیں جسے چیک کرنا ہے، ایسی قسم نہیں جسے نافذ کرنا ہے۔

ہم نے اس کے بجائے کیا کیا

ڈکشنریاں سادہ TypeScript آبجیکٹس ہیں، ہر زبان کے لیے ایک، اور انگریزی فائل معیاری ہے:

const en = {
  hero: { headline: "...", body: "..." },
  nav: { items: ["Home", "About", "Contact"] },
} as const;

ہر دوسری زبان satisfies Dictionary کے ساتھ لکھی جاتی ہے، جہاں Dictionary خود انگریزی آبجیکٹ سے ایک ری کرسیو mapped type کے ذریعے اخذ کی جاتی ہے:

type Widen<T> = T extends string ? string
  : T extends number ? number
  : T extends object ? { readonly [K in keyof T]: Widen<T[K]> }
  : T;

export type Dictionary = Widen<typeof en>;

Widen انگریزی ڈکشنری کی ساخت میں گھومتا ہے اور ہر لفظی سٹرنگ کو عمومی string قسم سے بدل دیتا ہے — اس لیے ترجمہ بالکل مختلف الفاظ استعمال کرنے میں آزاد ہے، جبکہ جس آبجیکٹ میں وہ رہتا ہے اس کی ساخت انگریزی سے بالکل ملتی ہوئی، کلید بہ کلید، نیسٹنگ سطح بہ سطح مقفل رہتی ہے۔

ٹیوپل کا معاملہ کیوں اہم ہے

Mapped type اریوں پر بھی اسی طرح چلتی ہے جیسے آبجیکٹس پر — مطلب یہ صرف کلیدوں کے نام نہیں، لمبائی بھی محفوظ رکھتی ہے۔ اوپر والا nav.items انگریزی فائل میں سٹرنگز کا ٣-ٹیوپل ہے، اس لیے Dictionary["nav"]["items"] بھی ایک ٣-ٹیوپل ہے — string[] نہیں۔ اگر کسی ترجمہ شدہ فائل میں دو یا چار آئٹمز درج ہوں، تو TypeScript عین اسی کال سائٹ پر Source has 2 element(s) but target requires 3 رپورٹ کرتا ہے — next build کے دوران، کچھ بھی شپ ہونے سے پہلے۔ ہم اس پر مسلسل انحصار کرتے ہیں: نیویگیشن مینوز، فیچر چیک لسٹس، اور شماریاتی قطاریں سب مقررہ لمبائی کے ٹیوپلز کے طور پر لکھی جاتی ہیں، خاص طور پر تاکہ ایک مترجم غلطی سے کوئی اندراج نہ چھوڑے یا دہرائے بغیر بلڈ کے پکڑے۔

سمجھوتہ

یہ کمپائل ٹائم یقین خریدتا ہے، اس قیمت پر کہ ہر لوکیل فائل کو ایک مکمل، اچھی طرح ٹائپ شدہ TypeScript ماڈیول ہونا ضروری ہے، نہ کہ ایک آسان JSON فائل جسے کوئی غیر انجینئر ہاتھ سے ترمیم کر سکے۔ چار زبانوں کی ایک سائٹ کے لیے جسے وہی ٹیم برقرار رکھتی ہے جو کوڈ بیس کی مالک ہے، یہ سمجھوتہ قابلِ قدر تھا۔ ایک بہت بڑے لوکلائزیشن آپریشن کے لیے جہاں بیرونی مترجمین براہ راست سٹرنگز میں ترمیم کرتے ہوں، ایک اسکیما تصدیق شدہ JSON پائپ لائن شاید بہتر انتخاب ہوتا — بات یہ نہیں کہ یہ مخصوص تکنیک ہمیشہ درست ہے، بلکہ یہ کہ ڈکشنری کی ساخت بالکل اسی قسم کی مستقل مثال ہے جسے ٹائپ سسٹم برقرار رکھنے میں اچھا ہوتا ہے، اور یہ پوچھنا قابلِ قدر ہے کہ کیا آپ کا نظام فی الحال ایسا کر رہا ہے۔