Дуже пізно до теми, але використовувана нами методика, передвугольна, - це скористатися JSON та гнучкістю JS для динамічного посилання ключів колекції та використання невід'ємних фактів оточення (ім'я сервера хоста, поточна мова браузера тощо) як вхідні дані для вибіркової дискримінації / переваги суфіксальних імен ключів у структурі даних JSON.
Це забезпечує не просто контекст середовища розгортання (на ОП), але будь-який довільний контекст (наприклад, мова), щоб забезпечити i18n або будь-яку іншу необхідну дисперсію одночасно, і (в ідеалі) в рамках одного маніфесту конфігурації, без дублювання, і зрозуміло очевидним.
ВІД 10 ЛІНІЙ VANILLA JS
Приблизно спрощений, але класичний приклад: Базова URL-адреса кінцевої точки API у файлі властивостей, відформатованих JSON, змінюється залежно від середовища, де (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 в самовиконанні JS-закриття, включаючи функцію preference (), і подаємо основні властивості імені хоста та language-code (і приймає будь-які додаткові довільні суфікси, які можуть знадобитися):
(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 для посилання.
Кутовий сайт, як етап завантаження / init, просто копіює мертвий предмет реквізиту в $ 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>
Пляшки? Символ @ не є дійсним іменуванням змінної JS / JSON / клавіш, але поки прийнято. Якщо це розрив угод, замініть будь-яку конвенцію, яка вам подобається, наприклад "__" (подвійне підкреслення), поки ви дотримуєтесь цього.
Ця методика може бути застосована на стороні сервера, перенесена на Java або C #, але ефективність / компактність можуть відрізнятися.
Крім того, функція / умова може бути частиною вашого сценарію компіляції на передньому кінці, так що повноцінне середовище / всемовний 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 віддає перевагу '@dev' над '@fr', віддає перевагу '@ dev & fr' над усіма іншими
4 (те саме, що 3, але віддає перевагу '@fr' над '@dev')
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'
- якщо ви помістіть його в конфіги вахти під ,'gruntfile'
якtasks: ['ngconstant:development']
- ви не повинні перезавантаженняgrunt serve
при оновленні змінних розвитку в gruntfile.