आप सही हैं कि 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लेकिन $LANGUAGEPOSIX लोकेल एपीआई का हिस्सा नहीं है, यह उसके ऊपर एक विस्तार है।
एक 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()जो gettextGNU सिस्टम पर आंतरिक रूप से उपयोग करता है:
$ 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बदल लेकिन स्थिति कुछ भिन्न है)।