थ्रेड को बहुत देर हो चुकी है, लेकिन एक तकनीक जो मैंने इस्तेमाल की है, प्री-एंगुलर, JSON और जेएस के लचीलेपन का लाभ लेने के लिए गतिशील रूप से संदर्भ संग्रह कुंजियों का उपयोग करना है, और पर्यावरण के निष्क्रिय तथ्यों (होस्ट सर्वर नाम, वर्तमान ब्राउज़र भाषा) का उपयोग करना है , आदि) के रूप में चुनिंदा भेदभाव करने के लिए इनपुट के रूप में / एक JSON डेटा संरचना के भीतर प्रत्यय प्रमुख नाम पसंद करते हैं।
यह न केवल तैनाती-पर्यावरण संदर्भ (प्रति ओपी) बल्कि किसी भी मनमाने संदर्भ (जैसे भाषा) को i18n या किसी भी अन्य विचरण को एक साथ प्रदान करने के लिए प्रदान करता है, और (आदर्श रूप से) एक एकल कॉन्फ़िगरेशन के भीतर, बिना दोहराव और आसानी से स्पष्ट।
10 लाइन्स वानीला जेएस के बारे में
ओवरली-सरलीकृत लेकिन क्लासिक उदाहरण: JSON-स्वरूपित गुण फ़ाइल में एक API एंडपॉइंट बेस URL जो प्रति वातावरण में भिन्न होता है जहां (natch) होस्ट सर्वर भी भिन्न होगा:
...
'svcs': {
'VER': '2.3',
'API@localhost': 'http://localhost:9090/',
'API@www.uat.productionwebsite.com': 'https://www.uat.productionwebsite.com:9090/res/',
'API@www.productionwebsite.com': 'https://www.productionwebsite.com:9090/api/res/'
},
...
भेदभाव फ़ंक्शन की एक कुंजी अनुरोध में सर्वर होस्टनाम है।
यह, स्वाभाविक रूप से, उपयोगकर्ता की भाषा सेटिंग्स के आधार पर एक अतिरिक्त कुंजी के साथ जोड़ा जा सकता है:
...
'app': {
'NAME': 'Ferry Reservations',
'NAME@fr': 'Réservations de ferry',
'NAME@de': 'Fähren Reservierungen'
},
...
भेदभाव / वरीयता का दायरा व्यक्तिगत कुंजी तक सीमित हो सकता है (ऊपर) जहाँ "आधार" कुंजी को केवल तब ही अधिलेखित कर दिया जाता है यदि फ़ंक्शन के इनपुट के लिए एक मिलान कुंजी + प्रत्यय है - या संपूर्ण संरचना, और वह संरचना स्वयं पारस्परिक रूप से भेदभाव / वरीयता प्रत्यय के लिए पुनरावर्ती:
'help': {
'BLURB': 'This pre-production environment is not supported. Contact Development Team with questions.',
'PHONE': '808-867-5309',
'EMAIL': 'coder.jen@lostnumber.com'
},
'help@www.productionwebsite.com': {
'BLURB': 'Please contact Customer Service Center',
'BLURB@fr': 'S\'il vous plaît communiquer avec notre Centre de service à la clientèle',
'BLURB@de': 'Bitte kontaktieren Sie unseren Kundendienst!!1!',
'PHONE': '1-800-CUS-TOMR',
'EMAIL': 'customer.service@productionwebsite.com'
},
एसओ, अगर उत्पादन वेबसाइट पर जाने वाले उपयोगकर्ता के पास जर्मन ( डी ) भाषा वरीयता सेटिंग है, तो उपरोक्त कॉन्फ़िगरेशन नीचे गिर जाएगा:
'help': {
'BLURB': 'Bitte kontaktieren Sie unseren Kundendienst!!1!',
'PHONE': '1-800-CUS-TOMR',
'EMAIL': 'customer.service@productionwebsite.com'
},
इस तरह की जादुई वरीयता / भेदभाव JSON- पुनर्लेखन समारोह कैसा दिखता है? बहुत ज्यादा नहीं:
// prefer(object,suffix|[suffixes]) by/par/durch storsoc
// prefer({ a: 'apple', a@env: 'banana', b: 'carrot' },'env') -> { a: 'banana', b: 'carrot' }
function prefer(o,sufs) {
for (var key in o) {
if (!o.hasOwnProperty(key)) continue; // skip non-instance props
if(key.split('@')[1]) { // suffixed!
// replace root prop with the suffixed prop if among prefs
if(o[key] && sufs.indexOf(key.split('@')[1]) > -1) o[key.split('@')[0]] = JSON.parse(JSON.stringify(o[key]));
// and nuke the suffixed prop to tidy up
delete o[key];
// continue with root key ...
key = key.split('@')[0];
}
// ... in case it's a collection itself, recurse it!
if(o[key] && typeof o[key] === 'object') prefer(o[key],sufs);
};
};
हमारे कार्यान्वयन में, जिसमें कोणीय और पूर्व-कोणीय वेबसाइट शामिल हैं, हम केवल JSON को एक स्व-निष्पादित जेएस क्लोजर के भीतर रखकर अन्य संसाधन कॉल के आगे कॉन्फ़िगरेशन को अच्छी तरह से बूटस्ट्रैप करते हैं, जिसमें पसंदीदा () फ़ंक्शन और होस्टनाम के बुनियादी गुण शामिल हैं भाषा-कोड (और आपके द्वारा आवश्यक किसी भी अतिरिक्त मनमाने प्रत्यय को स्वीकार कर सकता है):
(function(prefs){ var props = {
'svcs': {
'VER': '2.3',
'API@localhost': 'http://localhost:9090/',
'API@www.uat.productionwebsite.com': 'https://www.uat.productionwebsite.com:9090/res/',
'API@www.productionwebsite.com': 'https://www.productionwebsite.com:9090/api/res/'
},
...
/* yadda yadda moar JSON und bisque */
function prefer(o,sufs) {
// body of prefer function, broken for e.g.
};
// convert string and comma-separated-string to array .. and process it
prefs = [].concat( ( prefs.split ? prefs.split(',') : prefs ) || []);
prefer(props,prefs);
window.app_props = JSON.parse(JSON.stringify(props));
})([location.hostname, ((window.navigator.userLanguage || window.navigator.language).split('-')[0]) ] );
एक पूर्व-कोणीय साइट अब संदर्भित करने के लिए एक ढह गई (कोई @ प्रत्यय कुंजियाँ) window.app_props होगी।
एक कोणीय साइट, बूटस्ट्रैप / इनिट स्टेप के रूप में, बस डेड-ड्रॉप प्रॉप ऑब्जेक्ट को $ rootScope में कॉपी करता है, और (वैकल्पिक रूप से) इसे ग्लोबल / विंडो स्कोप से नष्ट कर देता है
app.constant('props',angular.copy(window.app_props || {})).run( function ($rootScope,props) { $rootScope.props = props; delete window.app_props;} );
बाद में नियंत्रकों में इंजेक्ट किया जाना है:
app.controller('CtrlApp',function($log,props){ ... } );
या विचारों में बाइंडिंग से संदर्भित:
<span>{{ props.help.blurb }} {{ props.help.email }}</span>
चेतावनियां? @ वर्ण जेएस / जेएसएन चर / कुंजी नामकरण मान्य नहीं है, लेकिन अब तक स्वीकृत है। यदि यह एक डील-ब्रेकर है, तो किसी भी कन्वेंशन का विकल्प चुनें, जैसे कि "__" (डबल अंडरस्कोर) जब तक आप उससे चिपके रहते हैं।
तकनीक को सर्वर-साइड पर लागू किया जा सकता है, जिसे जावा या सी # में पोर्ट किया जा सकता है, लेकिन आपकी दक्षता / कॉम्पैक्टनेस भिन्न हो सकती है।
वैकल्पिक रूप से, फ़ंक्शन / कन्वेंशन आपके फ्रंट-एंड कम्पाइल स्क्रिप्ट का हिस्सा हो सकता है, जिससे कि पूरा गोर ऑल-इनवायरमेंट / ऑल-लैंग्वेज JSON कभी भी वायर पर प्रसारित न हो।
अपडेट करें
हमने इस तकनीक का उपयोग एक कुंजी को कई प्रत्ययों की अनुमति देने के लिए किया है, ताकि संग्रह का उपयोग करने के लिए मजबूर होने से बचने के लिए (आप अभी भी, जितनी गहराई से चाहें), और साथ ही पसंदीदा प्रत्ययों के आदेश का सम्मान कर सकें।
उदाहरण (कार्यशील jsFiddle को भी देखें ):
var o = { 'a':'apple', 'a@dev':'apple-dev', 'a@fr':'pomme',
'b':'banana', 'b@fr':'banane', 'b@dev&fr':'banane-dev',
'c':{ 'o':'c-dot-oh', 'o@fr':'c-point-oh' }, 'c@dev': { 'o':'c-dot-oh-dev', 'o@fr':'c-point-oh-dev' } };
/*1*/ prefer(o,'dev'); // { a:'apple-dev', b:'banana', c:{o:'c-dot-oh-dev'} }
/*2*/ prefer(o,'fr'); // { a:'pomme', b:'banane', c:{o:'c-point-oh'} }
/*3*/ prefer(o,'dev,fr'); // { a:'apple-dev', b:'banane-dev', c:{o:'c-point-oh-dev'} }
/*4*/ prefer(o,['fr','dev']); // { a:'pomme', b:'banane-dev', c:{o:'c-point-oh-dev'} }
/*5*/ prefer(o); // { a:'apple', b:'banana', c:{o:'c-dot-oh'} }
1/2 (मूल उपयोग) '@dev' कुंजी पसंद करता है, अन्य सभी प्रत्यय कुंजियों को छोड़ देता है
3 '@ देवा' के ऊपर '@देव' पसंद करते हैं, अन्य सभी के ऊपर '@ देव और फ्र' पसंद करते हैं
4 (3 के समान) लेकिन '@ देवा' पर '@fr' पसंद करता है)
5 कोई पसंदीदा प्रत्यय नहीं, सभी प्रत्यय गुणों को गिराता है
यह प्रत्येक प्रत्यय संपत्ति को स्कोर करके और गैर-प्रत्यय संपत्ति के लिए एक प्रत्यय संपत्ति के मूल्य को बढ़ावा देने के द्वारा पूरा करता है जब संपत्तियों पर पुनरावृत्ति करता है और एक उच्च स्कोर वाले प्रत्यय पाता है।
इस संस्करण में कुछ क्षमताएँ, जिनमें JSON पर निर्भरता को गहरी-प्रतिलिपि करने के लिए, और केवल उन वस्तुओं में पुनरावृत्ति करना शामिल है जो उनकी गहराई पर स्कोरिंग दौर से बचते हैं:
function prefer(obj,suf) {
function pr(o,s) {
for (var p in o) {
if (!o.hasOwnProperty(p) || !p.split('@')[1] || p.split('@@')[1] ) continue; // ignore: proto-prop OR not-suffixed OR temp prop score
var b = p.split('@')[0]; // base prop name
if(!!!o['@@'+b]) o['@@'+b] = 0; // +score placeholder
var ps = p.split('@')[1].split('&'); // array of property suffixes
var sc = 0; var v = 0; // reset (running)score and value
while(ps.length) {
// suffix value: index(of found suffix in prefs)^10
v = Math.floor(Math.pow(10,s.indexOf(ps.pop())));
if(!v) { sc = 0; break; } // found suf NOT in prefs, zero score (delete later)
sc += v;
}
if(sc > o['@@'+b]) { o['@@'+b] = sc; o[b] = o[p]; } // hi-score! promote to base prop
delete o[p];
}
for (var p in o) if(p.split('@@')[1]) delete o[p]; // remove scores
for (var p in o) if(typeof o[p] === 'object') pr(o[p],s); // recurse surviving objs
}
if( typeof obj !== 'object' ) return; // validate
suf = ( (suf || suf === 0 ) && ( suf.length || suf === parseFloat(suf) ) ? suf.toString().split(',') : []); // array|string|number|comma-separated-string -> array-of-strings
pr(obj,suf.reverse());
}
'ngconstant:development'
में'serve'
यदि आप के तहत घड़ी की config में रख -'gruntfile'
के रूप मेंtasks: ['ngconstant:development']
आप पुनः आरंभ करने की जरूरत नहीं होगी -grunt serve
जब आप gruntfile में विकास चर अद्यतन करें।