आप सही हैं कि LC_*
शेल वेरिएबल्स को असाइन bash
करने से POSIX setlocale()
को वैरिएबल के मान के साथ संबंधित श्रेणी के लिए कॉल किया जा सकता है , चाहे वे निर्यात किए गए हों या नहीं। के लिए LANG
, यह कॉल setlocale(LC_ALL, thevalue)
का पालन setlocale(LC_*)
सभी के लिए फिर से LC_*
चर। के लिए LANGUAGE
, यह कुछ भी नहीं करता है।
अब, bash
जीएनयू परियोजना का खोल है। पाठ के स्थानीयकरण के लिए, यह GNU का उपयोग करता है gettext
, जिसे रूप में भी जाना जाता है libintl
। यहां तक कि यह अपने स्वयं के संस्करण के साथ आता है जो स्रोत के साथ बंडल होता है जिसे आप स्क्रिप्ट के साथ bash
कॉल करने पर संकलित कर सकते हैं ।configure
--with-included-gettext
gettext
प्रति भाषा डेटाबेस में संदेश अनुवाद दिखता है। यह किस भाषा की LC_MESSAGES
श्रेणी के मूल्य से निर्धारित होता है, हालांकि $LANGUAGE
पर्यावरण चर द्वारा इसे ओवरराइड किया जा सकता है ।
गेटटेक्स्ट डॉक्यूमेंटेशन के अनुसार, पिछला कॉल वह setlocale()
होना चाहिए जो श्रेणी के लिए मूल्य निर्धारित करता है, लेकिन कुछ जटिलताएं हैं:
Multithreaded अनुप्रयोगों के लिए, वर्तमान में कोई मानक API नहीं है जो गेटटेक्स्ट उस मान को पुनः प्राप्त करने के लिए उपयोग कर सकता है । bash
एक बहुपरत आवेदन नहीं है, लेकिन यहां तक कि क्या setlocale(category, NULL)
रिटर्न कार्यान्वयन को परिभाषित किया गया है और व्यवहार में हमेशा उपयोग करने योग्य नहीं है ।
तो व्यवहार में, gettext केवल का उपयोग करता है setlocale()
जब जीएनयू libc का हिस्सा है या एक प्रणाली है जहाँ libc जीएनयू libc (के साथ बनाया गया एक की तरह है पर बनाया गया भाषा नाम को पुनः प्राप्त करने bash
के साथ --with-included-gettext
एक जीएनयू सिस्टम पर), क्योंकि यह जानता है कि यह पर भरोसा कर सकते यह।
अन्य प्रणालियों पर, यह getenv()
स्थानीय को निर्धारित करने के लिए उपयोग करता है, भले ही setlocale()
पहले कैसे लागू किया गया था, यही कारण है कि आप उस व्यवहार को देख रहे हैं।
उन चरों को निर्यात करना एक आसान काम है। कोई यह तर्क दे सकता है कि यदि वे निर्यात नहीं किए जाते हैं, तो वे वैसे भी पर्यावरण का हिस्सा नहीं हैं। उस पर POSIX बहुत स्पष्ट नहीं है। इसे देखने का एक और तरीका यह है कि अनुवाद bash
किसी तीसरे पक्ष के तंत्र द्वारा नहीं किया जाता है , इसलिए जैसे अन्य आदेशों को निष्पादित करते समय , हमें दो सॉफ्टवेयर (यहां bash
और gettext
) के बीच स्थानीय जानकारी को पारित करने के लिए पर्यावरण चर का उपयोग करने की आवश्यकता होती है ।
अब, GNU सिस्टम पर, यह वास्तव में खराब हो जाता है।
जैसा कि ऊपर देखा गया है, गेटटेक्स्ट को जीएनयू परिवाद में शामिल किया गया है। $LANGUAGE
पूर्वता लेता है, $LC_MESSAGE
लेकिन $LANGUAGE
POSIX लोकेल एपीआई का हिस्सा नहीं है, यह उसके ऊपर एक विस्तार है।
एक GNU सिस्टम पर रहते हुए, gettext setlocale(LC_MESSAGES, NULL)
LC_MESSAGES श्रेणी के लिए नाम प्राप्त करने के लिए उपयोग करेगा LANGUAGE
, इसके लिए , यह हमेशा उपयोग होता है getenv()
, LANGUAGE
एक स्थानीय श्रेणी नहीं है।
समस्या यह है कि bash
अपने चर हैंडलिंग के हिस्से के रूप में पर्यावरण को प्रबंधित करता है, जो कि libc के environ[]
एरे से डिस्कनेक्ट किया गया है । इसका getenv()
अपना स्वयं का संस्करण है जो पर्यावरण के अपने स्वयं के संस्करण को क्वेरी करता है, लेकिन जब gettext
यह libc के भाग के रूप में बनाया गया है, और bash
यह libc से गतिशील रूप से जुड़ा हुआ dgettext()
कॉल है, getenv()
क्योंकि यह libc के भीतर एक आंतरिक कॉल है bash
, ऐसा नहीं है , इसलिए होगा केवल $LANGUAGE
उस समय से मूल्य प्राप्त bash
करना शुरू किया गया था।
जीएनयू सिस्टम पर, जब तक कि bash
इसे वैधानिक रूप से नहीं जोड़ा गया या इसके साथ नहीं बनाया गया , तब तक उत्पन्न होने वाले संदेशों के लिए --with-included-gettext
किसी भी परिवर्तन को $LANGUAGE
अनदेखा किया जाएगा bash
, चाहे वह चर निर्यात किया गया हो या नहीं। अन्य सिस्टम पर, वह ठीक (जब तक है $LANGUAGE
निर्यात किया जाता है) gettext libc का हिस्सा नहीं है के रूप में, तो यह कॉल करता bash
है getenv()
।
डेबियन पर:
$ LANGUAGE=fr bash -c 'LANGUAGE=es; eval fi'
bash: eval: ligne 0: erreur de syntaxe près du symbole inattendu « fi »
bash: eval: ligne 0: `fi'
(फ्रेंच में संदेश, $LANGUAGE
उस समय bash
का मूल्य लागू किया गया था, न कि स्पेनिश)।
वास्तव में यह अन्य गोले के साथ ज्यादा बेहतर नहीं है।
zsh
अन्य भाषाओं में अनुवादित नहीं है, लेकिन वह उपयोग करता है strerror()
जो gettext
GNU सिस्टम पर आंतरिक रूप से उपयोग करता है:
$ LANGUAGE=fr zsh -c 'LANGUAGE=es; true</x; LANGUAGE=en; true</a; true < /etc/shadow'
zsh:1: no existe el archivo o el directorio: /x
zsh:1: no existe el archivo o el directorio: /a
zsh:1: permission denied: /etc/shadow
LANGUAGE=es
सम्मानित लेकिन देखते हैं कि कैसे ENOENT के लिए दूसरा संदेश अंग्रेजी में दिखाया गया है नहीं किया गया है (शायद किसी भी तरह gettext द्वारा कैश, जब कि कैश अमान्य हो जाना चाहिए था गया था $LANGUAGE
बदल लेकिन स्थिति कुछ भिन्न है)।