diff --git a/src/app/components/creator/_dialogs/room-edit/room-edit.component.html b/src/app/components/creator/_dialogs/room-edit/room-edit.component.html
index 479407610b062b8325e81f40290498c157238ec5..9ee31f0d57d6a590ae5d4fe5040bc76c271b6f9e 100644
--- a/src/app/components/creator/_dialogs/room-edit/room-edit.component.html
+++ b/src/app/components/creator/_dialogs/room-edit/room-edit.component.html
@@ -58,10 +58,16 @@
     <div fxLayoutAlign="center center">
       <mat-slide-toggle [(ngModel)]= "check">{{ 'room-page.block' | translate }}</mat-slide-toggle>
     </div>
-    <div fxLayoutAlign="center center">
-      <mat-slide-toggle (change)="showMessage('words-will-be-overwritten')" [(ngModel)]= "profanityCheck">
+    <div fxLayoutAlign="center center" fxLayout="column">
+      <mat-slide-toggle (change)="showMessage('words-will-be-overwritten', $event.checked)" [(ngModel)]= "profanityCheck">
         {{ 'room-page.profanity-filter' | translate }}
       </mat-slide-toggle>
+      <mat-slide-toggle *ngIf="profanityCheck" (change)="showMessage('only-specific-language-will-be-filtered', $event.checked)" [(ngModel)]= "censorLanguageSpecificCheck">
+        {{ 'room-page.language-specific-filter' | translate }}
+      </mat-slide-toggle>
+      <mat-slide-toggle *ngIf="profanityCheck" (change)="showMessage('partial-words-will-be-filtered', $event.checked)" [(ngModel)]= "censorPartialWordsCheck">
+        {{ 'room-page.partial-words-filter' | translate }}
+      </mat-slide-toggle>
     </div>
     <div fxLayoutAlign="center center">
       <!-- <input type="checkbox" id= "myCheck" [(ngModel)]= "check" > -->
diff --git a/src/app/components/creator/_dialogs/room-edit/room-edit.component.ts b/src/app/components/creator/_dialogs/room-edit/room-edit.component.ts
index b947b5e081fbeff0b8522e4ec38be87a6edf9cb4..aa6468be4985a8de87814b3c65591b1ff7ce7d7b 100644
--- a/src/app/components/creator/_dialogs/room-edit/room-edit.component.ts
+++ b/src/app/components/creator/_dialogs/room-edit/room-edit.component.ts
@@ -1,6 +1,6 @@
 import { Component, Inject, OnInit } from '@angular/core';
 import { FormControl, Validators } from '@angular/forms';
-import { Room } from '../../../../models/room';
+import { ProfanityFilter, Room } from '../../../../models/room';
 import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
 import { RoomDeleteComponent } from '../room-delete/room-delete.component';
 import { NotificationService } from '../../../../services/util/notification.service';
