mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-22 01:22:54 +00:00
feat: add SCThingTranslator class. move functionality accordingly
This commit is contained in:
committed by
Karl-Philipp Wulfert
parent
797e5ca9de
commit
90e3d22399
5
package-lock.json
generated
5
package-lock.json
generated
@@ -2533,6 +2533,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ts-optchain": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ts-optchain/-/ts-optchain-0.1.2.tgz",
|
||||||
|
"integrity": "sha512-Xs1/xpXgTQhvgjP1qLIm5LWsgwAdpRnlfrHvMTyMPCNb4MP0WgYGCnK4xJBx0l4ZM+//IDubrmHkvp6BWfZfCg=="
|
||||||
|
},
|
||||||
"tslib": {
|
"tslib": {
|
||||||
"version": "1.9.3",
|
"version": "1.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
|
||||||
|
|||||||
@@ -38,12 +38,13 @@
|
|||||||
"@types/geojson": "1.0.6",
|
"@types/geojson": "1.0.6",
|
||||||
"@types/json-patch": "0.0.30",
|
"@types/json-patch": "0.0.30",
|
||||||
"json-patch": "0.7.0",
|
"json-patch": "0.7.0",
|
||||||
"jsonschema": "1.2.4"
|
"jsonschema": "1.2.4",
|
||||||
|
"ts-optchain": "0.1.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@openstapps/configuration": "0.6.0",
|
"@openstapps/configuration": "0.5.0",
|
||||||
"@openstapps/core-tools": "0.3.0",
|
"@openstapps/core-tools": "0.2.1",
|
||||||
"@openstapps/logger": "0.0.5",
|
"@openstapps/logger": "0.0.3",
|
||||||
"@types/chai": "4.1.7",
|
"@types/chai": "4.1.7",
|
||||||
"@types/humanize-string": "1.0.0",
|
"@types/humanize-string": "1.0.0",
|
||||||
"@types/node": "11.9.4",
|
"@types/node": "11.9.4",
|
||||||
|
|||||||
@@ -12,10 +12,8 @@
|
|||||||
* You should have received a copy of the GNU General Public License along with
|
* You should have received a copy of the GNU General Public License along with
|
||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import {SCThingsField} from './Classes';
|
|
||||||
import {SCOrganization} from './things/Organization';
|
import {SCOrganization} from './things/Organization';
|
||||||
import {SCPerson} from './things/Person';
|
import {SCPerson} from './things/Person';
|
||||||
import {isThingWithTranslations} from './types/Guards';
|
|
||||||
import {SCTranslations} from './types/i18n';
|
import {SCTranslations} from './types/i18n';
|
||||||
import {SCISO8601Date} from './types/Time';
|
import {SCISO8601Date} from './types/Time';
|
||||||
import {SCUuid} from './types/UUID';
|
import {SCUuid} from './types/UUID';
|
||||||
@@ -219,85 +217,9 @@ export class SCThingMeta {
|
|||||||
*/
|
*/
|
||||||
static fieldValueTranslations: any = {
|
static fieldValueTranslations: any = {
|
||||||
de: {
|
de: {
|
||||||
type: {
|
type: 'Ding',
|
||||||
AcademicTerm: 'Studienabschnitt',
|
|
||||||
Article: 'Artikel',
|
|
||||||
Book: 'Buch',
|
|
||||||
Catalog: 'Katalog',
|
|
||||||
Date: 'Termin',
|
|
||||||
Diff: 'Unterschied',
|
|
||||||
Dish: 'Essen',
|
|
||||||
Event: 'Veranstaltung',
|
|
||||||
Favorite: 'Favorit',
|
|
||||||
FloorPlan: 'Etagenplan',
|
|
||||||
Message: 'Nachricht',
|
|
||||||
Offer: 'Angebot',
|
|
||||||
Organization: 'Organisation',
|
|
||||||
Person: 'Person',
|
|
||||||
Place: 'Ort',
|
|
||||||
Setting: 'Einstellung',
|
|
||||||
Thing: 'Ding',
|
|
||||||
Ticket: 'Ticket',
|
|
||||||
Tour: 'Tour',
|
|
||||||
Video: 'Video',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Get field translation
|
|
||||||
*
|
|
||||||
* @param {keyof SCTranslations<T extends SCThing>} language Language to get field translation for
|
|
||||||
* @param {keyof T} field Field to get translation for
|
|
||||||
* @returns {string} Translated field or field itself
|
|
||||||
*/
|
|
||||||
static getFieldTranslation<T extends SCThing>(language: keyof SCTranslations<T>,
|
|
||||||
field: SCThingsField): string {
|
|
||||||
if (typeof this.fieldTranslations[language] !== 'undefined'
|
|
||||||
&& typeof this.fieldTranslations[language][field] !== 'undefined') {
|
|
||||||
return this.fieldTranslations[language][field];
|
|
||||||
}
|
|
||||||
|
|
||||||
return field as string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get field value translation
|
|
||||||
*
|
|
||||||
* @param {keyof SCTranslations<T>} language Language to get value translation for
|
|
||||||
* @param {string} field Field to get value translation for
|
|
||||||
* @param {T} thing SCThing to get value translation for
|
|
||||||
* @returns {string} Translated value or value itself
|
|
||||||
*/
|
|
||||||
static getFieldValueTranslation<T extends SCThing>(language: keyof SCTranslations<T>,
|
|
||||||
field: SCThingsField,
|
|
||||||
thing: T): string {
|
|
||||||
|
|
||||||
let translations: SCTranslations<SCThingTranslatableProperties>;
|
|
||||||
|
|
||||||
if (isThingWithTranslations(thing)) {
|
|
||||||
translations = thing.translations;
|
|
||||||
|
|
||||||
const languageTranslations: SCThingTranslatableProperties | undefined = translations[language];
|
|
||||||
|
|
||||||
if (typeof languageTranslations !== 'undefined') {
|
|
||||||
if (typeof (languageTranslations as any)[field] !== 'undefined') {
|
|
||||||
return (languageTranslations as any)[field];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get translation from meta object
|
|
||||||
if (typeof this.fieldValueTranslations[language] !== 'undefined'
|
|
||||||
&& typeof this.fieldValueTranslations[language][field] !== 'undefined'
|
|
||||||
&& typeof (thing as any)[field] !== 'undefined'
|
|
||||||
&& typeof this.fieldValueTranslations[language][field][(thing as any)[field]]) {
|
|
||||||
return this.fieldValueTranslations[language][field][(thing as any)[field]];
|
|
||||||
}
|
|
||||||
|
|
||||||
// fallback to value itself
|
|
||||||
return (thing as any)[field];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
303
src/core/Translator.ts
Normal file
303
src/core/Translator.ts
Normal file
@@ -0,0 +1,303 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 StApps
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
import {SCClasses, SCThingsField} from './Classes';
|
||||||
|
import {SCThing, SCThingType} from './Thing';
|
||||||
|
|
||||||
|
import {SCTranslations} from './types/i18n';
|
||||||
|
|
||||||
|
import {Defined, OCType} from 'ts-optchain';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SCThingTranslator class
|
||||||
|
*/
|
||||||
|
export class SCThingTranslator {
|
||||||
|
/**
|
||||||
|
* Property representing the translators base language.
|
||||||
|
* This means every translation is given for this language.
|
||||||
|
*/
|
||||||
|
private baseLanguage: keyof SCTranslations<SCThing>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property representing the translators target language
|
||||||
|
*/
|
||||||
|
private language: keyof SCTranslations<SCThing>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property provinding a mapping from a SCThingType to its known own meta class.
|
||||||
|
*/
|
||||||
|
private metaClasses: typeof SCClasses;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @example
|
||||||
|
* // returns translator instance for german
|
||||||
|
* new SCThingTranslator('de');
|
||||||
|
*/
|
||||||
|
constructor(language: keyof SCTranslations<SCThing>, baseLanguage?: keyof SCTranslations<SCThing>) {
|
||||||
|
this.baseLanguage = baseLanguage ? baseLanguage : 'en';
|
||||||
|
this.language = language;
|
||||||
|
this.metaClasses = SCClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get field value translation recursively
|
||||||
|
*
|
||||||
|
* @param firstObject Top level object that gets passed through the recursion
|
||||||
|
* @param data The intermediate object / primitive returned by the Proxys get() method
|
||||||
|
* @param keyPath The keypath that (in the end) leads to the translatable property (when added to firstObject)
|
||||||
|
* @returns an OCType<T> object allowing for access to translations or a translated value(s)
|
||||||
|
*/
|
||||||
|
private deeptranslate<T, K extends SCThing>(firstObject: K, data?: T, keyPath?: string): OCType<T> {
|
||||||
|
const proxy = new Proxy(
|
||||||
|
((defaultValue?: Defined<T>) => (data == null ? defaultValue : data)) as OCType<T>,
|
||||||
|
{
|
||||||
|
get: (target, key) => {
|
||||||
|
const obj: any = target();
|
||||||
|
const extendedKeyPath = [keyPath, key.toString()].filter((e) => e != null).join('.');
|
||||||
|
let possiblePrimitive = obj[key];
|
||||||
|
// check if obj[key] is an array that contains primitive type (arrays in SCThings are not mixing types)
|
||||||
|
if (obj[key] instanceof Array && obj[key].length) {
|
||||||
|
possiblePrimitive = obj[key][0];
|
||||||
|
}
|
||||||
|
if (typeof possiblePrimitive === 'string' ||
|
||||||
|
typeof possiblePrimitive === 'number' ||
|
||||||
|
typeof possiblePrimitive === 'boolean') {
|
||||||
|
// returns final translation for primitive data types
|
||||||
|
return this.deeptranslate(firstObject,
|
||||||
|
this.getFieldValueTranslation(firstObject, extendedKeyPath),
|
||||||
|
extendedKeyPath);
|
||||||
|
}
|
||||||
|
// recursion to get more calls to the Proxy handler 'get()' (key path not complete)
|
||||||
|
return this.deeptranslate(firstObject, obj[key], extendedKeyPath);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies only known field translations of the given SCThings meta class to an instance
|
||||||
|
*
|
||||||
|
* @param thingType The type of thing that will be translated
|
||||||
|
* @param language The language the thing property values are translated to
|
||||||
|
* @returns The thing with all known meta values translated
|
||||||
|
*/
|
||||||
|
private getAllMetaFieldTranslations<T extends SCThing>(thingType: SCThingType,
|
||||||
|
language: keyof SCTranslations<T>): object | undefined {
|
||||||
|
const fieldTranslations = {};
|
||||||
|
const metaClass = this.getMetaClassInstance(thingType);
|
||||||
|
if (metaClass === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assigns every property in fieldTranslations to the known base language translation
|
||||||
|
if (metaClass.fieldTranslations[this.baseLanguage] !== undefined) {
|
||||||
|
Object.keys(metaClass.fieldTranslations[this.baseLanguage]).forEach((key) => {
|
||||||
|
(fieldTranslations as any)[key] = metaClass.fieldTranslations[this.baseLanguage][key];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assigns every property in fieldTranslations to the known translation in given language
|
||||||
|
if (metaClass.fieldTranslations[language] !== undefined) {
|
||||||
|
Object.keys(metaClass.fieldTranslations[language]).forEach((key) => {
|
||||||
|
(fieldTranslations as any)[key] = metaClass.fieldTranslations[language][key];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return fieldTranslations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns meta class needed for translations given a SCThingType
|
||||||
|
*
|
||||||
|
* @param thingType
|
||||||
|
* @returns An instance of the metaclass
|
||||||
|
*/
|
||||||
|
private getMetaClassInstance(thingType: SCThingType): any {
|
||||||
|
if (thingType in this.metaClasses) {
|
||||||
|
return new (this.metaClasses as any)[thingType]();
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns property value at a certain (key) path of an object.
|
||||||
|
* @example
|
||||||
|
* // returns value of dish.offers[0].inPlace.categories[1]
|
||||||
|
* const dish: SCDish = {...};
|
||||||
|
* this.valueFromPath(dish, 'offers[0].inPlace.categories[1]');
|
||||||
|
* @param path Key path to evaluate
|
||||||
|
* @param obj Object to evaluate the key path upon
|
||||||
|
* @param separator Key path seperation element. Defaults to '.'
|
||||||
|
* @returns Property value at at key path
|
||||||
|
*/
|
||||||
|
private valueFromPath<T extends SCThing>(path: string, obj: T, separator = '.') {
|
||||||
|
path = path.replace(/\[/g, '.');
|
||||||
|
path = path.replace(/\]/g, '.');
|
||||||
|
path = path.replace(/\.\./g, '.');
|
||||||
|
path = path.replace(/\.$/, '');
|
||||||
|
const properties = path.split(separator);
|
||||||
|
return properties.reduce((prev: any, curr: any) => prev && prev[curr], obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get field value translation
|
||||||
|
* @example
|
||||||
|
* // returns translation of the property (if available) in the language defined when creating the translator object
|
||||||
|
* const dish: SCDish = {...};
|
||||||
|
* translator.translate(dish, 'offers[0].inPlace.categories[1]');
|
||||||
|
* @param thing SCThing to get value translation for
|
||||||
|
* @param field Field to get value translation for (keypath allowed)
|
||||||
|
* @returns Translated value(s) or value(s) itself
|
||||||
|
*/
|
||||||
|
public getFieldValueTranslation<T extends SCThing>(thing: T,
|
||||||
|
field: SCThingsField): string | string[] {
|
||||||
|
let translationPath = 'translations.' + this.language + '.' + field;
|
||||||
|
const regexTrimProperties = /.*(?:(\..*)(\[\d+\])|(\.[^\d]*$)|(\..*)(\.[\d]*$))/;
|
||||||
|
|
||||||
|
const pathMatch = field.match(regexTrimProperties);
|
||||||
|
|
||||||
|
// when translation is given in thing
|
||||||
|
let translation = this.valueFromPath(translationPath, thing);
|
||||||
|
if (translation) {
|
||||||
|
return translation;
|
||||||
|
} else if (pathMatch && pathMatch[1] && pathMatch[2] || pathMatch && pathMatch[4] && pathMatch[5]) {
|
||||||
|
// accessing iteratable of nested thing
|
||||||
|
const keyPath = (pathMatch[1] ? pathMatch[1] : pathMatch[4]) + (pathMatch[2] ? pathMatch[2] : pathMatch[5]);
|
||||||
|
const redactedField = field.replace(keyPath, '');
|
||||||
|
|
||||||
|
// when translation is given in nested thing
|
||||||
|
translationPath = `${redactedField}.translations.${this.language}${keyPath}`;
|
||||||
|
translation = this.valueFromPath(translationPath, thing);
|
||||||
|
if (translation) {
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
// when translation is given in nested meta thing via iterateable index
|
||||||
|
const nestedType = this.valueFromPath(field.replace(keyPath, '.type'), thing) as SCThingType;
|
||||||
|
translationPath = `fieldValueTranslations.${this.language}${keyPath}`;
|
||||||
|
translation = this.valueFromPath(translationPath.replace(
|
||||||
|
/\[(?=[^\[]*$).*|(?=[\d+]*$).*/, '[' + this.valueFromPath(field, thing) + ']'),
|
||||||
|
this.getMetaClassInstance(nestedType));
|
||||||
|
if (translation) {
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (pathMatch && pathMatch[3]) {
|
||||||
|
// accessing meta or instance of nested thing primitive value depth > 0
|
||||||
|
const keyPath = pathMatch[3];
|
||||||
|
const redactedField = field.replace(pathMatch[3], '');
|
||||||
|
|
||||||
|
// when translation is given in nested thing
|
||||||
|
translationPath = `${redactedField}.translations.${this.language}${keyPath}`;
|
||||||
|
if (this.valueFromPath(translationPath, thing)) {
|
||||||
|
return this.valueFromPath(translationPath, thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
// when translation is given in nested meta thing
|
||||||
|
const nestedType = this.valueFromPath(field.replace(keyPath, '.type'), thing) as SCThingType;
|
||||||
|
translationPath = `fieldValueTranslations.${this.language}${keyPath}`;
|
||||||
|
translation = this.valueFromPath(translationPath, this.getMetaClassInstance(nestedType));
|
||||||
|
if (translation instanceof Object) { // lookup translated keys in meta thing property
|
||||||
|
const translations: string[] = [];
|
||||||
|
this.valueFromPath(field, thing).forEach((key: string) => {
|
||||||
|
translationPath = `fieldValueTranslations.${this.language}${keyPath}.${key}`;
|
||||||
|
translations.push(this.valueFromPath(translationPath, this.getMetaClassInstance(nestedType)));
|
||||||
|
});
|
||||||
|
return translations;
|
||||||
|
}
|
||||||
|
if (!translation) { // translation not given, return as is
|
||||||
|
return this.valueFromPath(field, thing) as string;
|
||||||
|
}
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
// accessing meta thing primitive value depth = 0
|
||||||
|
translationPath = `fieldValueTranslations.${this.language}.${field}`;
|
||||||
|
translation = this.valueFromPath(translationPath, this.getMetaClassInstance(thing.type));
|
||||||
|
if (translation) {
|
||||||
|
if (translation instanceof Object) { // lookup translated keys in meta thing property
|
||||||
|
const translations: string[] = [];
|
||||||
|
this.valueFromPath(field, thing).forEach((key: string) => {
|
||||||
|
translationPath = `fieldValueTranslations.${this.language}.${field}.${key}`;
|
||||||
|
translations.push(this.valueFromPath(translationPath, this.getMetaClassInstance(thing.type)));
|
||||||
|
});
|
||||||
|
return translations;
|
||||||
|
}
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
// accessing meta thing primitive via iteratable index value depth = 0
|
||||||
|
translation = this.valueFromPath(translationPath.replace(
|
||||||
|
/\[(?=[^\[]*$).*|(?=[\d+]*$).*/, '[' + this.valueFromPath(field, thing) + ']'),
|
||||||
|
this.getMetaClassInstance(thing.type));
|
||||||
|
if (translation) {
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
// last resort: return as is
|
||||||
|
return this.valueFromPath(field, thing) as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get field value translation recursively
|
||||||
|
* @example
|
||||||
|
* const dish: SCDish = {...};
|
||||||
|
* translator.translate(dish).offers[0].inPlace.categories[1]());
|
||||||
|
* // or
|
||||||
|
* const dishTranslatedAccess = translator.translate(dish);
|
||||||
|
* dishTranslatedAccess.offers[0].inPlace.categories[1]();
|
||||||
|
* // undoing the OCType<T>
|
||||||
|
* const dishAsBefore: SCDish = dishTranslatedAccess()!;
|
||||||
|
* @param data Top level object that gets passed through the recursion
|
||||||
|
* @returns an OCType<T> object allowing for access to translations or a translated value(s)
|
||||||
|
*/
|
||||||
|
public translate<T extends SCThing>(data?: T): OCType<T> {
|
||||||
|
return new Proxy(
|
||||||
|
((defaultValue?: Defined<T>) => (data == null ? defaultValue : data)) as OCType<T>,
|
||||||
|
{
|
||||||
|
get: (target, key) => {
|
||||||
|
const obj: any = target();
|
||||||
|
let translatable = obj[key];
|
||||||
|
if (obj[key] instanceof Array && obj[key].length) {
|
||||||
|
translatable = obj[key][0];
|
||||||
|
if (typeof obj[key][0] === 'object' && !obj[key][0].origin) {
|
||||||
|
translatable = obj[key][0][Object.keys(obj[key][0])[0]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof translatable === 'string') {
|
||||||
|
// retrieve final translation
|
||||||
|
return this.deeptranslate(data!, this.getFieldValueTranslation(data!, key.toString()), key.toString());
|
||||||
|
}
|
||||||
|
// recursion to get more calls to the Proxy handler 'get()' (key path not complete)
|
||||||
|
return this.deeptranslate(data!, obj[key], key.toString());
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a SCThingType this function returns an object with the same basic structure as the corresponding SCThing.
|
||||||
|
* All the values will be set to the known translations of the property/key name.
|
||||||
|
* @example
|
||||||
|
* const translatedMetaDish = translator.translatedPropertyNames<SCCourseOfStudies>(SCThingType.CourseOfStudies);
|
||||||
|
* @param language The language the object is translated to
|
||||||
|
* @param thingType
|
||||||
|
* @returns An object with the properties of the SCThingType where the values are the known property tranlations
|
||||||
|
*/
|
||||||
|
public translatedPropertyNames<T extends SCThing>(thing: T,
|
||||||
|
language?: keyof SCTranslations<T>): T | undefined {
|
||||||
|
const targetLanguage = (language) ? language : this.language;
|
||||||
|
// return {...{}, ...this.getAllMetaFieldTranslations(thing.type, targetLanguage) as T};
|
||||||
|
return this.getAllMetaFieldTranslations(thing.type, targetLanguage) as T;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,4 +38,14 @@ export interface SCPlaceWithoutReferences extends SCThing {
|
|||||||
* @see http://wiki.openstreetmap.org/wiki/Key:opening_hours/specification
|
* @see http://wiki.openstreetmap.org/wiki/Key:opening_hours/specification
|
||||||
*/
|
*/
|
||||||
openingHours?: string;
|
openingHours?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translated fields of a place
|
||||||
|
*/
|
||||||
|
translations?: SCTranslations<SCPlaceWithoutReferencesTranslatableProperties>;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SCPlaceWithoutReferencesTranslatableProperties extends SCThingTranslatableProperties {
|
||||||
|
address?: SCPostalAddress;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License along with
|
* You should have received a copy of the GNU General Public License along with
|
||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import {SCPlaceWithoutReferences} from '../base/Place';
|
import {SCPlaceWithoutReferences, SCPlaceWithoutReferencesTranslatableProperties} from '../base/Place';
|
||||||
import {
|
import {
|
||||||
SCThingWithCategoriesSpecificValues,
|
SCThingWithCategoriesSpecificValues,
|
||||||
SCThingWithCategoriesTranslatableProperties,
|
SCThingWithCategoriesTranslatableProperties,
|
||||||
@@ -48,7 +48,7 @@ export interface SCBuildingWithoutReferences
|
|||||||
/**
|
/**
|
||||||
* Translated fields of a building
|
* Translated fields of a building
|
||||||
*/
|
*/
|
||||||
translations?: SCTranslations<SCThingWithCategoriesTranslatableProperties>;
|
translations?: SCTranslations<SCBuildingTranslatableProperties>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type of the building
|
* Type of the building
|
||||||
@@ -62,16 +62,33 @@ export interface SCBuildingWithoutReferences
|
|||||||
* @validatable
|
* @validatable
|
||||||
*/
|
*/
|
||||||
export interface SCBuilding extends SCBuildingWithoutReferences {
|
export interface SCBuilding extends SCBuildingWithoutReferences {
|
||||||
|
/**
|
||||||
|
* Translated fields of a building
|
||||||
|
*/
|
||||||
|
translations?: SCTranslations<SCBuildingTranslatableProperties>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type of the building
|
* Type of the building
|
||||||
*/
|
*/
|
||||||
type: SCThingType.Building;
|
type: SCThingType.Building;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SCBuildingTranslatableProperties
|
||||||
|
extends SCPlaceWithoutReferencesTranslatableProperties, SCThingWithCategoriesTranslatableProperties {
|
||||||
|
floors?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Meta information about a place
|
* Meta information about a place
|
||||||
*/
|
*/
|
||||||
export class SCBuildingMeta extends SCThingMeta {
|
export class SCBuildingMeta extends SCThingMeta {
|
||||||
|
static fieldTranslations = {
|
||||||
|
...SCThingMeta.fieldTranslations,
|
||||||
|
de: {
|
||||||
|
floors: 'Etagen',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static fieldValueTranslations = {
|
static fieldValueTranslations = {
|
||||||
...SCThingMeta.fieldValueTranslations,
|
...SCThingMeta.fieldValueTranslations,
|
||||||
de: {
|
de: {
|
||||||
@@ -85,6 +102,7 @@ export class SCBuildingMeta extends SCThingMeta {
|
|||||||
'restroom': 'Toilette',
|
'restroom': 'Toilette',
|
||||||
'student canteen': 'Mensa',
|
'student canteen': 'Mensa',
|
||||||
},
|
},
|
||||||
|
type: 'Gebäude',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,8 +88,12 @@ export interface SCDish extends SCDishWithoutReferences {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface SCDishTranslatableProperties
|
export interface SCDishTranslatableProperties
|
||||||
extends SCThingWithCategoriesTranslatableProperties,
|
extends SCThingWithCategoriesTranslatableProperties, SCThingThatCanBeOfferedTranslatableProperties {
|
||||||
SCThingThatCanBeOfferedTranslatableProperties {}
|
/**
|
||||||
|
* Characteristics of the dish
|
||||||
|
*/
|
||||||
|
characteristics?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dish meta data
|
* Dish meta data
|
||||||
@@ -101,6 +105,21 @@ export class SCDishMeta extends SCThingMeta {
|
|||||||
categories: 'Kategorien',
|
categories: 'Kategorien',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static fieldValueTranslations = {
|
||||||
|
...SCThingMeta.fieldValueTranslations,
|
||||||
|
de: {
|
||||||
|
categories: {
|
||||||
|
appetizer: 'Vorspeise',
|
||||||
|
dessert: 'Nachtisch',
|
||||||
|
'main dish': 'Hauptgericht',
|
||||||
|
salad: 'Salat',
|
||||||
|
'side dish': 'Beilage',
|
||||||
|
soup: 'Suppe',
|
||||||
|
},
|
||||||
|
type: 'Essen',
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,7 +16,16 @@ import {SCThingWithTranslations} from '../base/ThingWithTranslations';
|
|||||||
import {SCBulkResponse} from '../protocol/routes/bulk/BulkResponse';
|
import {SCBulkResponse} from '../protocol/routes/bulk/BulkResponse';
|
||||||
import {SCMultiSearchResponse} from '../protocol/routes/search/MultiSearchResponse';
|
import {SCMultiSearchResponse} from '../protocol/routes/search/MultiSearchResponse';
|
||||||
import {SCSearchResponse} from '../protocol/routes/search/SearchResponse';
|
import {SCSearchResponse} from '../protocol/routes/search/SearchResponse';
|
||||||
import {SCThing} from '../Thing';
|
import {SCThing, SCThingType} from '../Thing';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type guard to check if something is a SCThing
|
||||||
|
*
|
||||||
|
* @param {any} something Something to check
|
||||||
|
*/
|
||||||
|
export function isThing(something: any): something is SCThing {
|
||||||
|
return (something.type && something.type in SCThingType);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type guard to check if translations exist
|
* Type guard to check if translations exist
|
||||||
|
|||||||
@@ -668,7 +668,7 @@ export type SCNationality =
|
|||||||
/**
|
/**
|
||||||
* Translations for specific languages
|
* Translations for specific languages
|
||||||
*
|
*
|
||||||
* @see https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
|
* @see https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
|
||||||
*/
|
*/
|
||||||
export interface SCTranslations<T> {
|
export interface SCTranslations<T> {
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user