চ্যাট-নির্মিত অ্যাপের জন্য আন্তর্জাতিকীকরণ আর্কিটেকচার: স্থিতিশীল স্ট্রিং কী, বহুবচন নিয়ম এবং ওয়েব ও মোবাইল উভয়েই একরকম থাকা অনুবাদ কর্মপ্রবাহ নির্ধারণ করুন।

প্রথম যে জিনিস ভাঙে তা কোড নয়। তা হলো শব্দগুলো।
চ্যাট-নির্মিত অ্যাপগুলো প্রায়ই দ্রুত প্রোটোটাইপ হিসেবে শুরু হয়: আপনি টাইপ করেন “Add a button that says Save”, UI দেখা যায়, এবং আপনি আগানো যান। কয়েক সপ্তাহ পরে, আপনি স্প্যানিশ এবং জার্মান চান, এবং খুঁজে পান যে সেই “অস্থায়ী” লেবেলগুলো স্ক্রিন, কম্পোনেন্ট, ইমেইল এবং এরর মেসেজ জুড়ে ছড়িয়ে আছে।
কপি পরিবর্তন কোড পরিবর্তনের চেয়ে বেশি ঘনঘন ঘটে। প্রোডাক্ট নাম বদলায়, আইনি টেক্সট আপডেট হয়, অনবোর্ডিং পুনর্লিখিত হয়, এবং সাপোর্ট পরিষ্কার এরর মেসেজ চায়। যদি টেক্সট সরাসরি UI কোডের ভেতর থাকে, প্রতিটি ছোট শব্দের পরিবর্তনই একটি ঝুঁকিপূর্ণ রিলিজে পরিণত হয়, এবং আপনি এমন জায়গাগুলো মিস করবেন যেখানে একই ধারণা আলাদাভাবে বলা হয়েছে।
নিচে কিছু প্রাথমিক লক্ষণ আছে যা ইঙ্গিত করে যে আপনি অনুবাদের দেনা তৈরি করছেন:
একটি বাস্তব উদাহরণ: আপনি Koder.ai-তে একটি সাধারণ CRM তৈরি করেন। ওয়েব অ্যাপে লেখা আছে “Deal stage”, মোবাইল অ্যাপে লেখা আছে “Pipeline step”, এবং একটি এরর টোস্ট বলে “Invalid status”。 এমনকি তিনই অনুবাদ করা থাকলেও, ব্যবহারকারীরা অ্যাপকে অপ্রতিসংগত মনে করবে কারণ ধারণাগুলো মিলছে না।
“সঙ্গতিপূর্ণ” মানে সব জায়গায় একই অক্ষর নয়। এর মানে হলো:
একবার আপনি টেক্সটকে সজ্জা নয় বরং প্রোডাক্ট ডেটা হিসেবে ধরলে, ভাষা যোগ করা আর হাহাকার হয়ে উঠবে না বরং বিল্ডিং-এর এক নিয়মিত অংশ হয়ে যাবে।
Internationalization (i18n) হলো সেই কাজ যাতে একটি অ্যাপ বহু ভাষা সমর্থন করতে পারে পুনঃলিখন ছাড়া। Localization (l10n) হলো নির্দিষ্ট ভাষা ও অঞ্চলের জন্য বাস্তব কন্টেন্ট—যেমন French (Canada) যেখানে সঠিক শব্দ, তারিখ ফরম্যাট এবং টোন থাকে।
একটি সহজ লক্ষ্য: প্রতিটি ব্যবহারকারী-উন্মুখ টেক্সট একটি স্থিতিশীল কী দ্বারা নির্বাচিত হোক, UI কোডে সরাসরি টাইপ করা না হয়। যদি আপনি একটি বাক্য পরিবর্তন করতে পারেন React কম্পোনেন্ট বা Flutter উইজেট খুলে না করেই, আপনি সঠিক পথে আছেন। এটা চ্যাট-নির্মিত অ্যাপগুলোর জন্য i18n আর্কিটেকচারের 핵। সেখানে চ্যাট সেশন চলাকালে সহজে হার্ড-কোডেড কপি পাঠিয়ে দেওয়া হয়ে যায়।
ব্যবহারকারী-উন্মুখ টেক্সট অনেক বেশি বিস্তৃত যা বেশিরভাগ টিম আশা করে না। এর মধ্যে আছে বাটন, লেবেল, ভ্যালিডেশন এরর, খালি স্টেট, অনবোর্ডিং টিপস, পুশ নোটিফিকেশন, ইমেইল, PDF এক্সপোর্ট এবং যে কোনো মেসেজ যা ব্যবহারকারী দেখতে বা শুনতে পারে। সাধারণত এর মধ্যে অন্তর্ভুক্ত নয়: ইনটার্নাল লগ, ডাটাবেস কলাম নাম, অ্যানালিটিক্স ইভেন্ট আইডি, ফিচার ফ্ল্যাগ বা অ্যাডমিন-শুধুমাত্র ডিবাগ আউটপुट।
অনুবাদ কোথায় থাকা উচিত? বাস্তবে, এটি প্রায়ই উভয়—ফ্রন্টেন্ড এবং ব্যাকএন্ড—এ থাকে, একটি পরিষ্কার সীমানা সহ:
ভুল যা এড়াতে হবে—দায়িত্ব মিশ্রিত করা। যদি ব্যাকএন্ড UI এররগুলোর জন্য সম্পূর্ণ লেখা ইংরেজি বাক্য ফেরত দেয়, তাহলে ফ্রন্টএন্ড সেগুলোকে সুন্দরভাবে লোকালাইজ করতে পারবে না। একটি ভালো প্যাটার্ন হলো: ব্যাকএন্ড একটি এরর কোড ফেরত দেয় (এবং সম্ভব হলে নিরাপদ প্যারামিটার), এবং ক্লায়েন্ট সেই কোডকে লোকালাইজড মেসেজে ম্যাপ করে।
কপি মালিকানা একটি প্রোডাক্ট সিদ্ধান্ত, প্রযুক্তিগত বিস্তারিত নয়। শুরুতেই ঠিক করুন কে শব্দগুলো পরিবর্তন করতে এবং টোন অনুমোদন করতে পারবে।
যদি প্রোডাক্ট কপি মালিক থাকে, অনুবাদকে কন্টেন্ট হিসেবে বিবেচনা করুন: ভার্সন করুন, রিভিউ দিন এবং প্রোডাক্টকে পরিবর্তনের অনুরোধ করার নিরাপদ উপায় দিন। যদি ইঞ্জিনিয়ারিং কপি মালিক হয়, নীতি ঠিক করুন যে কোনো নতুন UI স্ট্রিং শিপ করার আগে তার সাথে একটি কী এবং ডিফল্ট অনুবাদ থাকতে হবে।
উদাহরণ: যদি আপনার সাইনআপ ফ্লো তিনটি আলাদা স্ক্রিনে “Create account” বলে, একটাই কী ব্যবহার করুন। এটা অর্থ সঙ্গত রাখে, অনুবাদককে দ্রুত করে এবং ছোট শব্দ পরিবর্তনকে পরবর্তী সময়ে একাধিক স্ক্রিন ক্লিনআপে পরিণত হওয়া থেকে রোধ করে।
কীগুলো হলো আপনার UI এবং অনুবাদের মধ্যে চুক্তি। যদি সেই চুক্তি বারবার বদলে যায়, আপনি মিসিং টেক্সট, তাড়াহুড়ো ফিক্স, এবং ওয়েব ও মোবাইলের মধ্যে অসমঞ্জস্য পাবেন। চ্যাট-নির্মিত অ্যাপগুলোর জন্য ভালো i18n আর্কিটেকচার শুরু হয় এক নিয়ম দিয়ে: কীগুলো অর্থ বর্ণনা করুক, বর্তমান ইংরেজি বাক্য নয়।
স্থিতিশীল আইডি ব্যবহার করুন কী হিসেবে (যেমন billing.invoice.payNow) পুরো বাক্য হিসেবে (যেমন "Pay now") এর বদলে। বাক্য-কী তখনই ভেঙে যায় যখন কেউ শব্দ পরিবর্তন করে, বিরামচিহ্ন যোগ করে, বা কেস বদলে দেয়।
একটি ব্যবহারিক প্যাটার্ন যা রিডেবল এবং স্থিতিশীল থাকে: screen (অথবা domain) + component + intent। বোরিং এবং পূর্বানুমানযোগ্য রাখুন।
উদাহরণ:
auth.login.titleauth.login.emailLabelbilling.checkout.payButtonnav.settingserrors.network.offlineকী পুনরায় ব্যবহার করবেন না করলে কবে করবেন—এমন সিদ্ধান্ত নিন: “প্রতিটি জায়গায় অর্থ কি পুরোপুরি একই?” সাধারণ ক্রিয়াগুলোর জন্য কী পুনরায় ব্যবহার করুন, কিন্তু প্রাসঙ্গিকতা বদলে গেলে কী আলাদা করে ফেলুন। উদাহরণস্বরূপ, প্রোফাইল স্ক্রীনের “Save” হয়তো সরল অ্যাকশন, যেখানে একটি জটিল এডিটরে “Save” কিছু ভাষায় ভিন্ন টোন প্রয়োজন হতে পারে—তবে তখন আলাদা কী ব্যবহার করা উচিত।
শেয়ার করা UI টেক্সটকে নিবেদিত namespace-এ রাখুন যাতে স্ক্রিন জুড়ে ডুপ্লিকেশন না হয়। সাধারণভাবে কাজ করে এমন বকেটগুলো:
common.actions.* (save, cancel, delete)common.status.* (loading, success)common.fields.* (search, password)errors.* (validation, network)nav.* (tabs, menu items)যখন অর্থ একই থাকে কিন্তু শব্দ পরিবর্তিত হয়, কী রাখুন এবং শুধুমাত্র অনুবাদ আপডেট করুন। এটিই স্থিতিশীল আইডির পুরো উদ্দেশ্য। যদি অর্থ বদলে যায় (এমনকি সূক্ষ্মভাবে), নতুন কী তৈরি করুন এবং পুরনোটি তখনও ব্যবহার না হওয়া নিশ্চিত হওয়া পর্যন্ত রাখুন। এতে এমন “নীরব” অসঙ্গতি এড়ায় যেখানে পুরনো অনুবাদ আছে কিন্তু এখন ভুল।
Koder.ai-স্টাইল ফ্লো থেকে একটি ছোট উদাহরণ: আপনার চ্যাট একই সাথে React ওয়েব অ্যাপ এবং Flutter মোবাইল অ্যাপ উত্পন্ন করে। যদি উভয়ই common.actions.save ব্যবহার করে, আপনি সারাক্ষণ সঙ্গতিপূর্ণ অনুবাদ পাবেন। কিন্তু যদি ওয়েব profile.save ব্যবহার করে এবং মোবাইল account.saveButton ব্যবহার করে, সময়ের সাথে আপনি বিচ্যুত হবেন, যদিও ইংরেজি আজ একই দেখাচ্ছে।
আপনার সোর্স ভাষা (আসলে প্রায়শই ইংরেজি) কে একক সত্যের উৎস হিসেবে বিবেচনা করুন। এক জায়গায় রাখুন, কোডের মতো রিভিউ করুন, এবং স্ট্রিংগুলোকে র্যান্ডম কম্পোনেন্টে “অপেক্ষার জন্য” ঢুকতে দেবেন না। এটা হার্ড-কোডেড UI কপি এড়ানোর সবচেয়ে দ্রুত উপায়।
একটি সহজ নিয়ম সাহায্য করে: অ্যাপ কেবল i18n সিস্টেম থেকে টেক্সট দেখাতে পারবে। কেউ যদি নতুন কপি প্রয়োজন মনে করে, আগে কী ও ডিফল্ট মেসেজ যোগ করে তারপর UI-তে সেই কী ব্যবহার করবে। এটি আপনার চ্যাট-নির্মিত অ্যাপগুলোর জন্য i18n আর্কিটেকচারকে স্থিতিশীল রাখে—যখন ফিচারগুলি সরায়।
যদি আপনি ওয়েব এবং মোবাইল উভয়ই শিপ করেন, একটি শেয়ার্ড কী ক্যাটালগ চান, প্লাস ফিচার টিমগুলোর কাজ করার স্থান যাতে তারা একে অপরের ওপর পা না ফেলে। একটি ব্যবহারিক লেআউট:
প্ল্যাটফর্ম জোড়ে কী একই রাখুন, যদিও ইমপ্লিমেন্টেশন আলাদা (React ওয়েবে, Flutter মোবাইলে)। যদি আপনি Koder.ai-এর মতো প্ল্যাটফর্ম ব্যবহার করে চ্যাট থেকে উভয় অ্যাপ জেনারেট করেন, সোর্স কোড এক্সপোর্ট করা সহজতর হয় যখন উভয় প্রজেক্ট একই কী নাম এবং একই মেসেজ ফরম্যাট নির্দেশ করে।
অনুবাদ সময়ের সাথে বদলায়। পরিবর্তনগুলোকে প্রোডাক্ট পরিবর্তনের মতো ট্রিট করুন: ছোট, রিভিউ করা এবং ট্র্যাকেবল। একটি ভালো রিভিউ অর্থ ও পুনরায় ব্যবহারের ওপর মনোযোগ দেয়, কেবল বানান নয়।
কীগুলো ভিন্ন টিমের মধ্যে ভেসে যেতে না দেওয়ার জন্য, কীগুলো ফিচারভিত্তিক (billing., auth.) করে মালিকানাধীন করুন, এবং কেবল শব্দ পরিবর্তন হওয়ায় কী নাম বদলাবেন না। কী হলো আইডেন্টিফায়ার, কপি নয়।
বহুবচন নিয়ম ভাষাভেদে বদলে যায়, তাই ইংরেজির সহজ প্যাটার্ন (1 বনাম সবকিছু) দ্রুত ভাঙে। কিছু ভাষায় 0, 1, 2-4 আলাদা ফর্ম থাকে, এবং অন্যগুলোর ক্ষেত্রে পুরো বাক্য বদলে যায়, শুধুমাত্র নাম নয়। যদি আপনি UI-তে if-else দিয়ে বহুবচন লজিক বেক করেন, তখন আপনি কপি ডুপ্লিকেট করবেন এবং এজ-কেস মিস করবেন।
একটি নিরাপদ উপায় হলো প্রতিটি ধারণার জন্য একটি নমনীয় মেসেজ রাখা এবং i18n স্তরকে সঠিক ফর্ম বেছে নিতে দেওয়া। ICU-স্টাইল মেসেজগুলো এই কাজে করা। এগুলো গ্রাম্যাটিক সিদ্ধান্তগুলো অনুবাদে রাখে, কোডে না।
নিচে একটি ছোট উদাহরণ যা মানুষ প্রায় ভুলে যায়ঃ
itemsCount = "{count, plural, =0 {No items} one {# item} other {# items}}"
উই একক কী 0, 1 এবং অন্যান্য সব কভার করে। অনুবাদকরা তাদের ভাষার সঠিক বহুবচন ফর্ম দিয়ে এটি প্রতিস্থাপন করতে পারবেন কোড স্পর্শ না করে।
যখন লিঙ্গ বা ভূমিকা-ভিত্তিক লেখা প্রয়োজন হয়, আলাদা কী তৈরি করা এড়ান যেমন welcome_male এবং welcome_female যদি প্রোডাক্ট সত্যিই তা চায় না। select ব্যবহার করুন যাতে বাক্য এক ইউনিট থাকে:
welcomeUser = "{gender, select, female {Welcome, Ms. {name}} male {Welcome, Mr. {name}} other {Welcome, {name}}}"
ব্যাকরণগত কেস নিয়ে নিজেকে জটিল পরিস্থিতিতে ঠেলে দেওয়া থেকে বাঁচতে, বাক্যগুলো যতটা সম্ভব পূর্ণ রাখুন। এমন ফ্র্যাগমেন্ট একত্রিত করে তৈরি করা যেমন "{count} " + t('items') ব্যবহার করা এড়ান, কারণ অনেক ভাষায় শব্দের ক্রম পরিবর্তন করা যাবে না। একটি মেসেজে সংখ্যা, নাম এবং চারপাশের শব্দগুলো মিলিয়ে রাখুন।
চ্যাট-নির্মিত অ্যাপগুলোতে (Koder.ai প্রজেক্টসহ) একটি সহজ নিয়ম কাজ করে: যদি একটি বাক্যে সংখ্যা, কোনো ব্যক্তি, অথবা একটি স্ট্যাটাস থাকে, প্রথম দিন থেকেই এটিকে ICU করুন। এটা সামান্য অতিরিক্ত খরচ করে কিন্তু পরে অনেক অনুবাদ দেনা বাঁচায়।
যদি আপনার React ওয়েব অ্যাপ ও Flutter মোবাইল অ্যাপ আলাদা অনুবাদ ফাইল রাখে, তারা বিচ্ছিন্ন হবে। একই বাটন ভিন্ন শব্দ পাবে, একটি কী ওয়েবে এক অর্থ নেবে এবং মোবাইলের আরেকটি, এবং সাপোর্ট টিকেটে লেখা থাকবে “অ্যাপ বলছে X কিন্তু ওয়েবসাইট বলছে Y”।
সহজতম সমাধানই সবচেয়ে গুরুত্বপূর্ণ: একটি উৎস ফরম্যাট বেছে নিন এবং সেটাকে কোডের মতো ট্রিট করুন। বেশিরভাগ টিমের জন্য তা মানে একটি শেয়ারড সেট লোকেল ফাইল (উদাহরণ: JSON ব্যবহার করে ICU-স্টাইল মেসেজ) যা ওয়েব ও মোবাইল দুটোই ব্যবহার করে। যখন আপনি চ্যাট ও জেনারেটর ব্যবহার করে অ্যাপ তৈরি করেন, এটা আরও গুরুত্বপূর্ণ, কারণ সহজে দুটি জায়গায় নতুন টেক্সট তৈরি হয়ে যেতে পারে।
একটি ব্যবহারিক সেটআপ হলো একটি ছোট “i18n প্যাকেজ” বা ফোল্ডার যাতে থাকে:
React এবং Flutter তারপর কেবল কনজিউমার হয়। তাদের নতুন কী লোকালি তৈরি করা উচিত নয়। Koder.ai-স্টাইল ওয়ার্কফ্লোতে (React ওয়েব, Flutter মোবাইল) আপনি উভয় ক্লায়েন্ট একই কী সেট থেকে জেনারেট করতে পারেন এবং পরিবর্তনগুলো অন্যান্য কোড পরিবর্তনের মতো রিভিউ করে রাখতে পারেন।
ব্যাকএন্ড সমন্বয় একই গল্পের অংশ। এরর, নোটিফিকেশন এবং ইমেইলগুলো Go-তে হাতে-লিখিত ইংরেজি স্ট্রিং হয়ে থাকা উচিত নয়। বরং স্টেবল এরর কোড ফেরত দিন (যেমন auth.invalid_password) এবং নিরাপদ প্যারামিটার সহ। তারপর ক্লায়েন্টগুলো কোডকে অনুবাদিত টেক্সটে ম্যাপ করে। সার্ভার-সাইড ইমেইলের জন্য সার্ভার একই কী এবং লোকেল ফাইল ব্যবহার করে টেমপ্লেট রেন্ডার করতে পারে।
একটি ছোট রুলবুক তৈরি করুন এবং কোড রিভিউতে সেটা প্রয়োগ করুন:
ডুপ্লিকেট কী ও বিভিন্ন অর্থ ঠেকাতে অনুবাদক এবং ভবিষ্যৎ আপনার জন্য “description” ফিল্ড (অথবা একটি কমেন্ট ফাইল) যোগ করুন। উদাহরণ: billing.trial_days_left বর্ণনা করে দিন এটি একটি ব্যানারে দেখাচ্ছে নাকি ইমেইলে—একটি বাক্য প্রায়ই “ক্লোজ এনাফ” পুনঃব্যবহার রোধ করে যা পরে দেনা সৃষ্টি করে।
এই সঙ্গতিটাই চ্যাট-নির্মিত অ্যাপগুলোর জন্য একটি আন্তর্জাতিকীকরণ আর্কিটেকচারের কাঁধ: একটি শেয়ার্ড শব্দভাণ্ডার, বহু সারফেস, এবং পরবর্তী ভাষা শিপ করার সময় কোনো বিস্ময় নেই।
চ্যাট-নির্মিত অ্যাপগুলোর জন্য একটি ভালো i18n আর্কিটেকচার সরলভাবে শুরু করে: একটি কী সেট, কপি’র জন্য একটি উৎস-স্থান, এবং একই নিয়ম ওয়েব ও মোবাইলে। যদি আপনি দ্রুত বিল্ড করেন (উদাহরণস্বরূপ Koder.ai দিয়ে), এই কাঠামো দ্রুততা ধরে রাখে কিন্তু অনুবাদ দেনা তৈরি হতে দেয় না।
আপনার লোকেলগুলো আগেভাগেই নির্ধারণ করুন এবং মিসিং অনুবাদ হলে কী হবে তা ঠিক করুন। সাধারণ পছন্দ হলো: ব্যবহারকারীর পছন্দভাষা থাকলে তা দেখান, নতুবা ইংরেজিতে ফেলব্যাক করুন, এবং মিসিং কী লগ করুন যাতে পরের রিলিজের আগে ঠিক করা যায়।
তারপর এটি স্থাপন করুন:
billing.plan_name.pro বা auth.error.invalid_password. একই কী সব জায়গায় রাখুন।t("key") ব্যবহার করুন। Flutter-এ একটি লোকালাইজেশন ওয়্রাপার ব্যবহার করুন এবং উইজেটে একই কী-ভিত্তিক লগিক কল করুন। লক্ষ্য হলো একই কী ব্যবহার, লাইব্রেরি হওয়া না।{count, plural, one {# file} other {# files}} এবং Hello, {name}। এতে স্ক্রিন জুড়ে if (count === 1) জাতীয় হ্যাক ছড়ায় না।শেষে, একটি ভাষা টেস্ট করুন যার শব্দ দীর্ঘ হয় (জার্মান ক্লাসিক) এবং আরেকটি যেখানে বিরামচিহ্ন ভিন্ন। এটি দ্রুত বাটন ওভারফ্লো, শিরোনামের র্যাপ এবং লেআউট অনুমানবিহীনতা উন্মোচিত করবে।
যদি আপনি অনুবাদগুলো শেয়ার্ড ফোল্ডারে রাখেন (অথবা জেনারেটেড প্যাকেজ) এবং কপি পরিবর্তনগুলোকে কোড পরিবর্তনের মতো ট্রিট করেন, আপনার ওয়েব ও মোবাইল অ্যাপগুলো দ্রুতই সঙ্গতিপূর্ণ থাকে এমনকি যখন ফিচারগুলো চ্যাটে দ্রুত তৈরি করা হয়।
অনুবাদিত UI স্ট্রিং কেবল সমস্যার অর্ধেক। বেশিরভাগ অ্যাপ এছাড়াও পরিবর্তনশীল মান দেখায় যেমন তারিখ, দাম, গণনা, এবং নাম। যদি আপনি এই মানগুলোকে সাধারণ টেক্সট মেনে নেন, আপনি অদ্ভুত ফরম্যাট, ভুল টাইমজোন, এবং এমন বাক্য পাবেন যা অনেক ভাষায় “অদ্ভুত” শোনায়।
শুরুতেই সংখ্য, মুদ্রা, ও তারিখগুলো লোকেল নিয়ম ব্যবহার করে ফরম্যাট করুন, কাস্টম কোড দিয়ে নয়। ফ্রান্সের একজন ব্যবহারকারী আশা করে “1 234,50 €”, আর মার্কিন ব্যবহারকারী আশা করে “$1,234.50”。একই নিয়ম তারিখেও প্রযোজ্য: “03/04/2026” অস্পষ্ট হতে পারে, কিন্তু লোকেল ফরম্যাটিং স্পষ্ট করে।
টাইমজোন পরবর্তী ফাঁদ। সার্ভার সাধারনত timestamp গুলো neutral ফরমে (সাধারণত UTC) স্টোর করে, কিন্তু ব্যবহারকারীরা তাদের নিজের জোনে সময় দেখা আশা করে। উদাহরণ: একটি অর্ডার 23:30 UTC-তে তৈরি হলে টোকিওর কারো জন্য সেটা “আগামীকাল” হতে পারে। প্রতিটি স্ক্রিনে একটি নীতি সিদ্ধান্ত নিন: ব্যক্তিগত ইভেন্টে ব্যবহারকারীর লোকাল সময় দেখান, এবং স্টোর পিকআপ উইন্ডোর মতো ব্যবসায়িক টাইম জোনে ফিক্সড সময় দেখান (এবং স্পষ্ট লেবেল দিন)।
অনুবাদকৃত ফ্র্যাগমেন্ট গেঁথে বাক্য তৈরি করা এড়ান। এটা ব্যাকরণ ভেঙে দেয় কারণ শব্দের ক্রম ভাষাভেদে বদলে যায়। এর বদলে:
"{count} " + t("items") + " " + t("in_cart")
এরকম নয়—একটি মেসেজ ব্যবহার করুন প্লেসহোল্ডারসহ, যেমন: "{count} items in your cart"। অনুবাদক তখন শব্দগুলো সঠিকভাবে বিন্যস্ত করতে পারবেন।
RTL কেবল টেক্সট দিক নয়। লেআউট ফ্লো উল্টে যায়, কিছু আইকন মিরর করতে হয় (যেমন ব্যাক অ্যারো), এবং মিশ্র কনটেন্ট (আরবী সঙ্গে ইংরেজি প্রোডাক্ট কোড) অপ্রত্যাশিত অর্ডারে রেন্ডার হতে পারে। আসল স্ক্রিনগুলো টেস্ট করুন, শুধু একটি লেবেল নয়, এবং নিশ্চিত করুন আপনার UI কম্পোনেন্টগুলো ডিরেকশন পরিবর্তন সমর্থন করে।
ব্যবহারকারী যা লিখেছে তা কখনও অনুবাদ করবেন না (নাম, ঠিকানা, সাপোর্ট টিকিট, চ্যাট মেসেজ)। আপনি এর চারপাশের লেবেল অনুবাদ করতে পারেন, এবং চারপাশের মেটাডাটা (তারিখ, সংখ্যা) ফরম্যাট করতে পারেন, কিন্তু কন্টেন্টই অক্ষত রাখুন। যদি পরে অটো-অনুবাদ যোগ করেন, তা একটি স্পষ্ট ফিচার হিসেবে রাখুন যেখানে একটি “original/translated” টগল আছে।
একটি ব্যবহারিক উদাহরণ: একটি Koder.ai-নির্মিত অ্যাপ দেখাতে পারে “{name} renewed on {date} for {amount}”。এটিকে একটি মেসেজ হিসেবে রাখুন, {date} ও {amount} লোকেল অনুযায়ী ফরম্যাট করুন, এবং ব্যবহারকারীর টাইমজোনে দেখান। এই এক প্যাটার্ন অনেক অনুবাদ দেনা রোধ করে।
দ্রুত নিয়মগুলো যা সাধারণত বাগ প্রতিরোধ করে:
অনুবাদ দেনা সাধারণত শুরু হয় “একটি দ্রুত স্ট্রিং” হিসেবে এবং পরে সপ্তাহের পর সপ্তাহ পরিষ্কার করার প্রয়োজন হয়। চ্যাট-নির্মিত প্রজেক্টে, এটা আরও দ্রুত হয় কারণ UI টেক্সট কম্পোনেন্ট, ফর্ম এবং এমনকি ব্যাকএন্ড মেসেজের ভেতরেই জেনারেট হয়ে যায়।
যেগুলো সবচেয়ে ব্যয়বহুল সমস্যা সেগুলো হলো যেগুলো অ্যাপ জুড়ে ছড়িয়ে পড়ে এবং খুঁজে পাওয়া কঠিন হয়।
ধরুন একটি React ওয়েব অ্যাপ এবং একটি Flutter মোবাইল অ্যাপ উভয়ই একটি বিলিং ব্যানার দেখায়: “You have 1 free credit left”。 কেউ ওয়েব টেক্সট বদলে “You have one credit remaining” করে এবং কীকে পুরো বাক্য রেখেই রাখে। মোবাইল এখনও পুরনো কী ব্যবহার করে। এখন আপনার এক ধারণার জন্য দুইটি কী হয়ে গেছে, এবং অনুবাদক উভয়টি দেখেন।
একটি ভালো প্যাটার্ন হলো স্থিতিশীল কীগুলো (যেমন billing.creditsRemaining) এবং ICU-ভিত্তিক বহুবচন যাতে ব্যাকরণ সব ভাষায় সঠিক থাকে। যদি আপনি Koder.ai-এর মতো ভিব-কোডিং টুল ব্যবহার করেন, একটি নিয়ম শুরুর দিকে যোগ করুন: চ্যাটে তৈরি কোনো ব্যবহারকারী-উন্মুখ টেক্সট অবশ্যই ট্রান্সলেশন ফাইলেই নামুক, কম্পোনেন্ট বা সার্ভার এররগুলোর ভেতর নয়। এই ছোট অভ্যাসটি আপনার চ্যাট-নির্মিত অ্যাপগুলোর i18n আর্কিটেকচারকে বড় হয়ে ওঠার সময় রক্ষা করবে।
যখন আন্তর্জাতিকীকরণ অগোছালো মনে হয়, সাধারণত কারণ বেসিকগুলো লেখা হয়নি। একটি ছোট চেকলিস্ট এবং একটি কনক্রিট উদাহরণ আপনার টিম (এবং ভবিষ্যৎ আপনি) কে অনুবাদ দেনা থেকে রাখবে।
নিচে একটি দ্রুত চেকলিস্ট প্রতিটি নতুন স্ক্রিনে চালানোর জন্য:
billing.invoice.paidStatus, নয় billing.greenLabel)।একটি সহজ উদাহরণ: আপনি ইংরেজি, স্প্যানিশ, এবং জাপানি-তে একটি বিলিং স্ক্রিন লঞ্চ করতে যাচ্ছেন। UI-তে আছে: “Invoice”, “Paid”, “Due in 3 days”, “1 payment method” / “2 payment methods”, এবং একটি টোটাল যেমন “$1,234.50”。 যদি আপনি একটি আন্তর্জাতিকীকরণ আর্কিটেকচারে এটি বানান, আপনি একবার কী সংজ্ঞায়িত করবেন (ওয়েব ও মোবাইলে শেয়ার করা), এবং প্রতিটি ভাষা কেবল মান পূরণ করবে। “Due in {days} days” একটি ICU মেসেজ হবে, এবং মুদ্রা ফরম্যাটিং লোকেল-সচেতন ফরম্যাটারের মাধ্যমে হবে, না হার্ড-কোডেড কমার দিয়ে।
ভাষা সাপোর্ট ধাপে ধাপে ফেলুন, পুরো রিরাইট নয়:
দুইটি জিনিস ডকুমেন্ট করুন যেন নতুন ফিচারগুলো সঙ্গতিশীল থাকে: আপনার কী নামকরণ নিয়ম (উদাহরণসহ) এবং স্ট্রিংগুলোর “ডেফিনিশন অফ ডান” (কোনো হার্ড-কোডেড কপি নয়, বহুবচনের জন্য ICU, তারিখ/সংখ্যার ফরম্যাটিং, শেয়ার্ড ক্যাটালগে যোগ করা)।
পরবর্তী ধাপ: যদি আপনি Koder.ai-তে বিল্ড করছেন, Planning Mode ব্যবহার করে স্ক্রিন ও কীগুলো জেনারেট করার আগে নির্ধারণ করুন। তারপর স্ন্যাপশট ও রোলব্যাক ব্যবহার করে নিরাপদে কপি ও অনুবাদ নিয়ে ওয়েব ও মোবাইলে পুনরাবৃত্তি করুন যাতে কোনো ভাঙা রিলিজের ঝুঁকি না থাকে।