सबसे अच्छा अभ्यास बहु भाषा वेबसाइट


179

मैं इस सवाल से पिछले कुछ महीनों से जूझ रहा था, लेकिन मैं ऐसी स्थिति में नहीं था कि मुझे पहले सभी संभावित विकल्पों का पता लगाने की जरूरत थी। अभी, मुझे ऐसा लग रहा है कि संभावनाओं को जानने और अपनी आगामी परियोजनाओं में उपयोग करने के लिए अपनी व्यक्तिगत पसंद बनाने का समय आ गया है।

मुझे पहले जिस स्थिति की तलाश है, उसका वर्णन करता हूं

मैं एक कंटेंट मैनेजमेंट सिस्टम को अपग्रेड / रिडेवलप करने वाला हूं, जिसका उपयोग मैं काफी समय से कर रहा हूं। हालाँकि, मुझे लग रहा है कि बहु भाषा इस प्रणाली में एक महान सुधार है। इससे पहले कि मैं किसी भी ढांचे का उपयोग नहीं करता था, लेकिन मैं आगामी परियोजना के लिए लारावल 4 का उपयोग करने जा रहा हूं। Laravel PHP को कोड करने के लिए एक क्लीनर तरीके का सबसे अच्छा विकल्प लगता है। Sidenote: Laraval4 should be no factor in your answer। मैं अनुवाद के सामान्य तरीकों की तलाश कर रहा हूं जो प्लेटफ़ॉर्म / फ्रेमवर्क स्वतंत्र हों।

क्या अनुवाद किया जाना चाहिए

जैसा कि सिस्टम मैं देख रहा हूं कि उपयोगकर्ता के अनुकूल होने की आवश्यकता है जितना संभव हो अनुवाद का प्रबंधन करने का तरीका सीएमएस के अंदर होना चाहिए। अनुवाद फ़ाइलों या किसी html / php पार्स किए गए टेम्प्लेट को संशोधित करने के लिए एफ़टीपी कनेक्शन शुरू करने की आवश्यकता नहीं होनी चाहिए।

इसके अलावा, मैं अतिरिक्त टेबल बनाने की आवश्यकता के बिना कई डेटाबेस तालिकाओं का अनुवाद करने का सबसे आसान तरीका ढूंढ रहा हूं।

मैं खुद क्या लेकर आया था

जैसा कि मैं पहले से ही चीजों को खोज रहा हूं, पढ़ रहा हूं और कोशिश कर रहा हूं। मेरे पास कुछ विकल्प हैं। लेकिन मुझे अभी भी ऐसा महसूस नहीं होता है कि मैं वास्तव में जो चाह रहा हूं, उसके लिए एक सर्वोत्तम अभ्यास विधि तक पहुंच गया हूं। अभी, यह वही है जिसके साथ मैं आया हूं, लेकिन इस पद्धति के दुष्प्रभाव भी हैं।

  1. PHP पार्स्ड टेम्पलेट : टेम्पलेट सिस्टम को PHP द्वारा पार्स किया जाना चाहिए। इस तरह से मैं HTML में अनुवादित मापदंडों को सम्मिलित करने में सक्षम हूं, बिना टेम्पलेट्स को खोलने और उन्हें संशोधित किए बिना। इसके अलावा, PHP पार्स किए गए टेम्पलेट मुझे प्रत्येक भाषा के लिए एक सबफ़ोल्डर (जो मैंने पहले किया है) के बजाय एक पूर्ण वेबसाइट के लिए 1 टेम्पलेट रखने की क्षमता देता है। इस लक्ष्य तक पहुँचने की विधि स्मार्टी, टेम्प्लेटपावर, लारवेल्स ब्लेड या कोई अन्य टेम्प्लेट पार्सर हो सकती है। जैसा कि मैंने कहा कि यह लिखित समाधान के लिए स्वतंत्र होना चाहिए।
  2. डेटाबेस संचालित : शायद मुझे फिर से इसका उल्लेख करने की आवश्यकता नहीं है। लेकिन समाधान डेटाबेस संचालित होना चाहिए। CMS का उद्देश्य ऑब्जेक्ट ओरिएंटेड और MVC है, इसलिए मुझे स्ट्रिंग्स के लिए एक तार्किक डेटा संरचना के बारे में सोचना होगा। जैसा कि मेरे टेम्पलेट संरचित होंगे: टेम्प्लेट / नियंत्रक / View.php शायद यह संरचना सबसे अधिक समझ में आएगी Controller.View.parameter:। डेटाबेस तालिका में ये फ़ील्ड एक फ़ील्ड के साथ एक लंबा होगा value। टेम्प्लेट के अंदर हम कुछ तरह की विधि का उपयोग कर सकते हैं echo __('Controller.View.welcome', array('name', 'Joshua'))और पैरामीटर में शामिल है Welcome, :name। इस प्रकार परिणाम हो रहा है Welcome, Joshua। ऐसा करने का यह एक अच्छा तरीका है, क्योंकि पैरामीटर जैसे: नाम संपादक द्वारा समझना आसान है।
  3. निम्न डेटाबेस लोड : निश्चित रूप से उपरोक्त सिस्टम डेटाबेस लोड का कारण होगा यदि ये तार चलते समय लोड किए जा रहे हैं। इसलिए मुझे एक कैशिंग प्रणाली की आवश्यकता होगी जो भाषा फ़ाइलों को प्रशासन वातावरण में संपादित / सहेजते ही पुनः प्रस्तुत कर दे। क्योंकि फाइलें उत्पन्न होती हैं, एक अच्छी फाइल सिस्टम लेआउट की भी जरूरत होती है। मुझे लगता है कि हम languages/en_EN/Controller/View.phpया .इन के साथ जा सकते हैं , जो भी आपको सबसे अच्छा लगता है। शायद अनीनी भी अंत में तेज तर्रार है। इस fould में डेटा होना चाहिए format parameter=value; । मुझे लगता है कि यह ऐसा करने का सबसे अच्छा तरीका है, क्योंकि प्रत्येक दृश्य जो प्रदान किया गया है, उसमें मौजूद होने पर यह स्वयं की भाषा फ़ाइल शामिल कर सकता है। भाषा मापदंडों को तब एक विशिष्ट दृश्य में लोड किया जाना चाहिए और एक वैश्विक दायरे में नहीं होना चाहिए ताकि मापदंडों को एक-दूसरे को अधिलेखित करने से रोका जा सके।
  4. डेटाबेस टेबल अनुवाद : यह वास्तव में वह चीज है जिसके बारे में मैं सबसे अधिक चिंतित हूं। मैं समाचार / पृष्ठ / आदि के अनुवाद बनाने का एक रास्ता खोज रहा हूँ। जितना जल्दी हो सके। प्रत्येक मॉड्यूल (उदाहरण के लिए के लिए दो तालिकाओं के बाद Newsऔर News_translations) एक विकल्प है, लेकिन यह एक अच्छा प्रणाली पाने के लिए ज्यादा काम करने के लिए की तरह लगता है। बातें मैं के साथ एक पर आधारित है आया से एक data versioningप्रणाली मैं ने लिखा है: वहाँ एक डेटाबेस तालिका नाम है Translations, इस तालिका का एक अद्वितीय संयोजन है language, tablenameऔरprimarykey। उदाहरण के लिए: en_En / News / 1 (ID = 1 के साथ समाचार आइटम के अंग्रेजी संस्करण का संदर्भ)। लेकिन इस विधि के लिए 2 बड़े नुकसान हैं: सबसे पहले यह तालिका डेटाबेस में बहुत अधिक डेटा के साथ बहुत लंबा हो जाता है और दूसरी बात यह है कि तालिका को खोजने के लिए इस सेटअप का उपयोग करना एक नौकरी का नरक होगा। उदाहरण के लिए आइटम के एसईओ स्लग की खोज एक पूर्ण पाठ खोज होगी, जो बहुत गूंगा है। लेकिन दूसरी ओर: यह बहुत तेजी से हर तालिका में अनुवाद करने योग्य सामग्री बनाने का एक त्वरित तरीका है, लेकिन मुझे विश्वास नहीं है कि यह समर्थक शंकुओं पर हावी है।
  5. फ्रंट-एंड वर्क : इसके अलावा फ्रंट-एंड को कुछ सोच की आवश्यकता होगी। निश्चित रूप से हम उपलब्ध भाषाओं को एक डेटाबेस में संग्रहीत करेंगे और (डी) उन लोगों को सक्रिय करेंगे जिनकी हमें आवश्यकता है। इस तरह से स्क्रिप्ट किसी भाषा का चयन करने के लिए एक ड्रॉपडाउन उत्पन्न कर सकती है और बैक-एंड स्वचालित रूप से निर्णय ले सकती है कि सीएमएस का उपयोग करके क्या अनुवाद किए जा सकते हैं। तब चुनी गई भाषा (उदाहरण के लिए en_EN) का उपयोग तब किया जाएगा जब भाषा फ़ाइल को देखने के लिए या वेबसाइट पर एक सामग्री आइटम के लिए सही अनुवाद प्राप्त करने के लिए।

तो, वे वहाँ हैं। मेरे विचार अब तक। वे अभी तक तारीखों आदि के लिए स्थानीयकरण के विकल्पों को भी शामिल नहीं करते हैं, लेकिन जैसा कि मेरा सर्वर PHP5.3.2 का समर्थन करता है + सबसे अच्छा विकल्प यहां बताए अनुसार इंटैल एक्सटेंशन का उपयोग करना है: http://devzone.zend.com/1500/internationalization-in -php-53 / - लेकिन यह विकास के किसी भी बाद के स्टेडियम में उपयोग किया जाएगा। अब मुख्य मुद्दा यह है कि किसी वेबसाइट में सामग्री के अनुवाद का सर्वोत्तम अभ्यास कैसे किया जाए।

यहाँ मैंने जो कुछ भी समझाया उसके अलावा, मेरे पास अभी भी एक और बात है, जो मैंने अभी तक तय नहीं की है, यह एक साधारण प्रश्न की तरह दिखता है, लेकिन वास्तव में यह मुझे सिरदर्द दे रहा है:

URL अनुवाद? हमें ऐसा करना चाहिए या नहीं? और किस तरीके से

इसलिए .. अगर मेरे पास यह url है: http://www.domain.com/about-usऔर अंग्रेजी मेरी डिफ़ॉल्ट भाषा है। क्या http://www.domain.com/over-onsमुझे अपनी भाषा के रूप में डच चुनने पर इस URL का अनुवाद करना चाहिए ? या हमें आसान सड़क पर जाना चाहिए और बस पृष्ठ की सामग्री को बदलना चाहिए /about। आखिरी चीज एक वैध विकल्प नहीं लगती है क्योंकि यह एक ही URL के कई संस्करण उत्पन्न करेगा, सामग्री को अनुक्रमित करने से यह सही तरीके से विफल हो जाएगा।

http://www.domain.com/nl/about-usइसके बजाय दूसरा विकल्प उपयोग कर रहा है । यह प्रत्येक सामग्री के लिए कम से कम एक अद्वितीय URL बनाता है। इसके अलावा दूसरी भाषा में जाना आसान होगा, उदाहरण के लिए http://www.domain.com/en/about-usऔर प्रदान किया गया URL Google और मानव आगंतुकों दोनों के लिए समझना आसान है। इस विकल्प का उपयोग करते हुए, हम डिफ़ॉल्ट भाषाओं के साथ क्या करते हैं? क्या डिफ़ॉल्ट भाषा को डिफ़ॉल्ट रूप से चयनित भाषा को हटा देना चाहिए? इसलिए पुनर्निर्देशित http://www.domain.com/en/about-usकरना http://www.domain.com/about-us... मेरी नजर में यह सबसे अच्छा समाधान है, क्योंकि जब सीएमएस केवल एक भाषा के लिए सेटअप होता है तो URL में इस भाषा की पहचान होने की कोई आवश्यकता नहीं है।

और तीसरा विकल्प दोनों विकल्पों में से एक संयोजन है: http://www.domain.com/about-usमुख्य भाषा के लिए "भाषा-पहचान-कम" -URL ( ) का उपयोग करना। और sublanguages ​​के लिए अनुवादित एसईओ स्लग के साथ एक URL का उपयोग करें: http://www.domain.com/nl/over-onsऔरhttp://www.domain.com/de/uber-uns

