
Rails में एक अंतर्निहित अंतर्राष्ट्रीयकरण फ्रेमवर्क होता है। शुरुआत करने के लिए आपको इससे ज़्यादा कुछ नहीं चाहिए – I18n API स्टैक का हिस्सा है, और यह बुनियादी कार्यों को अच्छी तरह से संभालता है: स्थिर स्ट्रिंग का अनुवाद करना, दिनांक और संख्याओं को फ़ॉर्मेट करना, और विभिन्न लोकेशंस में बहुवचन का प्रबंधन करना।
लेकिन "अंतर्निहित" का मतलब "पूर्ण" नहीं है। जैसे ही आपकी ज़रूरतें स्थानीयकृत यूआरएल, जावास्क्रिप्ट अनुवाद या बहुभाषी एसईओ तक बढ़ जाती हैं, आप रेल्स द्वारा प्रदान की जाने वाली सुविधाओं से बाहर काम कर रहे होते हैं। इन कमियों को दूर करने के लिए आर्किटेक्चर संबंधी सोच-समझकर निर्णय लेने पड़ते हैं।
आइए दोनों स्तरों पर विस्तार से चर्चा करें: रेल्स I18n API क्या संभालता है, और आपको कहां निर्माण करने या कार्य सौंपने की आवश्यकता होगी।
I18n API आपको दो मुख्य विधियाँ प्रदान करता है: स्ट्रिंग का अनुवाद करने के लिए I18n.t और दिनांक और संख्याओं का स्थानीयकरण करने के लिए I18n.l। दोनों config/locales/ में स्थित YAML या Ruby फ़ाइलों से डेटा पढ़ते हैं, और Rails स्टार्टअप के समय उन्हें स्वचालित रूप से लोड कर लेता है।
इसमें मूलतः स्टैटिक यूआई स्ट्रिंग्स, दिनांक और संख्या फ़ॉर्मेटिंग, और एक्टिवरिकॉर्ड सत्यापन संदेश शामिल हैं। अधिकांश एकल-भाषा से एक-भाषा परियोजनाओं के लिए, यह शिपिंग के लिए पर्याप्त है।
आगे बढ़ने पर अंतराल तेजी से दिखाई देने लगते हैं।
Rails I18n URL संरचना के बारे में कोई विशेष राय नहीं रखता: इसमें न तो स्थानीयकृत रूट हैं, न ही सबडोमेन पहचान, और न ही पाथ प्रीफिक्स। इसमें उत्पाद नामों या ब्लॉग पोस्ट जैसी डेटाबेस में संग्रहीत सामग्री के अनुवाद के लिए कोई तंत्र नहीं है। जावास्क्रिप्ट फाइलें पूरी तरह से पाइपलाइन से बाहर होती हैं। और बहुभाषी SEO, जैसे कि hreflang टैग, अनुवादित स्लग और भाषा-विशिष्ट साइटमैप, के लिए अलग से काम करने की आवश्यकता होती है, जिसे फ्रेमवर्क छूता भी नहीं है।
निर्माण शुरू करने से पहले आपको यह जानना होगा कि सीमा कहाँ स्थित है।
आप rails-i18n gem से शुरुआत कर सकते हैं।
Rails केवल अंग्रेज़ी लोकेल डेटा ही प्रदान करता है, इसलिए इसके बिना, I18n.l(Date.today) गैर-अंग्रेज़ी लोकेल में विफल हो जाता है और Active Record सत्यापन संदेशों जैसी फ्रेमवर्क-स्तरीय स्ट्रिंग वर्तमान लोकेल की परवाह किए बिना अंग्रेज़ी में ही रहती हैं।
# जेमफ़ाइल
जेम "रेल्स-i18n"फिर अपने एप्लिकेशन के डिफ़ॉल्ट सेटिंग्स को कॉन्फ़िगर करें:
# config/application.rb
config.i18n.default_locale = :en
config.i18n.available_locales = [:en, :fr]
config.i18n.enforce_available_locales = true
enforce_available_locales = true सेटिंग से त्रुटि उत्पन्न होती है यदि आपका ऐप उस सूची से बाहर किसी लोकेल को सेट करने का प्रयास करता है। इसके बिना, एक टाइपो या गलत URL पैरामीटर उत्पादन में चुपचाप एक असमर्थित लोकेल सेट कर देता है।
आधुनिक Rails एक स्तर तक स्कैन करता है, लेकिन अक्सर यह गहराई से नेस्टेड फ़ोल्डरों (जैसे config/locales/views/products/ ) को छोड़ देता है। इस लाइन को जोड़ने से यह सुनिश्चित होता है कि आपके ऐप के बढ़ने पर प्रत्येक सबडायरेक्टरी शामिल हो जाए:
config.i18n.load_path += Dir[Rails.root.join( "config" , "locales" , "**" , "*.{rb,yml}" )]इससे आप अनुवाद फ़ाइलों को डोमेन के आधार पर विभाजित कर सकते हैं:
config/locales/ en/ models.yml views.yml mailers.yml fr/ models.yml views.yml mailers.yml⚠️ YAML true और false जैसे मानों को बूलियन के रूप में पार्स करता है। यदि आपको उन्हें शाब्दिक पाठ के रूप में चाहिए, तो उन्हें स्पष्ट रूप से उद्धरण चिह्नों में लिखें। आधुनिक Ruby/YAML संस्करण अब yes और no को स्ट्रिंग के रूप में मानते हैं, लेकिन संगतता के लिए उन्हें उद्धरण चिह्नों में लिखना एक सुरक्षित आदत बनी हुई है:
en: answers: affirmative: "yes"
नकारात्मक : "नहीं"यह एक प्रकार के बग को पकड़ता है जो केवल तभी सामने आता है जब अनुवाद "हां" के बजाय "सही" लौटाता है और आपका दृश्य कुछ भी प्रदर्शित नहीं करता है, या इससे भी बदतर, "सही" स्ट्रिंग प्रदर्शित करता है।
व्यू में, t और l दो सहायक फ़ंक्शन हैं जिनका आप लगातार उपयोग करेंगे।
l फ़ंक्शन वर्तमान स्थानीय भाषा के अनुसार दिनांक, समय और संख्याओं का स्थानीयकरण करता है। rails-i18n इंस्टॉल होने पर, 100 से अधिक स्थानीय भाषाओं के लिए प्रारूप परिभाषाएँ शामिल होती हैं। इसके बिना, गैर-अंग्रेज़ी स्थानीय भाषा में l(Date.today) को कॉल करने पर आमतौर पर 'अनुवाद अनुपलब्ध' स्ट्रिंग या एक असंरचित दिनांक प्राप्त होगा, क्योंकि Rails में आवश्यक स्थानीयकृत प्रारूप पैटर्न मौजूद नहीं हैं।
<%= l(Date.today) %>
<%= l(Date.today, format: :long) %>t कुंजी द्वारा स्ट्रिंग का अनुवाद करता है। इसका पूरा रूप t("products.index.title") है, लेकिन व्यू में आप लेज़ी लुकअप शॉर्टहैंड का उपयोग कर सकते हैं:
<%= t(".title") %>शुरुआती बिंदु Rails को यह बताता है कि कुंजी को वर्तमान व्यू पाथ के सापेक्ष हल किया जाए। app/views/products/index.html.erb में, t(".title") स्वचालित रूप से t("products.index.title") में विस्तारित हो जाता है। इससे कुंजी संक्षिप्त रहती है और बिना किसी अतिरिक्त प्रयास के एक सुसंगत नामकरण प्रणाली लागू होती है।
For interpolation, use %{variable} in your YAML and pass the value as a keyword argument:
en:
welcome: "Hello, %{name}"<%= t(".welcome", name: current_user.name) %>यदि किसी अनुवाद में ऐसा HTML शामिल है जिस पर आपको भरोसा है, तो कुंजी के नाम के आगे _html जोड़ दें। Rails इसे स्वचालित रूप से सुरक्षित चिह्नित कर देगा, इसके लिए html_safe कॉल की आवश्यकता नहीं होगी।
en:
notice_html: "Please <strong>confirm</strong> your email."लेज़ी लुकअप केवल वहीं काम करता है जहाँ Rails व्यू पाथ का अनुमान लगा सकता है, यानी यह बैकग्राउंड जॉब्स और API कंट्रोलर्स में काम नहीं करता है। इन स्थितियों में, हर बार पूरी कुंजी का उपयोग करें।
कोई भी लोकेल-डिटेक्शन कोड लिखने से पहले, एक रणनीति चुनें। इसके पाँच मुख्य तरीके हैं, और सही तरीका आपके ऐप की संरचना और SEO आवश्यकताओं पर निर्भर करता है।
/fr/products जैसे पाथ प्रीफ़िक्स, सार्वजनिक रूप से उपयोग होने वाले Rails ऐप्स के लिए सबसे आम विकल्प है। यह प्रत्येक URL में स्थानीय भाषा को स्पष्ट रखता है, जिसे खोज इंजन प्रत्येक भाषा के अनुसार स्वतंत्र रूप से इंडेक्स कर सकते हैं।
जब आप एक मजबूत क्षेत्रीय पहचान चाहते हैं तो सबडोमेन और टीएलडी रणनीतियाँ अच्छी तरह से काम करती हैं, लेकिन वे डीएनएस कॉन्फ़िगरेशन और एसएसएल प्रमाणपत्र का अतिरिक्त भार बढ़ाती हैं।
यूआरएल पैरामीटर, जैसे /products?locale=fr , उन आंतरिक टूल के लिए ठीक हैं जहां एसईओ मायने नहीं रखता है।
डेटाबेस में संग्रहीत प्राथमिकताएं प्रमाणित ऐप्स के लिए काम करती हैं जहां स्थान उपयोगकर्ता का अनुसरण करता है, न कि यूआरएल का।
आप जो भी रणनीति चुनें, एक कार्यान्वयन त्रुटि है जो सूक्ष्म उत्पादन बग का कारण बनती है: I18n.locale = का सीधे उपयोग करना।
# Don't do this
before_action { I18n.locale = params[:locale] }I18n.locale = Thread.current में लिखता है.
यदि आप प्यूमा वेब सर्वर का उपयोग कर रहे हैं, तो यह अनुरोधों के दौरान थ्रेड्स का पुन: उपयोग करता है। यदि किसी अनुरोध में लोकेल को स्पष्ट रूप से सेट नहीं किया गया है, तो यह पिछले अनुरोध द्वारा छोड़े गए लोकेल को ही इनहेरिट करता है।
सिंगल थ्रेड के साथ लोकल डेवलपमेंट में यह समस्या कभी सामने नहीं आती। प्रोडक्शन में, यह बीच-बीच में गलत भाषा में प्रतिक्रियाएँ उत्पन्न करती है जिन्हें दोहराना मुश्किल होता है और जिनका पता लगाना और भी कठिन होता है।
इसके बजाय around_action के अंदर I18n.with_locale का उपयोग करें:
around_action :switch_localed
ef switch_locale(&action) locale = params[:locale] || I18n.default_locale I18n.with_locale(locale, &action) endwith_locale ब्लॉक समाप्त होने के बाद पिछली लोकेल को पुनर्स्थापित करता है, चाहे अनुरोध कैसे भी समाप्त हुआ हो।
अपने राउट्स को /:locale के अंतर्गत रखें और default_url_options को ओवरराइड करें ताकि Rails स्वचालित रूप से प्रत्येक URL में वर्तमान लोकेल जोड़ दे।
# config/routes.rb
scope "/:locale" do
resources :products
root "home#index"
end
# app/controllers/application_controller.rb
around_action :switch_locale
def switch_locale(&action)
locale = params[:locale]
# Fallback to default if the param is missing or unsupported
valid_locale = I18n.available_locales.map(&:to_s).include?(locale) ? locale : I18n.default_locale
I18n.with_locale(valid_locale, &action)
end
def default_url_options
{ locale: I18n.locale }
end
default_url_options सेट होने पर, जब वर्तमान लोकेल :fr होता है, तो products_path स्वचालित रूप से /fr/products के रूप में प्रदर्शित होता है।
यदि आप चाहते हैं कि डिफ़ॉल्ट लोकेल उपसर्ग को छोड़ दे, तो स्कोप "(:locale)" के साथ सेगमेंट को वैकल्पिक बनाएं। यह अंग्रेज़ी के लिए /products और फ़्रेंच के लिए /fr/products प्रदान करता है, लेकिन इससे अस्पष्टता उत्पन्न होती है। आपके रूट क्रम के आधार पर, /about जैसा पथ या तो अनुपलब्ध लोकेल या about नामक नियंत्रक से मेल खा सकता है।
सबडोमेन का पता लगाने के लिए, request.subdomains.first से पढ़ें और कुछ भी सेट करने से पहले available_locales के विरुद्ध सत्यापन करें:
def extract_locale_from_subdomain subdomain = request.subdomains.first यदि सबडोमेन खाली है या सबडोमेन का मान "www" के बराबर है तो nil लौटाएँ ।
यदि I18n.available_locales.map(&:to_s).include?(subdomain ) शामिल है तो उपडोमेनwww चेक इसे लोकेल के रूप में माने जाने से रोकता है। लोकलहोस्ट पर, request.subdomains एक खाली ऐरे लौटाता है, इसलिए विकास के दौरान सबडोमेन का पता लगाना विफल हो जाता है जब तक कि आप Pow सर्वर का उपयोग न करें या /etc/hosts में प्रविष्टियाँ न जोड़ें।
एक चीज़ जिसे अलग से कॉन्फ़िगर करना होगा: ApplicationController में परिभाषित default_url_options मेलर्स या बैकग्राउंड जॉब्स में लागू नहीं होता है। इन संदर्भों के लिए इसे स्पष्ट रूप से सेट करें:
Rails.application.routes.default_url_options = { host: "example.com", locale: :en }स्थानीयकृत रूट आपको यूआरएल संरचना प्रदान करते हैं, लेकिन इस सेटअप के बाद hreflang टैग , अनुवादित स्लॉग और बहुभाषी साइटमैप पूरी तरह से मैन्युअल ही रहते हैं।
Weglot इसका रिवर्स प्रॉक्सी इंटीग्रेशन उस लेयर को स्वचालित रूप से संभालता है, जिससे बिना किसी अतिरिक्त कॉन्फ़िगरेशन के hreflang टैग और भाषा-विशिष्ट URL उत्पन्न होते हैं।
अंग्रेजी में बहुवचन बनाना सरल है। एकवचन के लिए एक रूप और बाकी सभी के लिए दूसरा रूप।
en:
messages:
one: "%{count} message"
other: "%{count} messages"
अधिकांश भाषाएँ इतनी सरल नहीं होतीं।
उदाहरण के लिए, बल्गेरियाई भाषा में कुछ पुल्लिंग शब्दों के लिए एक सामान्य बहुवचन और एक विशेष "गणना बहुवचन" होता है। इसलिए, ден (दिन) सामान्य रूप से дни (कई दिन) हो जाता है, लेकिन गिनने पर два дена (दो दिन) हो जाता है।
bg:
cities:
one: "%{count} ден"
few: "%{count} дена"
many: "%{count} дни"
rails-i18n के बिना, Rails को उन नियमों की जानकारी नहीं होती। आपके बल्गेरियन अनुवाद या तो त्रुटि उत्पन्न करेंगे या प्रत्येक गणना के लिए दूसरे रूप में परिवर्तित हो जाएंगे।
यह जेम 100 से अधिक लोकेशंस के लिए बहुवचन तर्क प्रदान करता है, इसलिए बल्गेरियन, रूसी, अरबी, पोलिश और गैर-अंग्रेजी बहुवचन नियमों वाली किसी भी अन्य भाषा में चीजें सही ढंग से हल हो जाती हैं।
फ़ॉलबैक एक अलग मुद्दा है और डिफ़ॉल्ट रूप से बंद रहता है। इनके बिना, किसी भी गुम हुई अनुवाद कुंजी के कारण उत्पादन में अनुवाद स्ट्रिंग गुम हो जाती है। यही वह चीज़ है जो शिप होती है और स्क्रीनशॉट में दिखाई देती है।
config/application.rb में फ़ॉलबैक सक्षम करें और एक डिफ़ॉल्ट गंतव्य परिभाषित करें:
config.i18n.fallbacks = [I18n.default_locale]fallbacks = true के साथ, वर्तमान लोकेल में कोई कुंजी न होने पर default_locale पर वापस आ जाता है। क्षेत्रीय भिन्नताओं के लिए, आप स्पष्ट श्रृंखलाएँ परिभाषित कर सकते हैं:
config.i18n.fallbacks = { "fr-CA": :fr, "en-GB": :en }इसे पहले ही कॉन्फ़िगर कर लें। किसी ऐसे ऐप में फ़ॉलबैक व्यवहार को बाद में लागू करना, जिसमें पहले से ही आंशिक अनुवाद मौजूद हैं, शुरुआत में ही इसे सेट करने की तुलना में अधिक कठिन होता है।
जावास्क्रिप्ट की Rails I18n पाइपलाइन तक कोई पहुंच नहीं है।
आपके अनुवाद फ़ाइलों और स्टिमुलस कंट्रोलर के बीच कोई टी हेल्पर, वाईएएमएल लोडर या बिल्ट-इन ब्रिज उपलब्ध नहीं है। आपको सर्वर साइड से अनुवाद स्पष्ट रूप से पास करने होंगे।
स्टिमुलस के लिए सबसे सरल तरीका वैल्यू एपीआई का उपयोग करना है। कंट्रोलर पर अनुवाद को एक वैल्यू के रूप में परिभाषित करें, इसे HTML में सेट करें और जावास्क्रिप्ट में इसे पढ़ें:
# app/views/products/index.html.erb
<div data-controller="notification"
data-notification-message-value="<%= t('.success_message') %>">
यह मान सर्वर-साइड पर मानक t हेल्पर का उपयोग करके प्रस्तुत किया जाता है, इसलिए यह वर्तमान लोकेल का स्वचालित रूप से ध्यान रखता है। जावास्क्रिप्ट में, इसे एक स्थिर मान के रूप में घोषित करें और इसे वैल्यू API के माध्यम से पढ़ें:
// app/javascript/controllers/notification_controller.js
export default class extends Controller {
static values = { message: String }
show() {
alert(this.messageValue)
}
}
प्रत्येक अनुवाद स्पष्ट होता है और उस नियंत्रक तक सीमित होता है जिसे इसकी आवश्यकता होती है। कुछ भी वैश्विक दायरे में नहीं जाता है।
यदि किसी कंट्रोलर को एक साथ कई अनुवादों की आवश्यकता होती है, तो प्रत्येक स्ट्रिंग के लिए अलग-अलग मान परिभाषाएँ जोड़ने की तुलना में उन्हें JSON डेटा विशेषता के रूप में बंडल करना अधिक सुव्यवस्थित होता है:
<div data-controller="cart"
data-cart-i18n-value="<%= { add: t('.add'), remove: t('.remove') }.to_json %>">
जावास्क्रिप्ट की तरफ, i18n को एक ऑब्जेक्ट वैल्यू के रूप में घोषित करें और व्यक्तिगत कुंजियों को सीधे एक्सेस करें:
static values = { i18n: Object }
add() {
console.log(this.i18nValue.add)
}
उन ऐप्स के लिए जहां जावास्क्रिप्ट को कई नियंत्रकों में व्यापक अनुवाद पहुंच की आवश्यकता होती है, i18n-js जेम आपकी YAML फ़ाइलों को एक जावास्क्रिप्ट ऑब्जेक्ट में निर्यात करता है जिसे आप I18n.t("key") के रूप में क्वेरी कर सकते हैं।
यह काम करता है, लेकिन इससे एक बिल्ड स्टेप जुड़ जाता है और आपका पूरा ट्रांसलेशन सेट क्लाइंट को भेज दिया जाता है। इसका उपयोग तब करें जब पहले दो पैटर्न बार-बार दोहराए जाने लगें, डिफ़ॉल्ट के रूप में नहीं।
टर्बो फ्रेम्स का उपयोग करते समय, यदि किसी टर्बो फ्रेम के स्रोत URL में लोकेल उपसर्ग शामिल नहीं है, तो अनुरोध आमतौर पर रूटिंग त्रुटि (404) के साथ विफल हो जाएगा क्योंकि यह आपके स्कोप "/:locale" पैटर्न से मेल नहीं खाएगा। फ्रेम स्रोतों के लिए हमेशा लोकेल-जागरूक पथ सहायकों का उपयोग करें।
यह टर्बो की कोई गड़बड़ी नहीं है। बल्कि, यह रूटिंग में हुई एक चूक है, और लोकेल डिटेक्शन सेक्शन का around_action इसे तब तक रोकता है जब तक कि फ्रेम में मौजूद हर URL लोकेल-अवेयर पाथ हेल्पर का उपयोग करता है।
Weglot इसका रिवर्स प्रॉक्सी पूरी तरह से अलग दृष्टिकोण अपनाता है। यह पेज लोड होने के बाद रेंडर किए गए DOM का अनुवाद करता है, इसलिए स्टिमुलस द्वारा रेंडर की गई सामग्री और गतिशील रूप से डाली गई स्ट्रिंग्स को इस वायरिंग की आवश्यकता के बिना ही कवर किया जाता है।
तीन श्रेणियां पूरी तरह से Rails I18n के दायरे से बाहर हैं:
Weglot इन सभी समस्याओं का समाधान कोड लेयर के बजाय आउटपुट लेयर पर करता है:
हालांकि, इसका मूल्यांकन करने से पहले कुछ सीमाओं के बारे में जानना आवश्यक है:
Rails i18n के प्रत्येक कार्यान्वयन में लगभग समान क्रम में समान निर्णय लिए जाते हैं।
सबसे पहले, कोई भी लोकेल-डिटेक्शन कोड लिखने से पहले अपनी URL रणनीति चुनें। पाथ सेगमेंट अधिकांश सार्वजनिक ऐप्स के लिए उपयुक्त होते हैं। सबडोमेन तब उपयोगी होते हैं जब क्षेत्रीय पहचान मायने रखती है। डेटाबेस में संग्रहीत प्राथमिकताएं प्रमाणित ऐप्स के लिए उपयुक्त होती हैं जहां लोकेल URL के बजाय उपयोगकर्ता के साथ चलता है।
दूसरा, तय करें कि जावास्क्रिप्ट अनुवाद कैसे प्राप्त करता है। स्टिमुलस वैल्यूज़ एपीआई अधिकांश मामलों को कवर करता है। जब किसी कंट्रोलर को एक साथ कई स्ट्रिंग की आवश्यकता होती है, तो JSON एट्रिब्यूट काम करते हैं।
तीसरा, तय करें कि आप मैन्युअल रूप से क्या बना रहे हैं। Rails स्टैटिक स्ट्रिंग्स को अच्छी तरह से संभालता है। SEO लेयर, ट्रांसलेटर वर्कफ़्लो और डेटाबेस कंटेंट, इन सभी के लिए अलग-अलग निर्णय लेने की आवश्यकता होती है। आप इनमें से प्रत्येक को खुद बना सकते हैं, या आउटपुट लेयर को किसी टूल को सौंप सकते हैं। Weglot और इंजीनियरिंग का समय एप्लिकेशन पर ही केंद्रित करें।
आउटपुट लेयर को पूरी तरह से छोड़ दें। 14 दिनों के लिए Weglot मुफ़्त में आज़माएं और अपने i18n कोड को छुए बिना बहुभाषी SEO/GEO, अनुवादित URL और स्वचालित सामग्री पहचान प्राप्त करें।
शक्ति को समझने का सबसे अच्छा तरीका Weglot इसे स्वयं अनुभव करके देखें। बिना किसी शुल्क और प्रतिबद्धता के इसका परीक्षण करें।
यदि आप अभी अपनी वेबसाइट को कनेक्ट करने के लिए तैयार नहीं हैं, तो आपके डैशबोर्ड में एक डेमो वेबसाइट उपलब्ध है।