जबकि कुछ सॉफ्टवेयर सिस्टम का उपयोग सीमित संख्या में एक ही भाषा बोलने वाले उपयोगकर्ताओं द्वारा किया जाता है, अधिकांश संगठनों को दुनिया भर में विभिन्न भाषाएं बोलने वाले लोगों द्वारा उपयोग किए जाने के लिए अपने अनुप्रयोगों को एकीकृत और केंद्रीकृत करने की आवश्यकता होती है। बहुभाषी डेटाबेस डेटा मॉडल को डिजाइन और कार्यान्वित करने में कठिनाई का एक अतिरिक्त स्तर प्रस्तुत करते हैं। इस लेख में, हम इस चुनौती से निपटने के लिए कुछ उपाय सुझाते हैं।
एकाधिक भाषाओं में संग्रहीत करने के लिए हमें कौन-सी जानकारी की आवश्यकता है?
सतह पर, सभी स्ट्रिंग जानकारी कई भाषाओं में अनुवाद के लिए प्रशंसनीय लग सकती है। हालांकि, आमतौर पर ऐसा नहीं होता है। ग्राहक से संबंधित जानकारी जैसे CompanyName
या Address
अनुवाद किया जा सकता है, लेकिन यह एक अच्छा विचार नहीं हो सकता है।
यूनाइटेड किंगडम में "रिवरसाइड ट्रक्स" नामक एक व्यावसायिक ग्राहक को "123 अपर कैसल रोड" पर एक कार्यालय के साथ लें। आप नहीं चाहते कि कोई स्पैनिश भाषी उपयोगकर्ता "123 कैले कैस्टिलो सुपीरियर" पर स्थित "कैमियोन्स ओरिला" को एक पत्र प्रिंट और भेजे। रॉयल मेल (यूके की डाक सेवा) नहीं मिलेगी! आप शायद केवल वर्णनात्मक जानकारी वाले कॉलम का अनुवाद करना चाहते हैं, उचित नाम नहीं।
अनुवादों को संभालने के लिए एक प्रणाली तैयार करते समय, यह हमेशा पहले से ज्ञात नहीं होता है कि कौन से कॉलम अनुवाद योग्य हैं और किन लोगों को अनुवाद की आवश्यकता नहीं है। एक लचीला दृष्टिकोण चुनने से डिजाइन और विकास में बहुत समय की बचत होती है। कुछ उदाहरण देखने के लिए लेख "स्थानीयकरण-तैयार प्रणाली कैसे डिज़ाइन करें" पर एक नज़र डालें।
हम किन तरीकों पर विचार करते हैं?
इस लेख में, हम बहुभाषी डेटाबेस डिजाइन के लिए तीन दृष्टिकोणों का वर्णन करते हैं। हम सबसे सरल से शुरू करते हैं जो उतना लचीला नहीं है, फिर अन्य विकल्पों पर विचार करने के लिए आगे बढ़ते हैं, प्रत्येक के लिए पेशेवरों और विपक्षों को समझाते हुए।
इस आलेख में प्रयुक्त सिंटैक्स और डेटाबेस मॉडल (वर्टबेलो वेब-आधारित डेटा मॉडलर पर उपलब्ध) दोनों SQL सर्वर के लिए हैं। हालांकि, वे आसानी से किसी भी डेटाबेस इंजन के अनुकूल हो जाते हैं।
दृष्टिकोण 1:अनूदित सामग्री को रखने के लिए अतिरिक्त कॉलम बनाना
यह लागू करने का सबसे आसान तरीका है, हालांकि यह बहुत लचीला नहीं है। इसमें प्रत्येक कॉलम और भाषा के लिए एक कॉलम जोड़ना शामिल है जिसे हमें अपने सिस्टम में उपयोग करने की आवश्यकता है, जैसा कि निम्नलिखित वर्टाबेलो आरेख में दिखाया गया है:
हालांकि यह एक बहुत ही सरल समाधान की तरह लग सकता है, इसमें कुछ कमियां हैं। हम नीचे समझाते हैं।
Con:कोड जटिलता
यह दृष्टिकोण कोड को और अधिक जटिल बनाता है। इसके लिए हमें या तो प्रत्येक भाषा के लिए एक अलग प्रश्न लिखना होगा या एक CASE
. का उपयोग करना होगा उपयोगकर्ता कॉन्फ़िगरेशन के आधार पर उपयुक्त भाषा के लिए अनुवाद पुनर्प्राप्त करने के लिए निर्माण करें। उदाहरण के लिए निम्न कोड देखें:
SELECT ProductID, CASE @Language WHEN ‘ES’ THEN ProductName_ES WHEN ‘DE’ THEN ProductName_DE WHEN ‘FR’ THEN ProductName_FR ELSE ProductName END AS ProductName, CASE @Language WHEN ‘ES’ THEN ProductDescription_ES WHEN ‘DE’ THEN ProductDescription_DE WHEN ‘FR’ THEN ProductDescription_FR ELSE ProductDescription END AS ProductDescription, Price, Weight, ProductCategoryID FROM Product WHERE …
नोट: उदाहरण में, हम जिस भाषा का उपयोग करना चाहते हैं उसे रखने के लिए हम वेरिएबल @Language का उपयोग करते हैं। आप प्रत्येक उपयोगकर्ता के लिए भाषा सेट करने और पढ़ने के लिए SESSION_CONTEXT() (या Oracle में एप्लिकेशन संदर्भ) का उपयोग करने पर विचार कर सकते हैं।
Con:लचीलेपन की कमी
इस दृष्टिकोण में लचीलेपन का अभाव है। यदि हमें एक नई भाषा को लागू करने की आवश्यकता है, तो हमें अपने सिस्टम में प्रत्येक अनुवाद योग्य कॉलम के लिए नई भाषा के लिए एक कॉलम जोड़कर अपने डेटा मॉडल को संशोधित करने की आवश्यकता है। हमें प्रत्येक तालिका के लिए एक नई भाषा क्वेरी बनाने की भी आवश्यकता है (या एक नया CASE WHEN
जोड़कर मौजूदा को संपादित करें। खंड जो प्रत्येक अनुवाद योग्य कॉलम के लिए नई भाषा का उपयोग करता है)।
Con:अज्ञात जानकारी को संभालने में चुनौतियाँ
कल्पना कीजिए:एक उपयोगकर्ता एक उत्पाद जोड़ता है लेकिन यह नहीं जानता कि इसका अनुवाद कैसे किया जाए और अनुवादित कॉलम खाली छोड़ दें। उन भाषाओं को बोलने वाले उपयोगकर्ता NULL
see देखते हैं या कॉलम में रिक्त जानकारी की आवश्यकता हो सकती है।
दृष्टिकोण 2:अनुवाद योग्य स्तंभों को एक अलग तालिका में अलग करना
यह दृष्टिकोण तालिका में कॉलम को अनुवाद योग्य और गैर-अनुवाद योग्य कॉलम में समूहित करता है। गैर-अनुवाद योग्य कॉलम मूल तालिका में बने रहते हैं। इसके विपरीत, अनुवाद योग्य एक अलग तालिका में हैं, मूल तालिका के लिए एक विदेशी कुंजी और एक भाषा संकेतक के साथ। नीचे देखें:
आरेख सफेद रंग में मूल तालिकाएँ (बिना अनुवाद योग्य डेटा के) दिखाता है। अनुवाद रखने वाली टेबल हल्के नीले रंग में हैं, और भाषा की जानकारी रखने वाली मास्टर टेबल पीले रंग में है।
जैसा कि पहले चर्चा की गई थी, कई स्तंभों का उपयोग करने की तुलना में इसमें बड़े लचीलेपन के फायदे हैं। नई भाषा की आवश्यकता होने पर इस पद्धति में डेटा मॉडल को बदलने की आवश्यकता नहीं होती है। साथ ही, जानकारी को क्वेरी करने का सिंटैक्स सरल है:
SELECT p.ProductID, pt.ProductName, pt.ProductDescription, p.Price, p.Weight, p.ProductCategoryID FROM Product p LEFT JOIN ProductTranslation pt ON pt.ProductID = p.ProductID AND pt.LanguageID = @Language WHERE …
हालाँकि, अभी भी कुछ कमियाँ हैं, जैसा कि हम नीचे चर्चा करते हैं।
Con:चुनौतियां जब अतिरिक्त कॉलम का अनुवाद करने की आवश्यकता होती है
यदि हमें एक गैर-अनुवाद योग्य कॉलम को एक अनुवाद योग्य (या इसके विपरीत) में बदलने की आवश्यकता है, तो हमें कॉलम को एक टेबल से दूसरी टेबल पर ले जाकर अपने डेटा मॉडल को संशोधित करने की आवश्यकता है। यह आमतौर पर सिस्टम के लागू होने और उपयोग में आने के बाद अधिक लागत का संकेत देता है।
Con:अज्ञात जानकारी को संभालने में चुनौतियाँ
पहले दृष्टिकोण की तरह, अज्ञात जानकारी से निपटने के दौरान इस दृष्टिकोण में चुनौतियां हैं। दोबारा, यदि कोई उपयोगकर्ता कोई उत्पाद जोड़ता है, लेकिन उसका अनुवाद करना नहीं जानता और अनुवादित कॉलम खाली छोड़ देता है, तो उन भाषाओं को बोलने वाले उपयोगकर्ता NULL
देखते हैं या कॉलम में रिक्त जानकारी जिसकी आवश्यकता हो सकती है। साथ ही, क्वेरी के लिए LEFT JOIN
requires की आवश्यकता होती है यदि वर्तमान उपयोगकर्ता की भाषा के लिए अनुवाद अभी तक नहीं बनाया गया है ताकि गैर-अनुवाद योग्य डेटा अभी भी दिखाया जा सके।
दृष्टिकोण 3:अनुवाद सबसिस्टम जोड़ना
अनुवाद को एक ऐसी विशेषता के रूप में माना जा सकता है जो अनुवाद की आवश्यकता वाले डेटा मॉडल से पूरी तरह से स्वतंत्र है। एक आदर्श प्रणाली में, हम डेटा मॉडल में संशोधन की आवश्यकता के बिना किसी भी कॉलम के लिए अनुवाद को सक्षम या अक्षम कर सकते हैं। दुर्भाग्य से, ऐसा करने से कहना आसान है।
हम एक ऐसी विधि प्रस्तुत करते हैं जिसका मौजूदा डेटा मॉडल पर कोई प्रभाव नहीं पड़ता है और यह पूरी तरह से लचीला है। यद्यपि यह डेटा को क्वेरी करते समय जटिलता जोड़ता है, लेकिन कुछ तालिकाओं को छोड़कर इसे डेटा मॉडल में किसी अतिरिक्त परिवर्तन की आवश्यकता नहीं होती है। यह एक बढ़िया विकल्प हो सकता है यदि आपको किसी मौजूदा डेटा मॉडल में अनुवाद रखने की क्षमता जोड़ने की आवश्यकता है।
आइए मॉडल पर एक नज़र डालें और देखें कि यह कैसे काम करता है:
ध्यान देने वाली पहली बात यह है कि मूल डेटा मॉडल में कोई बदलाव नहीं है। साथ ही, उस मॉडल और अनुवाद सबसिस्टम के बीच कोई सीधा संबंध नहीं है।
अनुवाद सबसिस्टम में अनुवाद की आवश्यकता वाले टेबल और कॉलम के साथ एक छोटा डेटा डिक्शनरी शामिल है। इस डेटा डिक्शनरी को डेटा मॉडल में बदलाव किए बिना केवल पंक्तियों को जोड़कर/हटाकर संशोधित किया जा सकता है। अनुवादों को एक अलग तालिका में संग्रहीत किया जाता है, प्रत्येक मान को निम्नलिखित 3 स्तंभों द्वारा पहचाना जाता है:
ColumnID
:हम जिस कॉलम (और तालिका) का अनुवाद कर रहे हैं, उसकी विशिष्ट रूप से पहचान करता है।KeyID
:जिस विशिष्ट पंक्ति का हम अनुवाद कर रहे हैं उसकी आईडी (प्राथमिक कुंजी) को संग्रहीत करता है।LanguageID
:अनुवाद की भाषा की पहचान करता है।
यह डिज़ाइन डेटा को मूल तालिकाओं में दर्ज करने और संग्रहीत करने की अनुमति देता है, केवल आवश्यकता होने पर ही अनुवाद जोड़ता है। मूल डेटा (मूल भाषा में) को अछूता रखते हुए, डेटा पुनर्प्राप्त करते समय अनुवादित जानकारी का उपयोग किया जाता है।
ऊपर दिए गए उदाहरणों की तुलना में अधिक जटिल सिंटैक्स का उपयोग करके डेटा की पूछताछ की जा सकती है। इसके लिए एक अतिरिक्त JOIN
. की आवश्यकता है प्रत्येक अनुवाद योग्य कॉलम के लिए जैसा कि नीचे दिखाया गया है:
SELECT p.ProductID, ISNULL(t1.TranslationValue, p.ProductName) AS ProductName, ISNULL(t2.TranslationValue, p.ProductDescription) AS ProductDescription, p.Price, p.Weight, p.ProductCategoryID FROM Product p LEFT JOIN Translation t1 ON t1.ColumnID = <> AND t1.Key = p.ProductID AND t1.LanguageID = @Language LEFT JOIN Translation t2 ON t2.ColumnID = < > AND t2.Key = p.ProductID AND t2.LanguageID = @Language WHERE …;
नोट: “<<ProductName_ColumnID>>
” और “<<ProductDescription_ColumnID>>
" को ColumnInformation
में संग्रहीत के रूप में अनुवादित किए जाने वाले कॉलम की आईडी से प्रतिस्थापित किया जाना चाहिए टेबल। अंतिम उपयोगकर्ताओं के लिए जॉइन की जटिलता को छिपाने के लिए अनुवाद की आवश्यकता वाली प्रत्येक तालिका के लिए अनुवाद दृश्य उत्पन्न करने पर विचार करें। आप इस चरण को एक स्क्रिप्ट के साथ स्वचालित भी कर सकते हैं जो प्रत्येक दृश्य को उत्पन्न करती है। यह स्क्रिप्ट टेबल और कॉलम चुनने के लिए डेटाबेस के डेटा डिक्शनरी को क्वेरी कर सकती है और ColumnInformation
में मौजूद कॉलम के लिए ट्रांसलेशन लॉजिक जोड़ सकती है। टेबल।
अतिरिक्त युक्ति #1
आप वाक्य रचना को सरल भी कर सकते हैं। प्रत्येक जॉइन को कॉल के साथ एक ऐसे फ़ंक्शन में बदलें जो अनुवाद पहलू को संभालता है (और छुपाता है), जैसा कि नीचे दिखाया गया है:
SELECT p.ProductID, ISNULL(fn_translate(‘Product’,‘ProductName’,ProductID), p.ProductName) AS ProductName, ISNULL(fn_translate(‘Product’,‘ProductDescription’,ProductID), p.ProductDescription) AS ProductName, p.Price, p.Weight, p.ProductCategoryID FROM Product p WHERE …;
फ़ंक्शन संदर्भ से वांछित भाषा पढ़ सकता है, या आप इसे अतिरिक्त पैरामीटर के रूप में जोड़ सकते हैं। इस उदाहरण में, फ़ंक्शन वांछित अनुवाद को खोजने और वापस करने के लिए पैरामीटर के रूप में प्रदान की गई तालिका और कॉलम नामों के साथ-साथ पंक्ति कुंजी (पैरामीटर के रूप में भी प्रदान किया गया) का उपयोग करता है।
फ़ंक्शन को कॉल करना SQL और प्रक्रियात्मक भाषा के बीच संदर्भ स्विचिंग के कारण प्रदर्शन पर अतिरिक्त प्रभाव डालता है। हालांकि, यह डेटाबेस या तालिकाओं के लिए एक आसान समाधान हो सकता है जहां अनुवादित डेटा की मात्रा इसकी अनुमति देती है।
दोनों उदाहरण - एक जॉइन वाला और एक फ़ंक्शन वाला - ISNULL() SQL सर्वर फ़ंक्शन का उपयोग करें। इसलिए, जब वांछित भाषा में अनुवाद मौजूद नहीं होता है, तब भी यह रिक्त या NULL के बजाय ProductName और ProductDescription कॉलम में संग्रहीत मूल मान प्रदर्शित करता है।
सामान्य विचार
तीसरा दृष्टिकोण आमतौर पर बड़े डिजाइनों को लागू करने के लिए सबसे अच्छा होता है। यह डिज़ाइन और सिस्टम के उपयोग में आने के बाद दोनों में लचीलेपन की अनुमति देता है। हालांकि, ऐसे विशिष्ट विचार हैं जो अन्य दृष्टिकोणों को उपयोगी बना सकते हैं। अपनी पसंद के बावजूद, डिजाइन और विकास/कार्यान्वयन दोनों में समय बचाने के लिए निम्नलिखित पर विचार करें।
एब्स्ट्रैक्शन की एक परत जोड़ें
जैसा कि पहले उल्लेख किया गया है, ऐसे दृश्य बनाने पर विचार करें जो अनुवाद तर्क का ध्यान रखते हैं, उदाहरण के लिए, एकाधिक अनुवाद स्तंभों में से एक स्तंभ का चयन करना या विशिष्ट पंक्तियों में शामिल होना। यह विशिष्ट कार्यान्वयन विवरण प्रोग्रामर से छिपाए रखता है। जब भी उन्हें अनुवाद योग्य जानकारी वाली तालिका तक पहुंचने की आवश्यकता होती है, तो वे जटिल SQL वाक्यों का निर्माण करने के बजाय बस इन विचारों का उपयोग करते हैं।
डेटा फ़िल्टर करने के लिए प्रसंग का उपयोग करें
जैसा कि पहले उदाहरण में बताया गया है, अधिकांश डेटाबेस इंजनों में उपलब्ध संदर्भ कार्यों का उपयोग करने पर विचार करें। एक बार सिस्टम में लॉग इन करने के बाद उपयोगकर्ता भाषा की जानकारी संग्रहीत करने के लिए उनका उपयोग करें, फिर परिणामों को स्वचालित रूप से उन दृश्यों में फ़िल्टर करें जो अनुवाद का ध्यान रखते हैं।
स्वचालित
आधुनिक प्रणालियों में सैकड़ों या हजारों टेबल भी हो सकते हैं। प्रश्नों को एक-एक करके लिखने के बजाय स्वचालित रूप से अनुवाद दृश्य उत्पन्न करने के लिए समय निकालें। काम करने वाली स्क्रिप्ट पर पहुंचने में आपको कुछ समय लग सकता है, लेकिन फिर आप हमेशा एक सेकंड से भी कम समय में नए व्यू बना सकते हैं या मौजूदा व्यू को फिर से बना सकते हैं!