मुझे आशा है कि मेरा प्रश्न आपके सिर को क्रैक करता है, उन्होंने मुझे यकीन है कि फटा! इसने मुझे पहले से ही एक प्रश्न के रूप में यहाँ काम करने में मदद की। मुझे उन तरीकों की समीक्षा करने की संभावना दी है जो मैंने पहले इस्तेमाल किए हैं और मुझे अपने आगामी सीएमएस के लिए विचार हो रहा है।

पाठ के इस समूह को पढ़ने के लिए समय निकालने के लिए मैं आपको धन्यवाद देना चाहता हूं!

// Edit #1:

मैं उल्लेख करना भूल गया: __ () फ़ंक्शन किसी दिए गए स्ट्रिंग का अनुवाद करने के लिए एक उपनाम है। इस पद्धति के भीतर स्पष्ट रूप से कुछ प्रकार की फ़ॉलबैक विधि होनी चाहिए जहाँ अभी तक अनुवाद उपलब्ध नहीं होने पर डिफ़ॉल्ट पाठ लोड किया जाता है। यदि अनुवाद गायब है, तो इसे या तो डाला जाना चाहिए या अनुवाद फ़ाइल को फिर से बनाया जाना चाहिए।


3
गेटटेक्स्ट के बारे में क्या? php.net/manual/en/book.gettext.php
फ्रेंकोइस बुर्जुआ

जवाबों:


115

टॉपिक का आधार

बहुभाषी साइट में तीन अलग-अलग पहलू हैं:

  • इंटरफ़ेस अनुवाद
  • सामग्री
  • url रूटिंग

हालांकि वे सभी सीएमएस दृष्टिकोण से अलग-अलग तरीकों से जुड़े हुए हैं, वे अलग-अलग यूआई तत्वों का उपयोग करके प्रबंधित किए जाते हैं और अलग-अलग संग्रहीत होते हैं। आप अपने कार्यान्वयन और पहले दो की समझ में आश्वस्त लग रहे हैं। प्रश्न बाद के पहलू के बारे में था - "URL अनुवाद? हमें यह करना चाहिए या नहीं? और किस तरीके से?"

URL किससे बनाया जा सकता है?

एक बहुत ही महत्वपूर्ण बात है, IDN के साथ कल्पना मत करो । इसके बजाय पक्ष लिप्यंतरण (भी: प्रतिलेखन और रोमानीकरण)। जबकि पहली नज़र में IDN अंतरराष्ट्रीय URL के लिए व्यवहार्य विकल्प लगता है, यह वास्तव में दो कारणों से विज्ञापित के रूप में काम नहीं करता है:

  • कुछ ब्राउज़र गैर- ASCII वर्ण जैसे 'ч'या 'ž'में '%D1%87'और चालू करेंगे'%C5%BE'
  • यदि उपयोगकर्ता के पास कस्टम थीम हैं, तो थीम के फ़ॉन्ट में उन अक्षरों के लिए प्रतीक नहीं होने की बहुत संभावना है

मैंने वास्तव में कुछ साल पहले एक वाईआईआई आधारित परियोजना (भयानक रूपरेखा, आईएमएचओ) में आईडीएन दृष्टिकोण की कोशिश की थी। मैंने उस समाधान को स्क्रैप करने से पहले उपरोक्त दोनों समस्याओं का सामना किया। इसके अलावा, मुझे संदेह है कि यह एक हमला वेक्टर हो सकता है।

उपलब्ध विकल्प ... जैसा कि मैं उन्हें देखता हूं।

मूल रूप से आपके पास दो विकल्प हैं, जिन्हें निम्नानुसार सार किया जा सकता है:

  • http://site.tld/[:query]: जहां [:query]भाषा और सामग्री की पसंद दोनों निर्धारित करता है

  • http://site.tld/[:language]/[:query]: जहां [:language]URL का भाग भाषा की पसंद को परिभाषित करता है और [:query]इसका उपयोग केवल सामग्री की पहचान करने के लिए किया जाता है

प्रश्न Α और Α है।

कहते हैं कि तुम उठाओ http://site.tld/[:query]

उस मामले में आपके पास भाषा का एक प्राथमिक स्रोत है: [:query]खंड की सामग्री ; और दो अतिरिक्त स्रोत:

  • $_COOKIE['lang']उस विशेष ब्राउज़र के लिए मूल्य
  • HTTP Accept-Language (1) , (2) हैडर में भाषाओं की सूची

सबसे पहले, आपको क्वेरी को परिभाषित रूटिंग पैटर्न में से एक से मेल खाना चाहिए (यदि आपकी पिक लारवेल है, तो यहां पढ़ें )। पैटर्न के सफल मिलान पर आपको फिर भाषा खोजने की जरूरत है।

आपको पैटर्न के सभी खंडों से गुजरना होगा। उन सभी सेगमेंट के लिए संभावित अनुवाद खोजें और निर्धारित करें कि किस भाषा का उपयोग किया गया था। दो अतिरिक्त स्रोतों (कुकी और हेडर) का उपयोग रूटिंग संघर्ष को हल करने के लिए किया जाएगा, जब वे "नहीं तो") उठते हैं।

उदाहरण के लिए ले लो: http://site.tld/blog/novinka

इसका लिप्यंतरण "блог, новинка"अंग्रेजी में है, जिसका अर्थ है लगभग "blog", "latest"

जैसा कि आप पहले से ही नोटिस कर सकते हैं, रूसी में "блог" का अनुवाद "ब्लॉग" के रूप में किया जाएगा। जिसका अर्थ है कि [:query]आपके पहले भाग के लिए ( सर्वोत्तम स्थिति में ) ['en', 'ru']संभव भाषाओं की सूची के साथ समाप्त हो जाएगा । फिर आप अगला खंड लेते हैं - "नोविंका"। संभावनाओं की सूची में केवल एक ही भाषा हो सकती है ['ru']:।

जब सूची में एक आइटम होता है, तो आपने भाषा को सफलतापूर्वक ढूंढ लिया है।

लेकिन अगर आप 2 के साथ समाप्त होते हैं (उदाहरण: रूसी और यूक्रेनी) या अधिक संभावनाएं .. या 0 संभावनाएं, जैसा कि मामला हो सकता है। आपको सही विकल्प खोजने के लिए कुकी और / या हेडर का उपयोग करना होगा।

और यदि अन्य सभी विफल हो जाते हैं, तो आप साइट की डिफ़ॉल्ट भाषा चुनें।

पैरामीटर के रूप में भाषा

वैकल्पिक URL का उपयोग करना है, जिसे परिभाषित किया जा सकता है http://site.tld/[:language]/[:query]। इस मामले में, क्वेरी का अनुवाद करते समय, आपको भाषा का अनुमान लगाने की आवश्यकता नहीं है, क्योंकि उस बिंदु पर आप पहले से ही जानते हैं कि किसका उपयोग करना है।

भाषा का एक माध्यमिक स्रोत भी है: कुकी मूल्य। लेकिन यहाँ स्वीकार-भाषा हेडर के साथ खिलवाड़ करने का कोई मतलब नहीं है, क्योंकि आप "कोल्ड स्टार्ट" (जब उपयोगकर्ता पहली बार कस्टम क्वेरी के साथ साइट खोलता है) के मामले में अज्ञात भाषाओं से अनजान राशि से नहीं निपट रहे हैं।

इसके बजाय आपके पास 3 सरल, प्राथमिकता वाले विकल्प हैं:

  1. यदि [:language]खंड सेट है, तो इसका उपयोग करें
  2. यदि $_COOKIE['lang']सेट है, तो इसका उपयोग करें
  3. डिफ़ॉल्ट भाषा का उपयोग करें

जब आपके पास भाषा होती है, तो आप बस क्वेरी का अनुवाद करने का प्रयास करते हैं, और यदि अनुवाद विफल हो जाता है, तो उस विशेष खंड के लिए "डिफ़ॉल्ट मान" (रूटिंग परिणामों के आधार पर) का उपयोग करें।

यहाँ एक तीसरा विकल्प नहीं है?

हाँ, तकनीकी रूप से आप दोनों दृष्टिकोण को जोड़ सकते हैं, लेकिन यह प्रक्रिया जटिल और केवल उन लोगों के लिए मैन्युअल रूप से परिवर्तन यूआरएल करना चाहते जगह बन सका http://site.tld/en/newsकरने के लिए http://site.tld/de/newsऔर जर्मन के लिए परिवर्तन करने के लिए खबर पेज की उम्मीद है।

लेकिन इस मामले को भी कम जादू और आशा के साथ लागू करने के लिए कुकी मूल्य (जिसमें भाषा की पिछली पसंद के बारे में जानकारी होगी) का उपयोग करके संभावित रूप से कम किया जा सकता है।

किस दृष्टिकोण का उपयोग करें?

जैसा कि आप पहले ही अनुमान लगा चुके हैं, मैं http://site.tld/[:language]/[:query]अधिक समझदार विकल्प के रूप में सिफारिश करूंगा ।

वास्तविक शब्द स्थिति में भी आपके पास URL में तीसरा प्रमुख भाग होगा: "शीर्षक"। जैसा कि ऑनलाइन शॉप में उत्पाद के नाम पर या समाचार साइट में लेख का शीर्षक।

उदाहरण: http://site.tld/en/news/article/121415/EU-as-global-reserve-currency

इस मामले '/news/article/121415'में क्वेरी होगी, और 'EU-as-global-reserve-currency'शीर्षक है। पूरी तरह से एसईओ प्रयोजनों के लिए।

क्या यह लारवेल में किया जा सकता है?

Kinda, लेकिन डिफ़ॉल्ट रूप से नहीं।

मैं इससे बहुत परिचित नहीं हूं, लेकिन मैंने जो देखा है, उसमें से लारवेल सरल पैटर्न-आधारित रूटिंग तंत्र का उपयोग करता है। बहुभाषी URL को लागू करने के लिए आपको संभवतः कोर क्लास (तों) का विस्तार करना होगा , क्योंकि बहुभाषी रूटिंग को विभिन्न प्रकार के स्टोरेज (डेटाबेस, कैश और / या कॉन्फ़िगरेशन फ़ाइलों) तक पहुंचने की आवश्यकता होती है।

यह रूट किया गया है। अब क्या?

सभी के परिणामस्वरूप आप दो मूल्यवान जानकारी के साथ समाप्त हो जाएंगे: वर्तमान भाषा और क्वेरी के अनुवादित खंड। इन मूल्यों का उपयोग तब वर्ग (तों) को भेजने के लिए किया जा सकता है जो परिणाम उत्पन्न करेगा।

मूल रूप से, निम्न URL: http://site.tld/ru/blog/novinka(या बिना संस्करण '/ru') कुछ इस तरह से बदल जाता है

$parameters = [
   'language' => 'ru',
   'classname' => 'blog',
   'method' => 'latest',
];

जिसे आप सिर्फ प्रेषण के लिए उपयोग करते हैं:

$instance = new {$parameter['classname']};
$instance->{'get'.$parameters['method']}( $parameters );

.. या इसका कुछ भिन्नता, विशेष रूप से कार्यान्वयन पर निर्भर करता है।


1
एक और अंतर्दृष्टि के लिए धन्यवाद! बहुत विचारशील! मैं URL में भाषा पैरामीटर को अस्वस्थ होने के बारे में सोच रहा था। यह केवल एक विशेष भाषा की पहचान करने का सबसे अच्छा तरीका है, न केवल उपयोगकर्ता के लिए, बल्कि एसईओ प्रयोजनों के लिए भी। यदि कोई उपयोगकर्ता / en / news / / de / news में परिवर्तन करता है, तो मेरा विचार उदाहरण के लिए / de / nachrichten को 301 (स्थायी) पुनर्निर्देशित करना था। बस यह सुनिश्चित करने के लिए कि प्रत्येक भाषा में प्रति पृष्ठ केवल एक अद्वितीय URL है (पुन: एसईओ प्रयोजनों के लिए)
यहोशू - पेन्डो

