সম্প্রতি মুক্তি পাওয়া একটি Cache-Control analyzer-এর ইংরেজি সংস্করণে জাপানি টেক্সট দেখা গিয়েছিল—এর স্ট্যাটাস "Fresh"-এর পরিবর্তে "新鮮" দেখাচ্ছিল। এই ভুলের মূলে ছিল একটি শেয়ারড লজিক (shared logic), যা হার্ড-কোডেড জাপানি স্ট্রিং রিটার্ন করছিল, যদিও পেজটি শুধুমাত্র ইংরেজি লেবেল সরবরাহ করছিল।

ডেভেলপার হালকা ওজনের (lightweight) ব্রাউজার টুলের একটি সিরিজ তৈরি করেন, যার প্রতিটি টুলের একটি ইংরেজি পেজ এবং একটি জাপানি পেজ রয়েছে যা একই পার্সিং ফাংশন এবং কোর লজিক পুনরায় ব্যবহার করে। শুধুমাত্র দৃশ্যমান শব্দগুলো আলাদা হওয়া উচিত ছিল। যখন Cache-Control analyzer-টি রিলিজ করা হলো, ইংরেজি ইন্টারফেসটি সঠিক লেবেল প্রদর্শন করছিল, কিন্তু এটি যে ভ্যালুগুলো রেন্ডার করছিল সেগুলো লজিক লেয়ার থেকে আসছিল, যেখানে তখনও জাপানি লিটারেল (literals) ছিল। কনসোলে কোনো এরর দেখা দেয়নি; পেজটি দেখতে স্বাভাবিক ছিল, তবুও ইংরেজিভাষী ব্যবহারকারীদের কাছে উপস্থাপিত তথ্যটি ভুল ছিল।

কেন শেয়ারড লজিক অনুবাদের ক্ষেত্রে সমস্যা তৈরি করতে পারে

এই বাগটি একটি ডিজাইনের পছন্দের কারণে তৈরি হয়েছিল: যা প্রদর্শন করতে হবে তা নির্ধারণকারী কোর ফাংশনটি জাপানি ভাষায় লিটারেল স্ট্রিং রিটার্ন করছিল। পেজ লেয়ার, যা চারপাশের ইংরেজি টেক্সটের জন্য দায়ী, সেই ভ্যালুগুলো পরিবর্তন করার সুযোগই পায়নি। যেহেতু লজিক এবং UI স্পষ্টভাবে আলাদা ছিল, তাই টেস্টিংয়ের সময় সমস্যাটি ধরা পড়েনি—প্রযুক্তিগতভাবে সবকিছু "কাজ করছিল", যদিও ব্যবহারকারীর জন্য প্রদর্শিত ভাষাটি ভুল ছিল।

এর অসুবিধা হলো, শেয়ারড মডিউলের ভেতরে ব্যবহৃত ভাষাটি সেই মডিউল ব্যবহারকারী প্রতিটি ফ্রন্ট-এন্ডের জন্য ডিফল্ট হয়ে যায়। যদি অন্য কোনো ভাষার প্রয়োজন হয়, তবে এই ডিফল্ট ভাষাটি একটি লুকানো বাগ হিসেবে কাজ করে।

সমাধান: কী (keys), প্যাক (packs) এবং একটি সেফটি নেট

লেখক বিষয়গুলোকে আলাদা করার জন্য আর্কিটেকচারটি পুনরায় লিখলেন:

  • Message packs এখন প্রতিটি ভাষার জন্য সমস্ত মানুষের পাঠযোগ্য (human-readable) স্ট্রিং ধারণ করে।
  • Shared logic শুধুমাত্র সিম্বলিক কী (symbolic keys) রিটার্ন করে, কখনোই সরাসরি টেক্সট নয়।
  • Pages কী-এর ওপর ভিত্তি করে সংশ্লিষ্ট প্যাক থেকে সঠিক শব্দটি খুঁজে নেয়।

