Phrasen Plugin: async loadCategory function & use Vue.computed()

This commit is contained in:
cgfhtw
2023-11-16 15:23:40 +01:00
parent 5b2bfb9340
commit a82df1058d
9 changed files with 95 additions and 118 deletions
+3 -3
View File
@@ -35,13 +35,13 @@ $this->load->view(
antrag-type="<?= $antrag_type; ?>"
studierendenantrag-id="<?= $studierendenantrag_id; ?>"
v-model:info-array="infoArray"
v-model:status-msg="statusMsg"
v-model:status-severity="statusSeverity"
v-model:status-msg="status.msg"
v-model:status-severity="status.severity"
>
</studierendenantrag-antrag>
</div>
<div class="col-sm-4 mb-3">
<studierendenantrag-status :msg="statusMsg" :severity="statusSeverity"></studierendenantrag-status>
<studierendenantrag-status :msg="status.msg" :severity="status.severity"></studierendenantrag-status>
<studierendenantrag-infoblock :infos="infoArray"></studierendenantrag-infoblock>
</div>
</div>
+4 -2
View File
@@ -13,8 +13,10 @@ const app = Vue.createApp({
},
data() {
return {
statusMsg: "",
statusSeverity: "",
status: {
msg: '',
severity: ''
},
infoArray: []
};
}
@@ -52,7 +52,7 @@ export default {
this.data = result.data.retval;
if (this.data.status) {
this.$emit("setStatus", {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.data.statustyp}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.data.statustyp})),
severity: this.statusSeverity
});
}
@@ -63,7 +63,7 @@ export default {
createAntrag() {
bootstrap.Modal.getOrCreateInstance(this.$refs.modal).hide();
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_saving')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_saving')})),
severity: 'warning'
});
this.saving = true;
@@ -89,7 +89,7 @@ export default {
this.errors.default.push(result.data.retval[k]);
}
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_error')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_error')})),
severity: 'danger'
});
}
@@ -100,13 +100,13 @@ export default {
this.data = result.data.retval;
if (this.data.status) {
this.$emit("setStatus", {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.data.statustyp}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.data.statustyp})),
severity: this.statusSeverity
});
}
else
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_open')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_open')})),
severity:'success'
});
}
@@ -116,7 +116,7 @@ export default {
},
cancelAntrag() {
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_cancelling')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_cancelling')})),
severity: 'warning'
});
this.saving = true;
@@ -140,7 +140,7 @@ export default {
this.errors.default.push(result.data.retval[k]);
}
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_error')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_error')})),
severity:'danger'
});
}
@@ -152,13 +152,13 @@ export default {
this.data = result.data.retval;
if (this.data.status) {
this.$emit("setStatus", {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.data.statustyp}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.data.statustyp})),
severity: this.statusSeverity
});
}
else
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_cancelled')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_cancelled')})),
severity: 'danger'
});
}
@@ -52,7 +52,7 @@ export default {
this.data = result.data.retval;
if (this.data.status) {
this.$emit("setStatus", {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.data.statustyp}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.data.statustyp})),
severity: this.statusSeverity
});
}
@@ -63,7 +63,7 @@ export default {
createAntrag() {
bootstrap.Modal.getOrCreateInstance(this.$refs.modal).hide();
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_saving')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_saving')})),
severity: 'warning'
});
this.saving = true;
@@ -89,7 +89,7 @@ export default {
this.errors.default.push(result.data.retval[k]);
}
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_error')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_error')})),
severity: 'danger'
});
}
@@ -100,13 +100,13 @@ export default {
this.data = result.data.retval;
if (this.data.status) {
this.$emit("setStatus", {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.data.statustyp}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.data.statustyp})),
severity: this.statusSeverity
});
}
else
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_open')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_open')})),
severity:'success'
});
}
@@ -75,7 +75,7 @@ export default {
this.data = result.data.retval;
if (this.data.status) {
this.$emit("setStatus", {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.data.statustyp}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.data.statustyp})),
severity: this.statusSeverity
});
}
@@ -85,7 +85,7 @@ export default {
},
createAntrag() {
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_saving')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_saving')})),
severity: 'warning'
});
this.saving = true;
@@ -122,7 +122,7 @@ export default {
this.errors.default.push(result.data.retval[k]);
}
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_error')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_error')})),
severity: 'danger'
});
}
@@ -133,13 +133,13 @@ export default {
this.data = result.data.retval;
if (this.data.status) {
this.$emit("setStatus", {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.data.statustyp}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.data.statustyp})),
severity: this.statusSeverity
});
}
else
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_created')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_created')})),
severity: 'info'
});
}
@@ -149,7 +149,7 @@ export default {
},
cancelAntrag() {
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_cancelling')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_cancelling')})),
severity: 'warning'
});
this.saving = true;
@@ -173,7 +173,7 @@ export default {
this.errors.default.push(result.data.retval[k]);
}
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_error')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_error')})),
severity: 'danger'
});
}
@@ -185,13 +185,13 @@ export default {
this.data = result.data.retval;
if (this.data.status) {
this.$emit("setStatus", {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.data.statustyp}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.data.statustyp})),
severity: this.statusSeverity
});
}
else
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_cancelled')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_cancelled')})),
severity: 'danger'
});
}
@@ -67,7 +67,7 @@ export default {
}
this.$emit('update:status', this.data.status);
this.$emit("setStatus", {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.data.statustyp}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.data.statustyp})),
severity: this.statusSeverity
});
return result;
@@ -85,7 +85,7 @@ export default {
let nextState = repeat ? 'Erstellt' : 'Verzichtet';
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_saving')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_saving')})),
severity: 'warning'
});
this.saving = true;
@@ -112,7 +112,7 @@ export default {
this.errors.default.push(result.data.retval[k]);
}
this.$emit('setStatus', {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_error')}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.$p.t('studierendenantrag', 'status_error')})),
severity: 'danger'
});
}
@@ -125,7 +125,7 @@ export default {
this.data.status = nextState;
this.$emit('update:status', this.data.status);
this.$emit("setStatus", {
msg: this.$p.t_ref('studierendenantrag', 'status_x', {status: this.data.statustyp}),
msg: Vue.computed(() => this.$p.t('studierendenantrag', 'status_x', {status: this.data.statustyp})),
severity: this.statusSeverity
});
}
@@ -139,7 +139,7 @@ export default {
},
mounted() {
this.infos = [...Array(5).keys()].map(n => ({
body: this.$p.t_ref('studierendenantrag', 'infotext_Wiederholung_' + n)
body: Vue.computed(() => this.$p.t('studierendenantrag', 'infotext_Wiederholung_' + n))
}));
this.$emit('setInfos', this.infos);
},
@@ -6,9 +6,6 @@ export default {
toggleColumn(col) {
col.visible = !col.visible;
col.original.toggle()
},
show() {
}
},
template: `
@@ -74,7 +74,8 @@ export default {
this.$refs.lvList.show();
}
},
mounted() {
async mounted() {
await this.$p.loadCategory(['lehre', 'studierendenantrag', 'person', 'global', 'ui']);
function dateFormatter(cell)
{
let val = cell.getValue();
@@ -112,7 +113,7 @@ export default {
title: '#'
}, {
field: 'bezeichnung',
title: this.$p.t_node('lehre', 'studiengang'),
title: this.$p.t('lehre', 'studiengang'),
headerFilter: 'list',
headerFilterParams: {
valuesLookup: true,
@@ -121,7 +122,7 @@ export default {
}
}, {
field: 'orgform',
title: this.$p.t_node('lehre', 'organisationsform'),
title: this.$p.t('lehre', 'organisationsform'),
headerFilter: 'list',
headerFilterParams: {
valuesLookup: true,
@@ -130,7 +131,7 @@ export default {
}
}, {
field: 'typ',
title: this.$p.t_node('studierendenantrag', 'antrag_typ'),
title: this.$p.t('studierendenantrag', 'antrag_typ'),
headerFilter: 'list',
headerFilterParams: {
valuesLookup: true,
@@ -142,7 +143,7 @@ export default {
}
}, {
field: 'statustyp',
title: this.$p.t_node('studierendenantrag', 'antrag_status'),
title: this.$p.t('studierendenantrag', 'antrag_status'),
headerFilter: 'list',
headerFilterParams: {
valuesLookup: true,
@@ -164,32 +165,32 @@ export default {
}
}, {
field: 'matrikelnr',
title: this.$p.t_node('person', 'personenkennzeichen'),
title: this.$p.t('person', 'personenkennzeichen'),
headerFilter: 'input'
}, {
field: 'prestudent_id',
title: this.$p.t_node('lehre', 'prestudent'),
title: this.$p.t('lehre', 'prestudent'),
headerFilter: 'input'
}, {
field: 'name',
title: this.$p.t_node('global', 'name'),
title: this.$p.t('global', 'name'),
mutator: (value, data) => (data.vorname + ' ' + data.nachname).replace(/^\s*(.*)\s*$/, '$1'),
headerFilter: 'input'
}, {
field: 'datum',
title: this.$p.t_node('global', 'datum'),
title: this.$p.t('global', 'datum'),
formatter: dateFormatter,
headerFilterFunc: 'dates',
headerFilter: dateFilter
}, {
field: 'datum_wiedereinstieg',
title: this.$p.t_node('studierendenantrag', 'antrag_datum_wiedereinstieg'),
title: this.$p.t('studierendenantrag', 'antrag_datum_wiedereinstieg'),
formatter: dateFormatter,
headerFilterFunc: 'dates',
headerFilter: dateFilter
}, {
field: 'grund',
title: this.$p.t_node('studierendenantrag', 'antrag_grund'),
title: this.$p.t('studierendenantrag', 'antrag_grund'),
formatter: (cell, formatterParams, onRendered) => {
let link = document.createElement('a'),
val = cell.getValue();
@@ -204,7 +205,7 @@ export default {
}
}, {
field: 'dms_id',
title: this.$p.t_node('studierendenantrag', 'antrag_dateianhaenge'),
title: this.$p.t('studierendenantrag', 'antrag_dateianhaenge'),
formatter: (cell, formatterParams, onRendered) => {
let val = cell.getValue();
if (!val)
@@ -216,13 +217,13 @@ export default {
val;
link.setAttribute('target', '_blank');
link.innerHTML = '<i class="fa fa-paperclip" aria-hidden="true"></i>';
link.append(this.$p.t_node('studierendenantrag/antrag_anhang'));
link.append(this.$p.t('studierendenantrag/antrag_anhang'));
return link;
}
}, {
field: 'actions',
frozen: true,
title: this.$p.t_node('ui', 'aktion'),
title: this.$p.t('ui', 'aktion'),
headerFilter: false,
headerSort: false,
formatter: (cell, formatterParams, onRendered) => {
@@ -246,7 +247,7 @@ export default {
if (data.typ == 'AbmeldungStgl' && data.status == 'Genehmigt') {
// NOTE(chris): Object
let button = document.createElement('button');
button.append(this.$p.t_node('studierendenantrag', 'btn_object'));
button.append(this.$p.t('studierendenantrag', 'btn_object'));
button.className = "btn btn-outline-secondary";
button.addEventListener('click', () => this.$emit('action:object', [cell.getData()]));
container.append(button);
@@ -255,14 +256,14 @@ export default {
if (data.typ == 'AbmeldungStgl' && data.status == 'Beeinsprucht') {
// NOTE(chris): Deny Objection
let button = document.createElement('button');
button.append(this.$p.t_node('studierendenantrag', 'btn_objection_deny'));
button.append(this.$p.t('studierendenantrag', 'btn_objection_deny'));
button.className = "btn btn-outline-secondary";
button.addEventListener('click', () => this.$emit('action:objectionDeny', [cell.getData()]));
container.append(button);
// NOTE(chris): Approve Objection
button = document.createElement('button');
button.append(this.$p.t_node('studierendenantrag', 'btn_objection_approve'));
button.append(this.$p.t('studierendenantrag', 'btn_objection_approve'));
button.className = "btn btn-outline-secondary";
button.addEventListener('click', () => this.$emit('action:objectionApprove', [cell.getData()]));
container.append(button);
@@ -272,7 +273,7 @@ export default {
// NOTE(chris): Reopen
if (data.typ == 'Wiederholung' && data.status == 'Verzichtet') {
let button = document.createElement('button');
button.append(this.$p.t_node('studierendenantrag', 'btn_reopen'));
button.append(this.$p.t('studierendenantrag', 'btn_reopen'));
button.className = "btn btn-outline-secondary";
button.addEventListener('click', () => this.$emit('action:reopen', [cell.getData()]));
container.append(button);
@@ -280,7 +281,7 @@ export default {
// NOTE(chris): Lv Zuweisen
if (data.typ == 'Wiederholung' && (data.status == 'Erstellt' || data.status == 'Lvszugewiesen')) {
let button = document.createElement('a');
button.append(this.$p.t_node('studierendenantrag', 'btn_lvzuweisen'));
button.append(this.$p.t('studierendenantrag', 'btn_lvzuweisen'));
button.className = "btn btn-outline-secondary";
button.href = FHC_JS_DATA_STORAGE_OBJECT.app_root +
FHC_JS_DATA_STORAGE_OBJECT.ci_router +
@@ -302,7 +303,7 @@ export default {
// NOTE(chris): Cancel
if (data.typ == 'AbmeldungStgl' && (data.status == 'Erstellt' || data.status == 'Genehmigt' )) {
let button = document.createElement('button');
button.append(this.$p.t_node('studierendenantrag', 'btn_cancel'));
button.append(this.$p.t('studierendenantrag', 'btn_cancel'));
button.className = "btn btn-outline-secondary";
button.addEventListener('click',() => this.$emit('action:cancel', [cell.getData()]));
container.append(button);
@@ -313,7 +314,7 @@ export default {
// NOTE(chris): Approve
if ((data.typ == 'Wiederholung' && data.status == 'Lvszugewiesen') || (data.typ != 'Wiederholung' && data.status == 'Erstellt')) {
let button = document.createElement('button');
button.append(this.$p.t_node('studierendenantrag', 'btn_approve'));
button.append(this.$p.t('studierendenantrag', 'btn_approve'));
button.className = "btn btn-outline-secondary";
button.addEventListener('click', () => this.$emit('action:approve', [cell.getData()]));
container.append(button);
@@ -321,7 +322,7 @@ export default {
// NOTE(chris): Reject (Unterbrechung braucht grund)
if (data.status == 'Erstellt' && data.typ == 'Unterbrechung') {
let button = document.createElement('button');
button.append(this.$p.t_node('studierendenantrag', 'btn_reject'));
button.append(this.$p.t('studierendenantrag', 'btn_reject'));
button.className = "btn btn-outline-secondary";
button.addEventListener('click', () => this.$emit('action:reject', [cell.getData()]));
container.append(button);
@@ -331,7 +332,7 @@ export default {
// NOTE(chris): Show LVs
if (data.typ == 'Wiederholung' && (data.status == 'Lvszugewiesen' || data.status == 'Genehmigt')) {
let button = document.createElement('button');
button.append(this.$p.t_node('studierendenantrag', 'btn_show_lvs'));
button.append(this.$p.t('studierendenantrag', 'btn_show_lvs'));
button.className = "btn btn-outline-secondary";
button.addEventListener('click', () => this.showLVs(cell.getData()));
container.append(button);
+36 -59
View File
@@ -1,4 +1,4 @@
const categories = {};
const categories = Vue.reactive({});
const loadingModules = {};
function extractCategory(obj, category) {
@@ -8,37 +8,6 @@ function extractCategory(obj, category) {
return res;
}, {});
}
function reloadRefs(category) {
while (loadingModules[category].length) {
var v = loadingModules[category].pop();
if (v[0].nodeType && v[0].nodeType == Node.TEXT_NODE) {
v[0].textContent = getValueForLoadedPhrase(category, v[1], v[2]);
} else if (Vue.isRef(v[0])) {
v[0].value = getValueForLoadedPhrase(category, v[1], v[2]);
Vue.triggerRef(v[0]);
/*Vue.unref(v);*/
}
}
}
function loadLazy(category, val, phrase, params) {
// NOTE(chris): load module if it's not loaded yet
if (loadingModules[category]) {
loadingModules[category].push([val, phrase, params]);
if (categories[category]) // NOTE(chris): this is for safety in case the loading finished the moment before the val was pushed into the array
reloadRefs(category);
return;
}
loadingModules[category] = [[val, phrase, params]];
axios.get(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/components/Phrasen/loadModule/' + category).then(res => {
if (res.data.retval)
categories[category] = extractCategory(res.data.retval, category);
else
categories[category] = {};
reloadRefs(category);
}).catch(err => console.error(err));
}
function getValueForLoadedPhrase(category, phrase, params) {
let result = categories[category][phrase];
if (!result)
@@ -48,38 +17,46 @@ function getValueForLoadedPhrase(category, phrase, params) {
return result;
}
function t_intern(val, category, phrase, params) {
if (params === undefined && (
(Array.isArray(category) && category.length == 2) ||
(category.split && category.split('/').length == 2))
) {
params = phrase;
[category, phrase] = category.split ? category.split('/') : category;
}
if (phrase === undefined) {
console.error('invalid input', category, phrase, params);
return '';
}
if (categories[category])
return getValueForLoadedPhrase(category, phrase, params);
loadLazy(category, val, phrase, params);
return '';
}
const phrasen = {
t_ref(category, phrase, params) {
let val = Vue.ref('');
val.value = t_intern(val, category, phrase, params);
return val;
loadCategory(category) {
if (Array.isArray(category))
return Promise.all(category.map(cat => this.loadCategory(cat)));
if (!loadingModules[category])
loadingModules[category] = axios
.get(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/components/Phrasen/loadModule/' + category)
.then(res => {
if (res.data.retval)
categories[category] = extractCategory(res.data.retval, category);
else
categories[category] = {};
});
return loadingModules[category];
},
t_node(category, phrase, params) {
let val = document.createTextNode('');
val.textContent = t_intern(val, category, phrase, params);
return val;
t_ref(category, phrase, params) {
console.warn('depricated');
return Vue.computed(() => this.t(category, phrase, params));
},
t(category, phrase, params) {
return Vue.unref(this.t_ref(category, phrase, params));
if (params === undefined && (
(Array.isArray(category) && category.length == 2) ||
(category.split && category.split('/').length == 2))
) {
params = phrase;
[category, phrase] = category.split ? category.split('/') : category;
}
if (phrase === undefined) {
console.error('invalid input', category, phrase, params);
return '';
}
let val = Vue.computed(() => {
if (!categories[category])
return '';
return getValueForLoadedPhrase(category, phrase, params);
});
if (!categories[category])
this.loadCategory(category);
return val.value;
}
};