सर्वश्रेष्ठ उत्तर का चयन करना कठिन और कठिन होता जा रहा है, वर्तमान में लगभग 3/4 उत्तर हैं जो कम से कम इनाम के प्रत्येक भाग के लायक हैं। संयुक्त वे सब कुछ एक ठोस जवाब बन जाते हैं जो मैं एक साथ स्पष्ट करना चाहता था :)
यहोशू - पेन्डो

मैंने आपके उत्तर को स्वीकार करते हुए आपको URL अनुवाद पर दिए गए विस्तृत उत्तर के लिए कम से कम कुछ अतिरिक्त प्रतिनिधि देने के लिए कहा। अत्यधिक सराहना की! हालाँकि, यह इनाम आपके नीचे के व्यक्ति के लिए पुरस्कार विजेता है क्योंकि उसने मेरे सवाल के हर पहलू का एक स्वतंत्र तरीके से जवाब दिया।
जोशुआ - पेन्डो

52

थॉमस Bley द्वारा सुझाए अनुसार प्री-प्रोसेसर का उपयोग करके प्रदर्शन के बिना i18n को लागू करना

काम के दौरान, हम हाल ही में अपनी कुछ संपत्तियों पर i18n के कार्यान्वयन से गुज़रे, और जिन चीज़ों से हम जूझते रहे, उनमें से एक थी-ऑन-द-फ्लाई अनुवाद से निपटने का प्रदर्शन, फिर मैंने थॉमस बेली द्वारा इस महान ब्लॉग पोस्ट की खोज की जो न्यूनतम प्रदर्शन के मुद्दों के साथ बड़े ट्रैफ़िक लोड को संभालने के लिए i18n का उपयोग करने के तरीके से प्रेरित है।

हर अनुवाद ऑपरेशन के लिए कॉलिंग फ़ंक्शंस के बजाय, जैसा कि हम जानते हैं कि पीएचपी महंगा है, हम अपने आधार फ़ाइलों को प्लेसहोल्डर्स के साथ परिभाषित करते हैं, फिर उन फ़ाइलों को कैश करने के लिए एक पूर्व-प्रोसेसर का उपयोग करते हैं (हम फाइल संशोधन समय संग्रहीत करते हैं यह सुनिश्चित करने के लिए कि हम सेवा कर रहे हैं। हर समय नवीनतम सामग्री)।

अनुवाद टैग

थॉमस उपयोग करता है {tr} और {/tr}टैग को परिभाषित करने के लिए जहां अनुवाद शुरू और अंत होता है। इस तथ्य के कारण कि हम TWIG का उपयोग कर रहे हैं, हम {भ्रम से बचने के लिए उपयोग नहीं करना चाहते हैं इसलिए हम उपयोग करते हैं [%tr%]और [%/tr%]इसके बजाय। मूल रूप से, यह इस तरह दिखता है:

`return [%tr%]formatted_value[%/tr%];`

ध्यान दें कि थॉमस फ़ाइल में आधार अंग्रेजी का उपयोग करने का सुझाव देता है। हम ऐसा नहीं करते हैं क्योंकि अगर हम अंग्रेजी में मूल्य बदलते हैं तो हम सभी अनुवाद फ़ाइलों को संशोधित नहीं करना चाहते हैं।

INI फ़ाइलें

फिर, हम प्रत्येक भाषा के लिए प्रारूप में एक INI फ़ाइल बनाते हैं placeholder = translated:

// lang/fr.ini
formatted_value = number_format($value * Model_Exchange::getEurRate(), 2, ',', ' ') . '€'

// lang/en_gb.ini
formatted_value = '£' . number_format($value * Model_Exchange::getStgRate())

// lang/en_us.ini
formatted_value = '$' . number_format($value)

यह उपयोगकर्ता को सीएमएस के अंदर इन को संशोधित करने की अनुमति देने के लिए तुच्छ होगा, बस कीपर्स ए द्वारा प्राप्त करें preg_split पर \nया =और सीएमएस INI फ़ाइलों को लिखने में सक्षम बना रही है।

पूर्व-प्रोसेसर घटक

अनिवार्य रूप से, थॉमस आपके अनुवाद फ़ाइलों को लेने और डिस्क पर स्थिर PHP फ़ाइलों को बनाने के लिए इस तरह के (संकलक, हालांकि, सच में, यह एक पूर्वप्रक्रमक है) फ़ंक्शन का उपयोग करने का सुझाव देता है। इस प्रकार, हम अनिवार्य रूप से फ़ाइल में हर स्ट्रिंग के लिए अनुवाद फ़ंक्शन को कॉल करने के बजाय हमारी अनुवादित फ़ाइलों को कैश करते हैं:

// This function was written by Thomas Bley, not by me
function translate($file) {
  $cache_file = 'cache/'.LANG.'_'.basename($file).'_'.filemtime($file).'.php';
  // (re)build translation?
  if (!file_exists($cache_file)) {
    $lang_file = 'lang/'.LANG.'.ini';
    $lang_file_php = 'cache/'.LANG.'_'.filemtime($lang_file).'.php';

    // convert .ini file into .php file
    if (!file_exists($lang_file_php)) {
      file_put_contents($lang_file_php, '<?php $strings='.
        var_export(parse_ini_file($lang_file), true).';', LOCK_EX);
    }
    // translate .php into localized .php file
    $tr = function($match) use (&$lang_file_php) {
      static $strings = null;
      if ($strings===null) require($lang_file_php);
      return isset($strings[ $match[1] ]) ? $strings[ $match[1] ] : $match[1];
    };
    // replace all {t}abc{/t} by tr()
    file_put_contents($cache_file, preg_replace_callback(
      '/\[%tr%\](.*?)\[%\/tr%\]/', $tr, file_get_contents($file)), LOCK_EX);
  }
  return $cache_file;
}

नोट: मैंने यह सत्यापित नहीं किया कि रेगेक्स काम करता है, मैंने इसे हमारी कंपनी सर्वर से कॉपी नहीं किया है, लेकिन आप देख सकते हैं कि ऑपरेशन कैसे काम करता है।

इसे कैसे कॉल करें

फिर, यह उदाहरण थॉमस बिल का है, न कि मेरा:

// instead of
require("core/example.php");
echo (new example())->now();

// we write
define('LANG', 'en_us');
require(translate('core/example.php'));
echo (new example())->now();

हम भाषा को कुकी (या सत्र चर में संग्रहीत करते हैं यदि हमें कुकी नहीं मिल सकती है) और फिर उसे हर अनुरोध पर पुनः प्राप्त करते हैं। आप इसे एक वैकल्पिक के साथ जोड़ सकते हैं$_GET इसे भाषा को ओवरराइड करने के लिए पैरामीटर के हैं, लेकिन मैं उप-भाषा-प्रति-भाषा या पृष्ठ-प्रति-भाषा का सुझाव नहीं देता, क्योंकि इससे यह देखना कठिन हो जाएगा कि कौन से पृष्ठ लोकप्रिय हैं और इनबाउंड का मान कम कर देंगे लिंक के रूप में आप उन्हें और अधिक फैल जाएगा।

इस विधि का उपयोग क्यों करें?

हम तीन कारणों से प्रीप्रोसेसिंग की इस पद्धति को पसंद करते हैं:

  1. सामग्री के लिए फ़ंक्शंस का एक पूरा समूह नहीं बुलाने से बहुत बड़ा प्रदर्शन हासिल होता है, जो शायद ही कभी बदलता है (इस प्रणाली के साथ, फ्रेंच में 100k आगंतुक अभी भी केवल एक बार चल रहे अनुवाद प्रतिस्थापन को समाप्त कर देंगे)।
  2. यह हमारे डेटाबेस में कोई भार नहीं जोड़ता है, क्योंकि यह सरल फ्लैट-फ़ाइलों का उपयोग करता है और शुद्ध-पीएचपी समाधान है।
  3. हमारे अनुवादों के भीतर PHP के भावों का उपयोग करने की क्षमता।

अनुवादित डेटाबेस सामग्री प्राप्त करना

हम अपने डेटाबेस में सामग्री के लिए एक कॉलम जोड़ते हैं language, फिर हम उस LANGस्थिरांक के लिए एक एक्सेसर विधि का उपयोग करते हैं जिसे हमने पहले परिभाषित किया था, इसलिए हमारी SQL कॉल (ZF1 का उपयोग करते हुए, दुख की बात है) इस तरह दिखती है:

$query = select()->from($this->_name)
                 ->where('language = ?', User::getLang())
                 ->where('id       = ?', $articleId)
                 ->limit(1);

हमारे लेखों में एक यौगिक प्राथमिक कुंजी है idऔर languageइसलिए लेख 54सभी भाषाओं में मौजूद हो सकता है। निर्दिष्ट न LANGहोने पर हमारी चूक en_US

URL स्लग अनुवाद

मैं यहां दो चीजों को जोड़ूंगा, एक आपके बूटस्ट्रैप में एक फ़ंक्शन है जो $_GETभाषा के लिए एक पैरामीटर स्वीकार करता है और कुकी चर को ओवरराइड करता है, और दूसरा रूटिंग है जो कई स्लग स्वीकार करता है। फिर आप अपनी रूटिंग में कुछ ऐसा कर सकते हैं:

"/wilkommen" => "/welcome/lang/de"
... etc ...

इन्हें एक सपाट फ़ाइल में संग्रहित किया जा सकता है जिसे आसानी से आपके व्यवस्थापक पैनल से लिखा जा सकता है। JSON या XML उन्हें समर्थन देने के लिए एक अच्छी संरचना प्रदान कर सकता है।

कुछ अन्य विकल्पों के संबंध में नोट्स

PHP- ऑन-द-फ्लाई ट्रांसलेशन

मैं नहीं देख सकता कि ये पूर्व-संसाधित अनुवादों पर कोई लाभ प्रदान करते हैं।

फ्रंट-एंड बेस्ड ट्रांसलेशन

मैं लंबे समय से इन दिलचस्प पाया है, लेकिन कुछ caveats हैं। उदाहरण के लिए, आपको उपयोगकर्ता को अपनी वेबसाइट पर वाक्यांशों की पूरी सूची उपलब्ध करानी होगी, जिसे आप अनुवाद करने की योजना बनाते हैं, यह समस्याग्रस्त हो सकता है यदि आपके द्वारा छिपाए जा रहे साइट के क्षेत्र हैं या उन्हें एक्सेस करने की अनुमति नहीं है।

आपको यह भी मानना ​​होगा कि आपके सभी उपयोगकर्ता अपनी साइट पर जावास्क्रिप्ट का उपयोग करने के लिए तैयार हैं और सक्षम हैं, लेकिन मेरे आंकड़ों से, हमारे लगभग 2.5% उपयोगकर्ता इसके बिना चल रहे हैं (या इसे उपयोग करने से हमारी साइटों को अवरुद्ध करने के लिए Noscript का उपयोग कर रहे हैं) ।

डेटाबेस-प्रेरित अनुवाद

PHP के डेटाबेस कनेक्टिविटी की गति घर के बारे में लिखने के लिए कुछ भी नहीं है, और यह अनुवाद करने के लिए हर वाक्यांश पर एक फ़ंक्शन को कॉल करने के पहले से ही उच्च ओवरहेड में जोड़ता है। प्रदर्शन और मापनीयता के मुद्दे इस दृष्टिकोण के साथ भारी लगते हैं।


मैं देखता हूं कि मैंने आपको "फ्रंट-एंड ट्रांसलेशन" के साथ भ्रमित किया है, जो मेरा मतलब था कि स्क्रीन पर अनुवादित स्ट्रिंग्स को पार्स करने का एक तरीका था। मैं निश्चित रूप से ग्राहक की ओर से इसका अनुवाद करने का तरीका नहीं खोज रहा हूँ! मेरा मतलब था कि सामने के छोर पर भाषाओं को स्विच करने का सबसे आसान तरीका था, लेकिन यह स्पष्ट रूप से एक कुकी या उपयोगकर्ता सेटिंग का उपयोग कर रहा है :)
यहोशू - पेन्डो