যখন কোনো মেসেজে একটি সংখ্যা অন্তর্ভুক্ত করা প্রয়োজন হয়, তখন নতুন কোডটি টেমপ্লেট স্ট্রিংয়ের পরিবর্তে একটি ছোট ফাংশন ব্যবহার করে। এটি প্রতিটি ভাষাকে সিদ্ধান্ত নিতে দেয় যে সংখ্যাটি কোথায় বসবে, যা শব্দের ক্রমের পার্থক্যগুলো সামঞ্জস্য করতে সাহায্য করে।

একটি সাধারণ স্ট্যাটিক-অ্যানালাইসিস (static-analysis) ধাপও যোগ করা হয়েছে: বিল্ড প্রসেসটি শেয়ারড ফাইলগুলোতে জাপানি ক্যারেক্টার আছে কি না তা স্ক্যান করে। যদি কোনো জাপানি অক্ষর পাওয়া যায়, তবে ডেভেলপারকে সাথে সাথে সতর্ক করা হয়, যা হার্ড-কোডেড বিদেশি টেক্সট পুনরায় ফিরে আসা রোধ করে।

এই অভিজ্ঞতা লেখককে যা শিখিয়েছে

  1. অনুবাদ একটি রিভিউ পাস হিসেবে কাজ করে। ইংরেজি মেসেজ লেখার সময় লেখক লক্ষ্য করেছিলেন যে কিছু জাপানি সমার্থক শব্দ অস্পষ্ট ছিল। অনুবাদ করার ফলে উভয় ভাষাতেই আরও স্পষ্ট বাক্য গঠন করা সম্ভব হয়েছে।
  2. যেসব শেয়ারড ফাংশন স্ট্রিং রিটার্ন করে, তা সবার জন্য একটি নির্দিষ্ট ভাষাকে লক করে দেয়। যদি একটি ফাংশন ভাষা নির্ধারণ করে ফেলে, তবে অন্য কোনো ভাষা প্রত্যাশা করা ব্যবহারকারী বা সিস্টেম সেই ভুলটিই উত্তরাধিকারসূত্রে পায়। এই বাগটি কোনো UI গ্লিচ নয়; এটি একটি লজিক ত্রুটি।

বহুভাষিক টুল রক্ষণাবেক্ষণকারীদের জন্য সুপারিশমালা

  • কোর ফাংশন থেকে স্ট্রিং নয়, বরং কী (keys) রিটার্ন করুন। লোকালাইজেশনের কাজ UI লেয়ারকে করতে দিন।
  • অথবা কাঙ্ক্ষিত স্ট্রিংগুলোকে প্যারামিটার হিসেবে ফাংশনে পাস করুন। এটি লজিককে ভাষার প্রভাবমুক্ত রাখে।
  • শেয়ারড মডিউলগুলোতে হার্ড-কোডেড মাতৃভাষার টেক্সট আছে কি না তা অডিট করুন। নন-ASCII ক্যারেক্টারের জন্য একটি দ্রুত অনুসন্ধান লুকানো সমস্যাগুলো সামনে আনতে পারে।
  • শেয়ারড কোডে বিদেশি ক্যারেক্টার আছে কি না তা দেখার জন্য বিল্ড-টাইম চেক যোগ করুন। রিলিজের পরের বিভ্রান্তির চেয়ে আগাম শনাক্তকরণ অনেক ভালো।

পরবর্তীতে যা খেয়াল রাখতে হবে

মূল শিক্ষা (Takeaway): যদি আপনার প্রজেক্টের বিভিন্ন ভাষার সংস্করণের মধ্যে কোড শেয়ার করা হয়, তবে নিশ্চিত করুন যে শেয়ারড অংশটি যেন কখনোই শব্দের ধরন নির্ধারণ না করে। প্রতিটি পেজকে তার নিজস্ব শব্দ সরবরাহ করতে দিন, তাহলে আপনি একটি ইংরেজি পেজ ভুলবশত জাপানি ভাষায় কথা বলার মতো বিব্রতকর পরিস্থিতি এড়াতে পারবেন।