implemented tabulator localization

This commit is contained in:
adisposkofh
2026-05-06 10:54:18 +02:00
parent 552faefa51
commit b6e1bb06f3
8 changed files with 603 additions and 63 deletions
@@ -32,6 +32,7 @@ class Phrasen extends FHCAPI_Controller
'setLanguage' => self::PERM_ANONYMOUS,
'getLanguage' => self::PERM_ANONYMOUS,
'getAllLanguages' => self::PERM_ANONYMOUS,
'getPhrases' => self::PERM_ANONYMOUS
]);
$this->load->helper('hlp_language');
@@ -92,4 +93,30 @@ class Phrasen extends FHCAPI_Controller
$this->terminateWithSuccess($langs);
}
public function getPhrases()
{
$languages = json_decode($this->input->get('languages'));
if (!$languages || !count($languages)) {
$this->load->model('system/Sprache_model', 'sprachenModel');
$activeLanguages = $this->sprachenModel->loadWhere(array('content' => true));
$activeLanguagesData = $this->getDataOrTerminateWithError($activeLanguages);
$languages = array_map(
function ($languageData) {
return $languageData->sprache;
},
$activeLanguagesData
);
}
$this->load->model('system/Phrase_model', 'phraseModel');
$phrasesGroupedByCategory = json_decode($this->input->get('phrasesGroupedByCategory'));
$result = [];
foreach ($languages as $language) {
$phrases = $this->phraseModel->getPhrasesByCategoryAndPhrasesAndLanguage($phrasesGroupedByCategory, $language);
$result[$language] = $this->getDataOrTerminateWithError($phrases);
}
$this->terminateWithSuccess($result);
}
}
+11 -1
View File
@@ -41,5 +41,15 @@ export default {
method: 'get',
url: '/api/frontend/v1/phrasen/getAllLanguages'
};
}
},
getPhrases(phrasesGroupedByCategory, languages = []) {
return {
method: 'get',
url: '/api/frontend/v1/phrasen/getPhrases',
params: {
phrasesGroupedByCategory: JSON.stringify(phrasesGroupedByCategory),
languages: JSON.stringify(languages),
},
};
},
};
@@ -34,7 +34,6 @@ export default {
return {
showModal: false,
editDataFilter: null,
preloadedPhrasen:{},
// tabulator options
funktionen_table_options: {
persistenceID: "filterTableMaProfilFunktionen",
@@ -46,6 +45,7 @@ export default {
responsiveLayout: "collapse",
responsiveLayoutCollapseUseFormatters: false,
responsiveLayoutCollapseFormatter: Vue.$collapseFormatter,
locale: true,
columns: [
{
title:
@@ -59,21 +59,21 @@ export default {
visible: true
},
{
title: Vue.computed(() => this.preloadedPhrasen.bezeichnungPhrase),
title: "ui/bezeichnung",
field: "Bezeichnung",
headerFilter: true,
minWidth: 200,
visible: true
},
{
title: Vue.computed(() => this.preloadedPhrasen.organisationseinheitPhrase),
title: "lehre/organisationseinheit",
field: "Organisationseinheit",
headerFilter: true,
minWidth: 200,
visible: true
},
{
title: Vue.computed(() => this.preloadedPhrasen.gueltigVonPhrase),
title: "global/gueltigVon",
field: "Gültig_von",
headerFilterFunc: 'dates',
headerFilter: dateFilter,
@@ -84,7 +84,7 @@ export default {
formatterParams: this.datetimeFormatterParams()
},
{
title: Vue.computed(() => this.preloadedPhrasen.gueltigBisPhrase),
title: "global/gueltigBis",
field: "Gültig_bis",
headerFilterFunc: 'dates',
headerFilter: dateFilter,
@@ -95,7 +95,7 @@ export default {
formatterParams: this.datetimeFormatterParams()
},
{
title: Vue.computed(() => this.preloadedPhrasen.wochenstundenPhrase),
title: "profil/wochenstunden",
field: "Wochenstunden",
headerFilter: true,
minWidth: 200,
@@ -115,6 +115,7 @@ export default {
responsiveLayoutCollapseUseFormatters: false,
responsiveLayoutCollapseFormatter: Vue.$collapseFormatter,
data: [{betriebsmittel: "", Nummer: "", Ausgegeben_am: ""}],
locale: true,
columns: [
{
title:
@@ -128,14 +129,14 @@ export default {
visible: true
},
{
title: Vue.computed(() => this.preloadedPhrasen.entlehnteBetriebsmittelPhrase),
title: "profil/entlehnteBetriebsmittel",
field: "betriebsmittel",
headerFilter: true,
minWidth: 200,
visible: true
},
{
title: Vue.computed(() => this.preloadedPhrasen.inventarnummerPhrase),
title: "profil/inventarnummer",
field: "Nummer",
headerFilter: true,
resizable: true,
@@ -143,7 +144,7 @@ export default {
visible: true
},
{
title: Vue.computed(() => this.preloadedPhrasen.ausgabedatumPhrase),
title: "profil/ausgabedatum",
field: "Ausgegeben_am",
headerFilterFunc: 'dates',
headerFilter: dateFilter,
@@ -299,18 +300,6 @@ export default {
},
created() {
// preload phrasen
this.$p.loadCategory(["ui","lehre","global","profil"]).then(() => {
this.preloadedPhrasen.bezeichnungPhrase = this.$p.t('ui/bezeichnung');
this.preloadedPhrasen.organisationseinheitPhrase = this.$p.t('lehre/organisationseinheit');
this.preloadedPhrasen.gueltigVonPhrase = this.$p.t('global/gueltigVon');
this.preloadedPhrasen.gueltigBisPhrase = this.$p.t('global/gueltigBis');
this.preloadedPhrasen.wochenstundenPhrase = this.$p.t('profil/wochenstunden');
this.preloadedPhrasen.entlehnteBetriebsmittelPhrase = this.$p.t('profil/entlehnteBetriebsmittel');
this.preloadedPhrasen.inventarnummerPhrase = this.$p.t('profil/inventarnummer');
this.preloadedPhrasen.ausgabedatumPhrase = this.$p.t('profil/ausgabedatum');
this.preloadedPhrasen.loaded=true;
});
//? sorts the profil Updates: pending -> accepted -> rejected
this.data.profilUpdates?.sort(this.sortProfilUpdates);
@@ -440,7 +429,6 @@ export default {
<div class="col-12 mb-4" >
<!-- FUNKTIONEN TABELLE -->
<core-filter-cmpt
v-if="preloadedPhrasen.loaded"
@tableBuilt="funktionenTableBuilt"
:title="$p.t('person','funktionen')"
ref="funktionenTable"
@@ -452,7 +440,6 @@ export default {
<div class="col-12 mb-4" >
<!-- BETRIEBSMITTEL TABELLE -->
<core-filter-cmpt
v-if="preloadedPhrasen.loaded"
@tableBuilt="betriebsmittelTableBuilt"
:title="$p.t('profil','entlehnteBetriebsmittel')"
ref="betriebsmittelTable"
@@ -20,7 +20,6 @@ export default {
data() {
return {
collapseIconFunktionen: true,
preloadedPhrasen:{},
funktionen_table_options: {
persistenceID: "filterTableMaViewProfilFunktionen",
persistence: {
@@ -31,6 +30,7 @@ export default {
responsiveLayout: "collapse",
responsiveLayoutCollapseUseFormatters: false,
responsiveLayoutCollapseFormatter: Vue.$collapseFormatter,
locale: true,
columns: [
//? option when wanting to hide the collapsed list
@@ -46,21 +46,21 @@ export default {
visible: true
},
{
title: Vue.computed(() => this.$p.t('ui/bezeichnung')),
title: "ui/bezeichnung",
field: "Bezeichnung",
headerFilter: true,
minWidth: 200,
visible: true
},
{
title: Vue.computed(() => this.$p.t('lehre/organisationseinheit')),
title: "lehre/organisationseinheit",
field: "Organisationseinheit",
headerFilter: true,
minWidth: 200,
visible: true
},
{
title: Vue.computed(() => this.$p.t('global/gueltigVon')),
title: "global/gueltigVon",
field: "Gültig_von",
headerFilterFunc: 'dates',
headerFilter: dateFilter,
@@ -71,7 +71,7 @@ export default {
formatterParams: this.datetimeFormatterParams()
},
{
title: Vue.computed(() => this.$p.t('global/gueltigBis')),
title: "global/gueltigBis",
field: "Gültig_bis",
headerFilterFunc: 'dates',
headerFilter: dateFilter,
@@ -82,7 +82,7 @@ export default {
formatterParams: this.datetimeFormatterParams()
},
{
title: Vue.computed(() => this.$p.t('profil/wochenstunden')),
title: "profil/wochenstunden",
field: "Wochenstunden",
headerFilter: true,
minWidth: 200,
@@ -113,9 +113,6 @@ export default {
'data.funktionen'(newVal) {
if(this.$refs.funktionenTable) this.$refs.funktionenTable.tabulator.setData(newVal);
},
'language.value'(newVal) { // reevaluates computed phrasen
if(this.$refs.funktionenTable) this.$refs.funktionenTable.tabulator.setColumns(this.funktionen_table_options.columns)
}
},
computed: {
getTelefonValue() {
@@ -180,16 +177,6 @@ export default {
};
},
},
created(){
this.$p.loadCategory(["ui", "lehre", "global", "profil"]).then(() => {
this.preloadedPhrasen.bezeichnungPhrase = this.$p.t('ui/bezeichnung');
this.preloadedPhrasen.organisationseinheitPhrase = this.$p.t('lehre/organisationseinheit');
this.preloadedPhrasen.gueltigVonPhrase = this.$p.t('global/gueltigVon');
this.preloadedPhrasen.gueltigBisPhrase = this.$p.t('global/gueltigBis');
this.preloadedPhrasen.wochenstundenPhrase = this.$p.t('profil/wochenstunden');
this.preloadedPhrasen.loaded = true;
});
},
template: /*html*/ `
@@ -247,7 +234,7 @@ export default {
<div class="row">
<!-- FIRST TABLE -->
<div class="col-12 mb-4" >
<core-filter-cmpt v-if="preloadedPhrasen.loaded" @tableBuilt="funktionenTableBuilt" :title="$p.t('person','funktionen')" ref="funktionenTable" :tabulator-options="funktionen_table_options" tableOnly :sideMenu="false" />
<core-filter-cmpt @tableBuilt="funktionenTableBuilt" :title="$p.t('person','funktionen')" ref="funktionenTable" :tabulator-options="funktionen_table_options" tableOnly :sideMenu="false" />
</div>
<!-- END OF THE ROW WITH THE TABLES UNDER THE PROFIL INFORMATION -->
</div>
+1 -1
View File
@@ -24,7 +24,7 @@ Vue.$collapseFormatter = function (data) {
let item2 = document.createElement("div");
item2.classList.add("col-6");
item.innerHTML = "<strong>" + col.title + "</strong>";
item.innerHTML = "<strong class=\"collapsedColumnHeading\" field=\"" + col.field + "\">placeholder</strong>";
item2.innerHTML = col.value ? col.value : "-";
list.appendChild(item);
@@ -33,7 +33,6 @@ export default {
showModal: false,
collapseIconBetriebsmittel: true,
editDataFilter: null,
preloadedPhrasen:{},
// tabulator options
zutrittsgruppen_table_options: {
persistenceID: "filterTableStudentProfilZutrittsgruppen",
@@ -43,7 +42,7 @@ export default {
minHeight: 200,
layout: "fitColumns",
columns: [{
title: Vue.computed(() => this.preloadedPhrasen.zutrittsGruppenPhrase),
title: "profil/zutrittsGruppen",
field: "bezeichnung"
}],
},
@@ -57,6 +56,7 @@ export default {
responsiveLayout: "collapse",
responsiveLayoutCollapseUseFormatters: false,
responsiveLayoutCollapseFormatter: Vue.$collapseFormatter,
locale: true,
columns: [
{
title:
@@ -69,14 +69,14 @@ export default {
headerClick: this.collapseFunction,
},
{
title: Vue.computed(()=>this.preloadedPhrasen.entlehnteBetriebsmittelPhrase),
title: "profil/entlehnteBetriebsmittel",
field: "betriebsmittel",
headerFilter: true,
minWidth: 200,
visible: true
},
{
title: Vue.computed(() =>this.preloadedPhrasen.inventarnummerPhrase) ,
title: "profil/inventarnummer",
field: "Nummer",
headerFilter: true,
resizable: true,
@@ -84,7 +84,7 @@ export default {
visible: true
},
{
title: Vue.computed(() =>this.preloadedPhrasen.ausgabedatum) ,
title: "profil/ausgabedatum",
field: "Ausgegeben_am",
headerFilterFunc: 'dates',
headerFilter: dateFilter,
@@ -242,14 +242,6 @@ export default {
},
},
created() {
// preload phrasen
this.$p.loadCategory('profil').then(() => {
this.preloadedPhrasen.zutrittsGruppenPhrase = this.$p.t('profil/zutrittsGruppen');
this.preloadedPhrasen.entlehnteBetriebsmittelPhrase = this.$p.t('profil/entlehnteBetriebsmittel');
this.preloadedPhrasen.inventarnummerPhrase = this.$p.t('profil/inventarnummer');
this.preloadedPhrasen.ausgabedatum = this.$p.t('profil/ausgabedatum');
this.preloadedPhrasen.loaded = true;
});
//? sorts the profil Updates: pending -> accepted -> rejected
this.data.profilUpdates?.sort(this.sortProfilUpdates);
},
@@ -379,7 +371,6 @@ export default {
<div class="row">
<div class="col-12 mb-4" >
<core-filter-cmpt
v-if="preloadedPhrasen.loaded"
@tableBuilt="betriebsmittelTableBuilt"
:title="$p.t('profil','entlehnteBetriebsmittel')"
ref="betriebsmittelTable"
@@ -389,7 +380,6 @@ export default {
</div>
<div class="col-12 mb-4" >
<core-filter-cmpt
v-if="preloadedPhrasen.loaded"
@tableBuilt="zutrittsgruppenTableBuilt"
:title="$p.t('profil','zutrittsGruppen')"
ref="zutrittsgruppenTable"
+160 -3
View File
@@ -24,6 +24,7 @@ import collapseAutoClose from '../../directives/collapseAutoClose.js';
import moduleLayoutFitDataStretchFrozen from '../../tabulator/layouts/fitDataStretchFrozen.js';
import ApiFilter from '../../api/factory/filter.js';
import ApiPhrases from '../../api/factory/phrasen.js';
//
const FILTER_COMPONENT_NEW_FILTER = 'Filter Component New Filter';
@@ -84,8 +85,9 @@ export const CoreFilterCmpt = {
useSelectionSpan: {
type: Boolean,
default: true
}
},
},
inject: ["language"],
data: function() {
return {
uuid: 0,
@@ -120,7 +122,7 @@ export const CoreFilterCmpt = {
headerFilter: false,
group: false,
page: false,
}
},
};
},
computed: {
@@ -213,6 +215,19 @@ export const CoreFilterCmpt = {
return this.datasetMetadata.map(el => ({...el, ...{title: filterTitles[el.name]}}));
}
},
watch: {
"language.value": {
handler(newSelectedLanguage) {
if (!this.$props.tabulatorOptions.locale) return;
this.tabulator.setLocale(newSelectedLanguage);
if (this.$props.tabulatorOptions.responsiveLayoutCollapseFormatter) {
this.localizeCollapsedColumnHeadings(newSelectedLanguage);
}
},
},
},
methods: {
reloadTable() {
if (this.tableOnly)
@@ -263,6 +278,11 @@ export const CoreFilterCmpt = {
persistence: this.persistence,
}, ...(this.tabulatorOptions || {})};
// set up localizations if required
if (tabulatorOptions.locale) {
tabulatorOptions = await this.configureTabulatorLocalizations(tabulatorOptions);
}
// set default height if no height property is set
if (tabulatorOptions.height === undefined &&
tabulatorOptions.minHeight === undefined &&
@@ -302,7 +322,13 @@ export const CoreFilterCmpt = {
for (let evt of this.tabulatorEvents)
this.tabulator.on(evt.event, evt.handler);
}
this.tabulator.on('tableBuilt', () => {this.tableBuilt = true; this.$emit('tableBuilt');});
this.tabulator.on('tableBuilt', () => {
this.tableBuilt = true;
this.$emit('tableBuilt');
if (tabulatorOptions.locale && tabulatorOptions.responsiveLayoutCollapseFormatter) {
this.localizeCollapsedColumnHeadings();
}
});
this.tabulator.on("rowSelectionChanged", data => {
this.selectedData = data;
});
@@ -340,6 +366,9 @@ export const CoreFilterCmpt = {
this.selectedFields = cols.filter(col => col.isVisible()).map(col => col.getField());
if (this.tabulator.options.persistence.headerFilter)
this._setHeaderFilter();
if (tabulatorOptions.locale && tabulatorOptions.responsiveLayoutCollapseFormatter) {
this.localizeCollapsedColumnHeadings();
}
});
}
@@ -349,6 +378,134 @@ export const CoreFilterCmpt = {
this.$emit("headerFilterOn", this.filterActive);
});
},
async configureTabulatorLocalizations(tabulatorOptions) {
tabulatorOptions.locale = this.$p.user_language.value;
tabulatorOptions.langs = {};
let phrasesGroupedByCategoryRequestParam = {
tabulator: [
"loading",
"error",
"item",
"items",
"page_size",
"page_title",
"first",
"first_title",
"last",
"last_title",
"prev",
"prev_title",
"next",
"next_title",
"all",
"showing",
"of",
"rows",
"pages",
],
};
tabulatorOptions.columns.forEach((column) => {
if (column.field === "collapse") return;
let [category, phrase] = column.title.split("/");
if (phrasesGroupedByCategoryRequestParam[category]) {
phrasesGroupedByCategoryRequestParam[category].push(phrase);
} else {
phrasesGroupedByCategoryRequestParam[category] = [phrase];
}
});
const phrasesResponse = await this.$api.call(
ApiPhrases.getPhrases(phrasesGroupedByCategoryRequestParam),
);
const phrasesData = phrasesResponse.data;
Object.keys(phrasesData).forEach((language) => {
let genericTabulatorPhrases = phrasesData[language].filter(
(phrase) => phrase.category === "tabulator",
);
let tabulatorPhraseToTranslationMapper = {};
genericTabulatorPhrases.forEach((phrase) => {
tabulatorPhraseToTranslationMapper[phrase.phrase] =
phrase.text;
});
tabulatorOptions.langs[language] = {
data: {
loading: tabulatorPhraseToTranslationMapper["loading"],
error: tabulatorPhraseToTranslationMapper["error"],
},
groups: {
item: tabulatorPhraseToTranslationMapper["item"],
items: tabulatorPhraseToTranslationMapper["items"],
},
pagination: {
page_size:
tabulatorPhraseToTranslationMapper["page_size"],
page_title:
tabulatorPhraseToTranslationMapper["page_title"],
first: tabulatorPhraseToTranslationMapper["first"],
first_title:
tabulatorPhraseToTranslationMapper["first_title"],
last: tabulatorPhraseToTranslationMapper["last"],
last_title:
tabulatorPhraseToTranslationMapper["last_title"],
prev: tabulatorPhraseToTranslationMapper["prev"],
prev_title:
tabulatorPhraseToTranslationMapper["prev_title"],
next: tabulatorPhraseToTranslationMapper["next"],
next_title:
tabulatorPhraseToTranslationMapper["next_title"],
all: tabulatorPhraseToTranslationMapper["all"],
counter: {
showing:
tabulatorPhraseToTranslationMapper["showing"],
of: tabulatorPhraseToTranslationMapper["of"],
rows: tabulatorPhraseToTranslationMapper["rows"],
pages: tabulatorPhraseToTranslationMapper["pages"],
},
},
};
let columnHeadingPhrases = phrasesData[language].filter(
(phrase) => phrase.category !== "tabulator",
);
let columnTitleToTranslationMapper = {};
columnHeadingPhrases.forEach((phrase) => {
columnTitleToTranslationMapper[
phrase.category + "/" + phrase.phrase
] = phrase.text;
});
let columnFieldToTranslationMapper = {};
tabulatorOptions.columns.forEach((column) => {
if (column.field === "collapse") return;
columnFieldToTranslationMapper[column.field] =
columnTitleToTranslationMapper[column.title];
});
tabulatorOptions.langs[language].columns =
columnFieldToTranslationMapper;
});
return tabulatorOptions;
},
async localizeCollapsedColumnHeadings() {
const columnHeadings = this.tabulator.getLang().columns;
this.$refs.table
.querySelectorAll(".collapsedColumnHeading")
.forEach((collapsedColumnHeadingElement) => {
const field = collapsedColumnHeadingElement.getAttribute("field");
if (!field?.length) return;
collapsedColumnHeadingElement.innerHTML =
columnHeadings[field];
});
},
updateTabulator() {
if (this.tabulator) {
if (this.tableBuilt)
+382
View File
@@ -58177,6 +58177,388 @@ I have been informed that I am under no obligation to consent to the transmissio
)
),
// ### Phrases Dashboard Admin END
// generic tabulator phrases START
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'loading',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Loading',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'error',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Error',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'item',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'item',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'items',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'items',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'page_size',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Page Size',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'page_title',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Show Page',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'first',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'First',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'first_title',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'First Page',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'last',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Last',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'last_title',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Last Page',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'prev',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Prev',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'prev_title',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Prev Page',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'next',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Next',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'next_title',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Next Page',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'all',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'All',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'showing',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Showing',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'of',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'of',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'rows',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'rows',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'tabulator',
'phrase' => 'pages',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '???',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'pages',
'description' => '',
'insertvon' => 'system'
)
)
),
// generic tabulator phrases END
);