ओह, और डेटाबेस-प्रेरित द्वारा मैं सभी अनुवादों को प्रबंधित करने की विधि पर अधिक लक्ष्य कर रहा था, इसलिए मेरा आदर्श समाधान एक बैक-एंड होगा जो एक डेटाबेस के अनुवादों को एक फ़ंक्शन द्वारा लिखता है जो पूर्व-प्रसंस्करण घटक उत्पन्न करता है जो PHP उत्पन्न करता है फ़ाइल। Why?: सरल .. मैं पाठ में थोड़े बदलाव से परेशान नहीं होना चाहता, उपयोगकर्ताओं को कोड संपादक और / या ftp प्रोग्राम का उपयोग किए बिना ऐसा करने में सक्षम होना चाहिए :)
यहोशू - पेन्डो

@ मुझे पता है कि आपको फ्रंट-एंड अनुवादों से मतलब नहीं था, यह उस उपयोगकर्ता की ओर एक पतली टिप्पणी थी जिसने जेएस का उपयोग करते हुए फ्रंट-एंड ट्रांसलेशन फ्रेमवर्क का सुझाव दिया था। ;)
१16:१६ पर गड़बड़ इच्छा

@ मैं स्वीकार करता हूं, जैसा कि आपने सुझाव दिया था मैं बैकएंड का उपयोग करूंगा लेकिन डेटाबेस के बजाय मैं प्रदर्शन कारणों से एक फ्लैट फ़ाइल का उपयोग करूंगा। बेशक, कोर यहाँ सुझाव पूर्व प्रतिपादन परिवर्तन पर टेम्पलेट्स ताकि आप बदल सकते है .INIके साथ एक 3 स्तंभ डेटाबेस तालिका के साथ फ़ाइलें placeholder, replacement, languageplaceholderऔर पर यौगिक कुंजी language। फिर एक और 2-कोल के साथ tempfile(टेम्पलेट का पथ) और modified(DATETIME)।
ग्लिच डिज़ायर

1
@PENDO धन्यवाद मैंने 250 वापस कर दिया है और मैं इसे 24 घंटों में टेरीस्को को देने की योजना बनाता हूं जब साइट मुझे अनुमति देती है, जैसा कि आपने दोनों उत्तरों को सही चुना है, और मुझे लगता है कि एक विभाजन आपके इरादों का सबसे अच्छा प्रतिनिधित्व करेगा।
ग्लिच डिज़ायर

15

मेरा सुझाव है कि आप एक पहिया का आविष्कार न करें और गेटटेक्स्ट और आईएसओ भाषाओं की सूची का उपयोग करें। क्या आपने देखा है कि लोकप्रिय CMSes या चौखटे में i18n / l10n कैसे लागू किया जाता है?

गेटटेक्स्ट का उपयोग करने से आपके पास एक शक्तिशाली उपकरण होगा जहां कई मामले पहले से ही संख्याओं के बहुवचन रूपों की तरह लागू होते हैं। अंग्रेजी में आपके पास केवल 2 विकल्प हैं: एकवचन और बहुवचन। लेकिन रूसी में उदाहरण के लिए 3 रूप हैं और इसके अंग्रेजी में सरल नहीं है।

इसके अलावा कई अनुवादकों को पहले से ही गेटटेक्स्ट के साथ काम करने का अनुभव है।

CakePHP या Drupal पर एक नज़र डालें । दोनों बहुभाषी सक्षम। CakePHP इंटरफ़ेस स्थानीयकरण और Drupal सामग्री अनुवाद के उदाहरण के रूप में।

डेटाबेस का उपयोग करने वाले l10n के लिए ऐसा बिल्कुल नहीं है। यह प्रश्नों पर टन होगा। मानक दृष्टिकोण प्रारंभिक चरण में मेमोरी में सभी l10n डेटा प्राप्त करना है (या यदि आप आलसी लोडिंग पसंद करते हैं तो i10n फ़ंक्शन पर पहली कॉल के दौरान)। इसे .po फ़ाइल या DB डेटा से एक ही बार में पढ़ा जा सकता है। और सरणी से सिर्फ अनुरोधित तार पढ़े हैं।

यदि आपको इंटरफ़ेस ट्रांसलेट करने के लिए ऑनलाइन टूल लागू करने की आवश्यकता है, तो आपके पास DB में वह सारा डेटा हो सकता है, लेकिन इसके साथ काम करने के लिए फाइल करने के लिए अभी भी सभी डेटा को सेव करें। स्मृति में डेटा की मात्रा को कम करने के लिए आप अपने सभी अनुवादित संदेशों / तारों को समूहों में विभाजित कर सकते हैं और केवल उन समूहों को लोड कर सकते हैं जिनकी आपको आवश्यकता है अगर यह संभव होगा।

तो आप अपने # 3 में पूरी तरह से सही हैं। एक अपवाद के साथ: आमतौर पर यह एक बड़ी फाइल है जो प्रति-नियंत्रक फ़ाइल नहीं है। क्योंकि प्रदर्शन के लिए एक फ़ाइल को खोलना सबसे अच्छा है। आप शायद जानते हैं कि कुछ हाईलोड किए गए वेब एप्लिकेशन फ़ाइल ऑपरेशन से बचने के लिए एक फ़ाइल में सभी PHP कोड को संकलित करते हैं जब इसमें शामिल / आवश्यकता होती है।

URL के बारे में। Google अप्रत्यक्ष रूप से अनुवाद का उपयोग करने का सुझाव देता है:

स्पष्ट रूप से फ्रांसीसी सामग्री को इंगित करने के लिए: http://example.ca/fr/vélo-de-montagne.html

इसके अलावा, मुझे लगता है कि आपको उपयोगकर्ता को डिफ़ॉल्ट भाषा उपसर्ग उदाहरण के लिए पुनर्निर्देशित करना होगा http://examlpe.com/about-us होगा करने के लिए रीडायरेक्ट http://examlpe.com/en/about-us इतना लेकिन अगर आपकी साइट उपयोग केवल एक ही भाषा आप उपसर्गों की आवश्यकता नहीं है।

बाहर की जाँच करें: http://www.audiomicro.com/trailer-hit-impact-psychodrama-sound-effects-836925 http://nl.audiomicro.com/aanhangwagen-hit-effect-psychodrama-geluidseffecten-836925 http: / /de.audiomicro.com/anhanger-hit-auswirkungen-psychodrama-sound-effekte-836925

सामग्री का अनुवाद करना अधिक कठिन काम है। मुझे लगता है कि यह विभिन्न प्रकार की सामग्री जैसे लेख, मेनू आइटम आदि के साथ कुछ अंतर होंगे, लेकिन # 4 में आप सही तरीके से हैं। अधिक विचार करने के लिए Drupal में एक नज़र डालें। इसमें स्पष्ट डीबी स्कीमा और अनुवाद के लिए अच्छा पर्याप्त इंटरफ़ेस है। जैसे आप लेख बनाते हैं और उसके लिए भाषा का चयन करते हैं। और आप बाद में इसे अन्य भाषाओं में अनुवाद कर सकते हैं।

Drupal अनुवाद इंटरफ़ेस

मुझे लगता है कि URL स्लग के साथ यह समस्या नहीं है। आप बस स्लग के लिए अलग टेबल बना सकते हैं और यह सही निर्णय होगा। साथ ही सही इंडेक्स का उपयोग करके डेटा की भारी मात्रा के साथ भी तालिका को क्वेरी करना समस्या नहीं है। और यह पूर्ण पाठ खोज नहीं था लेकिन स्ट्रिंग मिलान अगर स्लग के लिए varchar डेटा प्रकार का उपयोग करेगा और आपके पास उस फ़ील्ड पर एक सूचकांक भी हो सकता है।

PS क्षमा करें, मेरी अंग्रेजी हालांकि सही से बहुत दूर है।


मेरे प्रश्न का उत्तर देने में लगने वाले समय के लिए धन्यवाद। आपकी अंग्रेजी मुझे समझने के लिए पर्याप्त है! मैं +1 करने जा रहा हूँ आप पहले से ही अपने प्रयासों के लिए!
जोशुआ - पेन्डो

यारोस्लाव, एक बार फिर, आपके उत्तर के लिए धन्यवाद। हालाँकि मैं 2 अन्य उत्तरों के साथ गया था, जहाँ थोड़ा अधिक पूर्ण होता है और कोड के पीछे इस्तेमाल किए गए तरीकों को समझाता है कि यह इंगित करने के बजाय यह पहले से ही है।
जोशुआ - पेन्डो

2
कोई दिक्कत नहीं है। वास्तव में यह मेरे लिए भी पढ़ने के लिए अधिक पूर्ण और दिलचस्प जवाब देता है। लेकिन मुझे आशा है कि आपको मेरे उत्तर से भी कुछ उपयोगी मिलेगा।
यारोस्लाव

12

यह इस बात पर निर्भर करता है कि आपकी वेबसाइट में कितनी सामग्री है। सबसे पहले मैंने यहां अन्य सभी लोगों की तरह एक डेटाबेस का उपयोग किया, लेकिन यह एक डेटाबेस के सभी कामकाज को स्क्रिप्ट करने के लिए समय लेने वाला हो सकता है। मैं यह नहीं कहता कि यह एक आदर्श तरीका है और खासकर यदि आपके पास बहुत अधिक पाठ है, लेकिन यदि आप डेटाबेस का उपयोग किए बिना इसे तेजी से करना चाहते हैं, तो यह विधि काम कर सकती है, हालांकि, आप उपयोगकर्ताओं को डेटा इनपुट करने की अनुमति नहीं दे सकते जिसका अनुवाद-फ़ाइलों के रूप में उपयोग किया जाएगा। लेकिन अगर आप स्वयं अनुवाद जोड़ते हैं, तो यह काम करेगा:

मान लें कि आपके पास यह पाठ है:

Welcome!

आप इसका अनुवाद के साथ डेटाबेस में इनपुट कर सकते हैं, लेकिन आप यह भी कर सकते हैं:

$welcome = array(
"English"=>"Welcome!",
"German"=>"Willkommen!",
"French"=>"Bienvenue!",
"Turkish"=>"Hoşgeldiniz!",
"Russian"=>"Добро пожаловать!",
"Dutch"=>"Welkom!",
"Swedish"=>"Välkommen!",
"Basque"=>"Ongietorri!",
"Spanish"=>"Bienvenito!"
"Welsh"=>"Croeso!");

अब, यदि आपकी वेबसाइट कुकी का उपयोग करती है, तो आपके पास यह है:

$_COOKIE['language'];

इसे आसान बनाने के लिए आइए इसे एक कोड में परिवर्तित करें जिसे आसानी से उपयोग किया जा सकता है:

$language=$_COOKIE['language'];

यदि आपकी कुकी भाषा वेल्श है और आपके पास यह कोड है:

echo $welcome[$language];

इसका परिणाम यह होगा:

Croeso!

यदि आपको अपनी वेबसाइट के लिए बहुत सारे अनुवाद जोड़ने की आवश्यकता है और एक डेटाबेस बहुत अधिक खपत कर रहा है, तो सरणी का उपयोग करना एक आदर्श समाधान हो सकता है।


1
यह वह जगह नहीं है जहां मैं जवाब के लिए पूछ रहा था। इसके अलावा, प्रत्येक पृष्ठ पर सभी भाषाएँ उपलब्ध होने के बजाय, आप बेहतर तरीके से ऐसी फ़ाइलें बनाएँगे lang.en.phpजिनमें शामिल हों और उपयोग करें $lang['welcome']जो प्रत्येक फ़ाइल में घोषित की गई हों।
जोशुआ - पेन्डो

7

मैं आपको सुझाव दूंगा कि अनुवाद के लिए डेटाबेस पर वास्तव में निर्भर न होना वास्तव में एक गन्दा काम हो सकता है और डेटा एन्कोडिंग के मामले में एक चरम समस्या हो सकती है।

मेरी समस्या का समाधान करने के लिए मुझे पहले भी इसी तरह के मुद्दे का सामना करना पड़ा था और निम्न वर्ग को लिखा गया था

ऑब्जेक्ट: लोकेल \ लोकेल

