अपने प्रश्न को पूछें और दस्तावेज़ का सारांश प्राप्त करें, इस पृष्ठ और आपके चुने हुए AI प्रदाता का उपयोग करके
इस पृष्ठ की सामग्री एक AI द्वारा अनुवादित की गई है।
अंग्रेजी में मूल सामग्री के अंतिम संस्करण देखेंअगर आपके पास इस दस्तावेज़ को सुधारने के लिए कोई विचार है, तो कृपया GitHub पर एक पुल अनुरोध सबमिट करके योगदान देने में संकोच न करें।
दस्तावेज़ के लिए GitHub लिंकदस्तावेज़ का Markdown को क्लिपबोर्ड पर कॉपी करें
ICU मैसेज फॉर्मेट: सिंटैक्स और वो हिस्से जहां लोग गलती करते हैं
ICU MessageFormat एक स्ट्रिंग सिंटैक्स है जो अनुवाद को अपने स्वयं के ब्रांचिंग लॉजिक को शामिल करने की अनुमति देता है: बहुवचन, लिंग-आधारित रूप, संख्या और दिनांक स्वरूपण। इसका अस्तित्व इसलिए है क्योंकि व्याकरण अनुवादक का विषय है, न कि if (count === 1) लिखने वाले डेवलपर का। यह लेख सिंटैक्स, भाषा-निर्भर पहलुओं जो सरल कार्यान्वयनों को विफल करते हैं, और जावास्क्रिप्ट इकोसिस्टम इसे कैसे संभालता है, इस पर चर्चा करता है।
विषय सूची
व्यावहारिक रूप से समस्या
यहाँ वह कोड है जो लगभग हर कोई सबसे पहले लिखता है:
कोड को क्लिपबोर्ड पर कॉपी करें
यह अंग्रेजी में तो ठीक काम करता है लेकिन अन्य लगभग सभी भाषाओं में विफल हो जाता है:
- रूसी और पोलिश को दो नहीं, बल्कि तीन या चार रूपों की आवश्यकता होती है।
- जापानी को केवल एक रूप की आवश्यकता होती है, और जोड़ा गया स्पेस गलत होता है।
- अरबी को छह रूपों की आवश्यकता होती है, और संख्या को स्वयं स्थानीय अंक प्रणाली में प्रस्तुत किया जाना चाहिए।
- फ्रेंच में कुछ विराम चिह्नों से पहले नॉन-ब्रेकिंग स्पेस की आवश्यकता होती है, जिसे आपके
+ " "ने नष्ट कर दिया।
गहरी समस्या यह है कि वाक्य को टुकड़ों में काट दिया गया है। एक अनुवादक बिना किसी संदर्भ और वाक्य के क्रम को बदले बिना केवल item और items देखता है। ICU MessageFormat पूरे वाक्य को एक ही अनुवाद योग्य स्ट्रिंग में रखकर और अनुवादक को ब्रांचिंग ऑपरेटर देकर इसे हल करता है।
सरल तर्क (Simple Arguments)
सबसे छोटी इकाई एकल घुंघराले कोष्ठक (curly braces) में एक प्लेसहोल्डर है:
कोड को क्लिपबोर्ड पर कॉपी करें
फॉर्मेटिंग के समय आप { name: "Alice" } पास करते हैं और आपको Hello, Alice! मिलता है। घुंघराले कोष्ठक ही एकमात्र विशेष वर्ण हैं; किसी शाब्दिक कोष्ठक को प्रिंट करने के लिए आप उसे एकल उद्धरण चिह्नों में लपेटते हैं: '{'.
यह संपूर्ण "इंटरपोलेशन" सुविधा है। ICU में बाकी सब कुछ इसी के ऊपर बनाया गया है।
बहुवचन (Plural)
plural संख्या के आधार पर एक शाखा का चयन करता है:
कोड को क्लिपबोर्ड पर कॉपी करें
जानने योग्य तीन प्रमुख बातें:
#कोcountके स्थानीय-स्वरूपित मान से बदल दिया जाता है, जिससे1234en-USमें1,234औरhi-INमें1,234बन जाता है।otherअनिवार्य है। इसके बिना कोई भी ICU कार्यान्वयन त्रुटि देगा या सत्यापन में विफल रहेगा। जब कोई श्रेणी मेल नहीं खाती है तो यह फॉलबैक के रूप में कार्य करता है।=0,=1, … सटीक मानों से मेल खाते हैं और CLDR श्रेणियों से पहले जाँचे जाते हैं। इनका उपयोग विशेष मामलों ("कोई संदेश नहीं") के लिए करें, न किoneके विकल्प के रूप में।
कोड को क्लिपबोर्ड पर कॉपी करें
offset
offset:n श्रेणी चयन और # प्रतिस्थापन दोनों से पहले मान से n घटाता है। यह "Alice और 3 अन्य लोगों ने इसे पसंद किया" जैसे पैटर्न के लिए उपयोगी है:
कोड को क्लिपबोर्ड पर कॉपी करें
count: 4 के साथ, # का मान 3 प्रदर्शित होगा। offset वास्तव में उपयोगी है लेकिन विभिन्न रनटाइम में इसका समर्थन अलग-अलग हो सकता है, इसलिए उपयोग से पहले अपने परिवेश की जांच कर लें।
बहुवचन श्रेणियां भाषा-निर्भर हैं
यह वह हिस्सा है जहाँ लोग सबसे अधिक गलती करते हैं। श्रेणी नाम zero, one, two, few, many, other सार्वभौमिक बकेट नहीं हैं जिन्हें आप हर भाषा के लिए भरते हैं। प्रत्येक स्थानीय भाषा CLDR बहुवचन नियमों द्वारा परिभाषित एक उपसमूह का उपयोग करती है, और ये नियम व्याकरणिक हैं, न कि सहज गणितीय।
सभी डेटा सामग्री को स्पष्ट रूप से देखने के लिए तालिका को मोडल में खोलें
| भाषा | टैग | प्रयुक्त श्रेणियां | संख्या |
|---|---|---|---|
| जापानी | ja | other | 1 |
| चीनी | zh | other | 1 |
| अंग्रेजी | en | one, other | 2 |
| जर्मन | de | one, other | 2 |
| फ्रेंच | fr | one, many, other | 3 |
| चेक | cs | one, few, many, other | 4 |
| पोलिश | pl | one, few, many, other | 4 |
| रूसी | ru | one, few, many, other | 4 |
| अरबी | ar | zero, one, two, few, many, other | 6 |
| वेल्श | cy | zero, one, two, few, many, other | 6 |
दो परिणाम जो लोगों को आश्चर्यचकित करते हैं:
oneका अर्थ केवल "1" नहीं है। रूसी में,one1, 21, 31, 101 को कवर करता है: 1 पर समाप्त होने वाली कोई भी संख्या, सिवाय उन संख्याओं के जो 11 पर समाप्त होती हैं। फ्रेंच में,0भीoneमें आता है।- अंग्रेजी स्रोत में श्रेणी जोड़ने से कुछ नहीं होता। अंग्रेजी संदेश को केवल
oneऔरotherकी आवश्यकता होती है; पोलिश अनुवाद को चार शाखाओं की आवश्यकता होती है, और वह संरचना पोलिश स्ट्रिंग में रहती है, न कि अंग्रेजी स्ट्रिंग में। कोई भी प्रारूप जो सभी भाषाओं को एक समान कुंजी संरचना साझा करने के लिए मजबूर करता है, वह यहाँ समस्या पैदा करेगा।
आप बिना कुछ इंस्टॉल किए यह जांच सकते हैं कि रनटाइम वास्तव में क्या करता है:
कोड को क्लिपबोर्ड पर कॉपी करें
Intl.PluralRules हर आधुनिक ब्राउज़र और Node में CLDR डेटा प्रदान करता है। CLDR प्लूरलाइजेशन का दावा करने वाली कोई भी लाइब्रेरी लगभग हमेशा इसके नीचे इसी को कॉल कर रही होती है।
select और selectordinal
select किसी भी यादृच्छिक स्ट्रिंग पर शाखा बनाता है: लिंग, भूमिका, स्थिति या योजना स्तर।
कोड को क्लिपबोर्ड पर कॉपी करें
कुंजियों का शाब्दिक मिलान किया जाता है और यहाँ भी other अनिवार्य है। जब भी वाक्य की संरचना किसी इनम (enum) मान पर निर्भर करती है, तो select सही उपकरण है, क्योंकि भाषाएं इस बात पर असहमत होती हैं कि कौन से मान व्याकरण को प्रभावित करते हैं।
selectordinal का आकार plural जैसा ही होता है, लेकिन यह क्रमसूचक (ordinal) बहुवचन नियमों का उपयोग करता है, जो मूल (cardinal) नियमों से अलग तालिका में होते हैं:
कोड को क्लिपबोर्ड पर कॉपी करें
अंग्रेजी चार क्रमसूचक श्रेणियों (1st, 2nd, 3rd, 4th) का उपयोग करती है, भले ही वह केवल दो मूल श्रेणियों का उपयोग करती हो। ठीक इसी असमानता के कारण दोनों ऑपरेटर अलग-अलग हैं।
संख्या, दिनांक और समय तर्क
ICU अपने द्वारा प्रक्षिप्त मान को सीधे प्रारूपित कर सकता है:
कोड को क्लिपबोर्ड पर कॉपी करें
आधुनिक रूप skeleton है, जिसे ICU 60 के साथ पेश किया गया था और इसे :: उपसर्ग द्वारा चिह्नित किया जाता है। स्केलेटन पारंपरिक शैली नामों की तुलना में कहीं अधिक अभिव्यंजक हैं:
कोड को क्लिपबोर्ड पर कॉपी करें
इकोसिस्टम में स्केलेटन समर्थन अलग-अलग पुस्तकालयों में असमान है। FormatJS उन्हें पूरी तरह लागू करता है; कई अन्य रनटाइम केवल लेगेसी number, currency या date, long प्रारूप स्वीकार करते हैं। उत्पादन में उपयोग करने से पहले अपने रनटाइम में :: समर्थन की पुष्टि करें।
नेस्टिंग और पठनीयता
ICU संयोजन योग्य है। एक बहुवचन शाखा में एक select हो सकता है, जिसमें दूसरा बहुवचन हो सकता है:
कोड को क्लिपबोर्ड पर कॉपी करें
यह विहित ICU उदाहरण है और गहरी नेस्टिंग के खिलाफ प्रमुख तर्क भी है। दो स्तरों से आगे अनुवादक कोष्ठक की त्रुटियाँ करने लगते हैं और TMS संपादक मदद करना बंद कर देते हैं। अधिक से अधिक दो स्तरों तक नेस्ट करें; यदि आपको तीसरे की आवश्यकता है, तो वाक्य को दो संदेशों में विभाजित करें।
जेएस लाइब्रेरीज़ ICU को कैसे संभालती हैं
सभी डेटा सामग्री को स्पष्ट रूप से देखने के लिए तालिका को मोडल में खोलें
| लाइब्रेरी | ICU समर्थन | आप वास्तव में क्या लिखते हैं |
|---|---|---|
| react-intl (FormatJS) | नेटिव, पूर्ण | स्केलेटन और रिच-टेक्स्ट टैग सहित ICU स्ट्रिंग्स |
| next-intl | नेटिव | FormatJS के intl-messageformat के माध्यम से ICU स्ट्रिंग्स |
| i18next | प्लगइन आवश्यक | प्रत्यय कुंजियाँ key_one / key_other और {{name}}; ICU i18next-icu से |
| vue-i18n | आंशिक / अपना | {name} इंटरपोलेशन और पाइप से अलग की गई बहुवचन शाखाएं |
Angular ($localize) | उपसमूह | टेम्प्लेट के अंदर ICU plural / select, XLIFF में निकाला गया |
तालिका के संदर्भ में कुछ महत्वपूर्ण बिंदु:
- i18next का डिफ़ॉल्ट सिंटैक्स ICU नहीं है, और यह इसके लिए खराब नहीं है। प्रत्यय कुंजियाँ (
item_one,item_few)Intl.PluralRulesश्रेणियों पर मैप होती हैं और फ्लैट JSON में अनुवादकों के लिए संपादित करना आसान होती हैं। लेकिनselectऔर नेस्टेड ब्रांचिंग इसका हिस्सा नहीं हैं, इसलिए आपको या तोi18next-icuजोड़ना होगा या कोड में लॉजिक लिखना होगा। - vue-i18n के पाइप बहुवचन डिफ़ॉल्ट रूप से CLDR श्रेणियों के बजाय प्रति-लोकेल नियम फ़ंक्शन का उपयोग करते हैं। यह काम करता है, लेकिन नियम डेटा के बजाय ऐप कॉन्फ़िगरेशन में रहता है।
- FormatJS संदर्भ कार्यान्वयन है। जब लोग JS संदर्भ में "ICU MessageFormat" कहते हैं, तो उनका आमतौर पर मतलब वही होता है जो FormatJS स्वीकार करता है।
- पूर्ण ICU समर्थन में बंडल आकार की लागत होती है। पार्सर और स्केलेटन हैंडलिंग लगभग 10 KB संपीड़ित जावास्क्रिप्ट जोड़ते हैं। देखें ICU जावास्क्रिप्ट के लिए क्यों नहीं बना है।
Intlayer इसे कैसे संभालता है
Intlayer स्ट्रिंग DSL का उपयोग नहीं करता है। ब्रांचिंग ऑपरेटर कंटेंट डिक्लेरेशन फ़ाइल में टाइप-सुरक्षित फ़ंक्शन हैं, इसलिए प्रत्येक भाषा केवल उन श्रेणियों को घोषित करती है जिनकी उसके व्याकरण को आवश्यकता होती है:
कोड को क्लिपबोर्ड पर कॉपी करें
कोड को क्लिपबोर्ड पर कॉपी करें
ICU अवधारणाओं के साथ मैपिंग सीधी है:
सभी डेटा सामग्री को स्पष्ट रूप से देखने के लिए तालिका को मोडल में खोलें
| ICU निर्माण | Intlayer समकक्ष |
|---|---|
{name} | insert("Hello {{name}}"), या स्वचालित पहचान |
{count, plural, …} | plural({ one, few, many, other }) |
{value, select, …} | select({ draft, published, fallback }) |
select की लिंग शाखा | gender({ male, female, fallback }) |
select की बूलियन शाखा | cond({ true, false }) |
| संख्यात्मक सीमाएं (गैर-CLDR) | enu({ "0": …, ">5": …, fallback: … }) |
{n, number, ::currency/EUR} | useCurrency()(1234.5, { currency: "EUR" }) |
plural श्रेणी चयन को सीधे Intl.PluralRules को सौंपता है, इसलिए ऊपर दी गई CLDR तालिका बिना किसी बदलाव के लागू होती है। फ़ॉर्मेटिंग अलग रहती है: संख्याएं, दिनांक, मुद्राएं और सूचियां संदेश में एम्बेड होने के बजाय फ़ॉर्मेटर हुक के माध्यम से नियंत्रित की जाती हैं।
व्यावहारिक सीमाएं:
- Intlayer को एक बिल्ड चरण की आवश्यकता होती है; कंपाइलर बिल्ड समय पर घोषणाओं को निकालता है। यदि आप रनटाइम पर साधारण JSON लोड करना चाहते हैं, तो वह एक अलग मॉडल है।
pluralअभी अपनी शाखाओं के अंदर सीधेt()को नेस्ट नहीं कर सकता; आपpluralकोt()में लपेटते हैं, इसके विपरीत नहीं।- यह इकोसिस्टम i18next की तुलना में नया है, जिसमें कम तैयार TMS एकीकरण उपलब्ध हैं।
यदि आप किसी ऐसे कोडबेस से आ रहे हैं जिसमें पहले से ही वास्तविक ICU स्ट्रिंग्स हैं, तो react-intl कम्पैट एडेप्टर उन्हें सीधे पार्स करता है: plural, select, selectordinal, #, और लेगेसी number / date / time तर्क। स्केलेटन और offset: उस रिज़ॉल्वर द्वारा कवर नहीं किए गए हैं, इसलिए माइग्रेट करते समय उन संदेशों की जांच करें। i18next एडेप्टर इसके बजाय प्रत्यय रूपों (key_one, key_male) को Intl.PluralRules के विरुद्ध हल करता है।
सामान्य गलतियां
- जावास्क्रिप्ट में बहुवचन लॉजिक को हार्डकोड करना।
count === 1 ? a : bऊपर दी गई तालिका की 10 में से 8 भाषाओं के लिए गलत आउटपुट देता है। एक बार जब टर्नरी ऑपरेटर कोड में आ जाता है, तो कोई भी अनुवादक इसे ठीक नहीं कर सकता। - अनुवादित टुकड़ों को आपस में जोड़ना। शब्दों का क्रम, व्याकरणिक सहमति और विराम चिह्नों का अंतर सभी भाषा-निर्भर हैं। पूरे वाक्य को एक साथ रखें।
otherको छोड़ देना। यह विनिर्देश द्वारा आवश्यक है, कोई वैकल्पिक नियम नहीं। अधिकांश पार्सर संदेश को अस्वीकार कर देंगे या कुछ भी रेंडर नहीं करेंगे।- यह मान लेना कि आपकी श्रेणियां सार्वभौमिक हैं। अंग्रेजी स्रोत में
oneऔरotherहोने का मतलब यह नहीं है कि पोलिश फ़ाइल में केवल दो शाखाएं होंगी। प्रत्येक भाषा को अपनी स्वयं की शाखाएं घोषित करने दें। प्रति-भाषा सामग्री घोषणा देखें। - जहाँ
oneका मतलब था वहाँ=1का उपयोग करना।=1केवल शाब्दिक 1 से मेल खाता है। रूसी में, 21 कोoneकी आवश्यकता होती है, और=1इसके लिए कभी सक्रिय नहीं होगा। #को बहुवचन शाखा के बाहर रखना। यह केवलpluralयाselectordinalके अंदर विशेष है। अन्य जगहों पर यह केवल एक साधारण हैश चिह्न है।- यह भूल जाना कि
#पहले से ही स्वरूपित है। यदि आप कच्ची संख्या चाहते हैं, तो तर्क को नाम से इंटरपोलेट करें।
आगे पढ़ें
टिप्पणियाँ
अभी तक कोई टिप्पणी नहीं। अपने विचार साझा करने वाले पहले व्यक्ति बनें।