@@ -19,8 +19,10 @@ import { RoomDeleted } from '../../../../models/events/room-deleted';
 })
 export class RoomEditComponent implements OnInit {
   editRoom: Room;
-  check: boolean = false;
-  profanityCheck = true;
+  check = false;
+  profanityCheck: boolean;
+  censorPartialWordsCheck: boolean;
+  censorLanguageSpecificCheck: boolean;
 
   roomNameFormControl = new FormControl('', [Validators.required, Validators.minLength(3), Validators.maxLength(30)]);
 
@@ -36,7 +38,13 @@ export class RoomEditComponent implements OnInit {
 
   ngOnInit() {
     this.check = this.editRoom.questionsBlocked;
-    this.profanityCheck = this.editRoom.profanityFilter;
+    this.profanityCheck = this.editRoom.profanityFilter !== ProfanityFilter.deactivated;
+    if (this.editRoom.profanityFilter === ProfanityFilter.all){
+      this.censorLanguageSpecificCheck = this.censorPartialWordsCheck = true;
+    } else if (this.profanityCheck){
+      this.censorLanguageSpecificCheck = this.editRoom.profanityFilter === ProfanityFilter.languageSpecific;
+      this.censorPartialWordsCheck = this.editRoom.profanityFilter === ProfanityFilter.partialWords;
+    }
   }
 
   openDeleteRoomDialog(): void {
@@ -73,9 +81,15 @@ export class RoomEditComponent implements OnInit {
 
   save(): void {
     this.editRoom.questionsBlocked = this.check;
-    this.editRoom.profanityFilter = this.profanityCheck;
-    // temp solution until the backend is updated
-    localStorage.setItem('room-profanity-filter', (this.profanityCheck ? 'true' : 'false'));
+    this.editRoom.profanityFilter = this.profanityCheck ? ProfanityFilter.none : ProfanityFilter.deactivated;
+    if (this.profanityCheck) {
+      if (this.censorLanguageSpecificCheck && this.censorPartialWordsCheck) {
+        this.editRoom.profanityFilter = ProfanityFilter.all;
+      } else {
+        this.editRoom.profanityFilter = this.censorLanguageSpecificCheck ? ProfanityFilter.languageSpecific : ProfanityFilter.none;
+        this.editRoom.profanityFilter = this.censorPartialWordsCheck ? ProfanityFilter.partialWords : this.editRoom.profanityFilter;
+      }
+    }
     this.roomService.updateRoom(this.editRoom).subscribe(r => this.editRoom = r);
     if (!this.roomNameFormControl.hasError('required')
         && !this.roomNameFormControl.hasError('minlength')
@@ -99,8 +113,8 @@ export class RoomEditComponent implements OnInit {
     return () => this.save();
   }
 
-  showMessage(label?: string) {
-    if (this.profanityCheck){
+  showMessage(label: string, event: boolean) {
+    if (event) {
       this.translationService.get('room-page.'+label).subscribe(msg => {
         this.notificationService.show(msg);
       });
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 fbd0782ff8e02645ab6e575d767ed97d1b8e5b95..854f7595a5f0ec417b4cb034b2964583ac93b828 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
@@ -326,7 +326,8 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy {
         c.id = payload.id;
         c.timestamp = payload.timestamp;
         c.creatorId = payload.creatorId;
-        c.keywordsFromQuestioner = JSON.parse(payload.keywordsFromQuestioner);
+        c.keywordsFromQuestioner = payload.keywordsFromQuestioner ?
+                                   JSON.parse(payload.keywordsFromQuestioner as unknown as string) : null;
         c.userNumber = this.commentService.hashCode(c.creatorId);
         this.comments = this.comments.concat(c);
         break;
diff --git a/src/app/components/shared/_dialogs/create-comment/create-comment.component.html b/src/app/components/shared/_dialogs/create-comment/create-comment.component.html
index b2a76fad7c816a9134ef5aa7675ec9627229b2d7..978d076a300d08cc545bd77890cacefcca1cc8b1 100644
--- a/src/app/components/shared/_dialogs/create-comment/create-comment.component.html
+++ b/src/app/components/shared/_dialogs/create-comment/create-comment.component.html
@@ -23,19 +23,15 @@
   </div>
     <div class="anchor-wrp">
       <div class="anchor-right">
-        <mat-form-field *ngIf="tags"
-                        class="tag-form-field">
+        <mat-form-field *ngIf="tags" class="tag-form-field">
           <mat-label>
-            <mat-icon class="icon-svg"
-                      svgIcon="comment_tag"></mat-icon>
-            {{'comment-page.tag' | translate}}</mat-label>
-          <mat-select [(ngModel)]="selectedTag"
-                      class="tag-select">
+            <mat-icon class="icon-svg" svgIcon="comment_tag"></mat-icon>
+            {{'comment-page.tag' | translate}}
+          </mat-label>
+          <label for="tagSelect">{{selectedTag}}</label>
+          <mat-select [(ngModel)]="selectedTag" class="tag-select" id="tagSelect" style="display: inline">
             <mat-option>{{'comment-page.tag-reset' | translate}}</mat-option>
-            <mat-option *ngFor="let tag of tags"
-                        value="{{tag}}">
-              {{tag}}
-            </mat-option>
+            <mat-option *ngFor="let tag of tags" value="{{tag}}">{{tag}}</mat-option>
           </mat-select>
         </mat-form-field>
       </div>
@@ -102,7 +98,10 @@
   </ars-row>
   <ars-row ars-flex-box class="spellcheck">
     <ars-col>
-      <button mat-button class="spell-button" (click)="grammarCheck(commentBody)">
+      <button
+        [disabled]="this.commentBody.innerHTML.length === 0"
+        mat-flat-button class="spell-button"
+        (click)="grammarCheck(commentBody)">
         {{ 'comment-page.grammar-check' | translate}}
         <mat-icon *ngIf="isSpellchecking" style="margin: 0;">
           <mat-spinner diameter="20"></mat-spinner>
diff --git a/src/app/components/shared/_dialogs/create-comment/create-comment.component.ts b/src/app/components/shared/_dialogs/create-comment/create-comment.component.ts
index d39c798de3c1a306f8b69596cff455f17c7b1a22..5ca59b3528a5543b164bdd09a603854fb9d0d20f 100644
--- a/src/app/components/shared/_dialogs/create-comment/create-comment.component.ts
+++ b/src/app/components/shared/_dialogs/create-comment/create-comment.component.ts
@@ -1,5 +1,5 @@
 import { Component, Inject, OnDestroy, OnInit, ViewChild } from '@angular/core';
-import { Comment } from '../../../../models/comment';
+import { Comment, Language as CommentLanguage } from '../../../../models/comment';
 import { NotificationService } from '../../../../services/util/notification.service';
 import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
 import { TranslateService } from '@ngx-translate/core';
@@ -116,17 +116,18 @@ export class CreateCommentComponent implements OnInit, OnDestroy {
     }
   }
 
-  checkUTFEmoji(body: string): string {
-    const regex = /(?:\:.*?\:|[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])/g;
-
-    return body.replace(regex, '');
-  }
-
   openSpacyDialog(comment: Comment): void {
     CreateCommentKeywords.isSpellingAcceptable(this.languagetoolService, this.inputText, this.selectedLang)
       .subscribe((result) => {
         if (result.isAcceptable) {
           const commentLang = this.languagetoolService.mapLanguageToSpacyModel(result.result.language.code as Language);
+          const selectedLangExtend = this.selectedLang[2] === '-' ? this.selectedLang.substr(0, 2) : this.selectedLang;
+          // Store language if it was auto-detected
+          if (this.selectedLang === 'auto') {
+            comment.language = Comment.mapModelToLanguage(commentLang);
+          } else if (CommentLanguage[selectedLangExtend]) {
+            comment.language = CommentLanguage[selectedLangExtend];
+          }
           const dialogRef = this.dialog.open(SpacyDialogComponent, {
             data: {
               comment,
@@ -140,6 +141,7 @@ export class CreateCommentComponent implements OnInit, OnDestroy {
             }
           });
         } else {
+          comment.language = CommentLanguage.auto;
           this.dialogRef.close(comment);
         }
         this.isSendingToSpacy = false;
@@ -161,7 +163,7 @@ export class CreateCommentComponent implements OnInit, OnDestroy {
   }
 
   checkSpellings(text: string, language: Language = this.selectedLang) {
-    return this.languagetoolService.checkSpellings(text, language);
+    return this.languagetoolService.checkSpellings(CreateCommentKeywords.cleaningFunction(text), language);
   }
 
   maxLength(commentBody: HTMLDivElement): void {
diff --git a/src/app/components/shared/_dialogs/room-create/room-create.component.ts b/src/app/components/shared/_dialogs/room-create/room-create.component.ts
index 191ce27da1750415a4ee897360169d3f11e6f2c0..f0f7a36d8a0d221f8464e6df56b9b59bbbaefc1f 100644
--- a/src/app/components/shared/_dialogs/room-create/room-create.component.ts
+++ b/src/app/components/shared/_dialogs/room-create/room-create.component.ts
@@ -1,13 +1,12 @@
 import { Component, Inject, OnInit } from '@angular/core';
 import { RoomService } from '../../../../services/http/room.service';
-import { Room } from '../../../../models/room';
+import { ProfanityFilter, Room } from '../../../../models/room';
 import { UserRole } from '../../../../models/user-roles.enum';
 import { Router } from '@angular/router';
 import { NotificationService } from '../../../../services/util/notification.service';
 import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
 import { AuthenticationService } from '../../../../services/http/authentication.service';
 import { TranslateService } from '@ngx-translate/core';
-import { TSMap } from 'typescript-map';
 import { EventService } from '../../../../services/util/event.service';
 import { User } from '../../../../models/user';
 
@@ -76,7 +75,7 @@ export class RoomCreateComponent implements OnInit {
     newRoom.description = '';
     newRoom.blacklist = '[]';
     newRoom.questionsBlocked = false;
-    newRoom.profanityFilter = true;
+    newRoom.profanityFilter = ProfanityFilter.none;
     if (this.hasCustomShortId && this.customShortIdName && this.customShortIdName.length > 0) {
       if (!new RegExp('[1-9a-z,A-Z,\s,\-,\.,\_,\~]+').test(this.customShortIdName)
         || this.customShortIdName.startsWith(' ') || this.customShortIdName.endsWith(' ')) {
@@ -100,8 +99,8 @@ export class RoomCreateComponent implements OnInit {
       this.room = room;
       let msg1: string;
       let msg2: string;
-      this.translateService.get('home-page.created-1').subscribe(msg => { msg1 = msg; });
-      this.translateService.get('home-page.created-2').subscribe(msg => { msg2 = msg; });
+      this.translateService.get('home-page.created-1').subscribe(msg => msg1 = msg);
+      this.translateService.get('home-page.created-2').subscribe(msg => msg2 = msg);
       this.notification.show(msg1 + longRoomName + msg2);
       this.authenticationService.setAccess(encoded, UserRole.CREATOR);
       this.authenticationService.assignRole(UserRole.CREATOR);
diff --git a/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.html b/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.html
index aebb707b53bdc0b78d2addd685d9820fc061bf5d..aadff087cfc38dcbd323e9067faa3f68484aba41 100644
--- a/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.html
+++ b/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.html
@@ -1,6 +1,7 @@
 <ars-row>
   <div class="anchor-wrp">
     <span *ngIf="keywords.length > 0">
+        <span>{{ 'spacy-dialog.select-keywords' | translate }}</span>
       <ars-row class="select-all-section">
         <mat-checkbox class="select-all-checkbox"
                       id="checkAll"
@@ -42,14 +43,14 @@
                           matTooltipShowDelay="750">
             </mat-checkbox>
             <button *ngIf="!keyword.editing"
-                    (click)="onEdit(keyword)" mat-icon-button
+                    (click)="onEdit(keyword); onEditChange(1)" mat-icon-button
                     [ngClass]="{'keywords-actions-selected': keyword.selected}"
                     matTooltip="{{ 'spacy-dialog.edit-keyword-hint' | translate }}"
                     matTooltipShowDelay="750">
               <mat-icon>edit</mat-icon>
             </button>
             <button *ngIf="keyword.editing"
-                    (click)="onEndEditing(keyword)" mat-icon-button
+                    (click)="onEndEditing(keyword); onEditChange(-1)" mat-icon-button
                     class = "edit-accept"
                     matTooltip="{{ 'spacy-dialog.editing-done-hint' | translate }}"
                     matTooltipShowDelay="750">
@@ -75,6 +76,7 @@
   <ars-fill></ars-fill>
   <ars-col>
     <app-dialog-action-buttons
+      #appDialogActionButtons
       buttonsLabelSection="comment-page"
       confirmButtonLabel="send"
       [showDivider]="false"
diff --git a/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.ts b/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.ts
index 23ef9c3ebb2260255822b95ff9cb8277fe1f5f4d..45166229b358cbcc4c6a3c2c4765931d45931961 100644
--- a/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.ts
+++ b/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.ts
@@ -1,11 +1,12 @@
-import { AfterContentInit, Component, Inject, OnInit } from '@angular/core';
+import { AfterContentInit, Component, Inject, OnInit, ViewChild } from '@angular/core';
 import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
 
 import { CreateCommentComponent } from '../create-comment/create-comment.component';
 import { SpacyService, Model } from '../../../../services/http/spacy.service';
-import { LanguageService } from '../../../../services/util/language.service';
+import { LanguagetoolService } from '../../../../services/http/languagetool.service';
 import { Comment } from '../../../../models/comment';
 import { map } from 'rxjs/operators';
+import { DialogActionButtonsComponent } from '../../dialog/dialog-action-buttons/dialog-action-buttons.component';
 
 export interface Keyword {
   word: string;
@@ -21,6 +22,8 @@ export interface Keyword {
 })
 export class SpacyDialogComponent implements OnInit, AfterContentInit {
 
+  @ViewChild('appDialogActionButtons') appDialogActionButtons: DialogActionButtonsComponent;
+
   comment: Comment;
   commentLang: Model;
   commentBodyChecked: string;
@@ -29,9 +32,10 @@ export class SpacyDialogComponent implements OnInit, AfterContentInit {
   isLoading = false;
   langSupported: boolean;
   manualKeywords = '';
+  _concurrentEdits = 0
 
   constructor(
-    protected langService: LanguageService,
+    protected langService: LanguagetoolService,
     private spacyService: SpacyService,
     public dialogRef: MatDialogRef<CreateCommentComponent>,
     @Inject(MAT_DIALOG_DATA) public data) {
@@ -41,7 +45,7 @@ export class SpacyDialogComponent implements OnInit, AfterContentInit {
     this.comment = this.data.comment;
     this.commentLang = this.data.commentLang;
     this.commentBodyChecked = this.data.commentBodyChecked;
-    this.langSupported = this.commentLang !== 'auto';
+    this.langSupported = this.langService.isSupportedLanguage(this.data.commentLang);
   }
 
   ngAfterContentInit(): void {
@@ -143,4 +147,9 @@ export class SpacyDialogComponent implements OnInit, AfterContentInit {
       this.keywords = [];
     }
   }
+
+  onEditChange(change: number) {
+    this._concurrentEdits += change;
+    this.appDialogActionButtons.confirmButtonDisabled = (this._concurrentEdits > 0)
+  }
 }
diff --git a/src/app/components/shared/_dialogs/topic-cloud-administration/TopicCloudAdminData.ts b/src/app/components/shared/_dialogs/topic-cloud-administration/TopicCloudAdminData.ts
index 56cd2858586d64983eba399683c3547cbf59c18a..e20969aa89fd13f8f857dc00e9461068e1e795d7 100644
--- a/src/app/components/shared/_dialogs/topic-cloud-administration/TopicCloudAdminData.ts
+++ b/src/app/components/shared/_dialogs/topic-cloud-administration/TopicCloudAdminData.ts
@@ -1,63 +1,65 @@
 export interface TopicCloudAdminData {
-    blacklist: string[];
-    wantedLabels: {
-      de: string[];
-      en: string[];
-    };
-    considerVotes: boolean;
-    profanityFilter: boolean;
-    blacklistIsActive: boolean;
-    keywordORfulltext: KeywordOrFulltext;
+  blacklist: string[];
+  wantedLabels: {
+    de: string[];
+    en: string[];
+  };
+  considerVotes: boolean;
+  profanityFilter: boolean;
+  blacklistIsActive: boolean;
+  keywordORfulltext: KeywordOrFulltext;
 }
 
 export enum KeywordOrFulltext {
-    keyword,
-    fulltext,
-    both
+  keyword,
+  fulltext,
+  both
 }
 
 export interface Label {
-    readonly tag: string;
-    readonly label: string;
+  readonly tag: string;
+  readonly label: string;
+  readonly enabledByDefault: boolean;
 }
 
 export class Labels {
-    readonly de: Label[];
-    readonly en: Label[];
+  readonly de: Label[];
+  readonly en: Label[];
 
-    constructor(_de: Label[], _en: Label[]) {
-        this.de = _de;
-        this.en = _en;
-    }
+  constructor(_de: Label[], _en: Label[]) {
+    this.de = _de;
+    this.en = _en;
+  }
 }
 
 const deLabels: Label[] = [
-    {tag: 'sb',  label: 'Subjekt'},
-    {tag: 'pd',  label: 'Prädikat'},
-    {tag: 'og',  label: 'Genitivobjekt'},
-    {tag: 'ag',  label: 'Genitivattribut'},
-    {tag: 'app', label: 'Apposition'},
-    {tag: 'da',  label: 'Dativobjekt'},
-    {tag: 'oa',  label: 'Akkusativobjekt'},
-    {tag: 'nk',  label: 'Nomen Kernelement'},
-    {tag: 'mo',  label: 'Modifikator'},
-    {tag: 'cj',  label: 'Konjunktor'},
-    {tag: 'ROOT',  label: 'Satzkernelement'},
-    {tag: 'par',  label: 'Klammerzusatz'}
+  {tag: 'sb', label: 'Subjekt', enabledByDefault: true},
+  {tag: 'op', label: 'Präpositionalobjekt', enabledByDefault: true},
+  {tag: 'og', label: 'Genitivobjekt', enabledByDefault: true},
+  {tag: 'da', label: 'Dativobjekt', enabledByDefault: true},
+  {tag: 'oa', label: 'Akkusativobjekt', enabledByDefault: true},
+  {tag: 'pd', label: 'Prädikat', enabledByDefault: false},
+  {tag: 'ag', label: 'Genitivattribut', enabledByDefault: false},
+  {tag: 'app', label: 'Apposition', enabledByDefault: false},
+  {tag: 'nk', label: 'Nomen Kernelement', enabledByDefault: false},
+  {tag: 'mo', label: 'Modifikator', enabledByDefault: false},
+  {tag: 'cj', label: 'Konjunktor', enabledByDefault: false},
+  {tag: 'ROOT', label: 'Satzkernelement', enabledByDefault: false},
+  {tag: 'par', label: 'Klammerzusatz', enabledByDefault: false}
 ];
 
 const enLabels: Label[] = [
-    {tag: 'nsubj',   label: 'Nominal subject'},
-    {tag: 'nsubjpass',  label: 'Passive nominal subject'},
-    {tag: 'pobj',   label: 'Object of preposition'},
-    {tag: 'nummod',  label: 'Numeric modifier'},
-    {tag: 'compound',  label: 'Compound'},
-    {tag: 'dobj',  label: 'Direct object'},
-    {tag: 'amod',  label: 'Adjectival modifier'},
-    {tag: 'npadvmod',  label: 'Noun phrase as adverbial modifier'},
-    {tag: 'conj',  label: 'Conjunct'},
-    {tag: 'ROOT',  label: 'Sentence kernel element'},
-    {tag: 'intj',  label: 'Interjection'}
+  {tag: 'nsubj', label: 'Nominal subject', enabledByDefault: true},
+  {tag: 'pobj', label: 'Object of preposition', enabledByDefault: true},
+  {tag: 'dobj', label: 'Direct object', enabledByDefault: true},
+  {tag: 'compound', label: 'Compound', enabledByDefault: true},
+  {tag: 'nsubjpass', label: 'Passive nominal subject', enabledByDefault: true},
+  {tag: 'nummod', label: 'Numeric modifier', enabledByDefault: false},
+  {tag: 'amod', label: 'Adjectival modifier', enabledByDefault: false},
+  {tag: 'npadvmod', label: 'Noun phrase as adverbial modifier', enabledByDefault: false},
+  {tag: 'conj', label: 'Conjunct', enabledByDefault: false},
+  {tag: 'ROOT', label: 'Sentence kernel element', enabledByDefault: false},
+  {tag: 'intj', label: 'Interjection', enabledByDefault: false}
 ];
 
 export const spacyLabels = new Labels(deLabels, enLabels);
diff --git a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.html b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.html
index d825f6650f7d90a4aee98e0c7e1c92658e10f1f0..2f918ec39dea22417943f1dc7ac40536aef1f9a8 100644
--- a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.html
+++ b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.html
@@ -211,8 +211,8 @@
     
     <mat-accordion>
       <mat-expansion-panel class="color-surface" (opened)="panelOpenState = true" (closed)="panelOpenState = edit = false"
-        *ngFor="let keyword of
-                          (searchMode ? filteredKeywords : keywords); let i = index" [attr.data-index]="i">
+        *ngFor="let keyword of (searchMode ? filteredKeywords : keywords); let i = index" [attr.data-index]="i"
+        matTooltip="{{'topic-cloud-dialog.'+(keyword.keywordType === 0?'keyword-from-spacy':'keyword-from-questioner') | translate}}">
         <mat-expansion-panel-header class="color-surface">
           <mat-panel-title>
             {{profanityFilter ? keyword.keywordWithoutProfanity : keyword.keyword}}
diff --git a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.ts b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.ts
index 5a613e2705c76b45501f5f06557ce897d87c0281..5088205464787d718e56e630b759bfbdff170fb7 100644
--- a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.ts
+++ b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.ts
@@ -102,10 +102,9 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy {
   }
 
   refreshKeywords() {
-    const tempKeywords = this.keywords;
     this.keywords = [];
-    tempKeywords.forEach(keyword => {
-      keyword.comments.forEach(comment => this.pushInKeywords(comment));
+    this.roomDataService.currentRoomData.forEach(comment => {
+      this.pushInKeywords(comment);
     });
     if (this.searchMode) {
       this.searchKeyword();
@@ -113,13 +112,16 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy {
   }
 
   pushInKeywords(comment: Comment) {
+    let _keywordType = KeywordType.fromQuestioner;
     let keywords = comment.keywordsFromQuestioner;
     if (this.keywordORfulltext === KeywordOrFulltext[KeywordOrFulltext.both]) {
       if (!keywords || !keywords.length) {
         keywords = comment.keywordsFromSpacy;
+        _keywordType = KeywordType.fromSpacy;
       }
     } else if (this.keywordORfulltext === KeywordOrFulltext[KeywordOrFulltext.fulltext]) {
       keywords = comment.keywordsFromSpacy;
+      _keywordType = KeywordType.fromSpacy;
     }
     if (!keywords) {
       keywords = [];
@@ -134,6 +136,7 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy {
       } else {
         const keyword: Keyword = {
           keyword: _keyword,
+          keywordType: _keywordType,
           keywordWithoutProfanity: this.getKeywordWithoutProfanity(_keyword),
           comments: [comment],
           vote: comment.score
@@ -227,7 +230,7 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy {
   }
 
   getKeywordWithoutProfanity(keyword: string): string {
-    return this.topicCloudAdminService.filterProfanityWords(keyword);
+    return this.topicCloudAdminService.filterProfanityWords(keyword, true, false);
   }
 
   sortQuestions(sortMode?: string) {
@@ -450,6 +453,7 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy {
 
 interface Keyword {
   keyword: string;
+  keywordType: KeywordType;
   keywordWithoutProfanity: string;
   comments: Comment[];
   vote: number;
@@ -459,3 +463,8 @@ export interface Data {
   user: User;
 }
 
+enum KeywordType {
+  fromSpacy = 0,
+  fromQuestioner = 1
+}
+
diff --git a/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.html b/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.html
index 8838a59c151580b2f44d30605c35a1a93f4b7c81..3b1911cb570fcfb476624a32042e1763ed9859f8 100644
--- a/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.html
+++ b/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.html
@@ -1,30 +1,32 @@
-<div mat-dialog-content>
-  <p>{{'content.topic-cloud-content' | translate}}</p>
-</div>
-
 <mat-divider></mat-divider>
   <mat-radio-group [(ngModel)]="continueFilter" aria-label="Select an option">
-    <mat-radio-button value="continueWithAll">
+    <mat-radio-button checked="true" value="continueWithAll">
       <div class="elementRow">
         <div class="elementText">
           {{'content.continue-with-all-questions' | translate}}
         </div>
         <div class="elementIcons">
-          <mat-icon [inline]="true">comment</mat-icon> {{allComments.comments}}
-          <mat-icon [inline]="true">person</mat-icon> {{allComments.users}}
-          <mat-icon svgIcon="hashtag" class="comment_tag-icon"></mat-icon> {{allComments.keywords}}
+          <mat-icon [inline]="true"
+            matTooltip="{{'header.overview-question-tooltip' | translate}}">comment</mat-icon> {{allComments.comments}}
+          <mat-icon [inline]="true"
+            matTooltip="{{'header.overview-questioners-tooltip' | translate}}">person</mat-icon> {{allComments.users}}
+          <mat-icon svgIcon="hashtag" class="comment_tag-icon"
+            matTooltip="{{'header.overview-keywords-tooltip' | translate}}"></mat-icon> {{allComments.keywords}}
         </div>
       </div>
     </mat-radio-button>
-    <mat-radio-button checked="true" value="continueWithCurr" *ngIf="!disableCurrentFiltersOptions">
+    <mat-radio-button value="continueWithCurr" *ngIf="!disableCurrentFiltersOptions">
       <div class="elementRow">
         <div class="elementText">
           {{'content.continue-with-current-questions' | translate}}
         </div>
         <div class="elementIcons">
-          <mat-icon [inline]="true">comment</mat-icon> {{filteredComments.comments}}
-          <mat-icon [inline]="true">person</mat-icon> {{filteredComments.users}}
-          <mat-icon svgIcon="hashtag" class="comment_tag-icon"></mat-icon> {{filteredComments.keywords}}
+          <mat-icon [inline]="true"
+            matTooltip="{{'header.overview-question-tooltip' | translate}}">comment</mat-icon> {{filteredComments.comments}}
+          <mat-icon [inline]="true"
+            matTooltip="{{'header.overview-questioners-tooltip' | translate}}">person</mat-icon> {{filteredComments.users}}
+          <mat-icon svgIcon="hashtag" class="comment_tag-icon"
+            matTooltip="{{'header.overview-keywords-tooltip' | translate}}"></mat-icon> {{filteredComments.keywords}}
         </div>
       </div>
     </mat-radio-button>
diff --git a/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.ts b/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.ts
index f86b23334a449a41725206123391f314cabfeffd..2cce403e9e7d0e084aaff4bfb6af3ed7de2ab23f 100644
--- a/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.ts
+++ b/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.ts
@@ -1,4 +1,4 @@
-import { Component, Inject, OnInit, Input } from '@angular/core';
+import { Component, Inject, Input, OnInit } from '@angular/core';
 import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
 import { NotificationService } from '../../../../services/util/notification.service';
 import { TranslateService } from '@ngx-translate/core';
@@ -10,6 +10,8 @@ import { CommentFilter } from '../../../../utils/filter-options';
 import { RoomService } from '../../../../services/http/room.service';
 import { Comment } from '../../../../models/comment';
 import { CommentListData } from '../../comment-list/comment-list.component';
+import { TopicCloudAdminService } from '../../../../services/util/topic-cloud-admin.service';
+import { KeywordOrFulltext } from '../topic-cloud-administration/TopicCloudAdminData';
 
 class CommentsCount {
   comments: number;
@@ -23,14 +25,16 @@ class CommentsCount {
   styleUrls: ['./topic-cloud-filter.component.scss']
 })
 export class TopicCloudFilterComponent implements OnInit {
-  @Input() shortId: string;
+  @Input() target: string;
 
-  continueFilter = 'continueWithCurr';
+  continueFilter = 'continueWithAll';
   comments: Comment[];
   tmpFilter: CommentFilter;
   allComments: CommentsCount;
   filteredComments: CommentsCount;
   disableCurrentFiltersOptions = false;
+  private readonly _filter: KeywordOrFulltext;
+  private readonly _blacklist: string[];
 
   constructor(public dialogRef: MatDialogRef<RoomCreatorPageComponent>,
               public dialog: MatDialog,
@@ -42,6 +46,9 @@ export class TopicCloudFilterComponent implements OnInit {
               @Inject(MAT_DIALOG_DATA) public data: any,
               public eventService: EventService) {
     langService.langEmitter.subscribe(lang => translationService.use(lang));
+    const adminData = TopicCloudAdminService.getDefaultAdminData;
+    this._filter = adminData.keywordORfulltext;
+    this._blacklist = adminData.blacklist;
   }
 
   ngOnInit() {
@@ -76,9 +83,25 @@ export class TopicCloudFilterComponent implements OnInit {
       if (c.userNumber) {
         userSet.add(c.userNumber);
       }
-      if (c.keywordsFromQuestioner) {
-        c.keywordsFromQuestioner.forEach(k => {
-          keywordSet.add(k);
+      let source = c.keywordsFromQuestioner;
+      if (this._filter === KeywordOrFulltext.both) {
+        source = !source || !source.length ? c.keywordsFromSpacy : source;
+      } else if (this._filter === KeywordOrFulltext.fulltext) {
+        source = c.keywordsFromSpacy;
+      }
+      if (source) {
+        source.forEach(k => {
+          let isProfanity = false;
+          const lowerCasedKeyword = k.toLowerCase();
+          for (const word of this._blacklist) {
+            if (lowerCasedKeyword.includes(word)) {
+              isProfanity = true;
+              break;
+            }
+          }
+          if (!isProfanity) {
+            keywordSet.add(k);
+          }
         });
       }
     });
@@ -115,7 +138,7 @@ export class TopicCloudFilterComponent implements OnInit {
       }
 
       CommentFilter.currentFilter = filter;
-      this.dialogRef.close(this.router.navigateByUrl('/participant/room/' + this.shortId + '/comments/tagcloud'));
+      this.dialogRef.close(this.router.navigateByUrl(this.target));
     };
   }
 }
diff --git a/src/app/components/shared/_dialogs/worker-dialog/worker-dialog-task.ts b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog-task.ts
index 4a9613780829439612b4b081d0362dc6129ab69b..5bfdb4b459ff80efb336bd8635a6daed705b248d 100644
--- a/src/app/components/shared/_dialogs/worker-dialog/worker-dialog-task.ts
+++ b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog-task.ts
@@ -11,7 +11,6 @@ const concurrentCallsPerTask = 4;
 
 export class WorkerDialogTask {
 
-  initializing = true;
   error: string = null;
   readonly statistics = {
     succeeded: 0,
@@ -19,24 +18,26 @@ export class WorkerDialogTask {
     failed: 0,
     length: 0
   };
-  private _comments: Comment[] = null;
-  private _running: boolean[] = null;
+  private readonly _comments: Comment[] = null;
+  private readonly _running: boolean[] = null;
 
   constructor(public readonly room: Room,
+              private comments: Comment[],
               private spacyService: SpacyService,
               private commentService: CommentService,
               private languagetoolService: LanguagetoolService,
               private finished: () => void) {
-    this.commentService.getAckComments(room.id).subscribe((c) => {
-      this._comments = c;
-      this.statistics.length = c.length;
-      this.initializing = false;
-      this._running = new Array(concurrentCallsPerTask);
-      for (let i = 0; i < concurrentCallsPerTask; i++) {
-        this._running[i] = true;
-        this.callSpacy(i);
-      }
-    });
+    this._comments = comments;
+    this.statistics.length = comments.length;
+    this._running = new Array(concurrentCallsPerTask);
+    for (let i = 0; i < concurrentCallsPerTask; i++) {
+      this._running[i] = true;
+      this.callSpacy(i);
+    }
+  }
+
+  isRunning(): boolean {
+    return this._running.some(e => e === true);
   }
 
   private callSpacy(currentIndex: number) {
@@ -50,7 +51,6 @@ export class WorkerDialogTask {
       }
       return;
     }
-    const fallbackmodel = (localStorage.getItem('currentLang') || 'de') as Model;
     const currentComment = this._comments[currentIndex];
     CreateCommentKeywords.isSpellingAcceptable(this.languagetoolService, currentComment.body)
       .subscribe(result => {
@@ -59,9 +59,15 @@ export class WorkerDialogTask {
           this.callSpacy(currentIndex + concurrentCallsPerTask);
           return;
         }
-        const model = this.languagetoolService
-          .mapLanguageToSpacyModel(result.result.language.detectedLanguage.code as Language);
-        this.spacyService.getKeywords(result.text, model === 'auto' ? fallbackmodel : model)
+        const commentModel = currentComment.language.toLowerCase();
+        const model = commentModel !== 'auto' ? commentModel.toLowerCase() as Model :
+          this.languagetoolService.mapLanguageToSpacyModel(result.result.language.detectedLanguage.code as Language);
+        if (model === 'auto') {
+          this.statistics.badSpelled++;
+          this.callSpacy(currentIndex + concurrentCallsPerTask);
+          return;
+        }
+        this.spacyService.getKeywords(result.text, model)
           .subscribe(newKeywords => {
               const changes = new TSMap<string, string>();
               changes.set('keywordsFromSpacy', JSON.stringify(newKeywords));
@@ -73,19 +79,16 @@ export class WorkerDialogTask {
                   if (patchError instanceof HttpErrorResponse && patchError.status === 403) {
                     this.error = 'forbidden';
                   }
-                  console.log(patchError);
                 }, () => {
                   this.callSpacy(currentIndex + concurrentCallsPerTask);
                 });
             },
-            keywordError => {
+            __ => {
               this.statistics.failed++;
-              console.log(keywordError);
               this.callSpacy(currentIndex + concurrentCallsPerTask);
             });
-      }, error => {
+      }, _ => {
         this.statistics.failed++;
-        console.log(error);
         this.callSpacy(currentIndex + concurrentCallsPerTask);
       });
   }
diff --git a/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.html b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.html
index a57273c93fc28a10d7c6b051ae2a85da832af9f7..09e7320f9523027e0795585fc6197f2a992c5c7a 100644
--- a/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.html
+++ b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.html
@@ -2,16 +2,30 @@
   <div id="header" (window:beforeunload)="checkTasks($event)">
     <details>
       <summary>
-        <span>{{'worker-dialog.running' | translate}} # {{getRooms().length}}</span>
+        <span>{{'worker-dialog.running' | translate}} # {{getActiveRoomCount()}}</span>
         <span><button id="btn_hide" (click)="close()">x</button></span>
       </summary>
       <div mat-dialog-content>
-        <div id="entry" *ngFor="let task of getRooms().values()">
-          <mat-icon svgIcon="meeting_room"></mat-icon>
-          <span>{{ task.room.name }}</span>
-          <span style="width: 10px"></span>
-          <mat-icon>comment</mat-icon>
-          <span>{{ task.statistics.length }}</span>
+        <div class="entry" *ngFor="let task of getRooms().values()">
+          <div class="entryRow">
+            <mat-icon svgIcon="meeting_room" matTooltip="{{'worker-dialog.room-name' | translate}}"></mat-icon>
+            <span>{{ task.room.name }}</span>
+            <span *ngIf="task.error" style="color: var(--red)">{{task.error}}</span>
+          </div>
+          <div *ngIf="!task.error" class="entryRow">
+            <mat-icon matTooltip="{{'worker-dialog.comments' | translate}}">comment</mat-icon>
+            <span>{{task.statistics.succeeded}}/{{ task.statistics.length}}</span>
+            <mat-icon *ngIf="task.statistics.badSpelled" style="color: darkorange"
+              matTooltip="{{'worker-dialog.bad-spelled' | translate}}">warning</mat-icon>
+            <span *ngIf="task.statistics.badSpelled">
+              {{task.statistics.badSpelled}}
+            </span>
+            <mat-icon *ngIf="task.statistics.failed" style="color: var(--red)"
+              matTooltip="{{'worker-dialog.failed' | translate}}">error</mat-icon>
+            <span *ngIf="task.statistics.failed">
+              {{task.statistics.failed}}
+            </span>
+          </div>
         </div>
       </div>
     </details>
diff --git a/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.scss b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.scss
index b54f09a4c979f2b7c67c5a7d3e32fc6f87aac298..5ae6bb9888cac44a137dabd116bbb10f16e38bce 100644
--- a/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.scss
+++ b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.scss
@@ -22,19 +22,33 @@ button {
   padding-left: 5px;
 }
 
-summary {
+.entry {
+  display: flex;
+  flex-direction: column;
+  justify-content: left;
+  border-bottom: var(--primary) dashed 2px;
+  margin-bottom: 3px;
+  padding-bottom: 3px;
+}
+
+.entryRow {
+  display: flex;
+  flex-direction: row;
+  justify-content: left;
+  align-items: center;
+}
+
+span, mat-icon {
+  margin-right: 7px;
+}
+
+details > summary {
   border: none;
   outline: none;
-  box-shadow: 0 4px 4px -2px #232323;
-  -moz-box-shadow: 0 4px 4px -2px #232323;
-  -webkit-box-shadow: 0 4px 4px -2px #232323;
   cursor: pointer;
 }
 
-#entry {
-    display:flex;
-    flex-direction:row;
-    justify-content: left;
-  }
-
-
+details[open]> summary {
+  box-shadow: 0 4px 4px -2px #232323;
+  margin-bottom: 7px; 
+}
diff --git a/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.ts b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.ts
index bf1621a61c1b02602a88b7259c2ec0a0f2c6acec..40c69bc9afd546fbaaf63a161095bdde52661205 100644
--- a/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.ts
+++ b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.ts
@@ -6,6 +6,10 @@ import { TSMap } from 'typescript-map';
 import { MatDialog, MatDialogRef } from '@angular/material/dialog';
 import { WorkerDialogTask } from './worker-dialog-task';
 import { LanguagetoolService } from '../../../../services/http/languagetool.service';
+import { TranslateService } from '@ngx-translate/core';
+import { LanguageService } from '../../../../services/util/language.service';
+import { Comment } from '../../../../models/comment';
+import { RoomDataService } from '../../../../services/util/room-data.service';
 
 @Component({
   selector: 'app-worker-dialog',
@@ -19,7 +23,11 @@ export class WorkerDialogComponent implements OnInit {
 
   constructor(private commentService: CommentService,
               private languagetoolService: LanguagetoolService,
-              private spacyService: SpacyService) {
+              private spacyService: SpacyService,
+              protected langService: LanguageService,
+              private translateService: TranslateService,
+              private roomDataService: RoomDataService) {
+    langService.langEmitter.subscribe(lang => translateService.use(lang));
   }
 
   static addWorkTask(dialog: MatDialog, room: Room): boolean {
@@ -44,11 +52,12 @@ export class WorkerDialogComponent implements OnInit {
     if (this.queuedRooms.has(room.id)) {
       return false;
     }
-    this.dialogRef.componentInstance.appendRoom(room);
+    this.dialogRef.componentInstance.appendRoom(room, this.dialogRef.componentInstance.roomDataService.currentRoomData);
     return true;
   }
 
   ngOnInit(): void {
+    this.translateService.use(localStorage.getItem('currentLang'));
   }
 
   checkTasks(event: BeforeUnloadEvent) {
@@ -62,12 +71,25 @@ export class WorkerDialogComponent implements OnInit {
     return WorkerDialogComponent.queuedRooms;
   }
 
-  appendRoom(room: Room) {
+  getActiveRoomCount(): number {
+    let count = 0;
+    WorkerDialogComponent.queuedRooms.values().forEach(e => {
+      if (e.isRunning()) {
+        ++count;
+      }
+    });
+    return count;
+  }
+
+  appendRoom(room: Room, comments: Comment[]) {
     WorkerDialogComponent.queuedRooms.set(room.id,
-      new WorkerDialogTask(room, this.spacyService, this.commentService, this.languagetoolService, () => {
-        if (WorkerDialogComponent.queuedRooms.length === 0) {
-          setTimeout(() => this.close(), 2000);
-        }
+      new WorkerDialogTask(room, comments, this.spacyService, this.commentService, this.languagetoolService, () => {
+        setTimeout(() => {
+          WorkerDialogComponent.queuedRooms.delete(room.id);
+          if (WorkerDialogComponent.queuedRooms.length === 0) {
+            this.close();
+          }
+        }, 10_000);
       })
     );
   }
diff --git a/src/app/components/shared/comment-answer/comment-answer.component.ts b/src/app/components/shared/comment-answer/comment-answer.component.ts
index 7b8ce1a71568d2470b9ec659a4a9a8ce31a6dec2..c4641fc14f04fdac912d98ff94a15a935f9161e2 100644
--- a/src/app/components/shared/comment-answer/comment-answer.component.ts
+++ b/src/app/components/shared/comment-answer/comment-answer.component.ts
@@ -11,6 +11,7 @@ import { UserRole } from '../../../models/user-roles.enum';
 import { NotificationService } from '../../../services/util/notification.service';
 import { MatDialog } from '@angular/material/dialog';
 import { DeleteAnswerComponent } from '../../creator/_dialogs/delete-answer/delete-answer.component';
+import { RoomDataService } from '../../../services/util/room-data.service';
 
 @Component({
   selector: 'app-comment-answer',
@@ -33,6 +34,7 @@ export class CommentAnswerComponent implements OnInit {
               protected wsCommentService: WsCommentService,
               protected commentService: CommentService,
               private authenticationService: AuthenticationService,
+              private roomDataService: RoomDataService,
               public dialog: MatDialog) { }
 
   ngOnInit() {
diff --git a/src/app/components/shared/comment-list/comment-list.component.html b/src/app/components/shared/comment-list/comment-list.component.html
index a346dd2a1784d11facede53cc5973348a954592b..5edfdf4716cec1f1fe40eed822c598995f1d7808 100644
--- a/src/app/components/shared/comment-list/comment-list.component.html
+++ b/src/app/components/shared/comment-list/comment-list.component.html
@@ -30,7 +30,7 @@
           mat-icon-button
           class="searchBarButton close red"
           *ngIf="searchInput !== '' || search"
-          (click)="hideCommentsList=false; searchInput = ''; search = false; searchPlaceholder = '';"
+          (click)="hideCommentsList=false; searchInput = ''; search = false;"
           aria-labelledby="close_search">
     <mat-icon>close</mat-icon>
   </button>
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 7f908387c67f44a0c02dfd53054de1d51afa4b3a..f1c5032d3f8c00dc828e2c0036222822cf299606 100644
--- a/src/app/components/shared/comment-list/comment-list.component.ts
+++ b/src/app/components/shared/comment-list/comment-list.component.ts
@@ -29,6 +29,7 @@ import { CommentFilter, Period } from '../../../utils/filter-options';
 import { CreateCommentWrapper } from '../../../utils/CreateCommentWrapper';
 import { TopicCloudAdminService } from '../../../services/util/topic-cloud-admin.service';
 import { RoomDataService } from '../../../services/util/room-data.service';
+import { WsRoomService } from '../../../services/websockets/ws-room.service';
 
 export interface CommentListData {
   comments: Comment[];
@@ -95,9 +96,11 @@ export class CommentListComponent implements OnInit, OnDestroy {
   fromNow: number;
   moderatorIds: string[];
   commentsEnabled: boolean;
+  userNumberSelection: number = 0;
   createCommentWrapper: CreateCommentWrapper = null;
   private _subscriptionEventServiceTagConfig = null;
   private _subscriptionEventServiceRoomData = null;
+  private _subscriptionRoomService = null;
 
   constructor(
     private commentService: CommentService,
@@ -117,9 +120,15 @@ export class CommentListComponent implements OnInit, OnDestroy {
     private bonusTokenService: BonusTokenService,
     private moderatorService: ModeratorService,
     private topicCloudAdminService: TopicCloudAdminService,
-    private roomDataService: RoomDataService
+    private roomDataService: RoomDataService,
+    private wsRoomService: WsRoomService
   ) {
-    langService.langEmitter.subscribe(lang => translateService.use(lang));
+    langService.langEmitter.subscribe(lang => {
+      translateService.use(lang);
+      this.translateService.get('comment-list.search').subscribe(msg => {
+        this.searchPlaceholder = msg;
+      });
+    });
   }
 
   initNavigation() {
@@ -221,6 +230,7 @@ export class CommentListComponent implements OnInit, OnDestroy {
     this.userRole = this.route.snapshot.data.roles[0];
     this.route.params.subscribe(params => {
       this.shortId = params['shortId'];
+      this.authenticationService.checkAccess(this.shortId);
       this.authenticationService.guestLogin(UserRole.PARTICIPANT).subscribe(r => {
         this.roomService.getRoomByShortId(this.shortId).subscribe(room => {
           this.room = room;
@@ -262,12 +272,23 @@ export class CommentListComponent implements OnInit, OnDestroy {
     this.translateService.get('comment-list.search').subscribe(msg => {
       this.searchPlaceholder = msg;
     });
+    this._subscriptionRoomService = this.wsRoomService.getRoomStream(this.roomId).subscribe(msg => {
+      const message = JSON.parse(msg.body);
+      if (message.type === 'RoomPatched') {
+        this.room = message.payload.changes;
+        this.roomId = this.room.id;
+        this.moderationEnabled = this.room.moderated;
+        this.directSend = this.room.directSend;
+        this.commentsEnabled = (this.userRole > 0) || !this.room.questionsBlocked;
+      }
+    });
   }
 
   ngOnDestroy() {
     if (!this.freeze && this.commentStream) {
       this.commentStream.unsubscribe();
     }
+    this._subscriptionRoomService.unsubscribe();
     this.titleService.resetTitle();
     if (this.headerInterface) {
       this.headerInterface.unsubscribe();
@@ -309,9 +330,6 @@ export class CommentListComponent implements OnInit, OnDestroy {
   }
 
   activateSearch() {
-    this.translateService.get('comment-list.search').subscribe(msg => {
-      this.searchPlaceholder = msg;
-    });
     this.search = true;
     this.searchField.nativeElement.focus();
   }
@@ -431,6 +449,7 @@ export class CommentListComponent implements OnInit, OnDestroy {
   }
 
   clickedUserNumber(usrNumber: number): void {
+    this.userNumberSelection = usrNumber;
     this.filterComments(this.userNumber, usrNumber);
   }
 
@@ -570,6 +589,7 @@ export class CommentListComponent implements OnInit, OnDestroy {
     filter.periodSet = this.period;
     filter.keywordSelected = this.selectedKeyword;
     filter.tagSelected = this.selectedTag;
+    filter.userNumberSelected = this.userNumberSelection;
 
     if (filter.periodSet === Period.fromNow) {
       filter.timeStampNow = new Date().getTime();
diff --git a/src/app/components/shared/comment/comment.component.scss b/src/app/components/shared/comment/comment.component.scss
index b4f6c773b849c1b862afc4a41aba2f0dc61ad03b..88dce68e1e06883ec93e92dfb106709b564953f9 100644
--- a/src/app/components/shared/comment/comment.component.scss
+++ b/src/app/components/shared/comment/comment.component.scss
@@ -206,6 +206,10 @@ mat-card-content > :first-child {
   height: 18px !important;
 }
 
+.mat-badge-content {
+  background: #fb9a1c;
+}
+
 .user-number {
   cursor: pointer;
   color: var(--on-surface);
diff --git a/src/app/components/shared/comment/comment.component.ts b/src/app/components/shared/comment/comment.component.ts
index f3e688c7c685212c3e065a51acf81e775a04c15e..c8928f42f761bcb5a853408ec4afa5ef806ef354 100644
--- a/src/app/components/shared/comment/comment.component.ts
+++ b/src/app/components/shared/comment/comment.component.ts
@@ -17,6 +17,7 @@ import { UserRole } from '../../../models/user-roles.enum';
 import { Rescale } from '../../../models/rescale';
 import { RowComponent } from '../../../../../projects/ars/src/lib/components/layout/frame/row/row.component';
 import { User } from '../../../models/user';
+import { RoomDataService } from '../../../services/util/room-data.service';
 
 @Component({
   selector: 'app-comment',
@@ -67,6 +68,7 @@ export class CommentComponent implements OnInit, AfterViewInit {
     private commentService: CommentService,
     private notification: NotificationService,
     private translateService: TranslateService,
+    private roomDataService: RoomDataService,
     public dialog: MatDialog,
     protected langService: LanguageService) {
     langService.langEmitter.subscribe(lang => {
@@ -76,6 +78,7 @@ export class CommentComponent implements OnInit, AfterViewInit {
   }
 
   ngOnInit() {
+    this.checkProfanity();
     switch (this.userRole) {
       case UserRole.PARTICIPANT.valueOf():
         this.isStudent = true;
@@ -95,6 +98,12 @@ export class CommentComponent implements OnInit, AfterViewInit {
     this.inAnswerView = !this.router.url.includes('comments');
   }
 
+  checkProfanity(){
+    if (!this.router.url.includes('moderator/comments')) {
+      this.roomDataService.checkProfanity(this.comment);
+    }
+  }
+
   ngAfterViewInit(): void {
     this.isExpandable = this.commentBody.getRenderedHeight() > CommentComponent.COMMENT_MAX_HEIGHT;
     if (!this.isExpandable) {
@@ -128,10 +137,10 @@ export class CommentComponent implements OnInit, AfterViewInit {
   }
 
   setRead(comment: Comment): void {
-      // @ts-ignore
-
-    this.commentService.toggleRead(comment).subscribe(c => {this.comment = c; this.comment.keywordsFromQuestioner = JSON.parse(c.keywordsFromQuestioner)});
-    // @ts-ignore
+    this.commentService.toggleRead(comment).subscribe(c => {
+      this.comment = c;
+      this.checkProfanity();
+    });
   }
 
   markCorrect(comment: Comment, type: CorrectWrong): void {
@@ -140,16 +149,18 @@ export class CommentComponent implements OnInit, AfterViewInit {
       } else {
         comment.correct = type;
       }
-    // @ts-ignore
-    this.commentService.markCorrect(comment).subscribe(c => {this.comment = c; this.comment.keywordsFromQuestioner = JSON.parse(c.keywordsFromQuestioner)});
-   // @ts-ignore
+    this.commentService.markCorrect(comment).subscribe(c => {
+      this.comment = c;
+      this.checkProfanity();
+    });
   }
 
 
   setFavorite(comment: Comment): void {
-      // @ts-ignore
-    this.commentService.toggleFavorite(comment).subscribe(c => {this.comment = c; this.comment.keywordsFromQuestioner = JSON.parse(c.keywordsFromQuestioner)});
-      // @ts-ignore
+    this.commentService.toggleFavorite(comment).subscribe(c => {
+      this.comment = c;
+      this.checkProfanity();
+    });
   }
 
   voteUp(comment: Comment): void {
@@ -216,15 +227,17 @@ export class CommentComponent implements OnInit, AfterViewInit {
   }
 
   setAck(comment: Comment): void {
-    //@ts-ignore
-    this.commentService.toggleAck(comment).subscribe(c => {this.comment = c; this.comment.keywordsFromQuestioner = JSON.parse(c.keywordsFromQuestioner)});
-    //@ts-ignore
+    this.commentService.toggleAck(comment).subscribe(c => {
+      this.comment = c;
+      this.checkProfanity();
+    });
   }
 
   setBookmark(comment: Comment): void {
-    //@ts-ignore
-    this.commentService.toggleBookmark(comment).subscribe(c => {this.comment = c; this.comment.keywordsFromQuestioner = JSON.parse(c.keywordsFromQuestioner)});
-    //@ts-ignore
+    this.commentService.toggleBookmark(comment).subscribe(c => {
+      this.comment = c;
+      this.checkProfanity();
+    });
   }
 
   goToFullScreen(element: Element): void {
diff --git a/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.html b/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.html
index 9ae1ae502f68b18599444df4143b78f61c33e031..8dab567c3e7da153906678740f074605b9cb93a4 100644
--- a/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.html
+++ b/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.html
@@ -6,6 +6,7 @@
   <div fxLayoutAlign="end">
     <div fxLayout="row-reverse" fxLayoutGap="10px" class="buttons">
       <button
+        [disabled]="confirmButtonDisabled"
         *ngIf="confirmButtonClickAction !== undefined"
         type="button"
         mat-flat-button
@@ -18,6 +19,7 @@
         </mat-icon>
       </button>
       <button
+        [disabled]="cancelButtonDisabled"
         *ngIf="cancelButtonClickAction !== undefined"
         type="button"
         mat-flat-button
diff --git a/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.ts b/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.ts
index 6b4af6f658edb828d083568cfc3d33fc6786b48b..56c12bac7b2c8e2a2135e7bec99ef26213677ee7 100644
--- a/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.ts
+++ b/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.ts
@@ -16,6 +16,16 @@ export enum DialogConfirmActionButtonType {
 })
 export class DialogActionButtonsComponent implements OnInit {
 
+  /**
+   * gray out confirm button
+   */
+  @Input() confirmButtonDisabled: boolean = false
+
+  /**
+   * gray out cancel button
+   */
+  @Input() cancelButtonDisabled: boolean = false
+
   @Input() showDivider = true;
 
   /**
diff --git a/src/app/components/shared/dialog/topic-dialog-comment/topic-dialog-comment.component.ts b/src/app/components/shared/dialog/topic-dialog-comment/topic-dialog-comment.component.ts
index 0cb89b2aebbb7a1813ecdbedf859c5f1fb82d65a..2c58cb257810e1642c127b8af2f712a3d166b7fe 100644
--- a/src/app/components/shared/dialog/topic-dialog-comment/topic-dialog-comment.component.ts
+++ b/src/app/components/shared/dialog/topic-dialog-comment/topic-dialog-comment.component.ts
@@ -43,7 +43,7 @@ export class TopicDialogCommentComponent implements OnInit {
   }
 
   ngOnInit(): void {
-    this.questionWithoutProfanity = this.topicCloudAdminService.filterProfanityWords(this.question);
+    this.questionWithoutProfanity = this.topicCloudAdminService.filterProfanityWords(this.question, true, false);
     this.partsWithoutProfanity = this.splitQuestion(this.questionWithoutProfanity);
     this.parts = this.splitQuestion(this.question);
     this.partsWithoutProfanityShort = this.splitShortQuestion(this.questionWithoutProfanity);
diff --git a/src/app/components/shared/footer/footer.component.html b/src/app/components/shared/footer/footer.component.html
index dd8f018bdbd26b6e04430044ba0739cc74a0eac5..07c4ac5f8a91a7d2a7a01bf5385d8ca3e1a46e55 100644
--- a/src/app/components/shared/footer/footer.component.html
+++ b/src/app/components/shared/footer/footer.component.html
@@ -27,6 +27,7 @@
 
     <span class="fill-remaining-space"></span>
     <button [matMenuTriggerFor]="langMenu"
+            (menuOpened)="openMenu()"
             aria-labelledby="language-label"
             class="focus_button"
             id="language-menu"
diff --git a/src/app/components/shared/footer/footer.component.ts b/src/app/components/shared/footer/footer.component.ts
index 2af9c97542e300c39ccd7da357725bd7790811b2..6cba039d5c54209b096782eb9ae1d556d9de4149 100644
--- a/src/app/components/shared/footer/footer.component.ts
+++ b/src/app/components/shared/footer/footer.component.ts
@@ -1,5 +1,5 @@
-import { LanguageService } from './../../../services/util/language.service';
-import { Component, OnInit } from '@angular/core';
+import { LanguageService } from '../../../services/util/language.service';
+import { Component, OnInit, ViewChild } from '@angular/core';
 import { NotificationService } from '../../../services/util/notification.service';
 import { Router } from '@angular/router';
 import { MatDialog } from '@angular/material/dialog';
@@ -18,6 +18,7 @@ import { AppComponent } from '../../../app.component';
 import { StyleService } from '../../../../../projects/ars/src/lib/style/style.service';
 import { MotdService } from '../../../services/http/motd.service';
 import { MotdDialogComponent } from '../_dialogs/motd-dialog/motd-dialog.component';
+import { MatMenu } from '@angular/material/menu';
 
 @Component({
   selector: 'app-footer',
@@ -26,6 +27,8 @@ import { MotdDialogComponent } from '../_dialogs/motd-dialog/motd-dialog.compone
 })
 export class FooterComponent implements OnInit {
 
+  @ViewChild('langMenu') langaugeMenu: MatMenu;
+
   public demoId = 'Feedback';
 
   public room: Room;
@@ -177,4 +180,12 @@ export class FooterComponent implements OnInit {
   getLanguage(): string {
     return localStorage.getItem('currentLang');
   }
+
+  openMenu() {
+    if (this.getLanguage() === 'de') {
+      this.langaugeMenu._allItems.get(0).focus();
+    } else if (this.getLanguage() === 'en') {
+      this.langaugeMenu._allItems.get(1).focus();
+    }
+  }
 }
diff --git a/src/app/components/shared/header/header.component.html b/src/app/components/shared/header/header.component.html
index a896aa9a99812982272d9f0fc0dcb56886ecd897..6477bdd39727ee736b92541bd617f028eb6f371c 100644
--- a/src/app/components/shared/header/header.component.html
+++ b/src/app/components/shared/header/header.component.html
@@ -17,7 +17,7 @@
     </h2>
 
 
-    <ng-container *ngIf="room && room.closed && !router.url.includes('/room-list/')">
+    <ng-container *ngIf="room && room.questionsBlocked">
       <mat-icon>block</mat-icon><h1>{{'header.questions-blocked'|translate}}</h1>
     </ng-container>
 
@@ -125,7 +125,7 @@
           <ng-container *ngIf="router.url.endsWith('/comments')">
 
             <button mat-menu-item
-                    *ngIf="user && !router.url.endsWith('moderator/comments') && ((user.role > 0) || ((user.role == 0) && room && !room.closed))"
+                    *ngIf="user && !router.url.endsWith('moderator/comments') && ((user.role > 0) || ((user.role == 0) && room && !room.questionsBlocked))"
                     tabindex="0"
                     (click)="navigateCreateQuestion();">
               <mat-icon>
@@ -360,13 +360,14 @@
         <span>{{'header.delete-account' | translate}}</span>
       </button>
 
-      <ng-container *ngIf="router.url.includes('/creator') || router.url.includes('/moderator')">
+      <ng-container *ngIf="room && user && user.role > 0">
         <button mat-menu-item
                 (click)="blockQuestions()"
-                [ngClass]="{'color-warn': room && room.closed}"
+                [ngClass]="{'color-warn': room && room.questionsBlocked}"
                 tabindex="0">
           <mat-icon class="color-warn">block</mat-icon>
-          <span>{{'header.block' | translate}}</span>
+          <span *ngIf="!room.questionsBlocked">{{'header.block' | translate}}</span> 
+          <span *ngIf="room.questionsBlocked">{{'header.unlock' | translate}}</span> 
         </button>
       </ng-container>
 
diff --git a/src/app/components/shared/header/header.component.scss b/src/app/components/shared/header/header.component.scss
index 616d47238794e9ec610e9b7c3ccd752ebbe45acd..55b29273bbecdddcf6958e64f45ade386b888495 100644
--- a/src/app/components/shared/header/header.component.scss
+++ b/src/app/components/shared/header/header.component.scss
@@ -122,7 +122,27 @@ svg {
   * {
     background-color: transparent !important;
   }
+  *:hover {
+    color: var(--dialog);
+    background-color: var(--on-dialog) !important;
+
+    mat-icon{
+      color: var(--dialog);
+      background-color: var(--on-dialog) !important;
+    }
+  }
+
 }
-h1{
+h1 {
   color: red;
 }
+::ng-deep .mat-menu-item:hover .qrcode svg > path {
+  fill: var(--dialog);
+  color: var(--dialog);
+  background-color: var(--on-dialog) !important;
+}
+  
+::ng-deep #cdk-overlay-0 .mat-menu-content > button:hover mat-icon {
+  color: var(--dialog);
+  background-color: var(--on-dialog) !important;
+}
diff --git a/src/app/components/shared/header/header.component.ts b/src/app/components/shared/header/header.component.ts
index 41b092c9a233358cdd7e6fb7f96b373f465be5c2..55a70f0b2d9b054854dcb4199885cccd043da212 100644
--- a/src/app/components/shared/header/header.component.ts
+++ b/src/app/components/shared/header/header.component.ts
@@ -25,6 +25,7 @@ import { RoomService } from '../../../services/http/room.service';
 import { Room } from '../../../models/room';
 import { TagCloudMetaData } from '../../../services/util/tag-cloud-data.service';
 import { WorkerDialogComponent } from '../_dialogs/worker-dialog/worker-dialog.component';
+import { WsRoomService } from '../../../services/websockets/ws-room.service';
 
 @Component({
   selector: 'app-header',
@@ -43,6 +44,7 @@ export class HeaderComponent implements OnInit {
   commentsCountQuestions = 0;
   commentsCountUsers = 0;
   commentsCountKeywords = 0;
+  private _subscriptionRoomService = null;
 
   constructor(public location: Location,
               private authenticationService: AuthenticationService,
@@ -56,7 +58,8 @@ export class HeaderComponent implements OnInit {
               private _r: Renderer2,
               private motdService: MotdService,
               private confirmDialog: MatDialog,
-              private roomService: RoomService
+              private roomService: RoomService,
+              private wsRoomService: WsRoomService
   ) {
   }
 
@@ -118,12 +121,25 @@ export class HeaderComponent implements OnInit {
         const segments = this.router.parseUrl(this.router.url).root.children.primary.segments;
         this.shortId = '';
         this.room = null;
+        if (this._subscriptionRoomService) {
+          this._subscriptionRoomService.unsubscribe();
+          this._subscriptionRoomService = null;
+        }
 
         if (segments && segments.length > 2) {
           if (!segments[2].path.includes('%')) {
             this.shortId = segments[2].path;
             localStorage.setItem('shortId', this.shortId);
-            this.roomService.getRoomByShortId(this.shortId).subscribe(room => this.room = room);
+            this.roomService.getRoomByShortId(this.shortId).subscribe(room => {
+              this.room = room;
+              this._subscriptionRoomService = this.wsRoomService.getRoomStream(this.room.id).subscribe(msg => {
+                const message = JSON.parse(msg.body);
+                if (message.type === 'RoomPatched') {
+                  this.room.questionsBlocked = message.payload.changes.questionsBlocked;
+                  this.moderationEnabled = message.payload.changes.moderated;
+                }
+              });
+            });
           }
         }
       }
@@ -150,6 +166,12 @@ export class HeaderComponent implements OnInit {
     });
   }
 
+  ngOnDestroy() {
+    if (this._subscriptionRoomService) {
+      this._subscriptionRoomService.unsubscribe();
+    }
+  }
+
   showMotdDialog() {
     this.motdService.requestDialog();
   }
@@ -305,7 +327,7 @@ export class HeaderComponent implements OnInit {
     const confirmDialogRef = this.confirmDialog.open(TopicCloudFilterComponent, {
       autoFocus: false
     });
-    confirmDialogRef.componentInstance.shortId = this.shortId;
+    confirmDialogRef.componentInstance.target = this.router.url + '/tagcloud';
   }
 
   public navigateTopicCloudConfig() {
@@ -319,11 +341,10 @@ export class HeaderComponent implements OnInit {
   public blockQuestions() {
     // flip state if clicked
     this.room.questionsBlocked = !this.room.questionsBlocked;
-    this.roomService.updateRoom(this.room).subscribe(r => this.room = r);
+    this.roomService.updateRoom(this.room).subscribe();
   }
 
   public startWorkerDialog() {
     WorkerDialogComponent.addWorkTask(this.dialog, this.room);
   }
-
 }
diff --git a/src/app/components/shared/room-join/room-join.component.ts b/src/app/components/shared/room-join/room-join.component.ts
index 66cf2e77a76724c2c9ee0f052e788432d13c520d..cc6a6ea8e23488cf3626cbab9095f34f5a2d9916 100644
--- a/src/app/components/shared/room-join/room-join.component.ts
+++ b/src/app/components/shared/room-join/room-join.component.ts
@@ -74,7 +74,7 @@ export class RoomJoinComponent implements OnInit {
   joinRoom(id: string): void {
     if (!this.sessionCodeFormControl.hasError('required') && !this.sessionCodeFormControl.hasError('minlength')) {
       if (!this.user) {
-        this.authenticationService.guestLogin(UserRole.CREATOR).subscribe(() => {
+        this.authenticationService.guestLogin(UserRole.PARTICIPANT).subscribe(() => {
           this.getRoom(id);
         });
       } else {
@@ -93,6 +93,7 @@ export class RoomJoinComponent implements OnInit {
 
   addAndNavigate() {
     if (this.user.id === this.room.ownerId) {
+      this.authenticationService.setAccess(this.room.shortId, UserRole.CREATOR);
       this.router.navigate([`/creator/room/${this.room.shortId}/comments`]);
     } else {
       this.roomService.addToHistory(this.room.id);
diff --git a/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.html b/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.html
index c79c3e2823960818fdf21898ae076a1f2ad97e60..77632d2beca37497f11686c5500481ebd61944b5 100644
--- a/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.html
+++ b/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.html
@@ -42,7 +42,7 @@
         </p>
       </span>
     </div>
-    <div class="replacementContainer" *ngIf="checkLanguage && user && user.role >= 1">
+    <div class="replacementContainer" *ngIf="user && user.role >= 1">
       <mat-form-field>
         <mat-label>{{'tag-cloud-popup.tag-correction-placeholder' | translate}}</mat-label>
         <input type="text"
diff --git a/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.ts b/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.ts
index 0c25bfda2a286c6c3f77110629964be649708243..0ad09a4ccbc6945c625d236e41cbc45e3138b552 100644
--- a/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.ts
+++ b/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.ts
@@ -10,6 +10,7 @@ import { TSMap } from 'typescript-map';
 import { CommentService } from '../../../../services/http/comment.service';
 import { NotificationService } from '../../../../services/util/notification.service';
 import { MatAutocompleteTrigger } from '@angular/material/autocomplete';
+import { UserRole } from '../../../../models/user-roles.enum';
 
 const CLOSE_TIME = 1500;
 
@@ -30,7 +31,6 @@ export class TagCloudPopUpComponent implements OnInit, AfterViewInit {
   user: User;
   selectedLang: Language = 'en-US';
   spellingData: string[] = [];
-  checkLanguage = false;
   private _popupHoverTimer: number;
   private _popupCloseTimer: number;
   private _hasLeft = true;
@@ -77,10 +77,9 @@ export class TagCloudPopUpComponent implements OnInit, AfterViewInit {
     this.close();
   }
 
-  enter(elem: HTMLElement, tag: string, tagData: TagCloudDataTagEntry, hoverDelayInMs: number, checkLanguage: boolean): void {
-    this.checkLanguage = checkLanguage;
-    if (checkLanguage) {
-      this.spellingData = [];
+  enter(elem: HTMLElement, tag: string, tagData: TagCloudDataTagEntry, hoverDelayInMs: number): void {
+    this.spellingData = [];
+    if (this.user && this.user.role > UserRole.PARTICIPANT) {
       this.languagetoolService.checkSpellings(tag, 'auto').subscribe(correction => {
         const langKey = correction.language.code.split('-')[0].toUpperCase();
         if (['DE', 'FR', 'EN'].indexOf(langKey) < 0) {
diff --git a/src/app/components/shared/tag-cloud/tag-cloud.component.ts b/src/app/components/shared/tag-cloud/tag-cloud.component.ts
index bab62dd88ddd19b532fa6c658533e8be84bf4270..a75007d8a8441e15adf7706319dc7b1224505971 100644
--- a/src/app/components/shared/tag-cloud/tag-cloud.component.ts
+++ b/src/app/components/shared/tag-cloud/tag-cloud.component.ts
@@ -1,4 +1,4 @@
-import { AfterContentInit, Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
+import { AfterContentInit, AfterViewInit, Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
 
 import {
   CloudData,
@@ -111,16 +111,16 @@ const getResolvedDefaultColors = (): string[] => {
 const getDefaultCloudParameters = (): CloudParameters => {
   const resDefaultColors = getResolvedDefaultColors();
   const weightSettings: CloudWeightSettings = [
-    {maxVisibleElements: -1, color: resDefaultColors[1], rotation: 0},
-    {maxVisibleElements: -1, color: resDefaultColors[2], rotation: 0},
-    {maxVisibleElements: -1, color: resDefaultColors[3], rotation: 0},
-    {maxVisibleElements: -1, color: resDefaultColors[4], rotation: 0},
-    {maxVisibleElements: -1, color: resDefaultColors[5], rotation: 0},
-    {maxVisibleElements: -1, color: resDefaultColors[6], rotation: 0},
-    {maxVisibleElements: -1, color: resDefaultColors[7], rotation: 0},
-    {maxVisibleElements: -1, color: resDefaultColors[8], rotation: 0},
-    {maxVisibleElements: -1, color: resDefaultColors[9], rotation: 0},
-    {maxVisibleElements: -1, color: resDefaultColors[10], rotation: 0},
+    {maxVisibleElements: 5, color: resDefaultColors[1], rotation: 0},
+    {maxVisibleElements: 6, color: resDefaultColors[2], rotation: 0},
+    {maxVisibleElements: 5, color: resDefaultColors[3], rotation: 0},
+    {maxVisibleElements: 6, color: resDefaultColors[4], rotation: 0},
+    {maxVisibleElements: 5, color: resDefaultColors[5], rotation: 0},
+    {maxVisibleElements: 6, color: resDefaultColors[6], rotation: 0},
+    {maxVisibleElements: 5, color: resDefaultColors[7], rotation: 0},
+    {maxVisibleElements: 6, color: resDefaultColors[8], rotation: 0},
+    {maxVisibleElements: 5, color: resDefaultColors[9], rotation: 0},
+    {maxVisibleElements: 6, color: resDefaultColors[10], rotation: 0},
   ];
   return {
     fontFamily: 'Dancing Script',
@@ -136,7 +136,6 @@ const getDefaultCloudParameters = (): CloudParameters => {
     hoverDelay: 0.4,
     delayWord: 0,
     randomAngles: true,
-    checkSpelling: true,
     sortAlphabetically: false,
     textTransform: CloudTextStyle.normal,
     cloudWeightSettings: weightSettings
@@ -148,7 +147,7 @@ const getDefaultCloudParameters = (): CloudParameters => {
   templateUrl: './tag-cloud.component.html',
   styleUrls: ['./tag-cloud.component.scss']
 })
-export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit {
+export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit, AfterViewInit {
 
   @ViewChild(TCloudComponent, {static: false}) child: TCloudComponent;
   @ViewChild(TagCloudPopUpComponent) popup: TagCloudPopUpComponent;
@@ -228,7 +227,6 @@ export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit {
         this._createCommentWrapper.openCreateDialog(this.user);
       } else if (e === 'topicCloudConfig') {
         this.configurationOpen = !this.configurationOpen;
-        this.dataManager.demoActive = !this.dataManager.demoActive;
       } else if (e === 'topicCloudAdministration') {
         this.dialog.open(TopicCloudAdministrationComponent, {
           minWidth: '50%',
@@ -253,6 +251,7 @@ export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit {
     this.userRole = this.route.snapshot.data.roles[0];
     this.route.params.subscribe(params => {
       this.shortId = params['shortId'];
+      this.authenticationService.checkAccess(this.shortId);
       this.authenticationService.guestLogin(UserRole.PARTICIPANT).subscribe(r => {
         this.roomService.getRoomByShortId(this.shortId).subscribe(room => {
           this.room = room;
@@ -285,6 +284,10 @@ export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit {
     this.setCloudParameters(TagCloudComponent.getCurrentCloudParameters(), false);
   }
 
+  ngAfterViewInit() {
+    this.rebuildData();
+  }
+
   ngOnDestroy() {
     document.getElementById('footer_rescale').style.display = 'block';
     this.headerInterface.unsubscribe();
@@ -329,6 +332,9 @@ export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit {
   }
 
   rebuildData() {
+    if (!this.child || !this.dataManager.currentData) {
+      return;
+    }
     const newElements = [];
     const data = this.dataManager.currentData;
     const countFiler = [];
@@ -432,8 +438,7 @@ export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit {
       });
       elem.addEventListener('mouseenter', () => {
         this.popup.enter(elem, dataElement.text, dataElement.tagData,
-          (this._currentSettings.hoverTime + this._currentSettings.hoverDelay) * 1_000,
-          this._currentSettings.checkSpelling);
+          (this._currentSettings.hoverTime + this._currentSettings.hoverDelay) * 1_000);
       });
     });
   }
@@ -470,7 +475,7 @@ export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit {
         'font-size: ' + (this._currentSettings.fontSizeMin + fontRange * i).toFixed(0) + '%; }');
     }
     customTagCloudStyles.sheet.insertRule('.spacyTagCloud > span:hover, .spacyTagCloud > span:hover > a { ' +
-      'color: ' + this._currentSettings.fontColor + '; ' +
+      'color: ' + this._currentSettings.fontColor + ' !important; ' +
       'background-color: ' + this._currentSettings.backgroundColor + '; }');
     customTagCloudStyles.sheet.insertRule('.spacyTagCloudContainer { ' +
       'background-color: ' + this._currentSettings.backgroundColor + '; }');
diff --git a/src/app/components/shared/tag-cloud/tag-cloud.interface.ts b/src/app/components/shared/tag-cloud/tag-cloud.interface.ts
index b6f0edf187bf9b80fc536327d88e54c876e8b7c5..240eb3b0b6eade4a3b802b0b482c091fec322e10 100644
--- a/src/app/components/shared/tag-cloud/tag-cloud.interface.ts
+++ b/src/app/components/shared/tag-cloud/tag-cloud.interface.ts
@@ -94,10 +94,6 @@ export interface CloudParameters {
    * Sorts the cloud alphabetical.
    */
   sortAlphabetically: boolean;
-  /**
-   * Checks if the word is spelled correctly, if not, do not display it.
-   */
-  checkSpelling: boolean;
   /**
    * Custom CSS text transform setting
    */
diff --git a/src/app/models/comment.ts b/src/app/models/comment.ts
index 31f2711c1bb7d74934ca8e55802fd4aee2fdca20..8de26629ffa7d82ce9c47e34634dbe0b82b87de7 100644
--- a/src/app/models/comment.ts
+++ b/src/app/models/comment.ts
@@ -1,4 +1,4 @@
-import { dashCaseToCamelCase } from '@angular/compiler/src/util';
+import { Model } from '../services/http/spacy.service';
 import { CorrectWrong } from './correct-wrong.enum';
 
 export class Comment {
@@ -24,6 +24,7 @@ export class Comment {
   keywordsFromSpacy: string[];
   upvotes: number;
   downvotes: number;
+  language: Language;
 
   constructor(roomId: string = '',
               creatorId: string = '',
@@ -43,7 +44,8 @@ export class Comment {
               keywordsFromQuestioner: string[] = [],
               keywordsFromSpacy: string[] = [],
               upvotes = 0,
-              downvotes = 0) {
+              downvotes = 0,
+              language = Language.auto) {
     this.id = '';
     this.roomId = roomId;
     this.creatorId = creatorId;
@@ -65,5 +67,22 @@ export class Comment {
     this.keywordsFromSpacy = keywordsFromSpacy;
     this.upvotes = upvotes;
     this.downvotes = downvotes;
+    this.language = language;
+  }
+
+  static mapModelToLanguage(model: Model): Language {
+    return Language[model] || Language.auto;
   }
 }
+
+export enum Language {
+  de = 'DE',
+  en = 'EN',
+  fr = 'FR',
+  es = 'ES',
+  it = 'IT',
+  nl = 'NL',
+  pt = 'PT',
+  auto = 'AUTO'
+}
+
diff --git a/src/app/models/room.ts b/src/app/models/room.ts
index 6fff1025597c7b25ecf6da819201dc982f863d8d..abd4a42965183ac5dcf0adc0381067e857996cd1 100644
--- a/src/app/models/room.ts
+++ b/src/app/models/room.ts
@@ -1,5 +1,3 @@
-import { TSMap } from 'typescript-map';
-
 export class Room {
   id: string;
   revision: string;
@@ -15,7 +13,7 @@ export class Room {
   threshold: number;
   tags: string[];
   questionsBlocked: boolean;
-  profanityFilter: boolean;
+  profanityFilter: ProfanityFilter;
 
   constructor(
     ownerId: string = '',
@@ -30,7 +28,7 @@ export class Room {
     threshold: number = null,
     tags: string[] = [],
     questionsBlocked: boolean = false,
-    profanityFilter: boolean = true
+    profanityFilter: ProfanityFilter = ProfanityFilter.none
   ) {
     this.id = '';
     this.ownerId = ownerId;
@@ -48,3 +46,11 @@ export class Room {
     this.profanityFilter = profanityFilter;
   }
 }
+
+export enum ProfanityFilter {
+  all = 'ALL',
+  languageSpecific = 'LANGUAGE_SPECIFIC',
+  partialWords = 'PARTIAL_WORDS',
+  none = 'NONE',
+  deactivated = 'DEACTIVATED'
+}
diff --git a/src/app/services/http/comment.service.ts b/src/app/services/http/comment.service.ts
index 835a6ca0e5063f0eb97e07ed581c225a12d21c96..b92ecdd14da0249c69d83df9e6fd5cc067227104 100644
--- a/src/app/services/http/comment.service.ts
+++ b/src/app/services/http/comment.service.ts
@@ -86,7 +86,8 @@ export class CommentService extends BaseHttpService {
         roomId: comment.roomId, body: comment.body,
         read: comment.read, creationTimestamp: comment.timestamp, tag: comment.tag,
         keywordsFromSpacy: JSON.stringify(comment.keywordsFromSpacy),
-        keywordsFromQuestioner: JSON.stringify(comment.keywordsFromQuestioner)
+        keywordsFromQuestioner: JSON.stringify(comment.keywordsFromQuestioner),
+        language: comment.language
       }, httpOptions).pipe(
       tap(_ => ''),
       catchError(this.handleError<Comment>('addComment'))
@@ -152,6 +153,7 @@ export class CommentService extends BaseHttpService {
   patchComment(comment: Comment, changes: TSMap<string, any>) {
     const connectionUrl = this.apiUrl.base + this.apiUrl.comment + '/' + comment.id;
     return this.http.patch(connectionUrl, changes, httpOptions).pipe(
+      map(c => this.parseComment(c as Comment)),
       tap(_ => ''),
       catchError(this.handleError<any>('patchComment'))
     );
@@ -222,8 +224,10 @@ export class CommentService extends BaseHttpService {
 
 
   parseComment(comment: Comment): Comment {
+    if (!comment){
+      return;
+    }
     comment.userNumber = this.hashCode(comment.creatorId);
-    // make list out of string "array"
     comment.keywordsFromQuestioner = comment.keywordsFromQuestioner ?
                                      JSON.parse(comment.keywordsFromQuestioner as unknown as string) : null;
     comment.keywordsFromSpacy = comment.keywordsFromSpacy ? JSON.parse(comment.keywordsFromSpacy as unknown as string) : null;
diff --git a/src/app/services/http/languagetool.service.ts b/src/app/services/http/languagetool.service.ts
index 0305c581109d8a7b1c70634c1919a35ab810854a..5a3fea983bf29a2df95b61759ce242d2f868a177 100644
--- a/src/app/services/http/languagetool.service.ts
+++ b/src/app/services/http/languagetool.service.ts
@@ -5,7 +5,14 @@ import { catchError } from 'rxjs/operators';
 import { Model } from './spacy.service';
 import { Observable } from 'rxjs';
 
-export type Language = 'de-DE' | 'en-US' | 'fr' | 'auto';
+export type Language =  'de' | 'de-AT' | 'de-CH' | 'de-DE' |
+                        'en' | 'en-AU' | 'en-CA' | 'en-GB' | 'en-US' |
+                        'fr' |
+                        'es' |
+                        'it' |
+                        'nl' | 'nl-BE' |
+                        'pt' | 'pt-BR' | 'pt-PT' |
+                        'auto';
 
 export interface LanguagetoolResult {
   software: {
@@ -75,17 +82,40 @@ export class LanguagetoolService extends BaseHttpService {
 
   mapLanguageToSpacyModel(language: Language): Model {
     switch (language) {
+      case 'de':
+      case 'de-AT':
+      case 'de-CH':
       case 'de-DE':
         return 'de';
+      case 'en':
+      case 'en-AU':
+      case 'en-CA':
+      case 'en-GB':
       case 'en-US':
         return 'en';
+      case 'es':
+        return 'es';
       case 'fr':
-        return 'fr';
+          return 'fr';
+      case 'it':
+        return 'it';
+      case 'nl':
+      case 'nl-BE':
+        return 'nl';
+      case 'pt':
+      case 'pt-BR':
+      case 'pt-PT':
+        return 'pt';
       default:
         return 'auto';
     }
   }
 
+  isSupportedLanguage(language: Language) {
+    const supportedLanguages: Model[] = ['de', 'en', 'fr'];
+    return supportedLanguages.includes(this.mapLanguageToSpacyModel(language));
+  }
+
   checkSpellings(text: string, language: Language): Observable<LanguagetoolResult> {
     const url = '/languagetool';
     return this.http.get<LanguagetoolResult>(url, {
diff --git a/src/app/services/http/room.service.ts b/src/app/services/http/room.service.ts
index 9dcf954d9f142b1a368ce86090c362a625386d56..d6069923f54f827d312ab00661298510fea2caaa 100644
--- a/src/app/services/http/room.service.ts
+++ b/src/app/services/http/room.service.ts
@@ -1,15 +1,12 @@
 import { Injectable } from '@angular/core';
 import { Room } from '../../models/room';
-import { RoomJoined } from '../../models/events/room-joined';
-import { RoomCreated } from '../../models/events/room-created';
 import { UserRole } from '../../models/user-roles.enum';
 import { HttpClient, HttpHeaders } from '@angular/common/http';
 import { Observable } from 'rxjs';
-import { catchError, tap, map } from 'rxjs/operators';
+import { catchError, tap } from 'rxjs/operators';
 import { AuthenticationService } from './authentication.service';
 import { BaseHttpService } from './base-http.service';
 import { EventService } from '../util/event.service';
-import { TSMap } from 'typescript-map';
 
 const httpOptions = {
   headers: new HttpHeaders({})
@@ -110,7 +107,7 @@ export class RoomService extends BaseHttpService {
 
   addToHistory(roomId: string): void {
     const connectionUrl = `${ this.apiUrl.base + this.apiUrl.user }/${ this.authService.getUser().id }/roomHistory`;
-    this.http.post(connectionUrl, { roomId: roomId, lastVisit: this.joinDate.getTime() }, httpOptions).subscribe(() => {});
+    this.http.post(connectionUrl, { roomId, lastVisit: this.joinDate.getTime() }, httpOptions).subscribe();
   }
 
   removeFromHistory(roomId: string): Observable<Room> {
@@ -138,9 +135,6 @@ export class RoomService extends BaseHttpService {
   }
 
   setRoomId(room: Room): void {
-    // temp solution until the backend is updated
-    room.profanityFilter = localStorage.getItem('room-profanity-filter') !== 'false' ||
-                           !localStorage.getItem('room-profanity-filter') ? true : false;
     localStorage.setItem('roomId', room.id);
   }
 }
diff --git a/src/app/services/util/room-data.service.ts b/src/app/services/util/room-data.service.ts
index c7a52edb33ffe593c6578021ba112e54e47f3946..8314763856c1437fdbd67da408c87daa27a81d99 100644
--- a/src/app/services/util/room-data.service.ts
+++ b/src/app/services/util/room-data.service.ts
@@ -7,6 +7,8 @@ import { CommentService } from '../http/comment.service';
 import { CorrectWrong } from '../../models/correct-wrong.enum';
 import { RoomService } from '../http/room.service';
 import { TopicCloudAdminService } from './topic-cloud-admin.service';
+import { ProfanityFilter, Room } from '../../models/room';
+import { WsRoomService } from '../websockets/ws-room.service';
 
 export interface UpdateInformation {
   type: 'CommentCreated' | 'CommentPatched' | 'CommentHighlighted' | 'CommentDeleted';
@@ -92,11 +94,13 @@ export class RoomDataService {
   private _currentRoomId: string = null;
   private _savedCommentsBeforeFilter = new Map();
   private _savedCommentsAfterFilter = new Map();
+  private room: Room;
 
   constructor(private wsCommentService: WsCommentService,
               private commentService: CommentService,
               private roomService: RoomService,
-              private topicCloudAdminService: TopicCloudAdminService) {
+              private topicCloudAdminService: TopicCloudAdminService,
+              private wsRoomService: WsRoomService) {
   }
 
   get currentRoomData() {
@@ -115,7 +119,6 @@ export class RoomDataService {
 
   getRoomData(roomId: string, freezed: boolean = false): Observable<Comment[]> {
     if (roomId && roomId === this._currentRoomId) {
-      this.checkProfanity();
       return of(freezed ? [...this._currentComments] : this._currentComments);
     }
     const tempSubject = new Subject<Comment[]>();
@@ -127,23 +130,50 @@ export class RoomDataService {
     return tempSubject.asObservable();
   }
 
-  private checkProfanity() {
-    this.roomService.getRoom(localStorage.getItem('roomId')).subscribe(room => {
-      if (room.profanityFilter) {
-        this._currentComments.forEach(comment => {
-          comment.body = this._savedCommentsAfterFilter.get(comment.id);
-        });
+  public checkProfanity(comment: Comment) {
+    const finish = new Subject<boolean>();
+    const subscription = finish.asObservable().subscribe(_ => {
+      if (this.room.profanityFilter !== ProfanityFilter.deactivated) {
+        comment.body = this._savedCommentsAfterFilter.get(comment.id);
       } else {
-        this._currentComments.forEach(comment => {
-          comment.body = this._savedCommentsBeforeFilter.get(comment.id);
-        });
+        comment.body = this._savedCommentsBeforeFilter.get(comment.id);
       }
+      subscription.unsubscribe();
     });
+
+    if (!this._savedCommentsAfterFilter.get(comment.id) || !this.room) {
+      if (!this.room) {
+        this.roomService.getRoom(localStorage.getItem('roomId')).subscribe(room => {
+          this.room = room;
+          this.setCommentBody(comment);
+          finish.next(true);
+        });
+      } else {
+        this.setCommentBody(comment);
+        finish.next(true);
+      }
+    } else {
+      finish.next(true);
+    }
   }
 
-  private setCommentBodies(comment: Comment) {
+  private setCommentBody(comment: Comment) {
     this._savedCommentsBeforeFilter.set(comment.id, comment.body);
-    this._savedCommentsAfterFilter.set(comment.id, this.topicCloudAdminService.filterProfanityWords(comment.body));
+    this._savedCommentsAfterFilter.set(comment.id, this.filterCommentOfProfanity(this.room, comment));
+  }
+
+  private filterAllCommentsBodies() {
+    this._currentComments.forEach(comment => {
+      comment.body = this._savedCommentsBeforeFilter.get(comment.id);
+      this.setCommentBody(comment);
+      this.checkProfanity(comment);
+    });
+  }
+
+  private filterCommentOfProfanity(room: Room, comment: Comment): string {
+    const partialWords = room.profanityFilter === ProfanityFilter.all || room.profanityFilter === ProfanityFilter.partialWords;
+    const languageSpecific = room.profanityFilter === ProfanityFilter.all || room.profanityFilter === ProfanityFilter.languageSpecific;
+    return this.topicCloudAdminService.filterProfanityWords(comment.body, partialWords, languageSpecific, comment.language);
   }
 
   private removeCommentBodies(key: string) {
@@ -162,22 +192,29 @@ export class RoomDataService {
     if (this._wsCommentServiceSubscription) {
       this._wsCommentServiceSubscription.unsubscribe();
     }
-    this._wsCommentServiceSubscription = this.wsCommentService.getCommentStream(roomId)
-      .subscribe(msg => this.onMessageReceive(msg));
-    this.commentService.getAckComments(roomId).subscribe(comments => {
-      this._currentComments = comments;
-      for (const comment of comments) {
-        this.setCommentBodies(comment);
-        this._fastCommentAccess[comment.id] = comment;
+    this.roomService.getRoom(roomId).subscribe(room => {
+      this.room = room;
+      this._wsCommentServiceSubscription = this.wsCommentService.getCommentStream(roomId)
+        .subscribe(msg => this.onMessageReceive(msg));
+      this.commentService.getAckComments(roomId).subscribe(comments => {
+        this._currentComments = comments;
+        for (const comment of comments) {
+          this.setCommentBody(comment);
+          this._fastCommentAccess[comment.id] = comment;
+        }
+        this.triggerUpdate(UpdateType.force, null);
+      });
+    });
+    this.wsRoomService.getRoomStream(roomId).subscribe(msg => {
+      const message = JSON.parse(msg.body);
+      if (message.type === 'RoomPatched') {
+        this.room = message.payload.changes;
+        this.filterAllCommentsBodies();
       }
-      this.triggerUpdate(UpdateType.force, null);
     });
   }
 
   private triggerUpdate(type: UpdateType, additionalInformation: UpdateInformation) {
-    if ((additionalInformation && additionalInformation.type === 'CommentCreated') || !additionalInformation) {
-      this.checkProfanity();
-    }
     if (type === UpdateType.force) {
       this._commentUpdates.next(this._currentComments);
     } else if (type === UpdateType.commentStream) {
@@ -215,19 +252,23 @@ export class RoomDataService {
     c.tag = payload.tag;
     c.creatorId = payload.creatorId;
     c.userNumber = this.commentService.hashCode(c.creatorId);
+    c.keywordsFromQuestioner = JSON.parse(payload.keywordsFromQuestioner);
+    this._fastCommentAccess[c.id] = c;
+    this._currentComments.push(c);
     this.triggerUpdate(UpdateType.commentStream, {
       type: 'CommentCreated',
       finished: false,
       comment: c
     });
     this.commentService.getComment(c.id).subscribe(comment => {
-      this._fastCommentAccess[comment.id] = comment;
-      this._currentComments.push(comment);
-      this.setCommentBodies(comment);
+      for (const key of Object.keys(comment)) {
+        c[key] = comment[key];
+      }
+      this.setCommentBody(c);
       this.triggerUpdate(UpdateType.commentStream, {
         type: 'CommentCreated',
         finished: true,
-        comment
+        comment: c
       });
     });
   }
diff --git a/src/app/services/util/tag-cloud-data.service.ts b/src/app/services/util/tag-cloud-data.service.ts
index 176e496094b830ff131ea951bdd97faeb96ac83a..07fb647467c658e3ed2dc3dbec70508a26c8e83a 100644
--- a/src/app/services/util/tag-cloud-data.service.ts
+++ b/src/app/services/util/tag-cloud-data.service.ts
@@ -272,11 +272,6 @@ export class TagCloudDataService {
   private fetchData(): void {
     this._roomDataService.getRoomData(this._roomId).subscribe((comments: Comment[]) => {
       this._lastFetchedComments = comments;
-      if (this._isDemoActive) {
-        this._lastMetaData.commentCount = comments.length;
-      } else {
-        this._currentMetaData.commentCount = comments.length;
-      }
       this.rebuildTagData();
     });
   }
@@ -300,6 +295,7 @@ export class TagCloudDataService {
     const data: TagCloudData = new Map<string, TagCloudDataTagEntry>();
     const users = new Set<number>();
     const filteredComments = this._lastFetchedComments.filter(comment => this._currentFilter.checkComment(comment));
+    currentMeta.commentCount = filteredComments.length;
     for (const comment of filteredComments) {
       let keywords = comment.keywordsFromQuestioner;
       if (this._supplyType === TagCloudDataSupplyType.keywordsAndFullText) {
diff --git a/src/app/services/util/topic-cloud-admin.service.ts b/src/app/services/util/topic-cloud-admin.service.ts
index bc650ebd272310cc23e670f7429f0cafe3684c16..3652ccb577f00977a3e274877eb0f36ab40e821b 100644
--- a/src/app/services/util/topic-cloud-admin.service.ts
+++ b/src/app/services/util/topic-cloud-admin.service.ts
@@ -46,10 +46,10 @@ export class TopicCloudAdminService {
           de: this.getDefaultSpacyTagsDE(),
           en: this.getDefaultSpacyTagsEN()
         },
-        considerVotes: false,
+        considerVotes: true,
         profanityFilter: true,
         blacklistIsActive: true,
-        keywordORfulltext: KeywordOrFulltext.keyword
+        keywordORfulltext: KeywordOrFulltext.both
       };
     }
     return data;
@@ -58,7 +58,9 @@ export class TopicCloudAdminService {
   static getDefaultSpacyTagsDE(): string[] {
     const tags: string[] = [];
     spacyLabels.de.forEach(label => {
-      tags.push(label.tag);
+      if (label.enabledByDefault) {
+        tags.push(label.tag);
+      }
     });
     return tags;
   }
@@ -66,7 +68,9 @@ export class TopicCloudAdminService {
   static getDefaultSpacyTagsEN(): string[] {
     const tags: string[] = [];
     spacyLabels.en.forEach(label => {
-      tags.push(label.tag);
+      if (label.enabledByDefault) {
+        tags.push(label.tag);
+      }
     });
     return tags;
   }
@@ -85,6 +89,7 @@ export class TopicCloudAdminService {
       if (_adminData.profanityFilter) {
         _adminData.blacklist = _adminData.blacklist.concat(this.getProfanityListFromStorage().concat(this.profanityWords));
       }
+      localStorage.setItem(TopicCloudAdminService.adminKey, JSON.stringify(_adminData));
       this.adminData.next(_adminData);
     });
   }
@@ -179,20 +184,21 @@ export class TopicCloudAdminService {
       });
   }
 
-  filterProfanityWords(str: string): string {
-    let questionWithProfanity = str;
-    this.profanityWords.concat(this.getProfanityListFromStorage()).map((word) => {
-      questionWithProfanity = questionWithProfanity
-        .toLowerCase()
-        .includes(word)
-        ? this.replaceString(
-          questionWithProfanity,
-          word,
-          this.generateCensoredWord(word.length)
-        )
-        : questionWithProfanity;
+  filterProfanityWords(str: string, censorPartialWordsCheck: boolean, censorLanguageSpecificCheck: boolean, lang?: string){
+    let filteredString = str;
+    let profWords = [];
+    if (censorLanguageSpecificCheck) {
+      profWords = BadWords[(lang !== 'AUTO' ? lang.toLowerCase() : 'de')];
+    } else {
+      profWords = this.profanityWords;
+    }
+    const toCensoredString = censorPartialWordsCheck ? str.toLowerCase() : str.toLowerCase().split(' ');
+    profWords.concat(this.getProfanityListFromStorage()).forEach(word => {
+      if (toCensoredString.includes(word)) {
+        filteredString = this.replaceString(filteredString, word, this.generateCensoredWord(word.length));
+      }
     });
-    return questionWithProfanity;
+    return filteredString;
   }
 
   private replaceString(str: string, search: string, replace: string) {
diff --git a/src/app/services/websockets/ws-room.service.spec.ts b/src/app/services/websockets/ws-room.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..558c8827b4c64e95bf7a11943920f1377b16369a
--- /dev/null
+++ b/src/app/services/websockets/ws-room.service.spec.ts
@@ -0,0 +1,16 @@
+/*import { TestBed } from '@angular/core/testing';
+
+import { WsRoomService } from './ws-room.service';
+
+describe('WsRoomService', () => {
+  let service: WsRoomService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(WsRoomService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});*/
diff --git a/src/app/services/websockets/ws-room.service.ts b/src/app/services/websockets/ws-room.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ac1cb6817be34200f1806c265a1f441410e97f8f
--- /dev/null
+++ b/src/app/services/websockets/ws-room.service.ts
@@ -0,0 +1,16 @@
+import { Injectable } from '@angular/core';
+import { WsConnectorService } from './ws-connector.service';
+import { Observable } from 'rxjs';
+import { IMessage } from '@stomp/stompjs';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class WsRoomService {
+
+  constructor(private wsConnector: WsConnectorService) { }
+
+  getRoomStream(roomId: string): Observable<IMessage> {
+    return this.wsConnector.getWatcher(`/topic/${roomId}.room.stream`);
+  }
+}
diff --git a/src/app/utils/create-comment-keywords.ts b/src/app/utils/create-comment-keywords.ts
index ab2994e0f537e979de194f186838ac7989838343..1e9d595b5a48fddf1b7f26a077deb39986d4bb3d 100644
--- a/src/app/utils/create-comment-keywords.ts
+++ b/src/app/utils/create-comment-keywords.ts
@@ -4,7 +4,7 @@ import { map } from 'rxjs/operators';
 export class CreateCommentKeywords {
 
   static isSpellingAcceptable(languagetoolService: LanguagetoolService, text: string, language: Language = 'auto') {
-    text = this.cleanUTFEmoji(text);
+    text = this.cleaningFunction(text);
     return languagetoolService.checkSpellings(text, language).pipe(
       map(result => {
         const wordCount = text.trim().split(' ').length;
@@ -19,9 +19,16 @@ export class CreateCommentKeywords {
     );
   }
 
-  private static cleanUTFEmoji(text: string): string {
+  static cleaningFunction(text: string): string {
     // eslint-disable-next-line max-len
-    const regex = /(?:\:.*?\:|[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])/g;
-    return text.replace(regex, '');
+    const regexEmoji    = new RegExp('\uD918\uDD28|\ufe0f|\u200D|\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff]', 'g');
+    const regexKatex    = new RegExp('\\$[^$\\n ]+\\$|\\$\\$[^$\\n ]+\\$\\$','g');
+    const regexMarkdown = new RegExp('(?:__|[*#])|\\[(.+?)]\\((.+?)\\)', 'g');
+    const regexBlank    = new RegExp('[\\s]{2,}', 'gu');
+    text = text.replace(regexKatex,'');
+    text = text.replace(regexEmoji,'');
+    text = text.replace(regexMarkdown,'');
+    text = text.replace(regexBlank, ' ');
+    return text;
   }
 }
diff --git a/src/app/utils/filter-options.ts b/src/app/utils/filter-options.ts
index 7669a7d697a59d6d442d135815612e893562e45a..9268cbcf7cdb9cfab1ba03bc72c50e772f977386 100644
--- a/src/app/utils/filter-options.ts
+++ b/src/app/utils/filter-options.ts
@@ -26,12 +26,13 @@ export class CommentFilter {
   filterSelected = '';
   keywordSelected = '';
   tagSelected = '';
+  userNumberSelected = 0;
 
   paused = false;
   timeStampUntil = 0;
 
   periodSet: Period = Period.twoWeeks;
-  timeStampNow = 0;
+  timeStampNow = 0; 
 
   constructor(obj?: any) {
     if (obj) {
@@ -42,6 +43,7 @@ export class CommentFilter {
       this.timeStampUntil = obj.timeStampUntil;
       this.periodSet = obj.periodSet;
       this.timeStampNow = obj.timeStampNow;
+      this.userNumberSelected = obj.userNumberSelected;
     }
   }
 
@@ -56,6 +58,7 @@ export class CommentFilter {
   public static generateFilterNow(filterSelected: string): CommentFilter {
     const filter = new CommentFilter();
 
+    filter.userNumberSelected = 0;
     filter.filterSelected = filterSelected;
     filter.paused = false;
 
@@ -72,6 +75,8 @@ export class CommentFilter {
                                     tagSelected: string, keywordSelected: string): CommentFilter {
     const filter = new CommentFilter();
 
+
+    filter.userNumberSelected = 0;
     filter.filterSelected = filterSelected;
 
     filter.paused = true;
@@ -154,6 +159,10 @@ export class CommentFilter {
       }
     }
 
+    if (this.userNumberSelected !== 0) {
+      return com.userNumber === this.userNumberSelected;
+    }
+
     if (this.keywordSelected !== '') {
       return com.keywordsFromQuestioner.includes(this.keywordSelected);
     }
diff --git a/src/assets/i18n/creator/de.json b/src/assets/i18n/creator/de.json
index 801beca059362d3d9a25445d6676b8cea19be405..2002c269489ebc3c0230471daf0ce991b499fc13 100644
--- a/src/assets/i18n/creator/de.json
+++ b/src/assets/i18n/creator/de.json
@@ -333,7 +333,11 @@
     "token-deleted": "Der Token wurde gelöscht.",
     "tokens-deleted": "Alle Tokens dieser Sitzung wurden gelöscht.",
     "profanity-filter": "Schimpfwörter zensieren",
-    "words-will-be-overwritten": "profane words will be overwritten with '***'"
+    "language-specific-filter": "Sprachspezifisch filtern",
+    "partial-words-filter": "Teilwörter filtern",
+    "words-will-be-overwritten": "Profane Wörter werden mit '***' überschrieben",
+    "only-specific-language-will-be-filtered": "Nur die Sprache der Frage wird gefiltert",
+    "partial-words-will-be-filtered": "Profane Teilwörter werden auch gefiltert"
   },
   "session": {
     "a11y-description": "Gib eine Beschreibung für die Sitzung ein.",
@@ -343,6 +347,70 @@
     "session-name": "Name der Sitzung",
     "preview": "Vorschau"
   },
+  "tag-cloud-popup": {
+    "few-seconds": "wenige Sekunden",
+    "few-minutes": "wenige Minuten",
+    "some-minutes": "{{minutes}} Minuten",
+    "one-hour": "1 Stunde",
+    "some-hours": "{{hours}} Stunden",
+    "one-day": "1 Tag",
+    "some-days": "{{days}} Tage",
+    "one-week": "1 Woche",
+    "some-weeks": "{{weeks}} Wochen",
+    "some-months": "{{months}} Monate",
+    "tag-correction-placeholder": "Korrektur"
+  },
+  "topic-cloud-dialog": {
+    "cancel": "Abbrechen",
+    "save": "Speichern",
+    "edit": "Bearbeiten",
+    "delete": "Löschen",
+    "question-count-singular": "Frage",
+    "question-count-plural": "Fragen",
+    "edit-keyword-tip": "Neues Thema",
+    "no-keywords-note": "Es gibt keine Themen",
+    "consider-votes": "Votes berücksichtigen",
+    "profanity": "Schimpfwörter zensieren",
+    "hide-blacklist-words": "Blacklist Stichworte verbergen",
+    "sort-alpha": "Alphabetisch",
+    "sort-count": "Fragenanzahl",
+    "sort-vote": "Votes",
+    "keyword-search": "Stichwort suchen",
+    "edit-profanity-list": "Zensurliste bearbeiten",
+    "edit-blacklist-list": "Blackliste bearbeiten",
+    "add-word": "Wort hinzufügen",
+    "enter-word": "Wort eingeben",
+    "settings": "Einstellungen",
+    "keyword": "Stichwort",
+    "full-text": "Voller Text",
+    "both": "Beide",
+    "select-choice": "Wählen Sie aus",
+    "show-blacklist": "Zeige Blackliste",
+    "hide-blacklist": "Verberge Blackliste",
+    "show-profanity-list": "Zeige Schimpfwortliste",
+    "hide-profanity-list": "Verberge Schimpfwortliste",
+    "keyword-delete": "Stichwort gelöscht",
+    "keyword-edit": "Stichwort umbenannt",
+    "keywords-merge": "Stichwörter zusammengefügt",
+    "changes-gone-wrong": "Etwas ist schiefgelaufen",
+    "english": "Englisch",
+    "german": "Deutsch",
+    "select-all": "Alle auswählen",
+    "keyword-counter": "Anzahl der Themen",
+    "sort": "Sortieren",
+    "words-will-be-overwritten": "unanständige Wörter werden mit '***' überschrieben",
+    "keyword-from-spacy": "Stichwort von spaCy",
+    "keyword-from-questioner": "Stichwort vom Fragesteller"
+  },
+  "tag-cloud": {
+    "demo-data-topic": "Thema %d",
+    "overview-question-topic-tooltip": "Anzahl gestellter Fragen mit diesem Thema",
+    "overview-questioners-topic-tooltip": "Anzahl Fragensteller*innen mit diesem Thema",
+    "period-since-first-comment":"Zeitraum seit erstem Kommentar",
+    "upvote-topic": "Upvotes für dieses Thema",
+    "downvote-topic": "Downvotes für dieses Thema",
+    "blacklist-topic": "Thema zur Blacklist hinzufügen"
+  },
   "tag-cloud-config":{
     "general":"Allgemein",
     "overflow":"Überlauf",
diff --git a/src/assets/i18n/creator/en.json b/src/assets/i18n/creator/en.json
index 9093cab6536a3a8c5d51fd546de29ce5843724db..af74d8abae3339883382be940cc9d6ff2943396e 100644
--- a/src/assets/i18n/creator/en.json
+++ b/src/assets/i18n/creator/en.json
@@ -334,7 +334,11 @@
     "token-deleted": "Token has been deleted.",
     "tokens-deleted": "All tokens of this sessions have been deleted.",
     "profanity-filter": "Censor profanity",
-    "words-will-be-overwritten": "profane words will be overwritten with '***'"
+    "language-specific-filter": "Filter language-specific",
+    "partial-words-filter": "Filter partial words",
+    "words-will-be-overwritten": "Profane words will be overwritten with '***'",
+    "only-specific-language-will-be-filtered": "Only the language of the question will be filtered",
+    "partial-words-will-be-filtered": "Profane partial words will be also filtered"
   },
   "session": {
     "a11y-description": "Enter a description of the session",
@@ -344,6 +348,70 @@
     "session-name": "Session name",
     "preview": "Preview"
   },
+  "tag-cloud": {
+    "demo-data-topic": "Topic %d",
+    "overview-question-topic-tooltip": "Number of questions with this topic",
+    "overview-questioners-topic-tooltip": "Number of questioners with this topic",
+    "period-since-first-comment":"Period since first comment",
+    "upvote-topic": "Upvotes for this topic",
+    "downvote-topic": "Downvotes for this topic",
+    "blacklist-topic": "Add topic to blacklist"
+  },
+  "tag-cloud-popup": {
+    "few-seconds": "few seconds",
+    "few-minutes": "few minutes",
+    "some-minutes": "{{minutes}} minutes",
+    "one-hour": "1 hour",
+    "some-hours": "{{hours}} hours",
+    "one-day": "1 day",
+    "some-days": "{{days}} days",
+    "one-week": "1 week",
+    "some-weeks": "{{weeks}} weeks",
+    "some-months": "{{months}} months",
+    "tag-correction-placeholder": "Correction"
+  },
+  "topic-cloud-dialog":{
+    "edit": "Edit",
+    "delete": "Delete",
+    "cancel": "Cancel",
+    "save": "Save",
+    "question-count-singular": "Question",
+    "question-count-plural": "Questions",
+    "edit-keyword-tip": "New topic",
+    "no-keywords-note": "There are no topics!",
+    "consider-votes": "Consider Votes",
+    "profanity": "Censor profanity",
+    "hide-blacklist-words": "Hide blacklist keywords",
+    "sort-alpha": "Alphabetically",
+    "sort-count": "Questions count",
+    "sort-vote": "Votes",
+    "keyword-search": "Search keyword",
+    "edit-profanity-list": "Edit profanity list",
+    "edit-blacklist-list": "Edit blacklist list",
+    "add-word": "Add Word",
+    "enter-word": "Enter word",
+    "settings": "Settings",
+    "keyword": "Keyword",
+    "full-text": "Full-text",
+    "both": "Both",
+    "select-choice": "Select one",
+    "show-blacklist": "Show blacklist",
+    "hide-blacklist": "Hide blacklist",
+    "show-profanity-list": "Show profanity list",
+    "hide-profanity-list": "Hide profanity list",
+    "keyword-delete": "keyword deleted",
+    "keyword-edit": "keyword renamed",
+    "keywords-merge": "keywords merged",
+    "changes-gone-wrong": "somthing has gone wrong",
+    "english": "English",
+    "german": "German",
+    "select-all": "Select all",
+    "keyword-counter": "Topic count",
+    "sort": "Sort",
+    "words-will-be-overwritten": "profane words will be overwritten with '***'",
+    "keyword-from-spacy": "Keyword from spaCy",
+    "keyword-from-questioner": "Keyword from questioner"
+  },
   "tag-cloud-config":{
     "general":"General",
     "overflow":"Overflow",
diff --git a/src/assets/i18n/home/de.json b/src/assets/i18n/home/de.json
index d782b388faf7b8f76627c0e577b6790301aaae44..2d60f5976339e0bc05d73ce1818cc54b90bc4bb3 100644
--- a/src/assets/i18n/home/de.json
+++ b/src/assets/i18n/home/de.json
@@ -50,9 +50,9 @@
     "cancel": "Abbrechen",
     "continue": "Weiter",
     "reset": "Zurücksetzen",
-    "continue-with-all-questions" : "Weiter mit kompletter Fragenliste",
-    "continue-with-current-questions": "Weiter mit aktuellen Filtern",
-    "continue-with-all-questions-from-now": "Weiter mit allen Fragen ab jetzt"
+    "continue-with-all-questions" : "Weiter mit allen Fragen der Sitzung",
+    "continue-with-current-questions": "Weiter mit aktueller Fragenliste",
+    "continue-with-all-questions-from-now": "Weiter mit Fragen, die ab jetzt gestellt werden"
   },
   "header": {
     "abort": "Abbrechen",
@@ -70,6 +70,7 @@
     "login": "Anmelden",
     "logout": "Abmelden",
     "block": "Fragen sperren",
+    "unlock": "Fragen entsperen",
     "moderation-enabled": "Die Sitzung wird moderiert.",
     "QR": "QR-Code der Sitzung in Vollansicht",
     "my-account": "Optionen",
@@ -320,6 +321,10 @@
     "remove-successful": "Wort entfernt"
   },
   "worker-dialog": {
-    "running": "Laufend"
+    "running": "Laufend",
+    "room-name" : "Sitzungsname",
+    "comments" : "Abgearbeitete Fragen",
+    "bad-spelled" : "Zu schlechte Rechtschreibung",
+    "failed" : "Fehler aufgetreten"
   }
 }
diff --git a/src/assets/i18n/home/en.json b/src/assets/i18n/home/en.json
index 32e8901a62828fbf6c031af10f45fced05a79211..c55219181bb5f52aaf58cfb7e80eba8cb9745fec 100644
--- a/src/assets/i18n/home/en.json
+++ b/src/assets/i18n/home/en.json
@@ -56,6 +56,7 @@
     "cancel": "Cancel",
     "delete": "Delete",
     "block" : "Block questions",
+    "unlock": "Unlock questions",
     "delete-account": "Delete account",
     "home-header": "Collect and rate questions",
     "id": "Key",
@@ -130,9 +131,9 @@
     "cancel": "Cancel",
     "continue": "Continue",
     "reset": "Reset",
-    "continue-with-all-questions" : "Continue with complete list of questions",
-    "continue-with-current-questions": "Continue with current filters",
-    "continue-with-all-questions-from-now": "Continue with all questions from now"
+    "continue-with-all-questions" : "Continue with all questions of the session",
+    "continue-with-current-questions": "Continue with current question list",
+    "continue-with-all-questions-from-now": "Continue with questions that will be asked form now on"
 
   },
   "imprint": {
@@ -324,6 +325,10 @@
     "remove-successful": "Word removed"
   },
   "worker-dialog": {
-    "running": "running"
+    "running": "Running",
+    "room-name" : "Session name",
+    "comments" : "Questions",
+    "bad-spelled" : "Spelling too bad",
+    "failed" : "Error occured"
   }
 }
diff --git a/src/assets/i18n/participant/de.json b/src/assets/i18n/participant/de.json
index 9c2bb83c7765f125058880ef5cd96d9f0473cae6..1935f49aa27566449e936f8307cf797ac6998bdc 100644
--- a/src/assets/i18n/participant/de.json
+++ b/src/assets/i18n/participant/de.json
@@ -100,7 +100,8 @@
     "edit-keyword-hint": "Stichwort editieren",
     "editing-done-hint": "Editierung abschliessen",
     "force-language-selection": "Automatische Spracherkennung unpräzise, bitte gewählte Sprache prüfen!",
-    "add-manually": "Geben Sie bitte die Stichwörter unten mit separatem Komma ein"
+    "add-manually": "Geben Sie bitte die Stichwörter unten mit separatem Komma ein",
+    "select-keywords": "Wählen Sie die Stichwörter für Ihre Frage aus"
   },
   "comment-page": {
     "a11y-comment_input": "Gib deine Frage ein",
@@ -232,8 +233,6 @@
     "questions-blocked": "Fragen sind deaktiviert!"
   },
   "tag-cloud": {
-    "config": "Wolkenansicht ändern",
-    "administration": "Wolkenthemen editieren",
     "demo-data-topic": "Thema %d",
     "overview-question-topic-tooltip": "Anzahl gestellter Fragen mit diesem Thema",
     "overview-questioners-topic-tooltip": "Anzahl Fragensteller*innen mit diesem Thema",
@@ -293,7 +292,9 @@
     "select-all": "Alle auswählen",
     "keyword-counter": "Anzahl der Themen",
     "sort": "Sortieren",
-    "words-will-be-overwritten": "unanständige Wörter werden mit '***' überschrieben"
+    "words-will-be-overwritten": "unanständige Wörter werden mit '***' überschrieben",
+    "keyword-from-spacy": "Stichwort von spaCy",
+    "keyword-from-questioner": "Stichwort vom Fragesteller"
   },
   "topic-cloud-confirm-dialog": {
     "cancel": "Abbrechen",
diff --git a/src/assets/i18n/participant/en.json b/src/assets/i18n/participant/en.json
index 0d6ae27c2ed6414e5a9caa7a3d54e5c2481440c6..5fc4e2b3f87ed4c16cf29bc271dc31073ae14845 100644
--- a/src/assets/i18n/participant/en.json
+++ b/src/assets/i18n/participant/en.json
@@ -110,7 +110,8 @@
     "edit-keyword-hint": "Edit keyword",
     "editing-done-hint": "Finish editing",
     "force-language-selection": "Language detection inaccurate, please check language settings!",
-    "add-manually": "You can manually enter the keywords separated with a comma "
+    "add-manually": "You can manually enter the keywords separated with a comma",
+    "select-keywords": "Choose the keywords for your question"
   },
   "comment-page": {
     "a11y-comment_input": "Enter your question",
@@ -238,8 +239,6 @@
     "questions-blocked": "No further questions!"
   },
   "tag-cloud": {
-    "config": "Modify cloud view",
-    "administration": "Edit cloud topics",
     "demo-data-topic": "Topic %d",
     "overview-question-topic-tooltip": "Number of questions with this topic",
     "overview-questioners-topic-tooltip": "Number of questioners with this topic",
@@ -299,7 +298,9 @@
     "select-all": "Select all",
     "keyword-counter": "Topic count",
     "sort": "Sort",
-    "words-will-be-overwritten": "profane words will be overwritten with '***'"
+    "words-will-be-overwritten": "profane words will be overwritten with '***'",
+    "keyword-from-spacy": "Keyword from spaCy",
+    "keyword-from-questioner": "Keyword from questioner"
   },
   "topic-cloud-confirm-dialog":{
     "cancel": "Cancel",