<?php

  namespace Locale;

  class Locale{

// Following array stolen from Zend Framework
public $country_to_locale = array(
    'AD' => 'ca_AD',
    'AE' => 'ar_AE',
    'AF' => 'fa_AF',
    'AG' => 'en_AG',
    'AI' => 'en_AI',
    'AL' => 'sq_AL',
    'AM' => 'hy_AM',
    'AN' => 'pap_AN',
    'AO' => 'pt_AO',
    'AQ' => 'und_AQ',
    'AR' => 'es_AR',
    'AS' => 'sm_AS',
    'AT' => 'de_AT',
    'AU' => 'en_AU',
    'AW' => 'nl_AW',
    'AX' => 'sv_AX',
    'AZ' => 'az_Latn_AZ',
    'BA' => 'bs_BA',
    'BB' => 'en_BB',
    'BD' => 'bn_BD',
    'BE' => 'nl_BE',
    'BF' => 'mos_BF',
    'BG' => 'bg_BG',
    'BH' => 'ar_BH',
    'BI' => 'rn_BI',
    'BJ' => 'fr_BJ',
    'BL' => 'fr_BL',
    'BM' => 'en_BM',
    'BN' => 'ms_BN',
    'BO' => 'es_BO',
    'BR' => 'pt_BR',
    'BS' => 'en_BS',
    'BT' => 'dz_BT',
    'BV' => 'und_BV',
    'BW' => 'en_BW',
    'BY' => 'be_BY',
    'BZ' => 'en_BZ',
    'CA' => 'en_CA',
    'CC' => 'ms_CC',
    'CD' => 'sw_CD',
    'CF' => 'fr_CF',
    'CG' => 'fr_CG',
    'CH' => 'de_CH',
    'CI' => 'fr_CI',
    'CK' => 'en_CK',
    'CL' => 'es_CL',
    'CM' => 'fr_CM',
    'CN' => 'zh_Hans_CN',
    'CO' => 'es_CO',
    'CR' => 'es_CR',
    'CU' => 'es_CU',
    'CV' => 'kea_CV',
    'CX' => 'en_CX',
    'CY' => 'el_CY',
    'CZ' => 'cs_CZ',
    'DE' => 'de_DE',
    'DJ' => 'aa_DJ',
    'DK' => 'da_DK',
    'DM' => 'en_DM',
    'DO' => 'es_DO',
    'DZ' => 'ar_DZ',
    'EC' => 'es_EC',
    'EE' => 'et_EE',
    'EG' => 'ar_EG',
    'EH' => 'ar_EH',
    'ER' => 'ti_ER',
    'ES' => 'es_ES',
    'ET' => 'en_ET',
    'FI' => 'fi_FI',
    'FJ' => 'hi_FJ',
    'FK' => 'en_FK',
    'FM' => 'chk_FM',
    'FO' => 'fo_FO',
    'FR' => 'fr_FR',
    'GA' => 'fr_GA',
    'GB' => 'en_GB',
    'GD' => 'en_GD',
    'GE' => 'ka_GE',
    'GF' => 'fr_GF',
    'GG' => 'en_GG',
    'GH' => 'ak_GH',
    'GI' => 'en_GI',
    'GL' => 'iu_GL',
    'GM' => 'en_GM',
    'GN' => 'fr_GN',
    'GP' => 'fr_GP',
    'GQ' => 'fan_GQ',
    'GR' => 'el_GR',
    'GS' => 'und_GS',
    'GT' => 'es_GT',
    'GU' => 'en_GU',
    'GW' => 'pt_GW',
    'GY' => 'en_GY',
    'HK' => 'zh_Hant_HK',
    'HM' => 'und_HM',
    'HN' => 'es_HN',
    'HR' => 'hr_HR',
    'HT' => 'ht_HT',
    'HU' => 'hu_HU',
    'ID' => 'id_ID',
    'IE' => 'en_IE',
    'IL' => 'he_IL',
    'IM' => 'en_IM',
    'IN' => 'hi_IN',
    'IO' => 'und_IO',
    'IQ' => 'ar_IQ',
    'IR' => 'fa_IR',
    'IS' => 'is_IS',
    'IT' => 'it_IT',
    'JE' => 'en_JE',
    'JM' => 'en_JM',
    'JO' => 'ar_JO',
    'JP' => 'ja_JP',
    'KE' => 'en_KE',
    'KG' => 'ky_Cyrl_KG',
    'KH' => 'km_KH',
    'KI' => 'en_KI',
    'KM' => 'ar_KM',
    'KN' => 'en_KN',
    'KP' => 'ko_KP',
    'KR' => 'ko_KR',
    'KW' => 'ar_KW',
    'KY' => 'en_KY',
    'KZ' => 'ru_KZ',
    'LA' => 'lo_LA',
    'LB' => 'ar_LB',
    'LC' => 'en_LC',
    'LI' => 'de_LI',
    'LK' => 'si_LK',
    'LR' => 'en_LR',
    'LS' => 'st_LS',
    'LT' => 'lt_LT',
    'LU' => 'fr_LU',
    'LV' => 'lv_LV',
    'LY' => 'ar_LY',
    'MA' => 'ar_MA',
    'MC' => 'fr_MC',
    'MD' => 'ro_MD',
    'ME' => 'sr_Latn_ME',
    'MF' => 'fr_MF',
    'MG' => 'mg_MG',
    'MH' => 'mh_MH',
    'MK' => 'mk_MK',
    'ML' => 'bm_ML',
    'MM' => 'my_MM',
    'MN' => 'mn_Cyrl_MN',
    'MO' => 'zh_Hant_MO',
    'MP' => 'en_MP',
    'MQ' => 'fr_MQ',
    'MR' => 'ar_MR',
    'MS' => 'en_MS',
    'MT' => 'mt_MT',
    'MU' => 'mfe_MU',
    'MV' => 'dv_MV',
    'MW' => 'ny_MW',
    'MX' => 'es_MX',
    'MY' => 'ms_MY',
    'MZ' => 'pt_MZ',
    'NA' => 'kj_NA',
    'NC' => 'fr_NC',
    'NE' => 'ha_Latn_NE',
    'NF' => 'en_NF',
    'NG' => 'en_NG',
    'NI' => 'es_NI',
    'NL' => 'nl_NL',
    'NO' => 'nb_NO',
    'NP' => 'ne_NP',
    'NR' => 'en_NR',
    'NU' => 'niu_NU',
    'NZ' => 'en_NZ',
    'OM' => 'ar_OM',
    'PA' => 'es_PA',
    'PE' => 'es_PE',
    'PF' => 'fr_PF',
    'PG' => 'tpi_PG',
    'PH' => 'fil_PH',
    'PK' => 'ur_PK',
    'PL' => 'pl_PL',
    'PM' => 'fr_PM',
    'PN' => 'en_PN',
    'PR' => 'es_PR',
    'PS' => 'ar_PS',
    'PT' => 'pt_PT',
    'PW' => 'pau_PW',
    'PY' => 'gn_PY',
    'QA' => 'ar_QA',
    'RE' => 'fr_RE',
    'RO' => 'ro_RO',
    'RS' => 'sr_Cyrl_RS',
    'RU' => 'ru_RU',
    'RW' => 'rw_RW',
    'SA' => 'ar_SA',
    'SB' => 'en_SB',
    'SC' => 'crs_SC',
    'SD' => 'ar_SD',
    'SE' => 'sv_SE',
    'SG' => 'en_SG',
    'SH' => 'en_SH',
    'SI' => 'sl_SI',
    'SJ' => 'nb_SJ',
    'SK' => 'sk_SK',
    'SL' => 'kri_SL',
    'SM' => 'it_SM',
    'SN' => 'fr_SN',
    'SO' => 'sw_SO',
    'SR' => 'srn_SR',
    'ST' => 'pt_ST',
    'SV' => 'es_SV',
    'SY' => 'ar_SY',
    'SZ' => 'en_SZ',
    'TC' => 'en_TC',
    'TD' => 'fr_TD',
    'TF' => 'und_TF',
    'TG' => 'fr_TG',
    'TH' => 'th_TH',
    'TJ' => 'tg_Cyrl_TJ',
    'TK' => 'tkl_TK',
    'TL' => 'pt_TL',
    'TM' => 'tk_TM',
    'TN' => 'ar_TN',
    'TO' => 'to_TO',
    'TR' => 'tr_TR',
    'TT' => 'en_TT',
    'TV' => 'tvl_TV',
    'TW' => 'zh_Hant_TW',
    'TZ' => 'sw_TZ',
    'UA' => 'uk_UA',
    'UG' => 'sw_UG',
    'UM' => 'en_UM',
    'US' => 'en_US',
    'UY' => 'es_UY',
    'UZ' => 'uz_Cyrl_UZ',
    'VA' => 'it_VA',
    'VC' => 'en_VC',
    'VE' => 'es_VE',
    'VG' => 'en_VG',
    'VI' => 'en_VI',
    'VN' => 'vn_VN',
    'VU' => 'bi_VU',
    'WF' => 'wls_WF',
    'WS' => 'sm_WS',
    'YE' => 'ar_YE',
    'YT' => 'swb_YT',
    'ZA' => 'en_ZA',
    'ZM' => 'en_ZM',
    'ZW' => 'sn_ZW'
);

/**
 * Store the transaltion for specific languages
 *
 * @var array
 */
protected $translation = array();

/**
 * Current locale
 *
 * @var string
 */
protected $locale;

/**
 * Default locale
 *
 * @var string
 */
protected $default_locale;

/**
 *
 * @var string
 */
protected $locale_dir;

/**
 * Construct.
 *
 *
 * @param string $locale_dir            
 */
public function __construct($locale_dir)
{
    $this->locale_dir = $locale_dir;
}

/**
 * Set the user define localte
 *
 * @param string $locale            
 */
public function setLocale($locale = null)
{
    $this->locale = $locale;

    return $this;
}

/**
 * Get the user define locale
 *
 * @return string
 */
public function getLocale()
{
    return $this->locale;
}

/**
 * Get the Default locale
 *
 * @return string
 */
public function getDefaultLocale()
{
    return $this->default_locale;
}

/**
 * Set the default locale
 *
 * @param string $locale            
 */
public function setDefaultLocale($locale)
{
    $this->default_locale = $locale;

    return $this;
}

/**
 * Determine if transltion exist or translation key exist
 *
 * @param string $locale            
 * @param string $key            
 * @return boolean
 */
public function hasTranslation($locale, $key = null)
{
    if (null == $key && isset($this->translation[$locale])) {
        return true;
    } elseif (isset($this->translation[$locale][$key])) {
        return true;
    }

    return false;
}

/**
 * Get the transltion for required locale or transtion for key
 *
 * @param string $locale            
 * @param string $key            
 * @return array
 */
public function getTranslation($locale, $key = null)
{
    if (null == $key && $this->hasTranslation($locale)) {
        return $this->translation[$locale];
    } elseif ($this->hasTranslation($locale, $key)) {
        return $this->translation[$locale][$key];
    }

    return array();
}

/**
 * Set the transtion for required locale
 *
 * @param string $locale
 *            Language code
 * @param string $trans
 *            translations array
 */
public function setTranslation($locale, $trans = array())
{
    $this->translation[$locale] = $trans;
}

/**
 * Remove transltions for required locale
 *
 * @param string $locale            
 */
public function removeTranslation($locale = null)
{
    if (null === $locale) {
        unset($this->translation);
    } else {
        unset($this->translation[$locale]);
    }
}

/**
 * Initialize locale
 *
 * @param string $locale            
 */
public function init($locale = null, $default_locale = null)
{
    // check if previously set locale exist or not
    $this->init_locale();
    if ($this->locale != null) {
        return;
    }

    if ($locale == null || (! preg_match('#^[a-z]+_[a-zA-Z_]+$#', $locale) && ! preg_match('#^[a-z]+_[a-zA-Z]+_[a-zA-Z_]+$#', $locale))) {
        $this->detectLocale();
    } else {
        $this->locale = $locale;
    }

    $this->init_locale();
}

/**
 * Attempt to autodetect locale
 *
 * @return void
 */
private function detectLocale()
{
    $locale = false;

    // GeoIP
    if (function_exists('geoip_country_code_by_name') && isset($_SERVER['REMOTE_ADDR'])) {

        $country = geoip_country_code_by_name($_SERVER['REMOTE_ADDR']);

        if ($country) {

            $locale = isset($this->country_to_locale[$country]) ? $this->country_to_locale[$country] : false;
        }
    }

    // Try detecting locale from browser headers
    if (! $locale) {

        if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {

            $languages = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);

            foreach ($languages as $lang) {

                $lang = str_replace('-', '_', trim($lang));

                if (strpos($lang, '_') === false) {

                    if (isset($this->country_to_locale[strtoupper($lang)])) {

                        $locale = $this->country_to_locale[strtoupper($lang)];
                    }
                } else {

                    $lang = explode('_', $lang);

                    if (count($lang) == 3) {
                        // language_Encoding_COUNTRY
                        $this->locale = strtolower($lang[0]) . ucfirst($lang[1]) . strtoupper($lang[2]);
                    } else {
                        // language_COUNTRY
                        $this->locale = strtolower($lang[0]) . strtoupper($lang[1]);
                    }

                    return;
                }
            }
        }
    }

    // Resort to default locale specified in config file
    if (! $locale) {
        $this->locale = $this->default_locale;
    }
}

