diff --git a/src/app/components/creator/_dialogs/comment-settings/comment-settings.component.ts b/src/app/components/creator/_dialogs/comment-settings/comment-settings.component.ts index 501cb1d2b8eac23a3bcd1b29512c611c33fdea14..8fd808ffa2fde06e1c147d6e4ff50187b593a732 100644 --- a/src/app/components/creator/_dialogs/comment-settings/comment-settings.component.ts +++ b/src/app/components/creator/_dialogs/comment-settings/comment-settings.component.ts @@ -81,17 +81,6 @@ export class CommentSettingsComponent implements OnInit { this.commentService.deleteCommentsByRoomId(this.roomId).subscribe(); } - exportCSV(): void { - const exp: Export = new Export( - this.editRoom, - this.commentService, - this.bonusTokenService, - this.translationService, - 'room-page', - this.notificationService); - exp.exportAsCsv(); - } - closeDialog(): void { const commentSettings = new CommentSettings(); commentSettings.roomId = this.roomId; diff --git a/src/app/components/creator/room-creator-page/room-creator-page.component.ts b/src/app/components/creator/room-creator-page/room-creator-page.component.ts index f64d70b952792a17ea8df7eff179816cb619e002..b5a8bde9566b060477b0a9126f3bdc6f74a075bc 100644 --- a/src/app/components/creator/room-creator-page/room-creator-page.component.ts +++ b/src/app/components/creator/room-creator-page/room-creator-page.component.ts @@ -19,6 +19,7 @@ import { AuthenticationService } from '../../../services/http/authentication.ser import { HeaderService } from '../../../services/util/header.service'; import { ArsComposeService } from '../../../../../projects/ars/src/lib/services/ars-compose.service'; import { RoomEditComponent } from '../_dialogs/room-edit/room-edit.component'; +import { ModeratorService } from '../../../services/http/moderator.service'; @Component({ selector:'app-room-creator-page', @@ -41,15 +42,14 @@ export class RoomCreatorPageComponent extends RoomPageComponent implements OnIni private _r: Renderer2, public eventService: EventService, public titleService: TitleService, - protected notificationService: NotificationService, protected bonusTokenService: BonusTokenService, + protected moderatorService: ModeratorService, public router: Router, - public translationService: TranslateService, public authenticationService: AuthenticationService, public headerService: HeaderService, public composeService: ArsComposeService){ super(roomService, route, location, wsCommentService, commentService, eventService, headerService, composeService, - dialog, bonusTokenService, translateService, notificationService, authenticationService); + dialog, bonusTokenService, translateService, notification, authenticationService, moderatorService); this.commentCounterEmitSubscription = this.commentCounterEmit.subscribe(e => { this.titleService.attachTitle('(' + e + ')'); }); diff --git a/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.ts b/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.ts index 8e8a8fe0f67527ee5cd6d7c4aa063cca7beebc10..5a77176e398b9a1259ff4cc38a7d8d5eec7d43d3 100644 --- a/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.ts +++ b/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.ts @@ -161,7 +161,9 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy { this.bonusTokenService, this.translationService, 'comment-list', - this.notificationService); + this.notificationService, + this.filter.moderatorAccountIds, + this.user); exp.exportAsCsv(); }); this.headerInterface = this.eventService.on<string>('navigate').subscribe(e => { diff --git a/src/app/components/moderator/room-moderator-page/room-moderator-page.component.html b/src/app/components/moderator/room-moderator-page/room-moderator-page.component.html index 0ac213176b47879d8396cd6b2c727af940173f36..eb05da3e87f498fdd904825ac05b2636b632b061 100644 --- a/src/app/components/moderator/room-moderator-page/room-moderator-page.component.html +++ b/src/app/components/moderator/room-moderator-page/room-moderator-page.component.html @@ -82,7 +82,7 @@ <button id="question_answer-button2" mat-icon-button [disableRipple]="true" - routerLink="/creator/room/{{ room.shortId }}/comments" + routerLink="/moderator/room/{{ room.shortId }}/comments" aria-labelledby="question_answer"> <mat-icon matBadge="{{commentCounter > 0 ? commentCounter : null}}" class="main-icon" diff --git a/src/app/components/moderator/room-moderator-page/room-moderator-page.component.ts b/src/app/components/moderator/room-moderator-page/room-moderator-page.component.ts index c14a687d576465a9313bf45276661800f7894ef6..9fcaf6a7b62b3ec8e7048caaf0b15cf92927c1e5 100644 --- a/src/app/components/moderator/room-moderator-page/room-moderator-page.component.ts +++ b/src/app/components/moderator/room-moderator-page/room-moderator-page.component.ts @@ -17,6 +17,7 @@ import { HeaderService } from '../../../services/util/header.service'; import { ArsComposeService } from '../../../../../projects/ars/src/lib/services/ars-compose.service'; import { BonusTokenService } from '../../../services/http/bonus-token.service'; import { AuthenticationService } from '../../../services/http/authentication.service'; +import { ModeratorService } from '../../../services/http/moderator.service'; @Component({ selector: 'app-room-moderator-page', @@ -38,11 +39,12 @@ export class RoomModeratorPageComponent extends RoomPageComponent implements OnI protected composeService: ArsComposeService, protected bonusTokenService: BonusTokenService, protected authenticationService: AuthenticationService, + protected moderatorService: ModeratorService, public eventService: EventService, private liveAnnouncer: LiveAnnouncer, private _r: Renderer2) { super(roomService, route, location, wsCommentService, commentService, eventService, headerService, composeService, - dialog, bonusTokenService, translateService, notification, authenticationService); + dialog, bonusTokenService, translateService, notification, authenticationService, moderatorService); langService.langEmitter.subscribe(lang => translateService.use(lang)); } diff --git a/src/app/components/participant/room-participant-page/room-participant-page.component.ts b/src/app/components/participant/room-participant-page/room-participant-page.component.ts index 0e26914824bece09c7a391a707255ac8d9a03760..7787350925a1a15a55d8d95c2dd1bc225155ae4b 100644 --- a/src/app/components/participant/room-participant-page/room-participant-page.component.ts +++ b/src/app/components/participant/room-participant-page/room-participant-page.component.ts @@ -20,6 +20,7 @@ import { ArsComposeService } from '../../../../../projects/ars/src/lib/services/ import { MatDialog } from '@angular/material/dialog'; import { BonusTokenService } from '../../../services/http/bonus-token.service'; import { NotificationService } from '../../../services/util/notification.service'; +import { ModeratorService } from '../../../services/http/moderator.service'; @Component({ selector: 'app-room-participant-page', @@ -41,11 +42,12 @@ export class RoomParticipantPageComponent extends RoomPageComponent implements O protected composeService: ArsComposeService, protected bonusTokenService: BonusTokenService, protected notificationService: NotificationService, + protected moderatorService: ModeratorService, protected dialog: MatDialog, private _r: Renderer2, public eventService: EventService) { super(roomService, route, location, wsCommentService, commentService, eventService, headerService, composeService, - dialog, bonusTokenService, translateService, notificationService, authenticationService); + dialog, bonusTokenService, translateService, notificationService, authenticationService, moderatorService); langService.langEmitter.subscribe(lang => translateService.use(lang)); } diff --git a/src/app/components/shared/comment-list/comment-list.component.ts b/src/app/components/shared/comment-list/comment-list.component.ts index eb8fcf5079757bc12c6bc1bc3743a3837443fb74..750faa9b3a11ab2a99891433bf7baf283d2e60b7 100644 --- a/src/app/components/shared/comment-list/comment-list.component.ts +++ b/src/app/components/shared/comment-list/comment-list.component.ts @@ -196,7 +196,9 @@ export class CommentListComponent implements OnInit, OnDestroy { this.bonusTokenService, this.translationService, 'comment-list', - this.notificationService); + this.notificationService, + this.filter.moderatorAccountIds, + this.user); exp.exportAsCsv(); }); this.headerInterface = this.eventService.on<string>('navigate').subscribe(e => { diff --git a/src/app/components/shared/room-list/room-list.component.ts b/src/app/components/shared/room-list/room-list.component.ts index f727755e59ab4dc465055399421f3f45e00a4254..fd1b3e7778805272e71658533f92c3915af51bab 100644 --- a/src/app/components/shared/room-list/room-list.component.ts +++ b/src/app/components/shared/room-list/room-list.component.ts @@ -171,14 +171,17 @@ export class RoomListComponent implements OnInit, OnDestroy { } exportCsv(room: Room) { - const exp: Export = new Export( - room, - this.commentService, - this.bonusTokenService, - this.translateService, - 'room-list', - this.notificationService, - this.user); - exp.exportAsCsv(); + this.moderatorService.get(room.id).subscribe(mods => { + const exp: Export = new Export( + room, + this.commentService, + this.bonusTokenService, + this.translateService, + 'room-list', + this.notificationService, + new Set<string>(mods.map(mod => mod.accountId)), + this.user); + exp.exportAsCsv(); + }); } } diff --git a/src/app/components/shared/room-page/room-page.component.ts b/src/app/components/shared/room-page/room-page.component.ts index 8f8a77b98bab4a4577959dae64c0417b8dcccd9f..fed1de304e246fc46cfc65dba2042c5a8c573e2c 100644 --- a/src/app/components/shared/room-page/room-page.component.ts +++ b/src/app/components/shared/room-page/room-page.component.ts @@ -32,6 +32,7 @@ import { TagsComponent } from '../../creator/_dialogs/tags/tags.component'; import { AuthenticationService } from '../../../services/http/authentication.service'; import { ProfanitySettingsComponent } from '../../creator/_dialogs/profanity-settings/profanity-settings.component'; import { SyncFence } from '../../../utils/SyncFence'; +import { ModeratorService } from '../../../services/http/moderator.service'; @Component({ selector: 'app-room-page', @@ -68,7 +69,8 @@ export class RoomPageComponent implements OnInit, OnDestroy { protected bonusTokenService: BonusTokenService, protected translateService: TranslateService, protected notificationService: NotificationService, - protected authenticationService: AuthenticationService + protected authenticationService: AuthenticationService, + protected moderatorService: ModeratorService ) { } @@ -175,14 +177,19 @@ export class RoomPageComponent implements OnInit, OnDestroy { } exportQuestions() { - const exp: Export = new Export( - this.room, - this.commentService, - this.bonusTokenService, - this.translateService, - 'comment-list', - this.notificationService); - exp.exportAsCsv(); + this.moderatorService.get(this.room.id).subscribe(mods => { + const exp: Export = new Export( + this.room, + this.commentService, + this.bonusTokenService, + this.translateService, + 'comment-list', + this.notificationService, + new Set<string>(mods.map(mod => mod.accountId)), + this.user + ); + exp.exportAsCsv(); + }); } deleteQuestions() { diff --git a/src/app/models/export.ts b/src/app/models/export.ts index c6b6d9baff80b0646742f0f2798499d0bcf03576..0620469a96105e600f111fcc5ab0fec14ad7ebda 100644 --- a/src/app/models/export.ts +++ b/src/app/models/export.ts @@ -6,6 +6,58 @@ import { BonusToken } from './bonus-token'; import { TranslateService } from '@ngx-translate/core'; import { User } from './user'; import { NotificationService } from '../services/util/notification.service'; +import { ViewCommentDataComponent } from '../components/shared/view-comment-data/view-comment-data.component'; +import { forkJoin, Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { Comment } from './comment'; +import { UserRole } from './user-roles.enum'; +import { SpacyKeyword } from '../services/http/spacy.service'; +import { CorrectWrong } from './correct-wrong.enum'; + +interface RoomExportVariables { + empty: string; + roomName: string; + roomCode: string; + exportDate: string; + welcomeText: string; + questionCategories: string; +} + +const parseStringEntry = (str: string): string => '"' + str.replace(/[\r\n]/g, ' ') + .replace(/ +/g, ' ') + .replace(/"/g, '""') + '"'; + +const parseStringArray = (strings: string[]): string => parseStringEntry(strings + .map(str => str.replace(/\\/g, '\\\\').replace(/,/g, '\\,')).join(', ')); + +const parseBody = (body: string): string => { + if (!body) { + return ''; + } + const verify = (str: string) => str.replace(/{/g, '{{').replace(/}/g, '}}'); + body = JSON.parse(body).reduce((acc, e) => { + if (typeof e['insert'] === 'string') { + if (e.attributes) { + const str = JSON.stringify(e.attributes).replace(/\\/g, '\\\\').replace(/;/g, '\\;'); + return acc + '{attr=' + str + ';' + verify(e['insert']) + '}'; + } + return acc + verify(e['insert']); + } else if (typeof e === 'string') { + return acc + verify(e); + } else if (e.image) { + return acc + '{type=image;' + verify(e.image) + '}'; + } else if (e.video) { + return acc + '{type=video;' + verify(e.video) + '}'; + } else if (e.formula) { + return acc + '{type=formula;' + verify(e.formula) + '}'; + } else if (e.emoji) { + return acc + '{type=emoji;' + verify(e.emoji) + '}'; + } + return acc; + }, ''); + body = body.replace(/\r\n|\n/g, '{type=newline;}'); + return parseStringEntry(body); +}; class ExportMapper<E> { @@ -35,19 +87,33 @@ class ExportMapper<E> { this.list.push(row); } - public parse(delimiter: string, map?: Map<string, string>): string { - if (this.list.length <= 0) { return 'd'; } + public parse(delimiter: string, + keyTranslations: Map<string, string>, + roomTranslations: RoomExportVariables, + room: Room, + exportDate: string): string { + if (this.list.length <= 0) { + return 'd'; + } let parse = ''; - if (!map) { - map = new Map<string, string>(); - this.keys().forEach(e => map.set(e, e)); + const newLine = '\r\n'; + // room + parse += roomTranslations.roomName + delimiter + parseStringEntry(room.name) + delimiter; + parse += newLine + roomTranslations.roomCode + delimiter + parseStringEntry(room.shortId) + delimiter; + parse += newLine + roomTranslations.exportDate + delimiter + exportDate + delimiter; + parse += newLine + roomTranslations.welcomeText + delimiter + + (room.description ? parseBody(room.description) : roomTranslations.empty) + delimiter; + parse += newLine + roomTranslations.questionCategories + delimiter + (room.tags && room.tags.length ? + parseStringArray(room.tags) : roomTranslations.empty) + delimiter; + parse += newLine + delimiter + newLine; + // comments + if (!keyTranslations) { + keyTranslations = new Map<string, string>(); + this.keys().forEach(e => keyTranslations.set(e, e)); } - this.keys().forEach(e => parse += map.get(e) + delimiter); + parse += this.keys().map(e => keyTranslations.get(e)).join(delimiter) + delimiter; this.list.forEach(e => { - parse += '\r\n'; - this.keys().forEach(k => { - parse += e.get(k) + delimiter; - }); + parse += newLine + this.keys().map(k => e.get(k)).join(delimiter) + delimiter; }); return parse; } @@ -70,20 +136,67 @@ export class Export { private translateService: TranslateService, private translationPath: string, private notificationService: NotificationService, - private user?: User + private moderatorIds: Set<string>, + private user: User ) { this.mapper = new ExportMapper<CommentBonusTokenMixin>(); - this.bonusTokenMask = !this.user || this.user.role >= 2; + this.bonusTokenMask = this.user && this.user.role >= UserRole.PARTICIPANT; } public exportAsCsv() { + let correct = this.translationPath + '.comment-correct'; + let wrong = this.translationPath + '.comment-wrong'; + let acked = this.translationPath + '.comment-acked'; + let refused = this.translationPath + '.comment-refused'; + let bookmarked = this.translationPath + '.comment-bookmarked'; + let notBookmarked = this.translationPath + '.comment-not-bookmarked'; + const roles: [string, string, string] = [ + this.translationPath + '.comment-user-role-participant', + this.translationPath + '.comment-user-role-moderator', + this.translationPath + '.comment-user-role-creator' + ]; + const roomTranslations: RoomExportVariables = { + empty: this.translationPath + '.export-empty', + exportDate: this.translationPath + '.room-export-date', + roomCode: this.translationPath + '.room-code', + roomName: this.translationPath + '.room-name', + questionCategories: this.translationPath + '.room-categories', + welcomeText: this.translationPath + '.room-welcome' + }; + const roomKeys = Object.keys(roomTranslations); + const roomValues = roomKeys.map(key => roomTranslations[key]); + this.translateService.get([ + correct, wrong, acked, refused, bookmarked, notBookmarked, roles[0], roles[1], roles[2], ...roomValues + ]).subscribe(obj => { + correct = obj[correct]; + wrong = obj[wrong]; + acked = obj[acked]; + refused = obj[refused]; + bookmarked = obj[bookmarked]; + notBookmarked = obj[notBookmarked]; + roles[0] = obj[roles[0]]; + roles[1] = obj[roles[1]]; + roles[2] = obj[roles[2]]; + for (let i = 0; i < roomKeys.length; i++) { + roomTranslations[roomKeys[i]] = obj[roomValues[i]]; + } + }); this.mapper.add(m => { - m('question', e => this.parseBody(e.body)); + m('question-number', e => e.number); m('timestamp', e => this.parseDate(e.timestamp)); - m('presented', e => e.read); - m('correct/wrong', e => e.correct); + m('question', e => parseBody(e.body)); + m('chosen-category', e => e.tag || ''); + m('chosen-keywords', e => this.parseKeywords(e.keywordsFromQuestioner) || roomTranslations.empty); + m('answer', e => parseBody(e.answer)); + m('author-role', e => this.getUserString(e.creatorId, roles)); + m('user-name', e => e.questionerName); + m('user-number', e => e.userNumber); + m('upvotes', e => e.upvotes); + m('downvotes', e => e.downvotes); m('score', e => e.score); - m('answer', e => this.parseBody(e.answer)); + m('public/moderated', e => e.ack ? acked : refused); + m('correct/wrong', e => this.parseCorrectOrWrong(e.correct, correct, wrong)); + m('bookmark', e => e.bookmark ? bookmarked : notBookmarked); m('token', e => this.checkUser(e) && e.bonusToken ? e.bonusToken : ''); m('token-time', e => this.checkUser(e) ? this.parseDate(e.bonusTimeStamp) : ''); }); @@ -97,7 +210,7 @@ export class Export { this.mapper.acceptAll(comments); const date = new Date(); const dateString = date.toLocaleDateString(); - const data = this.mapper.parse(';', translationMap); + const data = this.mapper.parse(';', translationMap, roomTranslations, this.room, dateString); const fileName = this.room.name + '-' + this.room.shortId + '-' + dateString + '.csv'; this.exportData(data, fileName); } @@ -105,17 +218,41 @@ export class Export { }); } + private parseCorrectOrWrong(value: CorrectWrong, correct: string, wrong: string): string { + if (value === CorrectWrong.NULL) { + return ''; + } + if (value === CorrectWrong.CORRECT) { + return correct; + } + return wrong; + } + private checkUser(e: CommentBonusTokenMixin): boolean { return this.bonusTokenMask || e.creatorId === this.user.id; } - private parseBody(body: string): string { - if (!body) {return ''; } - return '"' + body.replace(/[\r\n]/g, ' ').replace(/ +/g, ' ').replace(/"/g, '""') + '"'; + private getUserString(id: string, roles: [participant: string, moderator: string, creator: string]): string { + if (id === this.room.ownerId) { + return roles[2]; + } + if (this.moderatorIds.has(id)) { + return roles[1]; + } + return roles[0]; + } + + private parseKeywords(keywords: SpacyKeyword[]): string { + if (!keywords || keywords.length < 1) { + return null; + } + return parseStringArray(keywords.map(keyword => keyword.text)); } private parseDate(date: Date): string { - if (!date) {return ''; } + if (!date) { + return ''; + } const d = new Date(date); return d.toLocaleDateString() + ' ' + d.toLocaleTimeString(); } @@ -129,31 +266,37 @@ export class Export { } private getCommentBonusTokenMixin(comments: (comments: CommentBonusTokenMixin[]) => void) { - this.commentService.getAckComments(this.room.id).subscribe(data => { + let source: Observable<Comment[]> = this.commentService.getAckComments(this.room.id); + if (this.bonusTokenMask) { + source = forkJoin(source, this.commentService.getRejectedComments(this.room.id)).pipe( + map(res => res[0].concat(res[1]).sort((a, b) => a.number - b.number)) + ); + } + source.subscribe(data => { this.bonusTokenService.getTokensByRoomId(this.room.id).subscribe(list => { const c = data.map(comment => { const bt: BonusToken = list.find(e => e.accountId === comment.creatorId && comment.id === e.commentId); - const commentWithToken: CommentBonusTokenMixin = <CommentBonusTokenMixin>comment; + const commentWithToken: CommentBonusTokenMixin = comment as CommentBonusTokenMixin; if (bt) { commentWithToken.bonusToken = bt.token; commentWithToken.bonusTimeStamp = bt.timestamp; } return commentWithToken; - }).sort(e => e.bonusToken ? -1 : 1); + }); comments(c); }); }); } - private createTranslationMap(ar: string[], map: ((m: Map<string, string>) => void)): void { + private createTranslationMap(ar: string[], translateMapping: ((m: Map<string, string>) => void)): void { const fields = this.addTranslationPath(ar); const tm: Map<string, string> = new Map<string, string>(); this.translateService.get(fields).subscribe(msgs => { Object.entries(msgs).forEach((e, i) => { - tm.set(ar[i], <string>e[1]); + tm.set(ar[i], e[1] as string); }); - map(tm); + translateMapping(tm); }); } diff --git a/src/assets/i18n/creator/de.json b/src/assets/i18n/creator/de.json index 36fe52b15d4f76523072fbac295de34cd8174712..22a0b2f257c85d00d3889ac90c26097f8e8b9acd 100644 --- a/src/assets/i18n/creator/de.json +++ b/src/assets/i18n/creator/de.json @@ -74,7 +74,32 @@ "timestamp": "Zeitstempel", "presented": "Präsentiert", "correct/wrong": "Richtig/Falsch", + "comment-correct": "Richtig", + "comment-wrong": "Falsch", + "author-role": "Autorenrolle", + "comment-user-role-participant": "Teilnehmer*in", + "comment-user-role-moderator": "Moderator*in", + "comment-user-role-creator": "Ersteller*in", + "user-name": "Name des Fragenstellers", + "user-number": "Benutzernummer", + "question-number": "Fragennummer", + "chosen-category": "Kategorie", + "public/moderated": "Öffentlich/Moderiert", + "comment-acked": "Öffentlich", + "comment-refused": "Moderiert", + "bookmark": "Lesezeichen", + "comment-bookmarked": "Ja", + "comment-not-bookmarked": "Nein", + "upvotes": "Upvotes", + "downvotes": "Downvotes", "score": "Score", + "export-empty": "(Leer)", + "room-export-date": "Exportdatum", + "room-code": "Raumcode", + "room-name": "Veranstaltungsname", + "room-categories": "Fragenkategorien", + "room-welcome": "Begrüßungstext", + "chosen-keywords": "Gewählte Stichwörter", "answer": "Antwort", "token": "Bonus-Token", "token-time": "Token-Zeitstempel", diff --git a/src/assets/i18n/creator/en.json b/src/assets/i18n/creator/en.json index a51014ba374198125cbc3b52f1c44b881beb4b91..1aef3eba2061aa036a1c1641982df810bb735edb 100644 --- a/src/assets/i18n/creator/en.json +++ b/src/assets/i18n/creator/en.json @@ -75,7 +75,32 @@ "timestamp": "Timestamp", "presented": "Presented", "correct/wrong": "Correct/Wrong", + "comment-correct": "Correct", + "comment-wrong": "Wrong", + "author-role": "Author role", + "comment-user-role-participant": "Participant", + "comment-user-role-moderator": "Moderator", + "comment-user-role-creator": "Creator", + "user-name": "Questioner name", + "user-number": "User number", + "question-number": "Question number", + "chosen-category": "Category", + "public/moderated": "Public/Moderated", + "comment-acked": "Public", + "comment-refused": "Moderated", + "bookmark": "Bookmark", + "comment-bookmarked": "Yes", + "comment-not-bookmarked": "No", + "upvotes": "Upvotes", + "downvotes": "Downvotes", "score": "Score", + "export-empty": "(None)", + "room-export-date": "Export date", + "room-code": "Room code", + "room-name": "Event name", + "room-categories": "Question categories", + "room-welcome": "Welcome text", + "chosen-keywords": "Chosen keywords", "answer": "Answer", "token": "Bonus token", "token-time": "Token timestamp", diff --git a/src/assets/i18n/home/de.json b/src/assets/i18n/home/de.json index 6ec8adf18e03d64e7baaa5b41a38e3f769b50c72..d083dd4fab7325ae23249210248e477445a69360 100644 --- a/src/assets/i18n/home/de.json +++ b/src/assets/i18n/home/de.json @@ -327,7 +327,32 @@ "timestamp": "Zeitstempel", "presented": "Präsentiert", "correct/wrong": "Richtig/Falsch", + "comment-correct": "Richtig", + "comment-wrong": "Falsch", + "author-role": "Autorenrolle", + "comment-user-role-participant": "Teilnehmer*in", + "comment-user-role-moderator": "Moderator*in", + "comment-user-role-creator": "Ersteller*in", + "user-name": "Name des Fragenstellers", + "user-number": "Benutzernummer", + "question-number": "Fragennummer", + "chosen-category": "Kategorie", + "public/moderated": "Öffentlich/Moderiert", + "comment-acked": "Öffentlich", + "comment-refused": "Moderiert", + "bookmark": "Lesezeichen", + "comment-bookmarked": "Ja", + "comment-not-bookmarked": "Nein", + "upvotes": "Upvotes", + "downvotes": "Downvotes", "score": "Score", + "export-empty": "(Leer)", + "room-export-date": "Exportdatum", + "room-code": "Raumcode", + "room-name": "Veranstaltungsname", + "room-categories": "Fragenkategorien", + "room-welcome": "Begrüßungstext", + "chosen-keywords": "Gewählte Stichwörter", "answer": "Antwort", "token": "Bonus-Token", "token-time": "Token-Zeitstempel", diff --git a/src/assets/i18n/home/en.json b/src/assets/i18n/home/en.json index 882e1548d80f06cd400785e593c147841bff3da4..b8e7cabf8e6a69f99c60e200c545ce6da94be153 100644 --- a/src/assets/i18n/home/en.json +++ b/src/assets/i18n/home/en.json @@ -329,7 +329,32 @@ "timestamp": "Timestamp", "presented": "Presented", "correct/wrong": "Correct/Wrong", + "comment-correct": "Correct", + "comment-wrong": "Wrong", + "author-role": "Author role", + "comment-user-role-participant": "Participant", + "comment-user-role-moderator": "Moderator", + "comment-user-role-creator": "Creator", + "user-name": "Questioner name", + "user-number": "User number", + "question-number": "Question number", + "chosen-category": "Category", + "public/moderated": "Public/Moderated", + "comment-acked": "Public", + "comment-refused": "Moderated", + "bookmark": "Bookmark", + "comment-bookmarked": "Yes", + "comment-not-bookmarked": "No", + "upvotes": "Upvotes", + "downvotes": "Downvotes", "score": "Score", + "export-empty": "(None)", + "room-export-date": "Export date", + "room-code": "Room code", + "room-name": "Event name", + "room-categories": "Question categories", + "room-welcome": "Welcome text", + "chosen-keywords": "Chosen keywords", "answer": "Answer", "token": "Bonus token", "token-time": "Token timestamp", diff --git a/src/assets/i18n/participant/de.json b/src/assets/i18n/participant/de.json index 1911433ba985a83f99efe311e0a47af8fa8cbbc7..e3cf4b7f250a4c09bcde7cce2060ac94f327347c 100644 --- a/src/assets/i18n/participant/de.json +++ b/src/assets/i18n/participant/de.json @@ -76,7 +76,32 @@ "timestamp": "Zeitstempel", "presented": "Präsentiert", "correct/wrong": "Richtig/Falsch", + "comment-correct": "Richtig", + "comment-wrong": "Falsch", + "author-role": "Autorenrolle", + "comment-user-role-participant": "Teilnehmer*in", + "comment-user-role-moderator": "Moderator*in", + "comment-user-role-creator": "Ersteller*in", + "user-name": "Name des Fragenstellers", + "user-number": "Benutzernummer", + "question-number": "Fragennummer", + "chosen-category": "Kategorie", + "public/moderated": "Öffentlich/Moderiert", + "comment-acked": "Öffentlich", + "comment-refused": "Moderiert", + "bookmark": "Lesezeichen", + "comment-bookmarked": "Ja", + "comment-not-bookmarked": "Nein", + "upvotes": "Upvotes", + "downvotes": "Downvotes", "score": "Score", + "export-empty": "(Leer)", + "room-export-date": "Exportdatum", + "room-code": "Raumcode", + "room-name": "Veranstaltungsname", + "room-categories": "Fragenkategorien", + "room-welcome": "Begrüßungstext", + "chosen-keywords": "Gewählte Stichwörter", "answer": "Antwort", "token": "Bonus-Token", "token-time": "Token-Zeitstempel", diff --git a/src/assets/i18n/participant/en.json b/src/assets/i18n/participant/en.json index 4b0e1df6893d232a2e8a3c47c2cd7d67e845417e..3e83563382323caffa231db5f302e080a998bea1 100644 --- a/src/assets/i18n/participant/en.json +++ b/src/assets/i18n/participant/en.json @@ -86,7 +86,32 @@ "timestamp": "Timestamp", "presented": "Presented", "correct/wrong": "Correct/Wrong", + "comment-correct": "Correct", + "comment-wrong": "Wrong", + "author-role": "Author role", + "comment-user-role-participant": "Participant", + "comment-user-role-moderator": "Moderator", + "comment-user-role-creator": "Creator", + "user-name": "Questioner name", + "user-number": "User number", + "question-number": "Question number", + "chosen-category": "Category", + "public/moderated": "Public/Moderated", + "comment-acked": "Public", + "comment-refused": "Moderated", + "bookmark": "Bookmark", + "comment-bookmarked": "Yes", + "comment-not-bookmarked": "No", + "upvotes": "Upvotes", + "downvotes": "Downvotes", "score": "Score", + "export-empty": "(None)", + "room-export-date": "Export date", + "room-code": "Room code", + "room-name": "Event name", + "room-categories": "Question categories", + "room-welcome": "Welcome text", + "chosen-keywords": "Chosen keywords", "answer": "Answer", "token": "Bonus token", "token-time": "Token timestamp",