mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-03-14 18:52:33 +00:00
refactor: add opening hours
This commit is contained in:
43
package-lock.json
generated
43
package-lock.json
generated
@@ -11310,6 +11310,24 @@
|
|||||||
"@babel/runtime": "^7.3.1"
|
"@babel/runtime": "^7.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"i18next-browser-languagedetector": {
|
||||||
|
"version": "6.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.2.tgz",
|
||||||
|
"integrity": "sha512-YDzIGHhMRvr7M+c8B3EQUKyiMBhfqox4o1qkFvt4QXuu5V2cxf74+NCr+VEkUuU0y+RwcupA238eeolW1Yn80g==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.14.6"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": {
|
||||||
|
"version": "7.14.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz",
|
||||||
|
"integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==",
|
||||||
|
"requires": {
|
||||||
|
"regenerator-runtime": "^0.13.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"iconv-lite": {
|
"iconv-lite": {
|
||||||
"version": "0.4.24",
|
"version": "0.4.24",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
@@ -14533,6 +14551,26 @@
|
|||||||
"integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==",
|
"integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"opening_hours": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/opening_hours/-/opening_hours-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-ETHEchqvpZxJiLznNSdYHiGyeIMikJVfYEjMjYe0oRAxcQejilyXWWGjJBcIOXLwgU6LaATeFb6LRTgEguz0yw==",
|
||||||
|
"requires": {
|
||||||
|
"i18next": "^20.2.1",
|
||||||
|
"i18next-browser-languagedetector": "^6.1.0",
|
||||||
|
"suncalc": "^1.8.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"i18next": {
|
||||||
|
"version": "20.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/i18next/-/i18next-20.3.2.tgz",
|
||||||
|
"integrity": "sha512-e8CML2R9Ng2sSQOM80wb/PrM2j8mDm84o/T4Amzn9ArVyNX5/ENWxxAXkRpZdTQNDaxKImF93Wep4mAoozFrKw==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.12.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"opn": {
|
"opn": {
|
||||||
"version": "5.5.0",
|
"version": "5.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz",
|
||||||
@@ -18613,6 +18651,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"suncalc": {
|
||||||
|
"version": "1.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/suncalc/-/suncalc-1.8.0.tgz",
|
||||||
|
"integrity": "sha1-HZiYEJVjB4dQ9JlKlZ5lTYdqy/U="
|
||||||
|
},
|
||||||
"supports-color": {
|
"supports-color": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||||
|
|||||||
@@ -89,6 +89,7 @@
|
|||||||
"ngx-logger": "4.1.9",
|
"ngx-logger": "4.1.9",
|
||||||
"ngx-markdown": "9.1.1",
|
"ngx-markdown": "9.1.1",
|
||||||
"ngx-moment": "5.0.0",
|
"ngx-moment": "5.0.0",
|
||||||
|
"opening_hours": "3.6.0",
|
||||||
"rxjs": "6.6.3",
|
"rxjs": "6.6.3",
|
||||||
"tslib": "1.14.1",
|
"tslib": "1.14.1",
|
||||||
"zone.js": "0.11.2"
|
"zone.js": "0.11.2"
|
||||||
|
|||||||
@@ -12,12 +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 {
|
import {CommonModule, LocationStrategy, PathLocationStrategy, registerLocaleData} from '@angular/common';
|
||||||
CommonModule,
|
|
||||||
HashLocationStrategy,
|
|
||||||
LocationStrategy,
|
|
||||||
registerLocaleData,
|
|
||||||
} from '@angular/common';
|
|
||||||
import {HttpClient} from '@angular/common/http';
|
import {HttpClient} from '@angular/common/http';
|
||||||
import localeDe from '@angular/common/locales/de';
|
import localeDe from '@angular/common/locales/de';
|
||||||
import {APP_INITIALIZER, NgModule, Provider} from '@angular/core';
|
import {APP_INITIALIZER, NgModule, Provider} from '@angular/core';
|
||||||
@@ -116,7 +111,7 @@ const providers: Provider[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: LocationStrategy,
|
provide: LocationStrategy,
|
||||||
useClass: HashLocationStrategy,
|
useClass: PathLocationStrategy,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: APP_INITIALIZER,
|
provide: APP_INITIALIZER,
|
||||||
|
|||||||
@@ -1,19 +1,36 @@
|
|||||||
<stapps-simple-card *ngIf="item.description" [title]="'description' | propertyNameTranslate: item | titlecase" [content]="'description' | thingTranslate: item"></stapps-simple-card>
|
<div [ngSwitch]="item.type">
|
||||||
<div [ngSwitch]="true">
|
<stapps-article-detail-content [item]="item" *ngSwitchCase="'article'"></stapps-article-detail-content>
|
||||||
<stapps-article-detail-content [item]="item" *ngSwitchCase="item.type === 'article'"></stapps-article-detail-content>
|
<stapps-catalog-detail-content [item]="item" *ngSwitchCase="'catalog'"></stapps-catalog-detail-content>
|
||||||
<stapps-catalog-detail-content [item]="item" *ngSwitchCase="item.type === 'catalog'"></stapps-catalog-detail-content>
|
<stapps-date-series-detail-content [item]="item" *ngSwitchCase="'date series'"></stapps-date-series-detail-content>
|
||||||
<stapps-date-series-detail-content [item]="item" *ngSwitchCase="item.type === 'date series'"></stapps-date-series-detail-content>
|
<stapps-dish-detail-content [item]="item" *ngSwitchCase="'dish'"></stapps-dish-detail-content>
|
||||||
<stapps-dish-detail-content [item]="item" *ngSwitchCase="item.type === 'dish'"></stapps-dish-detail-content>
|
<stapps-event-detail-content [item]="item" *ngSwitchCase="'academic event'"></stapps-event-detail-content>
|
||||||
<stapps-event-detail-content [item]="item" *ngSwitchCase="item.type === 'academic event'"></stapps-event-detail-content>
|
<stapps-event-detail-content [item]="item" *ngSwitchCase="'sport course'"></stapps-event-detail-content>
|
||||||
<stapps-event-detail-content [item]="item" *ngSwitchCase="item.type === 'sport course'"></stapps-event-detail-content>
|
<stapps-favorite-detail-content [item]="item" *ngSwitchCase="'favorite'"></stapps-favorite-detail-content>
|
||||||
<stapps-favorite-detail-content [item]="item" *ngSwitchCase="item.type === 'favorite'"></stapps-favorite-detail-content>
|
<stapps-message-detail-content [item]="item" *ngSwitchCase="'message'"></stapps-message-detail-content>
|
||||||
<stapps-message-detail-content [item]="item" *ngSwitchCase="item.type === 'message'"></stapps-message-detail-content>
|
<stapps-person-detail-content [item]="item" *ngSwitchCase="'person'"></stapps-person-detail-content>
|
||||||
<stapps-person-detail-content [item]="item" *ngSwitchCase="item.type === 'person'"></stapps-person-detail-content>
|
<stapps-place-detail-content [item]="item" *ngSwitchCase="'building'"></stapps-place-detail-content>
|
||||||
<stapps-place-detail-content [item]="item" *ngSwitchCase="item.type === 'building'"></stapps-place-detail-content>
|
<stapps-place-detail-content [item]="item" *ngSwitchCase="'floor'"></stapps-place-detail-content>
|
||||||
<stapps-place-detail-content [item]="item" *ngSwitchCase="item.type === 'floor'"></stapps-place-detail-content>
|
<stapps-place-detail-content [item]="item" *ngSwitchCase="'point of interest'"></stapps-place-detail-content>
|
||||||
<stapps-place-detail-content [item]="item" *ngSwitchCase="item.type === 'point of interest'"></stapps-place-detail-content>
|
<stapps-place-detail-content [item]="item" *ngSwitchCase="'room'"></stapps-place-detail-content>
|
||||||
<stapps-place-detail-content [item]="item" *ngSwitchCase="item.type === 'room'"></stapps-place-detail-content>
|
<stapps-semester-detail-content [item]="item" *ngSwitchCase="'semester'"></stapps-semester-detail-content>
|
||||||
<stapps-semester-detail-content [item]="item" *ngSwitchCase="item.type === 'semester'"></stapps-semester-detail-content>
|
<stapps-video-detail-content [item]="item" *ngSwitchCase="'video'"></stapps-video-detail-content>
|
||||||
<stapps-video-detail-content [item]="item" *ngSwitchCase="item.type === 'video'"></stapps-video-detail-content>
|
<ng-container *ngSwitchDefault>
|
||||||
<stapps-origin-detail [origin]="item.origin" ></stapps-origin-detail>
|
<ion-item class="ion-text-wrap" lines="inset">
|
||||||
|
<ion-thumbnail slot="start" class="ion-margin-end">
|
||||||
|
<ion-icon color="medium" [attr.name]="item.type | dataIcon"></ion-icon>
|
||||||
|
</ion-thumbnail>
|
||||||
|
<ion-grid>
|
||||||
|
<ion-row>
|
||||||
|
<ion-col>
|
||||||
|
<div class="ion-text-wrap">
|
||||||
|
<h2 class="name">{{item.name}}</h2>
|
||||||
|
<ion-note>{{item.type}}</ion-note>
|
||||||
|
</div>
|
||||||
|
</ion-col>
|
||||||
|
</ion-row>
|
||||||
|
</ion-grid>
|
||||||
|
</ion-item>
|
||||||
|
<stapps-simple-card *ngIf="item.description" [title]="'description' | propertyNameTranslate: item | titlecase" [content]="'description' | thingTranslate: item"></stapps-simple-card>
|
||||||
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
<stapps-origin-detail [origin]="item.origin" ></stapps-origin-detail>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<h2 class="name">{{ 'name' | thingTranslate: item }}</h2>
|
<h2 class="name">{{ 'name' | thingTranslate: item }}</h2>
|
||||||
<p>
|
<p>
|
||||||
<ion-icon name="calendar"></ion-icon>
|
<ion-icon name="calendar"></ion-icon>
|
||||||
<span>
|
<span *ngIf="item.dates[0] && item.dates[item.dates.length - 1]">
|
||||||
{{ item.repeatFrequency | amDuration }},
|
{{ item.repeatFrequency | amDuration }},
|
||||||
{{ item.dates[0] | dateFormat: 'weekday:long' }}
|
{{ item.dates[0] | dateFormat: 'weekday:long' }}
|
||||||
<span>
|
<span>
|
||||||
|
|||||||
@@ -2,9 +2,26 @@
|
|||||||
<ion-row>
|
<ion-row>
|
||||||
<ion-col>
|
<ion-col>
|
||||||
<div class="ion-text-wrap">
|
<div class="ion-text-wrap">
|
||||||
<h2 class="name">{{ 'name' | thingTranslate: item }}</h2>
|
<ion-label>{{'name' | thingTranslate: item}}</ion-label>
|
||||||
|
<ng-container *ngIf="item.type !== 'floor'">
|
||||||
|
<p>
|
||||||
|
<ion-note *ngIf="item.openingHours">
|
||||||
|
{{item.openingHours | openingHours}}
|
||||||
|
</ion-note>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<ion-note *ngIf="item.categories && item.type !== 'building'; else onlyType">
|
||||||
|
{{'categories' | thingTranslate: item | join:', ' | titlecase }}
|
||||||
|
</ion-note>
|
||||||
|
</p>
|
||||||
|
<ng-template #onlyType>
|
||||||
|
<ion-note>
|
||||||
|
{{'type' | thingTranslate: item}}
|
||||||
|
</ion-note>
|
||||||
|
</ng-template>
|
||||||
|
</ng-container>
|
||||||
<p *ngIf="item.description">
|
<p *ngIf="item.description">
|
||||||
{{ 'description' | thingTranslate: item }}
|
{{'description' | thingTranslate: item}}
|
||||||
</p>
|
</p>
|
||||||
<ion-note>
|
<ion-note>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -17,11 +34,10 @@
|
|||||||
</ion-note>
|
</ion-note>
|
||||||
</div>
|
</div>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
<ion-col width-20 text-right *ngIf="item.type !== 'building'">
|
<div *ngIf="item.type !== 'building'">
|
||||||
<span *ngIf="item.inPlace">
|
<ion-col width-20 text-right *ngIf="item.inPlace">
|
||||||
<ion-icon name="location"></ion-icon
|
<ion-icon name="location"></ion-icon>{{'name' | thingTranslate: item.inPlace}}
|
||||||
>{{ 'name' | thingTranslate: item.inPlace }}
|
</ion-col>
|
||||||
</span>
|
</div>
|
||||||
</ion-col>
|
|
||||||
</ion-row>
|
</ion-row>
|
||||||
</ion-grid>
|
</ion-grid>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export class PlaceMensaDetailComponent implements AfterViewInit {
|
|||||||
/**
|
/**
|
||||||
* number of days to display mensa menus for
|
* number of days to display mensa menus for
|
||||||
*/
|
*/
|
||||||
@Input() displayRange = 5;
|
@Input() displayRange = 7;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* TODO
|
||||||
|
|||||||
@@ -15,9 +15,15 @@
|
|||||||
|
|
||||||
import {Injectable, OnDestroy, Pipe, PipeTransform} from '@angular/core';
|
import {Injectable, OnDestroy, Pipe, PipeTransform} from '@angular/core';
|
||||||
import {LangChangeEvent, TranslateService} from '@ngx-translate/core';
|
import {LangChangeEvent, TranslateService} from '@ngx-translate/core';
|
||||||
|
import moment from 'moment';
|
||||||
import {Subscription} from 'rxjs';
|
import {Subscription} from 'rxjs';
|
||||||
import {logger} from '../_helpers/ts-logger';
|
import {logger} from '../_helpers/ts-logger';
|
||||||
|
|
||||||
|
// tslint:disable-next-line: no-var-requires
|
||||||
|
const openingHoursFn = require('opening_hours');
|
||||||
|
|
||||||
|
// tslint:disable: completed-docs
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@Pipe({
|
@Pipe({
|
||||||
name: 'join',
|
name: 'join',
|
||||||
@@ -89,6 +95,78 @@ export class StringSplitPipe implements PipeTransform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
@Pipe({
|
||||||
|
name: 'openingHours',
|
||||||
|
pure: false, // required to update the value when the promise is resolved
|
||||||
|
})
|
||||||
|
export class OpeningHoursPipe implements PipeTransform {
|
||||||
|
locale: string;
|
||||||
|
onLangChange?: Subscription;
|
||||||
|
value = '';
|
||||||
|
|
||||||
|
constructor(private readonly translate: TranslateService) {
|
||||||
|
this.locale = translate.currentLang;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _dispose(): void {
|
||||||
|
if (this.onLangChange?.closed === false) {
|
||||||
|
this.onLangChange?.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
transform(aString: string | unknown): string {
|
||||||
|
this.updateValue(aString);
|
||||||
|
this._dispose();
|
||||||
|
if (this.onLangChange?.closed === true) {
|
||||||
|
this.onLangChange = this.translate.onLangChange.subscribe((event: LangChangeEvent) => {
|
||||||
|
this.locale = event.lang;
|
||||||
|
this.updateValue(aString);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateValue(aString: string | unknown) {
|
||||||
|
if (typeof aString !== 'string'){
|
||||||
|
logger.warn(`openingHours pipe unable to parse input: ${aString}`);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const openingHours = new openingHoursFn(aString);
|
||||||
|
|
||||||
|
if ((openingHours.getWarnings() as string[]).length > 0){
|
||||||
|
logger.warn((openingHours.getWarnings() as string[]).join('. '));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isOpen: boolean = openingHours.getState();
|
||||||
|
const nextChange: Date = openingHours.getNextChange();
|
||||||
|
|
||||||
|
let prefixKey = isOpen ?
|
||||||
|
'common.openingHours.open_until' :
|
||||||
|
'common.openingHours.closed_until';
|
||||||
|
|
||||||
|
let formattedCalender = moment(nextChange)
|
||||||
|
.calendar();
|
||||||
|
|
||||||
|
if (moment(nextChange)
|
||||||
|
.isBefore(moment()
|
||||||
|
.add(1, 'hours'))) {
|
||||||
|
prefixKey= isOpen ?
|
||||||
|
'common.openingHours.closing_soon' :
|
||||||
|
'common.openingHours.opening_soon';
|
||||||
|
formattedCalender = formattedCalender.substr(0,1)
|
||||||
|
.toUpperCase() + formattedCalender.substr(1);
|
||||||
|
}
|
||||||
|
this.value = `${this.translate.instant(prefixKey)} ${formattedCalender}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@Pipe({
|
@Pipe({
|
||||||
name: 'numberLocalized',
|
name: 'numberLocalized',
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {ModuleWithProviders, NgModule, Provider} from '@angular/core';
|
import {ModuleWithProviders, NgModule, Provider} from '@angular/core';
|
||||||
import {ArrayJoinPipe, DateLocalizedFormatPipe, NumberLocalizedPipe, SentenceCasePipe, StringSplitPipe} from './common-string-pipes';
|
import {ArrayJoinPipe, DateLocalizedFormatPipe, NumberLocalizedPipe, SentenceCasePipe, StringSplitPipe, OpeningHoursPipe} from './common-string-pipes';
|
||||||
import {ThingTranslateDefaultParser, ThingTranslateParser} from './thing-translate.parser';
|
import {ThingTranslateDefaultParser, ThingTranslateParser} from './thing-translate.parser';
|
||||||
import {ThingPropertyNameTranslatePipe, ThingTranslatePipe} from './thing-translate.pipe';
|
import {ThingPropertyNameTranslatePipe, ThingTranslatePipe} from './thing-translate.pipe';
|
||||||
import {ThingTranslateService} from './thing-translate.service';
|
import {ThingTranslateService} from './thing-translate.service';
|
||||||
@@ -31,6 +31,7 @@ export interface ThingTranslateModuleConfig {
|
|||||||
ThingPropertyNameTranslatePipe,
|
ThingPropertyNameTranslatePipe,
|
||||||
ThingTranslatePipe,
|
ThingTranslatePipe,
|
||||||
DateLocalizedFormatPipe,
|
DateLocalizedFormatPipe,
|
||||||
|
OpeningHoursPipe,
|
||||||
SentenceCasePipe,
|
SentenceCasePipe,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
@@ -40,6 +41,7 @@ export interface ThingTranslateModuleConfig {
|
|||||||
ThingPropertyNameTranslatePipe,
|
ThingPropertyNameTranslatePipe,
|
||||||
ThingTranslatePipe,
|
ThingTranslatePipe,
|
||||||
DateLocalizedFormatPipe,
|
DateLocalizedFormatPipe,
|
||||||
|
OpeningHoursPipe,
|
||||||
SentenceCasePipe,
|
SentenceCasePipe,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -9,6 +9,14 @@
|
|||||||
"UNKNOWN": "Unbekannter Fehler"
|
"UNKNOWN": "Unbekannter Fehler"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"common": {
|
||||||
|
"openingHours": {
|
||||||
|
"closed_until": "Geschlossen bis",
|
||||||
|
"closing_soon": "Schließt bald!",
|
||||||
|
"open_until": "Geöffnet bis",
|
||||||
|
"opening_soon": "Öffnet"
|
||||||
|
}
|
||||||
|
},
|
||||||
"data": {
|
"data": {
|
||||||
"REFRESH_ACTION": "Aktualisieren",
|
"REFRESH_ACTION": "Aktualisieren",
|
||||||
"REFRESHING": "Aktualisierung läuft...",
|
"REFRESHING": "Aktualisierung läuft...",
|
||||||
|
|||||||
@@ -9,6 +9,14 @@
|
|||||||
"UNKNOWN": "Unknown problem"
|
"UNKNOWN": "Unknown problem"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"common": {
|
||||||
|
"openingHours": {
|
||||||
|
"closed_until": "Closed until",
|
||||||
|
"closing_soon": "Closing soon!",
|
||||||
|
"open_until": "Open until",
|
||||||
|
"opening_soon": "Opens"
|
||||||
|
}
|
||||||
|
},
|
||||||
"data": {
|
"data": {
|
||||||
"REFRESH_ACTION": "Refresh",
|
"REFRESH_ACTION": "Refresh",
|
||||||
"REFRESHING": "Refreshing...",
|
"REFRESHING": "Refreshing...",
|
||||||
|
|||||||
Reference in New Issue
Block a user