/**
 * Check if config for selected locale exists
 *
 * @return void
 */
private function init_locale()
{
    if (! file_exists(sprintf('%s/%s.php', $this->locale_dir, $this->locale))) {
        $this->locale = $this->default_locale;
    }
}

/**
 * Load a Transtion into array
 *
 * @return void
 */
private function loadTranslation($locale = null, $force = false)
{
    if ($locale == null)
        $locale = $this->locale;

    if (! $this->hasTranslation($locale)) {
        $this->setTranslation($locale, include (sprintf('%s/%s.php', $this->locale_dir, $locale)));
    }
}

/**
 * Translate a key
 *
 * @param
 *            string Key to be translated
 * @param
 *            string optional arguments
 * @return string
 */
public function translate($key)
{
    $this->init();
    $this->loadTranslation($this->locale);

    if (! $this->hasTranslation($this->locale, $key)) {

        if ($this->locale !== $this->default_locale) {

            $this->loadTranslation($this->default_locale);

            if ($this->hasTranslation($this->default_locale, $key)) {

                $translation = $this->getTranslation($this->default_locale, $key);
            } else {
                // return key as it is or log error here
                return $key;
            }
        } else {
            return $key;
        }
    } else {
        $translation = $this->getTranslation($this->locale, $key);
    }
    // Replace arguments
    if (false !== strpos($translation, '{a:')) {
        $replace = array();
        $args = func_get_args();
        for ($i = 1, $max = count($args); $i < $max; $i ++) {
            $replace['{a:' . $i . '}'] = $args[$i];
        }
        // interpolate replacement values into the messsage then return
        return strtr($translation, $replace);
    }

    return $translation;
  }
}

प्रयोग

 <?php
    ## /locale/en.php

    return array(
       'name' => 'Hello {a:1}'
       'name_full' => 'Hello {a:1} {a:2}'
   );

$locale = new Locale(__DIR__ . '/locale');
$locale->setLocale('en');// load en.php from locale dir
//want to work with auto detection comment $locale->setLocale('en');

echo $locale->translate('name', 'Foo');
echo $locale->translate('name', 'Foo', 'Bar');

यह काम किस प्रकार करता है

{a:1}विधि द्वारा पारित 1 तर्क द्वारा प्रतिस्थापित किया जाता है, विधि Locale::translate('key_name','arg1') {a:2}द्वारा पारित 2 तर्क द्वारा प्रतिस्थापित किया जाता हैLocale::translate('key_name','arg1','arg2')

कैसे पता चलता है काम करता है

  • डिफ़ॉल्ट रूप से यदि geoipइंस्टॉल किया गया है तो यह देश कोड को वापस कर देगा geoip_country_code_by_nameऔर यदि जियोइप में HTTP_ACCEPT_LANGUAGEहेडर के लिए फालबैक स्थापित नहीं किया गया है

किस तरह से एक डेटाबेस गड़बड़ होगा? विभिन्न भाषाओं में संभावित पात्रों के कारण? अब तक मैं मुख्य रूप से अंग्रेजी, फ्रेंच, डच, जर्मन वेबसाइटें बना रहा हूं ताकि अब कोई समस्या न हो। उत्तर के लिए धन्यवाद, लेकिन चूंकि यह उत्तर का सिर्फ एक हिस्सा है, इसलिए यह इनाम नहीं जीतेगा।
जोशुआ - पेन्डो

अच्छी तरह से मुझे लगता है कि आपका प्रश्न केवल आपके लिए उपयोगी है केवल कुछ लोग होंगे जो आपकी आवश्यक भाषाओं के विरुद्ध हिंदी, थाई, चीनी और अरबी (ये भाषाएं वर्णों का प्रतिनिधित्व करने के लिए 1 बाइट अधिक लेगी) जैसी भाषाओं का उपयोग करने पर विचार करेंगे। अगर आप db का उपयोग कर रहे हैं तो utf8_general_ciकोलाज करना उचित तरीका है।
शुशांत

मैं सहमत हूं, मुझे खुद वहां थोड़ा ट्रैक मिला। इंगित करने के लिए धन्यवाद, इस प्रश्न में उल्लेखित होने के लिए भी बहु-बिट पात्र महत्वपूर्ण हैं :)
जोशुआ - पेन्डो

5

बस एक उप जवाब: बिल्कुल उनके सामने एक भाषा पहचानकर्ता के साथ अनुवादित यूआरएल का उपयोग करें: http://www.domain.com/nl/over-ons
हाइब्रिड समाधान जटिल हो जाते हैं, इसलिए मैं बस इसके साथ रहना होगा। क्यों? क्योंकि यूआरएल एसईओ के लिए आवश्यक है।

डीबी अनुवाद के बारे में: क्या भाषाओं की संख्या कम या ज्यादा है? या अप्रत्याशित और गतिशील? यदि यह तय हो गया है, तो मैं सिर्फ नए कॉलम जोड़ूंगा, अन्यथा कई तालिकाओं के साथ जाएं।

लेकिन आम तौर पर, Drupal का उपयोग क्यों नहीं किया जाता है? मुझे पता है कि हर कोई अपना सीएमएस बनाना चाहता है क्योंकि यह तेज़, दुबला, इत्यादि है, लेकिन यह वास्तव में एक बुरा विचार है!


1
आपके उत्तर के लिए धन्यवाद। मैं Drupal / Joomla का उपयोग नहीं करना चाहता, इसका कारण यह है: मैं यह सुनिश्चित करना चाहता हूं कि मैं अपने सिस्टम के सभी ins और बहिष्कार, पॉज़िबल खामियों को जानता हूं, कोड कैसे बनता है (और महत्वपूर्ण: 300 प्रोग्रामर द्वारा एक साथ निर्माण नहीं) । मुझे ओपन सोर्स नहीं चुनने के लिए पर्याप्त कारणों से अधिक मिला है। इसके अलावा, मैं चाहता हूं कि मेरी कंपनी मेरे ग्राहकों के लिए एक महत्वपूर्ण कारक हो, यह एक बुरी बात है कि वे किसी भी अन्य डेवलपर के पास जा सकते हैं और मुझे कुछ भी नहीं छोड़ सकते हैं।
यहोशू - पेन्डो

7
मुझे लगता है कि ये सभी कारण बहुत सारे लेखों में विवादित हैं। आपके ग्राहक उम्मीद करेंगे कि वे आपको नहीं चुनेंगे क्योंकि आपके पास एक मालिकाना सीएमएस है जिसे कोई और नहीं रख सकता है। लेकिन वैसे भी, यह एक बिल्कुल अलग चर्चा है।
रेमी

1
मैं आपकी बात समझता हूं, फिर भी मैं एक ऐसी प्रणाली को पसंद करता हूं, जिसे मैं सभी ins और outs के लिए जानता हूं और जब मैं एक प्लगइन का उपयोग करता हूं, तो मुझे किसी के काम पर भरोसा करने के लिए कुछ भी महसूस नहीं होता है।
जोशुआ - पेन्डो

1
इसके अलावा, मैं अपने काम को अच्छी तरह से प्रलेखित करता हूं, क्योंकि मैं "वन मैन आर्मी" हूं, जो मेरे लिए काम करते हैं, उन्हें सिस्टम को जानने के लिए कठिन समय नहीं होना चाहिए।
जोशुआ - पेन्डो

बुरा विचार Drupal को चुनना है और यहां तक ​​कि Google का कहना है कि उन्हें परवाह नहीं है कि url अनुवादित है या नहीं। हालांकि इसमें एक स्थानीय पहचानकर्ता होना चाहिए।
अपरिभाषित

5

मैं पहले से दिए गए उत्तरों को परिष्कृत करने का प्रयास नहीं करने जा रहा हूं। इसके बजाय मैं आपको बताऊंगा कि जिस तरह से मेरा खुद का OOP PHP फ्रेमवर्क अनुवादों को संभालता है।

आंतरिक रूप से, मेरा ढांचा एन, फ्र, एसई, सीएन और इतने पर जैसे कोड का उपयोग करता है। एक सरणी वेबसाइट द्वारा समर्थित भाषाओं को रखती है: सरणी ('en', 'fr', 'es', 'cn') भाषा कोड $ _GET (lang = fr) के माध्यम से पारित किया जाता है और यदि पारित नहीं हुआ या मान्य नहीं है, तो यह सरणी में पहली भाषा पर सेट है। तो किसी भी समय कार्यक्रम के निष्पादन के दौरान और बहुत शुरुआत से, वर्तमान भाषा ज्ञात है।

यह उस सामग्री को समझने के लिए उपयोगी है जिसे किसी विशिष्ट अनुप्रयोग में अनुवादित करने की आवश्यकता है:

1) कक्षाओं से त्रुटि संदेश (या प्रक्रियात्मक कोड) 2) कक्षाओं (या प्रक्रियात्मक कोड) 3 से गैर-त्रुटि संदेश पृष्ठ सामग्री (आमतौर पर डेटाबेस में संग्रहीत) 4) साइट-वाइड स्ट्रिंग्स (जैसे वेबसाइट का नाम) 5) स्क्रिप्ट- विशिष्ट तार

पहला प्रकार समझने में सरल है। मूल रूप से, हम संदेशों के बारे में बात कर रहे हैं जैसे "डेटाबेस से कनेक्ट नहीं हो सका ..."। त्रुटि होने पर इन संदेशों को केवल लोड करने की आवश्यकता होती है। मेरा प्रबंधक वर्ग अन्य कक्षाओं से कॉल प्राप्त करता है और पास की गई जानकारी का उपयोग करते हुए पैरामीटर बस क्लास फ़ोल्डर को प्रासंगिक करता है और त्रुटि फ़ाइल को पुनर्प्राप्त करता है।

दूसरे प्रकार का त्रुटि संदेश उन संदेशों की तरह अधिक होता है जो आपको तब मिलते हैं जब किसी फॉर्म की मान्यता गलत हो जाती है। ("आप नहीं छोड़ सकते ... रिक्त" या "कृपया 5 से अधिक वर्णों वाला पासवर्ड चुनें")। क्लास चलने से पहले स्ट्रिंग्स को लोड करना होगा। मुझे पता है कि क्या है

वास्तविक पृष्ठ सामग्री के लिए, मैं भाषा के लिए एक तालिका का उपयोग करता हूं, प्रत्येक तालिका भाषा के लिए कोड द्वारा उपसर्ग करती है। तो en_content अंग्रेजी भाषा की सामग्री के साथ तालिका है, es_content चीन के लिए है, cn_content के लिए है और fr_content फ्रांसीसी सामान है।

चौथे प्रकार की स्ट्रिंग आपकी वेबसाइट पर प्रासंगिक है। यह भाषा के लिए कोड का उपयोग करके नाम कॉन्फ़िगरेशन फ़ाइल के माध्यम से लोड किया गया है, जो कि en_lang.php, es_lang.php और इसी तरह है। वैश्विक भाषा फ़ाइल में आपको अनुवादित भाषाओं जैसे सरणी ('अंग्रेजी', 'चीनी', 'स्पेनिश', 'फ्रेंच') को अंग्रेजी वैश्विक फ़ाइल और सरणी ('एंग्लिस', 'चिनचिन', ') में लोड करना होगा फ्रेंच फाइल में एस्पैग्नोल ',' फ्रैंकिस ')। इसलिए जब आप भाषा चयन के लिए एक ड्रॉपडाउन पॉप्युलेट करते हैं, तो यह सही भाषा में है;)

अंत में आपके पास स्क्रिप्ट-विशिष्ट स्ट्रिंग्स हैं। इसलिए यदि आप खाना पकाने का आवेदन लिखते हैं, तो यह हो सकता है "आपका ओवन पर्याप्त गर्म नहीं था"।

मेरे आवेदन चक्र में, वैश्विक भाषा फ़ाइल पहले भरी हुई है। वहां आपको न केवल वैश्विक तार मिलेंगे (जैसे "जैक की वेबसाइट"), लेकिन कुछ कक्षाओं के लिए सेटिंग्स भी। मूल रूप से कोई भी चीज जो भाषा या संस्कृति पर निर्भर है। वहाँ के कुछ तार में तारीखों के लिए मुखौटे (MMDDYYYY या DDMMYYYY), या ISO भाषा कोड शामिल हैं। मुख्य भाषा फ़ाइल में, मैं अलग-अलग वर्गों के लिए तार शामिल करता हूँ क्योंकि उनमें से बहुत कम हैं।

दूसरी और आखिरी भाषा की फाइल जो डिस्क से पढ़ी जाती है, वह स्क्रिप्ट लैंग्वेज फाइल होती है। lang_en_home_welcome.php होम / वेलकम स्क्रिप्ट के लिए भाषा फ़ाइल है। एक स्क्रिप्ट को एक मोड (होम) और एक एक्शन (स्वागत) द्वारा परिभाषित किया गया है। प्रत्येक स्क्रिप्ट में कॉन्फिग और लैंग फाइल्स के साथ अपना एक फोल्डर होता है।

स्क्रिप्ट डेटाबेस से सामग्री को ऊपर बताए अनुसार सामग्री तालिका का नामकरण खींचती है।

यदि कुछ गलत हो जाता है, तो प्रबंधक जानता है कि भाषा-निर्भर त्रुटि फ़ाइल कहाँ से प्राप्त करें। वह फ़ाइल केवल एक त्रुटि के मामले में भरी हुई है।

इसलिए निष्कर्ष स्पष्ट है। किसी एप्लिकेशन या ढांचे को विकसित करने से पहले अनुवाद के मुद्दों के बारे में सोचें। आपको अनुवादों को शामिल करने वाले विकास वर्कफ़्लो की भी आवश्यकता है। अपने ढांचे के साथ, मैं पूरी साइट को अंग्रेजी में विकसित करता हूं और फिर सभी प्रासंगिक फाइलों का अनुवाद करता हूं।

जिस तरह से अनुवाद के तार को लागू किया जाता है उस पर बस एक त्वरित अंतिम शब्द। मेरे ढांचे में एक वैश्विक, $ प्रबंधक है, जो किसी अन्य सेवा के लिए उपलब्ध सेवाएं चलाता है। इसलिए उदाहरण के लिए फॉर्म सेवा को html सेवा मिलती है और इसका उपयोग html लिखने के लिए किया जाता है। मेरे सिस्टम पर सेवाओं में से एक अनुवादक सेवा है। $ अनुवादक-> सेट ($ सेवा, $ कोड, $ स्ट्रिंग) वर्तमान भाषा के लिए एक स्ट्रिंग सेट करता है। भाषा फ़ाइल ऐसे बयानों की एक सूची है। $ अनुवादक-> ($ सेवा, $ कोड) एक अनुवाद स्ट्रिंग को पुनः प्राप्त करता है। $ कोड 1 या 'no_connection' जैसे स्ट्रिंग की तरह संख्यात्मक हो सकता है। सेवाओं के बीच कोई टकराव नहीं हो सकता क्योंकि प्रत्येक का अनुवादक के डेटा क्षेत्र में अपना स्वयं का नाम स्थान है।

मैं इसे इस उम्मीद में यहाँ पोस्ट करता हूँ कि यह किसी को पहिया को फिर से स्थापित करने के कार्य को बचाएगा जैसे मुझे कुछ साल पहले करना था।


4

सिम्फनी फ्रेमवर्क का उपयोग शुरू करने से पहले कुछ समय पहले मेरे पास एक ही प्रोबेम था ।

  1. बस एक फ़ंक्शन __ () का उपयोग करें जिसमें arameters pageId (या objectId, ऑब्जेक्टटेबल # 2 में वर्णित है), लक्ष्य भाषा और फ़ॉलबैक (डिफ़ॉल्ट) भाषा का एक वैकल्पिक पैरामीटर है। डिफ़ॉल्ट भाषा को कुछ वैश्विक कॉन्फ़िगरेशन में सेट किया जा सकता है ताकि बाद में इसे बदलने का एक आसान तरीका हो सके।

  2. डेटाबेस में सामग्री को संग्रहीत करने के लिए मैंने निम्नलिखित संरचना का उपयोग किया: (पेजआईड, भाषा, सामग्री, चर)।

    • pageId आपके पृष्ठ का FK होगा, जिसका आप अनुवाद करना चाहते हैं। यदि आपके पास अन्य वस्तुएं हैं, जैसे समाचार, गैलरी या जो भी हो, बस इसे 2 क्षेत्रों में विभाजित करें objectId, objectTable।

    • भाषा - जाहिर है कि यह ISO भाषा स्ट्रिंग EN_en, LT_lt, EN_us आदि को संग्रहीत करेगा।

    • सामग्री - वह पाठ जिसे आप वेरिएबल रिप्लेसिंग के लिए वाइल्डकार्ड के साथ अनुवाद करना चाहते हैं। उदाहरण "हैलो श्री। %% नाम %%। आपका खाता शेष%% शेष %% है।"

    • वैरिएबल - जसन एन्कोडेड वैरिएबल। PHP इनको जल्दी से पार्स करने के लिए कार्य प्रदान करता है। उदाहरण "नाम: लॉरेंस, संतुलन: 15.23"।

    • आपने स्लग क्षेत्र का भी उल्लेख किया है। आप इसे स्वतंत्र रूप से इस तालिका में जोड़ सकते हैं, इसके लिए एक त्वरित तरीका खोज सकते हैं।

  3. अनुवादों को कैच करने के साथ आपका डेटाबेस कॉल्स न्यूनतम होना चाहिए। इसे PHP सरणी में संग्रहीत किया जाना चाहिए, क्योंकि यह PHP भाषा में सबसे तेज़ संरचना है। आप यह कैसे करेंगे आप पर निर्भर है। मेरे अनुभव से आपके पास समर्थित प्रत्येक भाषा के लिए एक फ़ोल्डर और प्रत्येक पृष्ठ के लिए एक सरणी होनी चाहिए। अनुवाद को अपडेट करने के बाद कैश को फिर से बनाया जाना चाहिए। केवल परिवर्तित सरणी को पुनर्जीवित किया जाना चाहिए।

  4. मुझे लगता है कि मैंने # 2 में उत्तर दिया

  5. आपका विचार पूरी तरह से तार्किक है। यह एक बहुत सरल है और मुझे लगता है कि आपको कोई समस्या नहीं होगी।

अनुवाद तालिका में संग्रहीत स्लग का उपयोग करके URL का अनुवाद किया जाना चाहिए।

अंतिम शब्द

सर्वोत्तम प्रथाओं पर शोध करना हमेशा अच्छा होता है, लेकिन पहिया को सुदृढ़ नहीं करना चाहिए। बस अच्छी तरह से ज्ञात रूपरेखाओं से घटकों को लें और उनका उपयोग करें और उनका उपयोग करें।

सिम्फनी अनुवाद घटक पर एक नज़र डालें । यह आपके लिए एक अच्छा कोड आधार हो सकता है।


टिप्पणी के लिए धन्यवाद, अपने समय के लिए एक +1 प्राप्त करें। लारवेल (मेरे मामले में) अगर मैं गलत नहीं हूं तो कुछ सिम्फनी भागों का उपयोग कर रहा हूं, इसलिए आप पहिया को फिर से स्थापित नहीं करने के बारे में बिल्कुल सही हैं। मैंने यह प्रश्न (और इनाम) शुरू किया कि कुछ लोग जिस तरह से अनुवाद करते हैं, उसमें कुछ अंतर्दृष्टि प्राप्त करने के लिए, मुझे विश्वास है कि वहाँ सबसे अच्छा अभ्यास कर रहे हैं :-)
जोशुआ - पेन्डो

1

मैं अपने आप से संबंधित प्रश्न बार-बार पूछ रहा हूं, फिर औपचारिक भाषाओं में खो गया ... लेकिन बस आपको थोड़ी मदद करने के लिए मैं कुछ निष्कर्ष साझा करना चाहूंगा:

मैं उन्नत सीएमएस पर एक नज़र डालने की सलाह देता हूं

Typo3के लिए PHP (मुझे पता है कि सामान बहुत है, लेकिन मुझे लगता है कि सबसे अधिक परिपक्व है)

Plone में Python

यदि आपको पता चलता है कि 2013 में वेब को अलग काम करना चाहिए, तो खरोंच से शुरू करें। इसका मतलब होगा कि एक नया सीएमएस बनाने के लिए अत्यधिक कुशल / अनुभवी लोगों की टीम को एक साथ रखना। हो सकता है कि आप उस उद्देश्य के लिए बहुलक पर एक नज़र डालना चाहते हैं।

यदि यह कोडिंग और बहुभाषी वेबसाइटों / मूल भाषा समर्थन की बात आती है, तो मुझे लगता है कि हर प्रोग्रामर के पास यूनिकोड के बारे में एक सुराग होना चाहिए। यदि आप यूनिकोड नहीं जानते हैं तो आप निश्चित रूप से अपने डेटा को गड़बड़ कर देंगे। हजारों आईएसओ कोड के साथ मत जाओ। वे आपको केवल कुछ मेमोरी बचाएंगे। लेकिन आप यूटीएफ -8 के साथ शाब्दिक रूप से चीनी चरस की दुकान भी कर सकते हैं। लेकिन इसके लिए आपको 2 या 4 बाइट वर्णों को संग्रहीत करने की आवश्यकता होगी जो इसे मूल रूप से utf-16 या utf-32 बनाता है।

यदि यह URL एन्कोडिंग के बारे में है, तो वहां फिर से आपको एनकोडिंग नहीं मिलनी चाहिए और पता होना चाहिए कि कम से कम डोमेन नाम के लिए अलग-अलग लॉबी द्वारा परिभाषित नियम हैं जो ब्राउज़र की तरह एप्लिकेशन प्रदान करते हैं। जैसे डोमेन बहुत समान हो सकता है:

ьankofamerica.com या bankofamerica.com samesamebutdifferent;)

बेशक आपको सभी एन्कोडिंग के साथ काम करने के लिए फाइल सिस्टम की आवश्यकता है। Utf-8 फाइलसिस्टम का उपयोग करके यूनिकोड के लिए एक और प्लस।

यदि इसके अनुवाद के बारे में, दस्तावेजों की संरचना के बारे में सोचें। जैसे कोई किताब या कोई लेख। आपके पास docbookउन संरचनाओं के बारे में समझने के लिए विनिर्देश हैं। लेकिन HTML में इसकी सामग्री ब्लॉक के बारे में है। इसलिए आप उस स्तर पर अनुवाद करना चाहते हैं, वह भी वेबपेज स्तर या डोमेन स्तर पर। इसलिए यदि कोई ब्लॉक मौजूद नहीं है, तो यदि कोई वेबपेज मौजूद नहीं है, तो आप ऊपरी नेविगेशन स्तर पर पुनर्निर्देशित हो जाएंगे। यदि किसी डोमेन को नेविगेशन संरचना में पूरी तरह से अलग होना चाहिए, तो .. इसके प्रबंधन के लिए एक पूर्ण अलग संरचना। यह पहले से ही टाइपो 3 के साथ किया जा सकता है।

अगर इसके ढांचे के बारे में, सबसे अधिक परिपक्व जिन्हें मैं जानता हूं, एमवीसी की तरह सामान्य सामान करने के लिए (buzzword मैं वास्तव में इसे नफरत करता हूं! जैसे "प्रदर्शन" यदि आप कुछ बेचना चाहते हैं, तो प्रदर्शन और करतब दिखाने वाले शब्द का उपयोग करें और आप बेचते हैं ... क्या द) है Zend । यह php अराजकता कॉडर्स के मानकों को लाने के लिए एक अच्छी बात साबित हुई है। लेकिन, टाइपो 3 में सीएमएस के अलावा एक फ्रेमवर्क भी है। हाल ही में इसका पुनर्विकास किया गया है और इसे फ्लो 3 कहा जाता है। बेशक डेटाबेस के ढांचे में अमूर्तता, टेम्प्लेटिंग और कैशिंग के लिए अवधारणाएं शामिल हैं, लेकिन व्यक्तिगत ताकत है।

यदि इसकी कैशिंग के बारे में ... जो कि बहुत जटिल / बहुस्तरीय हो सकता है। PHP में आप एक्सीलरेटर, ओपोड के बारे में सोचेंगे, लेकिन साथ ही html, httpd, mysql, xml, css, js ... किसी भी प्रकार का कैश। बेशक कुछ हिस्सों को कैश किया जाना चाहिए और ब्लॉग के जवाब की तरह गतिशील भागों को नहीं करना चाहिए। AJAX के लिए जनरेट किए गए यूआरएल के साथ कुछ अनुरोध किया जाना चाहिए। JSON, हैशबैंग आदि।

फिर, आप अपनी वेबसाइट पर केवल कुछ उपयोगकर्ताओं द्वारा एक्सेस या प्रबंधित होने के लिए कोई छोटा घटक रखना चाहते हैं , इसलिए वैचारिक रूप से यह एक बड़ी भूमिका निभाता है।

इसके अलावा, आप करना चाहते हैं आँकड़े , हो सकता है वितरित किया प्रणाली / facebooks आदि किसी भी सॉफ्टवेयर का एक फेसबुक अपने से अधिक शीर्ष सेमी की चोटी पर बनाया जाना है ... ताकि आप विभिन्न प्रकार की जरूरत के डेटाबेस , inmemory, bigdata, एक्सएमएल जो भी ।

ठीक है, मुझे लगता है कि अभी के लिए पर्याप्त है। यदि आपने टाइपो 3 / प्लॉन या उल्लेखित रूपरेखाओं के बारे में नहीं सुना है, तो आपके पास अध्ययन करने के लिए पर्याप्त है। उस रास्ते पर आपको उन सवालों के बहुत सारे समाधान मिलेंगे जो आपने अभी तक नहीं पूछे हैं।

यदि आप सोचते हैं, एक नया सीएमएस बनाने की अनुमति देता है क्योंकि इसका 2013 और php वैसे भी मरने वाला है, तो आप डेवलपर्स के किसी अन्य समूह में शामिल होने का स्वागत करते हैं, उम्मीद है कि खो नहीं जा रहा है।

सौभाग्य!

और btw। कैसे लोगों के बारे में भविष्य में अब और कोई वेबसाइट नहीं होगी? और हम सब गूगल + पर होंगे? मुझे आशा है कि डेवलपर्स थोड़ा और रचनात्मक हो जाएं और कुछ उपयोगी काम करें (बोरगेल द्वारा आत्मसात नहीं किया जाए)

//// संपादित करें /// अपने मौजूदा आवेदन के लिए बस थोड़ा सोचा:

यदि आपके पास php mysql CMS है और आप मल्टीलैंग सपोर्ट को एम्बेड करना चाहते हैं। आप या तो किसी भी भाषा के लिए एक विज्ञापन कॉलम के साथ अपनी तालिका का उपयोग कर सकते हैं या किसी ऑब्जेक्ट आईडी और उसी तालिका में एक भाषा आईडी के साथ अनुवाद सम्मिलित कर सकते हैं या किसी भी भाषा के लिए एक समान तालिका बना सकते हैं और वहां वस्तुओं को सम्मिलित कर सकते हैं, यदि आप चाहें तो एक चयन संघ बनाएं उन सभी को प्रदर्शित करने के लिए डेटाबेस के लिए utf8 सामान्य ci और निश्चित रूप से फ्रंट / बैकएंड उपयोग utf8 टेक्स्ट / एन्कोडिंग का उपयोग करें। मैंने url के लिए url पाथ सेगमेंट का उपयोग उस तरीके से किया है जिस तरह से आप पहले ही समझा चुके हैं

domain.org/en/about से आप लैंग आईडी को अपने कंटेंट टेबल पर मैप कर सकते हैं। वैसे भी आपको अपने यूआरएल के लिए मापदंडों का एक नक्शा होना चाहिए, ताकि आप अपने URL में किसी पाथसेलेक्ट से मैप किए जाने वाले पैरामीटर को परिभाषित करना चाहें, जैसे कि

domain.org/en/about/employees/IT/administrators/

लुकअप कॉन्फ़िगरेशन

pageid | यूआरएल

1 | /about/employees/../ ..

1 | /../about/employees../../

pathlact "" के लिए मानचित्र पैरामीटर

$parameterlist[lang] = array(0=>"nl",1=>"en"); // default nl if 0
$parameterlist[branch] = array(1=>"IT",2=>"DESIGN"); // default nl if 0
$parameterlist[employertype] = array(1=>"admin",1=>"engineer"); //could be a sql result 

$websiteconfig[]=$userwhatever;
$websiteconfig[]=$parameterlist;
$someparameterlist[] = array("branch"=>$someid);
$someparameterlist[] = array("employertype"=>$someid);
function getURL($someparameterlist){ 
// todo foreach someparameter lookup pathsegment 
return path;
}

प्रति कहना, कि ऊपरी पोस्ट में पहले से ही कवर किया गया था।

और भूल नहीं करने के लिए, आपको अपनी जनरेटिंग php फ़ाइल को url को फिर से लिखना होगा "जो कि ज्यादातर मामलों में index.pp होगी।


टिप्पणी के लिए धन्यवाद, सबसे निश्चित रूप से ऐसी चीजें हैं जिनके बारे में मुझे सोचना चाहिए। मैं पहले से ही कुछ वर्षों के लिए अब utf8 एन्कोडिंग का उपयोग कर रहा हूं, मैं एक बार चरित्र के साथ संघर्ष करता था;; दूसरी तरफ सीएमएस / फ्रेमवर्क का प्रकार आपके उत्तर में कोई कारक नहीं था, क्योंकि मैं एक की तलाश में था मंच स्वतंत्र विधि के रूप में अगर हम खरोंच से कोडिंग कर रहे थे।
जोशुआ - पेन्डो

यदि आप वास्तव में स्क्रैच से कोड करना चाहते हैं, तो मैं डार्टलैंग और बहुलक को देखने की सलाह देता हूं। चूंकि डार्टलैंग ब्राउज़र में काम कर रहा है और इसमें 32 और 64 बिट सपोर्ट है और इसे सर्वराइड पर अधिकांश उद्देश्यों के लिए इस्तेमाल किया जा सकता है और इसमें डार्ट 2js कंपाइलर है जिसका वास्तव में अध्ययन करने लायक है। अगर लोग प्लेटफ़ॉर्म आज़ादी के बारे में बात करते हैं तो वे जावा के बारे में सोचते हैं ... हम जानते हैं कि इसका क्या मतलब है। Buildprocess ... मुझे लगता है कि मैं JSON का उपयोग इंटरचेंज के लिए करूंगा। हैशबैंग और सर्वरसाइड के साथ वेबसाइट क्लाइंटसाइड जनरेट करें। सहयोग को सुनिश्चित करने के लिए आप जो भी करना चाहते हैं, अच्छी तरह से करें।
डॉ। दामा

डेटाबेसैलेयूट और पीढ़ी तर्क मुख्य कार्य है। नोबडीज़ आपके लिए यहां ऐसा करने जा रहा है ... लेकिन आइडिया अपने आप में मायने रखता है। चूंकि मैं लॉबी की परवाह नहीं करता हूं, लेकिन चीजों को पूरा करने के लिए, मुझे उम्मीद है कि आप मॉडल बना सकते हैं और कुछ सामान साझा कर सकते हैं। मैं अभी इसी तरह के कार्यों पर काम कर रहा हूं। लेकिन मैं अभी भी प्लानिंग में हूं। मैं टाइपो 3 को एक बैकएंड के रूप में मान रहा हूं और एक नई क्लाइंट संरचना तैयार कर रहा हूं। बहुभाषी पैटर्न बैकएंड में हल किया गया है और खोज इंजन / वेबसर्विसेज के लिए समर्पित तरीके से जानकारी साझा करेगा। वैसे भी इसके सभी संदर्भ और एक निरंतर निर्माण कार्य
डॉ। दामा

-1

डेटाबेस कार्य:

भाषा तालिका बनाएं 'भाषाएँ':

खेत:

language_id(primary and auto increamented)

language_name

created_at

created_by

updated_at

updated_by

डेटाबेस 'सामग्री' में एक तालिका बनाएँ:

खेत:

content_id(primary and auto incremented)

main_content

header_content

footer_content

leftsidebar_content

rightsidebar_content

language_id(foreign key: referenced to languages table)

created_at

created_by

updated_at

updated_by

फ्रंट एंड वर्क:

जब उपयोगकर्ता ड्रॉपडाउन या किसी भी क्षेत्र से किसी भी भाषा का चयन करता है, तो सत्र में चयनित भाषा आईडी जैसे,

$_SESSION['language']=1;

अब सत्र में संग्रहीत भाषा आईडी के आधार पर डेटाबेस तालिका 'सामग्री' से डेटा प्राप्त करें।

विवरण यहाँ पाया जा सकता है http://skillrow.com/multilingual-website-in-php-2/


1
यह सरल भाषा एकीकरण का एक तरीका है, तब क्या आपको भी पूरी पोस्ट और दिए गए उत्तर पढ़ने की कोशिश करनी चाहिए?
जोशुआ - पेन्डो

-2

एक व्यक्ति के रूप में, जो क्यूबेक में रहता है, जहां लगभग सभी साइटें फ्रेंच और अंग्रेजी हैं ... मैंने बहुत कोशिश की है कि अगर WP के लिए सबसे बहुभाषी प्लगइन न हो ... एक एकमात्र उपयोगी समाधान जो मेरी सभी साइट के साथ काम करता है mQtranslate ... मैं इसके साथ रहता और मरता हूँ!

https://wordpress.org/plugins/mqtranslate/


1
हाँ ठीक है, WP सवाल का कोई कारक नहीं था। यह एक टिप्पणी हो सकती है aswel
यहोशू - पेन्डो

-3

WORDPRESS + MULTI-LANGUAGE SITE BASIS(प्लगइन) के बारे में क्या ? साइट में संरचना होगी:

  • example.com/ eng / category1 / ...
  • example.com/ eng / मेरा पृष्ठ ...
  • example.com/ rus / category1 /…।
  • example.com/ rus / my-page…।

प्लगइन सरल तर्क के साथ अनुवाद सभी वाक्यांशों के लिए इंटरफ़ेस प्रदान करता है:

(ENG) my_title - "Hello user"
(SPA) my_title - "Holla usuario"

तो यह उत्पादन किया जा सकता है:
echo translate('my_title', LNG); // LNG is auto-detected

पी एस हालांकि, जाँच करें, अगर प्लगइन अभी भी सक्रिय है।


3
और स्पेनिश में "होला उपयोगकर्ताियो" नहीं है "होला उसेरियो"
भेटकोकर

1
लोल होला उपयोगकर्ताियो, यह अजीब था!
spekdrum

कारण मैं स्पेनिश नहीं जानता था (सिर्फ उदाहरण के लिए इस्तेमाल किया), जल्दी करो नीचा दिखाने के लिए !! :)
टी। टोडुआ

-5

एक बहुत ही सरल विकल्प जो किसी भी वेबसाइट के साथ काम करता है जहां आप जावास्क्रिप्ट अपलोड कर सकते हैं www.multilingualizer.com

यह आपको एक पृष्ठ पर सभी भाषाओं के लिए सभी पाठ डालने देता है और फिर उन भाषाओं को छुपाता है जिन्हें उपयोगकर्ता को देखने की आवश्यकता नहीं है। अच्छा काम करता है।


खबरदार, एसईओ बहुत बुरा होगा! साथ ही आप सभी सामग्री को लोड करते हैं जबकि आपको बस इसके एक हिस्से की आवश्यकता होती है जो वास्तव में बुरा अभ्यास है।
हाफेनक्रिंच ३०'१ran

अजीब सामान है कि साइट केवल अंग्रेजी में है ... वे अपने समाधान का उपयोग क्यों नहीं करते हैं ??
eduardo.lopes
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.