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 63389ced507071094e3a9eb437edbab8aedd3afd..c64c128017cfe15ccd475c5bb795bae290a6ec97 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
@@ -2,14 +2,14 @@ import { AfterContentInit, Component, Inject, OnInit, ViewChild } from '@angular
 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 { SpacyService, Model, SpacyKeyword } from '../../../../services/http/spacy.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;
+  dep: string[];
   completed: boolean;
   editing: boolean;
   selected: boolean;
@@ -28,7 +28,7 @@ export class SpacyDialogComponent implements OnInit, AfterContentInit {
   commentLang: Model;
   commentBodyChecked: string;
   keywords: Keyword[] = [];
-  keywordsOriginal: Keyword[] = [];
+  keywordsOriginal: SpacyKeyword[] = [];
   hasKeywordsFromSpacy = false;
   isLoading = false;
   langSupported: boolean;
@@ -64,8 +64,11 @@ export class SpacyDialogComponent implements OnInit, AfterContentInit {
 
   buildCreateCommentActionCallback() {
     return () => {
-      this.comment.keywordsFromQuestioner = this.keywords.filter(kw => kw.selected && kw.word.length).map(kw => kw.word);
-      this.comment.keywordsFromSpacy = this.keywordsOriginal.filter(kw => kw.word.length).map(kw => kw.word);
+      this.comment.keywordsFromQuestioner = this.keywords.filter(kw => kw.selected && kw.word.length).map(kw => ({
+        lemma: kw.word,
+        dep: kw.dep
+      } as SpacyKeyword));
+      this.comment.keywordsFromSpacy = this.keywordsOriginal;
       this.dialogRef.close(this.comment);
     };
   }
@@ -75,24 +78,17 @@ export class SpacyDialogComponent implements OnInit, AfterContentInit {
 
     // N at first pos = all Nouns(NN de/en) including singular(NN, NNP en), plural (NNPS, NNS en), proper Noun(NNE, NE de)
     this.spacyService.getKeywords(this.commentBodyChecked, model)
-      .pipe(
-        map(keywords => keywords.map(keyword => ({
-          word: keyword,
+      .subscribe(words => {
+        this.keywordsOriginal = words;
+        this.keywords = words.map(keyword => ({
+          word: keyword.lemma,
+          dep: [...keyword.dep],
           completed: false,
           editing: false,
           selected: false
-        } as Keyword)))
-      )
-      .subscribe(words => {
-        this.keywords = words;
+        } as Keyword));
         this.keywords.sort((a, b) => a.word.localeCompare(b.word));
         this.hasKeywordsFromSpacy = this.keywords.length > 0;
-
-        //deep copy
-        this.keywordsOriginal = [...words];
-        for (let i = 0; i < this.keywordsOriginal.length; i++) {
-          this.keywordsOriginal[i] = {...this.keywordsOriginal[i]};
-        }
       }, () => {
         this.keywords = [];
         this.keywordsOriginal = [];
@@ -143,6 +139,7 @@ export class SpacyDialogComponent implements OnInit, AfterContentInit {
       this.keywords = tempKeywords.split(',').map((keyword) => (
         {
           word: keyword,
+          dep: ['ROOT'],
           completed: true,
           editing: false,
           selected: true
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 6fac351f63babc38d63365239df7d20d5bbdcc5a..26570bb7ce2df2392043a9fd69dafb73a221ce30 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
@@ -307,6 +307,11 @@
                 <mat-icon>close</mat-icon>
               </button>
             </mat-form-field>
+            <button mat-button class="themeRequirementInput reset"
+                    [disabled]="!isTopicRequirementActive()"
+                    (click)="minQuestioners='1'; minQuestioners='1'; minUpvotes='0'; startDate=''; endDate=''">
+              {{'topic-cloud-dialog.topic-requirement-reset' | translate}}
+            </button>
           </mat-expansion-panel>
         </mat-accordion>
 
@@ -333,8 +338,7 @@
                   matTooltip="{{'topic-cloud-dialog.keyword-counter' | translate}}"></mat-icon>
         <p [ngClass]="{'animation-blink': searchMode}"
            matTooltip="{{'topic-cloud-dialog.keyword-counter' | translate}}">
-          {{searchMode ? filteredKeywords.length :
-          keywords.length}}</p>
+          {{searchMode ? filteredKeywords.length : keywords.size}}</p>
       </div>
       <div class="margin-left vertical-center">
         <button [ngClass]="{'animation-blink': sortMode!=='alphabetic'}" mat-icon-button [matMenuTriggerFor]="sortMenu">
@@ -362,17 +366,18 @@
     </mat-menu>
 
     <mat-card class="color-surface"
-              *ngIf="(keywords.length === 0 || (searchMode && filteredKeywords.length === 0))&&!isLoading">
+              *ngIf="(keywords.size === 0 || (searchMode && filteredKeywords.length === 0))&&!isLoading">
       <p class="color-on-surface" fxLayoutAlign="center">
         {{'topic-cloud-dialog.no-keywords-note' | translate}}
       </p>
     </mat-card>
 
     <mat-accordion>
-      <div *ngFor="let keyword of (searchMode ? filteredKeywords : keywords); let i = index">
+      <div *ngFor="let keyword of (searchMode ? filteredKeywords : getValues()); let i = index">
         <mat-expansion-panel class="color-surface" (opened)="panelOpenState = true"
-          (closed)="panelOpenState = edit = false" [attr.data-index]="i" *ngIf="(blacklistIncludesKeyword(keyword.keyword) && isCreatorOrMod) || !blacklistIncludesKeyword(keyword.keyword)"
-          matTooltip="{{blacklistIncludesKeyword(keyword.keyword)?'Blacklist: ':''}}{{'topic-cloud-dialog.'+(keyword.keywordType === 2?'Keyword-from-both':(keyword.keywordType === 0?'keyword-from-spacy':'keyword-from-questioner')) | translate}}">
+                             (closed)="panelOpenState = edit = false" [attr.data-index]="i"
+                             *ngIf="(blacklistIncludesKeyword(keyword.keyword) && isCreatorOrMod) || !blacklistIncludesKeyword(keyword.keyword)"
+                             matTooltip="{{blacklistIncludesKeyword(keyword.keyword)?'Blacklist: ':''}}{{'topic-cloud-dialog.'+(keyword.keywordType === 2?'Keyword-from-both':(keyword.keywordType === 0?'keyword-from-spacy':'keyword-from-questioner')) | translate}}">
           <mat-expansion-panel-header class="color-surface">
             <mat-panel-title [ngClass]="{'red': blacklistIncludesKeyword(keyword.keyword)}">
               {{profanityFilter ? keyword.keywordWithoutProfanity : keyword.keyword}}
@@ -384,8 +389,10 @@
           </mat-expansion-panel-header>
           <div *ngFor="let question of keyword.comments">
             <mat-divider></mat-divider>
-            <app-topic-dialog-comment [question]="question.body" [keyword]="keyword.keyword" [maxShowedCharachters]="140"
-                                      [profanityFilter]="profanityFilter" [languageSpecific]="censorLanguageSpecificCheck"
+            <app-topic-dialog-comment [question]="question.body" [keyword]="keyword.keyword"
+                                      [maxShowedCharachters]="140"
+                                      [profanityFilter]="profanityFilter"
+                                      [languageSpecific]="censorLanguageSpecificCheck"
                                       [partialWords]="censorPartialWordsCheck"
                                       [language]="question.language"></app-topic-dialog-comment>
           </div>
@@ -415,8 +422,10 @@
                 <button mat-raised-button class="redBackground margin-right"
                         (click)="cancelEdit()">{{'topic-cloud-dialog.cancel' | translate}}</button>
                 <button mat-raised-button class="primaryBackground"
-                        (click)="confirmEdit(keyword)">{{'topic-cloud-dialog.save'
-                  | translate}}</button>
+                        [disabled]="!newKeyword || newKeyword.toLowerCase() === keyword.keyword.toLowerCase()"
+                        (click)="confirmEdit(keyword)">
+                  {{'topic-cloud-dialog.save' | translate}}
+                </button>
               </div>
             </div>
           </div>
diff --git a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.scss b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.scss
index f672fae74a1e3ad92cd954a468e61a3edd90a22f..88ec3a23ad9b929e11de58f6d297aeaeb2d9bb6a 100644
--- a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.scss
+++ b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.scss
@@ -169,4 +169,11 @@ mat-dialog-content {
 ::ng-deep .ng-animating div mat-accordion mat-expansion-panel div.mat-expansion-panel-content {
   height: 0px;
   visibility: hidden;
-}
\ No newline at end of file
+}
+
+.reset {
+  margin: 25px auto auto auto;
+  background-color: var(--secondary);
+  color: black;
+  width: 100%;
+}
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 cd57065fd6baa759b545a30cd0242f152e9486df..f4dd4d29d01c5a55d6dcd4f8ab70f94b113db03f 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
@@ -60,7 +60,7 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy {
   startDate: string;
   endDate: string;
 
-  keywords: Keyword[] = [];
+  keywords: Map<string, Keyword> = new Map<string, Keyword>();
   private topicCloudAdminData: TopicCloudAdminData;
   private profanityFilter: boolean;
   private censorPartialWordsCheck: boolean;
@@ -101,19 +101,22 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy {
     this.initializeKeywords();
   }
 
+  getValues(): Keyword[] {
+    return [...this.keywords.values()];
+  }
+
   removeFromKeywords(comment: Comment) {
-    for (const keyword of this.keywords) {
-      keyword.comments.forEach(_comment => {
-        if (_comment.id === comment.id) {
-          keyword.comments.splice(keyword.comments.indexOf(comment, 0), 1);
-        }
-      });
+    for (const [_, keyword] of this.keywords.entries()) {
+      const index = keyword.comments.findIndex(c => c.id === comment.id);
+      if (index >= 0) {
+        keyword.comments.splice(index, 1);
+      }
     }
     this.refreshKeywords();
   }
 
   refreshKeywords() {
-    this.keywords = [];
+    this.keywords = new Map<string, Keyword>();
     this.roomDataService.currentRoomData.forEach(comment => {
       this.pushInKeywords(comment);
     });
@@ -138,28 +141,30 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy {
       keywords = [];
     }
     keywords.forEach(_keyword => {
-      const existingKey = this.checkIfKeywordExists(_keyword);
+      const existingKey = this.checkIfKeywordExists(_keyword.lemma);
       if (existingKey) {
         existingKey.vote += comment.score;
+        _keyword.dep.forEach(dep => existingKey.keywordDeps.add(dep));
         if (this.checkIfCommentExists(existingKey.comments, comment.id)) {
           existingKey.comments.push(comment);
         }
       } else {
         if (this.keywordORfulltext === KeywordOrFulltext[KeywordOrFulltext.both]) {
-          if (comment.keywordsFromQuestioner.includes(_keyword) && comment.keywordsFromSpacy.includes(_keyword)) {
+          const includedFromQuestioner = comment.keywordsFromQuestioner.findIndex(e => e.lemma === _keyword.lemma) >= 0;
+          if (includedFromQuestioner && comment.keywordsFromSpacy.findIndex(e => e.lemma === _keyword.lemma) >= 0) {
             _keywordType = KeywordType.fromBoth;
           } else {
-            _keywordType = comment.keywordsFromQuestioner.includes(_keyword) ? KeywordType.fromQuestioner : KeywordType.fromSpacy;
+            _keywordType = includedFromQuestioner ? KeywordType.fromQuestioner : KeywordType.fromSpacy;
           }
         }
-        const keyword: Keyword = {
-          keyword: _keyword,
+        this.keywords.set(_keyword.lemma, {
+          keyword: _keyword.lemma,
+          keywordDeps: new Set<string>(_keyword.dep),
           keywordType: _keywordType,
-          keywordWithoutProfanity: this.getKeywordWithoutProfanity(_keyword, comment.language),
+          keywordWithoutProfanity: this.getKeywordWithoutProfanity(_keyword.lemma, comment.language),
           comments: [comment],
           vote: comment.score
-        };
-        this.keywords.push(keyword);
+        } as Keyword);
       }
     });
   }
@@ -199,7 +204,7 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy {
       if (comments === null) {
         return;
       }
-      this.keywords = [];
+      this.keywords = new Map<string, Keyword>();
       comments.forEach(comment => {
         this.pushInKeywords(comment);
       });
@@ -324,21 +329,23 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy {
     if (sortMode !== undefined) {
       this.sortMode = sortMode;
     }
+    const entries = [...this.keywords.entries()];
     switch (this.sortMode) {
       case 'alphabetic':
-        this.keywords.sort((a, b) => a.keyword.localeCompare(b.keyword));
+        entries.sort(([a], [b]) => a.localeCompare(b));
         break;
       case 'questionsCount':
-        this.keywords.sort((a, b) => b.comments.length - a.comments.length);
+        entries.sort(([_, a], [__, b]) => b.comments.length - a.comments.length);
         break;
       case 'voteCount':
-        this.keywords.sort((a, b) => b.vote - a.vote);
+        entries.sort(([_, a], [__, b]) => b.vote - a.vote);
         break;
     }
+    this.keywords = new Map(entries);
   }
 
   checkIfThereAreQuestions() {
-    if (this.keywords.length === 0) {
+    if (this.keywords.size === 0) {
       this.translateService.get('topic-cloud-dialog.no-keywords-note').subscribe(msg => {
         this.notificationService.show(msg);
       });
@@ -359,10 +366,10 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy {
     key.comments.forEach(comment => {
       const changes = new TSMap<string, any>();
       let keywords = comment.keywordsFromQuestioner;
-      keywords.splice(keywords.indexOf(key.keyword, 0), 1);
+      keywords.splice(keywords.findIndex(e => e.lemma === key.keyword), 1);
       changes.set('keywordsFromQuestioner', JSON.stringify(keywords));
       keywords = comment.keywordsFromSpacy;
-      keywords.splice(keywords.indexOf(key.keyword, 0), 1);
+      keywords.splice(keywords.findIndex(e => e.lemma === key.keyword), 1);
       changes.set('keywordsFromSpacy', JSON.stringify(keywords));
       this.updateComment(comment, changes, message);
     });
@@ -374,12 +381,12 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy {
 
   updateComment(updatedComment: Comment, changes: TSMap<string, any>, messageTranslate?: string) {
     this.commentService.patchComment(updatedComment, changes).subscribe(_ => {
-      if (messageTranslate) {
-        this.translateService.get('topic-cloud-dialog.' + messageTranslate).subscribe(msg => {
-          this.notificationService.show(msg);
-        });
-      }
-    },
+        if (messageTranslate) {
+          this.translateService.get('topic-cloud-dialog.' + messageTranslate).subscribe(msg => {
+            this.notificationService.show(msg);
+          });
+        }
+      },
       error => {
         this.translateService.get('topic-cloud-dialog.changes-gone-wrong').subscribe(msg => {
           this.notificationService.show(msg);
@@ -395,21 +402,25 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy {
   confirmEdit(key: Keyword): void {
     const key2 = this.checkIfKeywordExists(this.newKeyword);
     if (key2) {
+      if (key === key2) {
+        return;
+      }
       this.openConfirmDialog('merge-message', 'merge', key, key2);
     } else {
       key.comments.forEach(comment => {
         const changes = new TSMap<string, any>();
         let keywords = comment.keywordsFromQuestioner;
-        for (let i = 0; i < keywords.length; i++) {
-          if (keywords[i].toLowerCase() === key.keyword.toLowerCase()) {
-            keywords[i] = this.newKeyword.trim();
+        const lowerCaseKeyword = key.keyword.toLowerCase();
+        for (const keyword of keywords) {
+          if (keyword.lemma.toLowerCase() === lowerCaseKeyword) {
+            keyword.lemma = this.newKeyword.trim();
           }
         }
         changes.set('keywordsFromQuestioner', JSON.stringify(keywords));
         keywords = comment.keywordsFromSpacy;
-        for (let i = 0; i < keywords.length; i++) {
-          if (keywords[i].toLowerCase() === key.keyword.toLowerCase()) {
-            keywords[i] = this.newKeyword.trim();
+        for (const keyword of keywords) {
+          if (keyword.lemma.toLowerCase() === lowerCaseKeyword) {
+            keyword.lemma = this.newKeyword.trim();
           }
         }
         changes.set('keywordsFromSpacy', JSON.stringify(keywords));
@@ -444,35 +455,45 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy {
     if (!this.searchedKeyword) {
       this.searchMode = false;
     } else {
-      this.filteredKeywords = this.keywords.filter(keyword =>
+      const entries = [...this.keywords.entries()];
+      this.filteredKeywords = entries.filter(([_, keyword]) =>
         keyword.keyword.toLowerCase().includes(this.searchedKeyword.toLowerCase())
-      );
+      ).map(e => e[1]);
       this.searchMode = true;
     }
   }
 
   mergeKeywords(key1: Keyword, key2: Keyword) {
     if (key1 !== undefined && key2 !== undefined) {
-      key1.comments.forEach(comment => {
+      key1.comments = key1.comments.filter(comment => {
         if (this.checkIfCommentExists(key2.comments, comment.id)) {
           const changes = new TSMap<string, any>();
+          const lowerKey1 = key1.keyword.toLowerCase();
+
           let keywords = comment.keywordsFromQuestioner;
-          keywords.push(key2.keyword);
+          let index = keywords.findIndex(k => k.lemma.toLowerCase() === lowerKey1);
+          keywords[index].lemma = key2.keyword;
           changes.set('keywordsFromQuestioner', JSON.stringify(keywords));
+
           keywords = comment.keywordsFromSpacy;
-          keywords.push(key2.keyword);
+          index = keywords.findIndex(k => k.lemma.toLowerCase() === lowerKey1);
+          keywords[index].lemma = key2.keyword;
           changes.set('keywordsFromSpacy', JSON.stringify(keywords));
+
           this.updateComment(comment, changes);
+          return false;
         }
+        return true;
       });
       this.deleteKeyword(key1);
     }
   }
 
   checkIfKeywordExists(key: string): Keyword {
-    for (const keyword of this.keywords) {
-      if (keyword.keyword.toLowerCase() === key.trim().toLowerCase()) {
-        return keyword;
+    const currentKeyword = key.toLowerCase();
+    for (const keyword of this.keywords.keys()) {
+      if (keyword.toLowerCase() === currentKeyword) {
+        return this.keywords.get(keyword);
       }
     }
     return undefined;
@@ -550,6 +571,7 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy {
 
 interface Keyword {
   keyword: string;
+  keywordDeps: Set<string>;
   keywordType: KeywordType;
   keywordWithoutProfanity: string;
   comments: Comment[];
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 6b869eb929b740b59d14729a5ac283cfdf3efbc6..6abf38ae94368566607da768f99e8ab0f75e5ad6 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
@@ -9,7 +9,7 @@
         <div class="elementText">
           {{(!isMobile() ? 'content.continue-with-all-questions' : 'content.continue-with-all-questions-short') | translate}}
         </div>
-        <div class="elementIcons">
+        <div class="elementIcons" *ngIf="allComments">
           <mat-icon [inline]="true"
             matTooltip="{{'header.overview-question-tooltip' | translate}}">comment</mat-icon> {{allComments.comments}}
           <mat-icon [inline]="true"
@@ -24,7 +24,7 @@
         <div class="elementText">
           {{(!isMobile() ? 'content.continue-with-current-questions' : 'content.continue-with-current-questions-short')| translate}}
         </div>
-        <div class="elementIcons">
+        <div class="elementIcons" *ngIf="filteredComments">
           <mat-icon [inline]="true"
             matTooltip="{{'header.overview-question-tooltip' | translate}}">comment</mat-icon> {{filteredComments.comments}}
           <mat-icon [inline]="true"
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 5bfdb4b459ff80efb336bd8635a6daed705b248d..ae6f6f9c8e150a3ab4041e153f03215551890c77 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
@@ -1,5 +1,5 @@
 import { Room } from '../../../../models/room';
-import { Model, SpacyService } from '../../../../services/http/spacy.service';
+import { Model, SpacyKeyword, SpacyService } from '../../../../services/http/spacy.service';
 import { CommentService } from '../../../../services/http/comment.service';
 import { Comment } from '../../../../models/comment';
 import { Language, LanguagetoolService } from '../../../../services/http/languagetool.service';
@@ -9,6 +9,12 @@ import { HttpErrorResponse } from '@angular/common/http';
 
 const concurrentCallsPerTask = 4;
 
+enum FinishType {
+  completed,
+  badSpelled,
+  failed
+}
+
 export class WorkerDialogTask {
 
   error: string = null;
@@ -55,41 +61,48 @@ export class WorkerDialogTask {
     CreateCommentKeywords.isSpellingAcceptable(this.languagetoolService, currentComment.body)
       .subscribe(result => {
         if (!result.isAcceptable) {
-          this.statistics.badSpelled++;
-          this.callSpacy(currentIndex + concurrentCallsPerTask);
+          this.finishSpacyCall(FinishType.badSpelled, currentIndex);
           return;
         }
         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);
+          this.finishSpacyCall(FinishType.badSpelled, currentIndex);
           return;
         }
         this.spacyService.getKeywords(result.text, model)
-          .subscribe(newKeywords => {
-              const changes = new TSMap<string, string>();
-              changes.set('keywordsFromSpacy', JSON.stringify(newKeywords));
-              this.commentService.patchComment(currentComment, changes).subscribe(_ => {
-                  this.statistics.succeeded++;
-                },
-                patchError => {
-                  this.statistics.failed++;
-                  if (patchError instanceof HttpErrorResponse && patchError.status === 403) {
-                    this.error = 'forbidden';
-                  }
-                }, () => {
-                  this.callSpacy(currentIndex + concurrentCallsPerTask);
-                });
-            },
-            __ => {
-              this.statistics.failed++;
-              this.callSpacy(currentIndex + concurrentCallsPerTask);
-            });
-      }, _ => {
+          .subscribe(newKeywords => this.finishSpacyCall(FinishType.completed, currentIndex, newKeywords),
+            __ => this.finishSpacyCall(FinishType.failed, currentIndex));
+      }, _ => this.finishSpacyCall(FinishType.failed, currentIndex));
+  }
+
+  private finishSpacyCall(finishType: FinishType, index: number, tags?: SpacyKeyword[]): void {
+    if (finishType === FinishType.completed) {
+      this.statistics.succeeded++;
+      this.patchToServer(tags, index);
+    } else if (finishType === FinishType.badSpelled) {
+      this.statistics.badSpelled++;
+      this.patchToServer([], index);
+    } else {
+      this.statistics.failed++;
+    }
+    this.callSpacy(index + concurrentCallsPerTask);
+  }
+
+  private patchToServer(tags: SpacyKeyword[], index: number) {
+    const changes = new TSMap<string, string>();
+    changes.set('keywordsFromSpacy', JSON.stringify(tags));
+    this.commentService.patchComment(this._comments[index], changes).subscribe(_ => {
+        this.statistics.succeeded++;
+      },
+      patchError => {
         this.statistics.failed++;
-        this.callSpacy(currentIndex + concurrentCallsPerTask);
+        if (patchError instanceof HttpErrorResponse && patchError.status === 403) {
+          this.error = 'forbidden';
+        }
+      }, () => {
+        this.callSpacy(index + concurrentCallsPerTask);
       });
   }
 
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 a20a0867daaa767446e0c2c087ab15c9a5523a91..17791bd18b2450e7d0667d1185c4e4da79cb7faa 100644
--- a/src/app/components/shared/comment-list/comment-list.component.ts
+++ b/src/app/components/shared/comment-list/comment-list.component.ts
@@ -78,6 +78,7 @@ export class CommentListComponent implements OnInit, OnDestroy {
   unanswered = 'unanswered';
   owner = 'owner';
   currentFilter = '';
+  currentFilterCompare: any = null;
   commentVoteMap = new Map<string, Vote>();
   scroll = false;
   scrollExtended = false;
@@ -371,6 +372,7 @@ export class CommentListComponent implements OnInit, OnDestroy {
 
   filterComments(type: string, compare?: any): void {
     this.currentFilter = type;
+    this.currentFilterCompare = compare;
     if (type === '') {
       this.filteredComments = this.commentsFilteredByTime;
       this.hideCommentsList = false;
@@ -402,8 +404,8 @@ export class CommentListComponent implements OnInit, OnDestroy {
           return c.userNumber === compare;
         case this.keyword:
           this.selectedKeyword = compare;
-          const isInQuestioner = c.keywordsFromQuestioner ? c.keywordsFromQuestioner.includes(compare) : false;
-          const isInSpacy = c.keywordsFromSpacy ? c.keywordsFromSpacy.includes(compare) : false;
+          const isInQuestioner = c.keywordsFromQuestioner ? c.keywordsFromQuestioner.findIndex(k => k.lemma === compare) >= 0 : false;
+          const isInSpacy = c.keywordsFromSpacy ? c.keywordsFromSpacy.findIndex(k => k.lemma === compare) >= 0 : false;
           return isInQuestioner || isInSpacy;
         case this.answer:
           return c.answer;
@@ -496,10 +498,10 @@ export class CommentListComponent implements OnInit, OnDestroy {
 
   subscribeCommentStream() {
     this.commentStream = this.roomDataService.receiveUpdates([
-      {type: 'CommentCreated', finished: true},
-      {type: 'CommentPatched', subtype: this.favorite},
-      {type: 'CommentPatched', subtype: 'score'},
-      {finished: true}
+      { type: 'CommentCreated', finished: true },
+      { type: 'CommentPatched', subtype: this.favorite },
+      { type: 'CommentPatched', subtype: 'score' },
+      { finished: true }
     ]).subscribe(update => {
       if (update.type === 'CommentCreated') {
         this.announceNewComment(update.comment.body);
@@ -591,7 +593,7 @@ export class CommentListComponent implements OnInit, OnDestroy {
       this.commentsFilteredByTime = this.comments;
     }
 
-    this.filterComments(this.currentFilter);
+    this.filterComments(this.currentFilter, this.currentFilterCompare);
     this.titleService.attachTitle('(' + this.commentsFilteredByTime.length + ')');
   }
 
diff --git a/src/app/components/shared/comment/comment.component.html b/src/app/components/shared/comment/comment.component.html
index 73f4485222293ad6b40631e6db42c5707255bcc3..3cb871d6950a6b9f18798623a9077ca069b2a0a5 100644
--- a/src/app/components/shared/comment/comment.component.html
+++ b/src/app/components/shared/comment/comment.component.html
@@ -342,8 +342,8 @@
           <mat-list dense class="keywords-list">
             <mat-list-item *ngFor="let keyword of sortKeywords(comment.keywordsFromQuestioner); let odd = odd; let even = even"
                             [class.keywords-alternate]="odd"
-                            [class.keywords-even]="even">                  
-                            <span (click)="this.clickedOnKeyword.emit(keyword)" class="keyword-span">{{keyword}}</span>
+                            [class.keywords-even]="even">
+                            <span (click)="this.clickedOnKeyword.emit(keyword.lemma)" class="keyword-span">{{keyword.lemma}}</span>
             </mat-list-item>
           </mat-list>
         </mat-menu>
diff --git a/src/app/components/shared/comment/comment.component.ts b/src/app/components/shared/comment/comment.component.ts
index c675aabe36bd77e15998dd2b5cc4feba85df09ad..ca06a69ac583a44ed8efa4b21aa249fe19b8ce88 100644
--- a/src/app/components/shared/comment/comment.component.ts
+++ b/src/app/components/shared/comment/comment.component.ts
@@ -18,6 +18,7 @@ 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';
+import { SpacyKeyword } from '../../../services/http/spacy.service';
 
 @Component({
   selector: 'app-comment',
@@ -128,8 +129,8 @@ export class CommentComponent implements OnInit, AfterViewInit {
     }
   }
 
-  sortKeywords(keywords: string[]){
-    return keywords.sort((a,b) => a.localeCompare(b));
+  sortKeywords(keywords: SpacyKeyword[]){
+    return keywords.sort((a,b) => a.lemma.localeCompare(b.lemma));
   }
 
   toggleExpand(evt: MouseEvent) {
diff --git a/src/app/components/shared/header/header.component.ts b/src/app/components/shared/header/header.component.ts
index 81c54354ecc5a87a8cfbe38a874e45444f340189..2ce0f4b17f2f8f66bf58157ff179d603aae79953 100644
--- a/src/app/components/shared/header/header.component.ts
+++ b/src/app/components/shared/header/header.component.ts
@@ -152,6 +152,7 @@ export class HeaderComponent implements OnInit {
     });
     this.moderationEnabled = (localStorage.getItem('moderationEnabled') === 'true') ? true : false;
 
+
     this._r.listen(document, 'keyup', (event) => {
       if (
         document.getElementById('back-button') &&
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 7dd38350aa990e372eedca47a6bfbfd1467e7ba8..578a141f9cfbf68bf5c8fb495d5446708821ff45 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
@@ -16,7 +16,7 @@
           {{tagData && tagData.distinctUsers.size}}
         </p>
       </span>
-      <button *ngIf="user && user.role >= 1" mat-button (click)="addBlacklistWord()">
+      <button *ngIf="user && user.role >= 1 && isBlacklistActive" mat-button (click)="addBlacklistWord()">
         <mat-icon matTooltip="{{'tag-cloud.blacklist-topic' | translate}}">gavel</mat-icon>
       </button>
     </div>
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 3b8c9e6eac50c42346b1f070f57b1dafcf0171e4..14b4e30c6cb2ac0eaa167288166eea0f7f705e3e 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
@@ -11,6 +11,7 @@ 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';
+import { SpacyKeyword } from '../../../../services/http/spacy.service';
 
 const CLOSE_TIME = 1500;
 
@@ -31,6 +32,7 @@ export class TagCloudPopUpComponent implements OnInit, AfterViewInit {
   user: User;
   selectedLang: Language = 'en-US';
   spellingData: string[] = [];
+  isBlacklistActive = true;
   private _popupHoverTimer: number;
   private _popupCloseTimer: number;
   private _hasLeft = true;
@@ -77,7 +79,10 @@ export class TagCloudPopUpComponent implements OnInit, AfterViewInit {
     this.close();
   }
 
-  enter(elem: HTMLElement, tag: string, tagData: TagCloudDataTagEntry, hoverDelayInMs: number): void {
+  enter(elem: HTMLElement, tag: string, tagData: TagCloudDataTagEntry, hoverDelayInMs: number, isBlacklistActive: boolean): void {
+    if (!elem) {
+      return;
+    }
     this.spellingData = [];
     if (this.user && this.user.role > UserRole.PARTICIPANT) {
       this.languagetoolService.checkSpellings(tag, 'auto').subscribe(correction => {
@@ -103,6 +108,7 @@ export class TagCloudPopUpComponent implements OnInit, AfterViewInit {
       this.categories = Array.from(tagData.categories.keys());
       this.calculateDateText(() => {
         this.position(elem);
+        this.isBlacklistActive = isBlacklistActive;
       });
     }, hoverDelayInMs);
   }
@@ -143,22 +149,22 @@ export class TagCloudPopUpComponent implements OnInit, AfterViewInit {
       return;
     }
     const tagReplacementInput = this.replacementInput.value.trim();
-    const renameKeyword = (elem: string, index: number, array: string[]) => {
-      if (elem === this.tag) {
-        array[index] = tagReplacementInput;
+    const renameKeyword = (elem: SpacyKeyword) => {
+      if (elem.lemma === this.tag) {
+        elem.lemma = tagReplacementInput;
       }
     };
     const tagReplacementInputLower = tagReplacementInput.toLowerCase();
     this.tagData.comments.forEach(comment => {
       const changes = new TSMap<string, any>();
-      if (comment.keywordsFromQuestioner.findIndex(e => e.toLowerCase() === tagReplacementInputLower) >= 0) {
-        comment.keywordsFromQuestioner = comment.keywordsFromQuestioner.filter(e => e !== this.tag);
+      if (comment.keywordsFromQuestioner.findIndex(e => e.lemma.toLowerCase() === tagReplacementInputLower) >= 0) {
+        comment.keywordsFromQuestioner = comment.keywordsFromQuestioner.filter(e => e.lemma !== this.tag);
       } else {
         comment.keywordsFromQuestioner.forEach(renameKeyword);
       }
       changes.set('keywordsFromQuestioner', JSON.stringify(comment.keywordsFromQuestioner));
-      if (comment.keywordsFromSpacy.findIndex(e => e.toLowerCase() === tagReplacementInputLower) >= 0) {
-        comment.keywordsFromSpacy = comment.keywordsFromSpacy.filter(e => e !== this.tag);
+      if (comment.keywordsFromSpacy.findIndex(e => e.lemma.toLowerCase() === tagReplacementInputLower) >= 0) {
+        comment.keywordsFromSpacy = comment.keywordsFromSpacy.filter(e => e.lemma !== this.tag);
       } else {
         comment.keywordsFromSpacy.forEach(renameKeyword);
       }
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 1722a332c74b757c09894757c64ddc892135f68d..90ef494e49ca4c0d40570ae3989eb3f6458c832a 100644
--- a/src/app/components/shared/tag-cloud/tag-cloud.component.ts
+++ b/src/app/components/shared/tag-cloud/tag-cloud.component.ts
@@ -112,18 +112,25 @@ const getResolvedDefaultColors = (): string[] => {
 
 const getDefaultCloudParameters = (): CloudParameters => {
   const resDefaultColors = getResolvedDefaultColors();
+  const minValue = window.innerWidth < window.innerHeight ? window.innerWidth : window.innerHeight;
+  const isMobile = minValue < 500;
+  const elements = isMobile ? 5 : -1;
   const weightSettings: CloudWeightSettings = [
-    {maxVisibleElements: -1, color: resDefaultColors[1], rotation: 0, allowManualTagNumber: false},
-    {maxVisibleElements: -1, color: resDefaultColors[2], rotation: 0, allowManualTagNumber: false},
-    {maxVisibleElements: -1, color: resDefaultColors[3], rotation: 0, allowManualTagNumber: false},
-    {maxVisibleElements: -1, color: resDefaultColors[4], rotation: 0, allowManualTagNumber: false},
-    {maxVisibleElements: -1, color: resDefaultColors[5], rotation: 0, allowManualTagNumber: false},
-    {maxVisibleElements: -1, color: resDefaultColors[6], rotation: 0, allowManualTagNumber: false},
-    {maxVisibleElements: -1, color: resDefaultColors[7], rotation: 0, allowManualTagNumber: false},
-    {maxVisibleElements: -1, color: resDefaultColors[8], rotation: 0, allowManualTagNumber: false},
-    {maxVisibleElements: -1, color: resDefaultColors[9], rotation: 0, allowManualTagNumber: false},
-    {maxVisibleElements: -1, color: resDefaultColors[10], rotation: 0, allowManualTagNumber: false},
+    { maxVisibleElements: elements, color: resDefaultColors[1], rotation: 0, allowManualTagNumber: isMobile },
+    { maxVisibleElements: elements, color: resDefaultColors[2], rotation: 0, allowManualTagNumber: isMobile },
+    { maxVisibleElements: elements, color: resDefaultColors[3], rotation: 0, allowManualTagNumber: isMobile },
+    { maxVisibleElements: elements, color: resDefaultColors[4], rotation: 0, allowManualTagNumber: isMobile },
+    { maxVisibleElements: elements, color: resDefaultColors[5], rotation: 0, allowManualTagNumber: isMobile },
+    { maxVisibleElements: elements, color: resDefaultColors[6], rotation: 0, allowManualTagNumber: isMobile },
+    { maxVisibleElements: elements, color: resDefaultColors[7], rotation: 0, allowManualTagNumber: isMobile },
+    { maxVisibleElements: elements, color: resDefaultColors[8], rotation: 0, allowManualTagNumber: isMobile },
+    { maxVisibleElements: elements, color: resDefaultColors[9], rotation: 0, allowManualTagNumber: isMobile },
+    { maxVisibleElements: elements, color: resDefaultColors[10], rotation: 0, allowManualTagNumber: isMobile },
   ];
+  const mapValue = (current: number, minInputValue: number, maxInputValue: number, minOut: number, maxOut: number) => {
+    const value = (current - minInputValue) * (maxOut - minOut) / (maxInputValue - minInputValue) + minOut;
+    return Math.min(maxOut, Math.max(minOut, value));
+  };
   return {
     fontFamily: 'Dancing Script',
     fontWeight: 'normal',
@@ -131,9 +138,9 @@ const getDefaultCloudParameters = (): CloudParameters => {
     fontSize: '10px',
     backgroundColor: resDefaultColors[11],
     fontColor: resDefaultColors[0],
-    fontSizeMin: 150,
-    fontSizeMax: 900,
-    hoverScale: 2,
+    fontSizeMin: mapValue(minValue, 375, 750, 125, 200),
+    fontSizeMax: mapValue(minValue, 375, 1500, 300, 900),
+    hoverScale: mapValue(minValue, 375, 1500, 1.4, 2),
     hoverTime: 1,
     hoverDelay: 0.4,
     delayWord: 100,
@@ -151,7 +158,7 @@ const getDefaultCloudParameters = (): CloudParameters => {
 })
 export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit, AfterViewInit {
 
-  @ViewChild(TCloudComponent, {static: false}) child: TCloudComponent;
+  @ViewChild(TCloudComponent, { static: false }) child: TCloudComponent;
   @ViewChild(TagCloudPopUpComponent) popup: TagCloudPopUpComponent;
   @Input() user: User;
   @Input() roomId: string;
@@ -270,6 +277,7 @@ export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit, A
             const message = JSON.parse(msg.body);
             if (message.type === 'RoomPatched') {
               this.room.questionsBlocked = message.payload.changes.questionsBlocked;
+              this.room.blacklistIsActive = message.payload.changes.blacklistIsActive;
             }
           });
           this.directSend = this.room.directSend;
@@ -301,7 +309,7 @@ export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit, A
   }
 
   ngAfterViewInit() {
-    this.rebuildData();
+    setTimeout(() => this.rebuildData());
   }
 
   ngOnDestroy() {
@@ -343,7 +351,7 @@ export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit, A
   }
 
   resetColorsToTheme() {
-    this.setCloudParameters(getDefaultCloudParameters());
+    this.setCloudParameters(getDefaultCloudParameters(), true);
   }
 
   onResize(event: UIEvent): any {
@@ -368,7 +376,7 @@ export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit, A
           if (remaining > 0) {
             --countFiler[tagData.adjustedWeight];
           }
-          let rotation = Math.random() < 0.5 ? this._currentSettings.cloudWeightSettings[tagData.adjustedWeight].rotation : 0;
+          let rotation = this._currentSettings.cloudWeightSettings[tagData.adjustedWeight].rotation;
           if (rotation === null || this._currentSettings.randomAngles) {
             rotation = Math.floor(Math.random() * 30 - 15);
           }
@@ -420,7 +428,7 @@ export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit, A
       this.eventService.broadcast('setTagConfig', tag.text);
       this._subscriptionCommentlist.unsubscribe();
     });
-    this.router.navigate(['../'], {relativeTo: this.route});
+    this.router.navigate(['../'], { relativeTo: this.route });
   }
 
   private updateAlphabeticalPosition(elements: TagComment[]): void {
@@ -461,7 +469,8 @@ export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit, A
         elem.dataset['tempRotation'] = transformMatch ? transformMatch[1] : '0deg';
         elem.style.transform = elem.style.transform.replace(transformationRotationKiller, '').trim();
         this.popup.enter(elem, dataElement.text, dataElement.tagData,
-          (this._currentSettings.hoverTime + this._currentSettings.hoverDelay) * 1_000);
+          (this._currentSettings.hoverTime + this._currentSettings.hoverDelay) * 1_000,
+          this.room && this.room.blacklistIsActive);
       });
     });
   }
diff --git a/src/app/models/comment.ts b/src/app/models/comment.ts
index 8de26629ffa7d82ce9c47e34634dbe0b82b87de7..5666ae256ff394f9dd3ccdfb7951688f4deda55e 100644
--- a/src/app/models/comment.ts
+++ b/src/app/models/comment.ts
@@ -1,4 +1,4 @@
-import { Model } from '../services/http/spacy.service';
+import { Model, SpacyKeyword } from '../services/http/spacy.service';
 import { CorrectWrong } from './correct-wrong.enum';
 
 export class Comment {
@@ -20,8 +20,8 @@ export class Comment {
   answer: string;
   userNumber: number;
   number: number;
-  keywordsFromQuestioner: string[];
-  keywordsFromSpacy: string[];
+  keywordsFromQuestioner: SpacyKeyword[];
+  keywordsFromSpacy: SpacyKeyword[];
   upvotes: number;
   downvotes: number;
   language: Language;
@@ -41,8 +41,8 @@ export class Comment {
               tag: string = '',
               answer: string = '',
               userNumber: number = 0,
-              keywordsFromQuestioner: string[] = [],
-              keywordsFromSpacy: string[] = [],
+              keywordsFromQuestioner: SpacyKeyword[] = [],
+              keywordsFromSpacy: SpacyKeyword[] = [],
               upvotes = 0,
               downvotes = 0,
               language = Language.auto) {
diff --git a/src/app/services/http/spacy.service.ts b/src/app/services/http/spacy.service.ts
index 3cd7101da0c520a1ea555a2f1b3c4211bef5bff1..6cf3fe6169d3c2debea9dc490c49cc306d292785 100644
--- a/src/app/services/http/spacy.service.ts
+++ b/src/app/services/http/spacy.service.ts
@@ -3,11 +3,15 @@ import { HttpClient, HttpHeaders } from '@angular/common/http';
 import { Observable } from 'rxjs';
 import { BaseHttpService } from './base-http.service';
 import { catchError, map, tap } from 'rxjs/operators';
-import { TopicCloudAdminService } from '../util/topic-cloud-admin.service';
 import { CreateCommentKeywords } from '../../utils/create-comment-keywords';
 
 export type Model = 'de' | 'en' | 'fr' | 'es' | 'it' | 'nl' | 'pt' | 'auto';
 
+export interface SpacyKeyword {
+  lemma: string;
+  dep: string[];
+}
+
 type EnglishParserLabels = 'ROOT' | //None
   'acl' | //clausal modifier of noun (adjectival clause)
   'acomp' | //adjectival complement
@@ -161,7 +165,7 @@ type KeywordList = AbstractKeyword[];
 
 const httpOptions = {
   // eslint-disable-next-line @typescript-eslint/naming-convention
-  headers: new HttpHeaders({'Content-Type': 'application/json'})
+  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
 };
 
 @Injectable({
@@ -177,17 +181,31 @@ export class SpacyService extends BaseHttpService {
     return LABELS[model];
   }
 
-  getKeywords(text: string, model: Model): Observable<string[]> {
+  getKeywords(text: string, model: Model): Observable<SpacyKeyword[]> {
     const url = '/spacy';
-    const wanted = TopicCloudAdminService.getDefaultAdminData.wantedLabels[model];
-    return this.http.post<KeywordList>(url, {text, model}, httpOptions)
+    return this.http.post<KeywordList>(url, { text, model }, httpOptions)
       .pipe(
         tap(_ => ''),
         catchError(this.handleError<any>('getKeywords')),
-        map((elem: KeywordList) => wanted != null ?
-          elem.filter(e => wanted.includes(e.dep) && CreateCommentKeywords.isKeywordAcceptable(e.lemma)) :
-          elem),
-        map((result: KeywordList) => [...new Set(result.map(e => e.lemma.trim()))])
+        map((elem: KeywordList) => {
+          const keywordsMap = new Map<string, { lemma: string; dep: Set<string> }>();
+          elem.forEach(e => {
+            const keyword = e.lemma.trim();
+            if (!CreateCommentKeywords.isKeywordAcceptable(keyword)) {
+              return;
+            }
+            let keywordObj = keywordsMap.get(keyword);
+            if (!keywordObj) {
+              keywordObj = {
+                lemma: keyword,
+                dep: new Set<string>()
+              };
+              keywordsMap.set(keyword, keywordObj);
+            }
+            keywordObj.dep.add(e.dep);
+          });
+          return [...keywordsMap.values()].map(e => ({ lemma: e.lemma, dep: [...e.dep] }));
+        })
       );
   }
 }
diff --git a/src/app/services/util/room-data.service.ts b/src/app/services/util/room-data.service.ts
index 20a1bad7ec6f4dc5016843ba56b9e870986e7a6d..1530f4e58e735f1a1f917e877eca77b02a135fbb 100644
--- a/src/app/services/util/room-data.service.ts
+++ b/src/app/services/util/room-data.service.ts
@@ -265,6 +265,7 @@ export class RoomDataService {
     c.creatorId = payload.creatorId;
     c.userNumber = this.commentService.hashCode(c.creatorId);
     c.keywordsFromQuestioner = JSON.parse(payload.keywordsFromQuestioner);
+    c.language = payload.language;
     this._fastCommentAccess[c.id] = c;
     this._currentComments.push(c);
     this.triggerUpdate(UpdateType.commentStream, {
diff --git a/src/app/services/util/tag-cloud-data.service.ts b/src/app/services/util/tag-cloud-data.service.ts
index 8d48d73ab0b051a7d02d7a56ac8fcbb8ff56085d..0c9373b74b5f4d9dadbf09c8c1745cc3fa0c4056 100644
--- a/src/app/services/util/tag-cloud-data.service.ts
+++ b/src/app/services/util/tag-cloud-data.service.ts
@@ -7,6 +7,7 @@ import { TranslateService } from '@ngx-translate/core';
 import { CloudParameters } from '../../components/shared/tag-cloud/tag-cloud.interface';
 import { Comment } from '../../models/comment';
 import { RoomDataService } from './room-data.service';
+import { SpacyKeyword } from '../http/spacy.service';
 
 export interface TagCloudDataTagEntry {
   weight: number;
@@ -18,6 +19,7 @@ export interface TagCloudDataTagEntry {
   firstTimeStamp: Date;
   lastTimeStamp: Date;
   categories: Set<string>;
+  dependencies: Set<string>;
   comments: Comment[];
 }
 
@@ -54,6 +56,8 @@ export enum TagCloudCalcWeightType {
   byLengthAndVotes
 }
 
+const DEBOUNCE_TIME = 3_000;
+
 @Injectable({
   providedIn: 'root'
 })
@@ -74,6 +78,8 @@ export class TagCloudDataService {
   private _adminData: TopicCloudAdminData = null;
   private _subscriptionAdminData: Subscription;
   private _currentFilter: CommentFilter;
+  private _debounceTimer = 0;
+  private _lastDebounceTime = new Date().getTime() - DEBOUNCE_TIME;
 
   constructor(private _tagCloudAdmin: TopicCloudAdminService,
               private _roomDataService: RoomDataService) {
@@ -100,8 +106,8 @@ export class TagCloudDataService {
     const data: TagCloudData = new Map<string, TagCloudDataTagEntry>();
     const users = new Set<number>();
     for (const comment of comments) {
-      TopicCloudAdminService.approveKeywordsOfComment(comment, adminData, (keyword) => {
-        let current: TagCloudDataTagEntry = data.get(keyword);
+      TopicCloudAdminService.approveKeywordsOfComment(comment, adminData, (keyword: SpacyKeyword) => {
+        let current: TagCloudDataTagEntry = data.get(keyword.lemma);
         const commentDate = new Date(comment.timestamp);
         if (current === undefined) {
           current = {
@@ -113,11 +119,13 @@ export class TagCloudDataService {
             adjustedWeight: 0,
             distinctUsers: new Set<number>(),
             categories: new Set<string>(),
+            dependencies: new Set<string>([...keyword.dep]),
             firstTimeStamp: commentDate,
             lastTimeStamp: commentDate
           };
-          data.set(keyword, current);
+          data.set(keyword.lemma, current);
         }
+        keyword.dep.forEach(dependency => current.dependencies.add(dependency));
         current.cachedVoteCount += comment.score;
         current.cachedUpVotes += comment.upvotes;
         current.cachedDownVotes += comment.downvotes;
@@ -150,19 +158,20 @@ export class TagCloudDataService {
     this._subscriptionAdminData = this._tagCloudAdmin.getAdminData.subscribe(adminData => {
       this.onReceiveAdminData(adminData, true);
     });
+    this._tagCloudAdmin.ensureRoomBound(roomId);
 
     this.fetchData();
     if (!this._currentFilter.paused) {
       this._commentSubscription = this._roomDataService.receiveUpdates([
-        {type: 'CommentCreated', finished: true},
-        {type: 'CommentDeleted'},
-        {type: 'CommentPatched', finished: true, updates: ['score']},
-        {type: 'CommentPatched', finished: true, updates: ['downvotes']},
-        {type: 'CommentPatched', finished: true, updates: ['upvotes']},
-        {type: 'CommentPatched', finished: true, updates: ['keywordsFromSpacy']},
-        {type: 'CommentPatched', finished: true, updates: ['keywordsFromQuestioner']},
-        {type: 'CommentPatched', finished: true, updates: ['ack']},
-        {type: 'CommentPatched', finished: true, updates: ['tag']},
+        { type: 'CommentCreated', finished: true },
+        { type: 'CommentDeleted' },
+        { type: 'CommentPatched', finished: true, updates: ['score'] },
+        { type: 'CommentPatched', finished: true, updates: ['downvotes'] },
+        { type: 'CommentPatched', finished: true, updates: ['upvotes'] },
+        { type: 'CommentPatched', finished: true, updates: ['keywordsFromSpacy'] },
+        { type: 'CommentPatched', finished: true, updates: ['keywordsFromQuestioner'] },
+        { type: 'CommentPatched', finished: true, updates: ['ack'] },
+        { type: 'CommentPatched', finished: true, updates: ['tag'] },
       ]).subscribe(_ => {
         this.rebuildTagData();
       });
@@ -190,6 +199,7 @@ export class TagCloudDataService {
           adjustedWeight: i - 1,
           categories: new Set<string>(),
           distinctUsers: new Set<number>(),
+          dependencies: new Set<string>(),
           firstTimeStamp: new Date(),
           lastTimeStamp: new Date()
         });
@@ -281,7 +291,18 @@ export class TagCloudDataService {
       newData = new Map<string, TagCloudDataTagEntry>([...current]
         .sort(([_, aTagData], [__, bTagData]) => bTagData.weight - aTagData.weight));
     }
-    this._dataBus.next(newData);
+    const currentTime = new Date().getTime();
+    const diff = currentTime - this._lastDebounceTime;
+    if (diff >= DEBOUNCE_TIME) {
+      this._dataBus.next(newData);
+      this._lastDebounceTime = currentTime;
+    } else {
+      clearTimeout(this._debounceTimer);
+      this._debounceTimer = setTimeout(() => {
+        this._dataBus.next(newData);
+        this._lastDebounceTime = new Date().getTime();
+      }, DEBOUNCE_TIME - diff);
+    }
   }
 
   private onReceiveAdminData(data: TopicCloudAdminData, update = false) {
diff --git a/src/app/services/util/topic-cloud-admin.service.ts b/src/app/services/util/topic-cloud-admin.service.ts
index e21964674fe463c9cb810dbceccc51e87817bc73..84cd5e70e621154544ed96590d786c912f54a202 100644
--- a/src/app/services/util/topic-cloud-admin.service.ts
+++ b/src/app/services/util/topic-cloud-admin.service.ts
@@ -10,7 +10,7 @@ import { TranslateService } from '@ngx-translate/core';
 import { NotificationService } from './notification.service';
 import { WsRoomService } from '../websockets/ws-room.service';
 import { ProfanityFilterService } from './profanity-filter.service';
-import { BehaviorSubject, Observable, Subject } from 'rxjs';
+import { BehaviorSubject, Observable, Subject, Subscription } from 'rxjs';
 import { Comment } from '../../models/comment';
 
 @Injectable({
@@ -22,6 +22,8 @@ export class TopicCloudAdminService {
   private blacklist: Subject<string[]>;
   private blacklistIsActive: Subject<boolean>;
   private blacklistActive: boolean;
+  private _subscriptionWsRoom: Subscription;
+
   constructor(private roomService: RoomService,
               private translateService: TranslateService,
               private wsRoomService: WsRoomService,
@@ -29,22 +31,10 @@ export class TopicCloudAdminService {
               private notificationService: NotificationService) {
     this.blacklist = new Subject<string[]>();
     this.blacklistIsActive = new Subject<boolean>();
-    this.wsRoomService.getRoomStream(localStorage.getItem('roomId')).subscribe(msg => {
-      const message = JSON.parse(msg.body);
-      const room = message.payload.changes;
-      if (message.type === 'RoomPatched') {
-        this.blacklist.next(room.blacklist ? JSON.parse(room.blacklist) : []);
-        this.blacklistActive = room.blacklistIsActive;
-        this.blacklistIsActive.next(room.blacklistIsActive);
-        const data = TopicCloudAdminService.getDefaultAdminData;
-        data.blacklistIsActive = this.blacklistActive;
-        this.setAdminData(data, false);
-      }
-    });
     this.adminData = new BehaviorSubject<TopicCloudAdminData>(TopicCloudAdminService.getDefaultAdminData);
   }
 
-  static approveKeywordsOfComment(comment: Comment, config: TopicCloudAdminData, keywordFunc: (string) => void) {
+  static approveKeywordsOfComment(comment: Comment, config: TopicCloudAdminData, keywordFunc: (SpacyKeyword) => void) {
     let source = comment.keywordsFromQuestioner;
     if (config.keywordORfulltext === KeywordOrFulltext.both) {
       source = !source || !source.length ? comment.keywordsFromSpacy : source;
@@ -54,9 +44,13 @@ export class TopicCloudAdminService {
     if (!source) {
       return;
     }
+    const wantedLabels = config.wantedLabels[comment.language.toLowerCase()];
     for (const keyword of source) {
+      if (wantedLabels && !keyword.dep.some(e => wantedLabels.includes(e))) {
+        continue;
+      }
       let isProfanity = false;
-      const lowerCasedKeyword = keyword.toLowerCase();
+      const lowerCasedKeyword = keyword.lemma.toLowerCase();
       for (const word of config.blacklist) {
         if (lowerCasedKeyword.includes(word)) {
           isProfanity = true;
@@ -130,6 +124,26 @@ export class TopicCloudAdminService {
     return this.adminData.asObservable();
   }
 
+  ensureRoomBound(roomId: string) {
+    if (this._subscriptionWsRoom) {
+      this._subscriptionWsRoom.unsubscribe();
+      this._subscriptionWsRoom = null;
+    }
+    this._subscriptionWsRoom = this.wsRoomService.getRoomStream(roomId).subscribe(msg => {
+      const message = JSON.parse(msg.body);
+      const room = message.payload.changes;
+      if (message.type === 'RoomPatched') {
+        this.blacklist.next(room.blacklist ? JSON.parse(room.blacklist) : []);
+        this.blacklistActive = room.blacklistIsActive;
+        this.blacklistIsActive.next(room.blacklistIsActive);
+        const data = TopicCloudAdminService.getDefaultAdminData;
+        data.profanityFilter = room.profanityFilter;
+        data.blacklistIsActive = this.blacklistActive;
+        this.setAdminData(data, false);
+      }
+    });
+  }
+
   setAdminData(_adminData: TopicCloudAdminData, updateRoom: boolean) {
     localStorage.setItem(TopicCloudAdminService.adminKey, JSON.stringify(_adminData));
     if (updateRoom) {
diff --git a/src/app/utils/create-comment-keywords.ts b/src/app/utils/create-comment-keywords.ts
index bc48116b89158b29f0f0d704f5f52c6b391acfd5..02f8ae6e3cfac85bf124cc0d322653c508328622 100644
--- a/src/app/utils/create-comment-keywords.ts
+++ b/src/app/utils/create-comment-keywords.ts
@@ -5,7 +5,7 @@ export class CreateCommentKeywords {
 
   static isKeywordAcceptable(keyword: string) {
     const regex = /(^[ -@\[-`{-~]+$)/g;
-    return keyword.match(regex) === null;
+    return keyword.match(regex) === null && keyword.length;
   }
 
   static isSpellingAcceptable(languagetoolService: LanguagetoolService, text: string, language: Language = 'auto') {
diff --git a/src/app/utils/filter-options.ts b/src/app/utils/filter-options.ts
index d2791cb73b89eedd7b2f5e338f3870b100913957..af92e68b70c03a3d4c54a74d7f1adf1f057da2a8 100644
--- a/src/app/utils/filter-options.ts
+++ b/src/app/utils/filter-options.ts
@@ -164,7 +164,7 @@ export class CommentFilter {
     }
 
     if (this.keywordSelected !== '') {
-      return com.keywordsFromQuestioner.includes(this.keywordSelected);
+      return com.keywordsFromQuestioner.findIndex(e => e.lemma === this.keywordSelected) >= 0;
     }
 
     if (this.tagSelected !== '') {
diff --git a/src/assets/i18n/creator/de.json b/src/assets/i18n/creator/de.json
index e063663d4ee6645dc5ce299d144008f92e8869ca..4a790c3bb5552bb61a6e0d60917527eaf2b7e5a7 100644
--- a/src/assets/i18n/creator/de.json
+++ b/src/assets/i18n/creator/de.json
@@ -423,7 +423,8 @@
     "topic-requirement-questioners": "Minimale Anzahl Fragensteller*innen",
     "topic-requirement-upvotes": "Minimale Anzahl Up-Votes",
     "topic-requirement-begin-datetime": "Beginn der Zeitspanne",
-    "topic-requirement-end-datetime": "Ende der Zeitspanne"
+    "topic-requirement-end-datetime": "Ende der Zeitspanne",
+    "topic-requirement-reset": "Zurücksetzen"
   },
   "topic-cloud-confirm-dialog": {
     "cancel": "Abbrechen",
@@ -494,8 +495,8 @@
     "notation-tooltip": "Einstellung der Schreibweise: klein, groß, wie vorgegeben",
     "alphabetical-sorting-tooltip": "Alphabetische Sortierung",
     "highestWeight-tooltip": "x Themen mit der höchsten Gewichtung anzeigen",
-    "rotate-weight": "Themen dieser Häufigkeitsgruppe zufällig um x Grad drehen",
-    "rotate-weight-tooltip": "Themen dieser Häufigkeitsgruppe zufällig um x Grad drehen",
+    "rotate-weight": "Themen dieser Häufigkeitsgruppe um x Grad drehen",
+    "rotate-weight-tooltip": "Themen dieser Häufigkeitsgruppe um x Grad drehen",
     "font":"Schrift",
     "reset-btn": "Auf Standardwerte setzen",
     "font-family-tooltip": "Schrift auswählen …",
diff --git a/src/assets/i18n/creator/en.json b/src/assets/i18n/creator/en.json
index 2f025a7940469c506c92fc47bde10bcdf5c79557..ae3434c96bd05fed577349be1aa2376cbaf59f91 100644
--- a/src/assets/i18n/creator/en.json
+++ b/src/assets/i18n/creator/en.json
@@ -430,7 +430,8 @@
     "topic-requirement-questioners": "Minimum number of questioners",
     "topic-requirement-upvotes": "Minimum number of upvotes",
     "topic-requirement-begin-datetime": "Earliest comment",
-    "topic-requirement-end-datetime": "Last comment"
+    "topic-requirement-end-datetime": "Last comment",
+    "topic-requirement-reset": "Reset"
   },
   "topic-cloud-confirm-dialog":{
     "cancel": "Cancel",
@@ -490,15 +491,14 @@
     "highestWeight": "Number of tags with highest weight",
     "notation-tooltip": "Notation-Settings: small, large, standard",
     "alphabetical-sorting-tooltip": "Alphabetical sorting",
-    "rotate-weight-tooltip": "Rotate some entries randomly by x degrees",
     "highestWeight-tooltip": "show x tags with the highest weight",
-    "rotate-weight": "Rotate some entries of this weight class randomly by x degrees",
+    "rotate-weight": "Rotate all entries of this class by x degrees",
+    "rotate-weight-tooltip": "Rotate all entries of this class by x degrees",
     "font":"Font",
     "reset-btn": "Reset",
     "font-family-tooltip": "Select font",
     "bold-notation-tooltip": "Select font-thickness bold",
     "font-style-bold" : "Bold",
-    "font-style-italic": "Italic",
     "font-family":"Font Family",
     "manual-weight-number": "Set quantity",
     "manual-weight-number-tooltip": "Quantity Limitation of this weight class",
diff --git a/src/assets/i18n/participant/de.json b/src/assets/i18n/participant/de.json
index 0505fe2b0b37d1353cd3540f36c8c811e229a60c..187ecce9e070aa2367594f4b22ee56c66c8e24df 100644
--- a/src/assets/i18n/participant/de.json
+++ b/src/assets/i18n/participant/de.json
@@ -307,7 +307,8 @@
     "topic-requirement-questioners": "Minimale Anzahl Fragensteller*innen",
     "topic-requirement-upvotes": "Minimale Anzahl Up-Votes",
     "topic-requirement-begin-datetime": "Beginn der Zeitspanne",
-    "topic-requirement-end-datetime": "Ende der Zeitspanne"
+    "topic-requirement-end-datetime": "Ende der Zeitspanne",
+    "topic-requirement-reset": "Zurücksetzen"
   },
   "dialog-comment": {
     "read-more": "Mehr lesen",
@@ -361,8 +362,8 @@
     "notation-tooltip": "Einstellung der Schreibweise: klein, groß, wie vorgegeben",
     "alphabetical-sorting-tooltip": "Alphabetische Sortierung",
     "highestWeight-tooltip": "x Themen mit der höchsten Gewichtung anzeigen",
-    "rotate-weight": "Themen dieser Häufigkeitsgruppe zufällig um x Grad drehen",
-    "rotate-weight-tooltip": "Themen dieser Häufigkeitsgruppe zufällig um x Grad drehen",
+    "rotate-weight": "Themen dieser Häufigkeitsgruppe um x Grad drehen",
+    "rotate-weight-tooltip": "Themen dieser Häufigkeitsgruppe um x Grad drehen",
     "font":"Schrift",
     "reset-btn": "Auf Standardwerte setzen",
     "font-family-tooltip": "Schrift auswählen …",
diff --git a/src/assets/i18n/participant/en.json b/src/assets/i18n/participant/en.json
index 11b915af1c9c9539c41ea633300286c399eb3e39..012260e357b8a19fddedf3fdc24d9bfe2bb2ac2a 100644
--- a/src/assets/i18n/participant/en.json
+++ b/src/assets/i18n/participant/en.json
@@ -313,7 +313,8 @@
     "topic-requirement-questioners": "Minimum number of questioners",
     "topic-requirement-upvotes": "Minimum number of upvotes",
     "topic-requirement-begin-datetime": "Earliest comment",
-    "topic-requirement-end-datetime": "Last comment"
+    "topic-requirement-end-datetime": "Last comment",
+    "topic-requirement-reset": "Reset"
   },
   "dialog-comment":{
     "read-more": "Read more",
@@ -366,15 +367,14 @@
     "highestWeight": "Number of tags with highest weight",
     "notation-tooltip": "Notation-Settings: small, large, standard",
     "alphabetical-sorting-tooltip": "Alphabetical sorting",
-    "rotate-weight-tooltip": "Rotate some entries randomly by x degrees",
-    "highestWeight-tooltip": "show x tags with the highest weight",
-    "rotate-weight": "Rotate some entries of this weight class randomly by x degrees",
+    "highestWeight-tooltip": "Show x tags with the highest weight",
+    "rotate-weight": "Rotate all entries of this class by x degrees",
+    "rotate-weight-tooltip": "Rotate all entries of this class by x degrees",
     "font":"Font",
     "reset-btn": "Reset",
     "font-family-tooltip": "Select font",
     "bold-notation-tooltip": "Select font-thickness bold",
     "font-style-bold" : "Bold",
-    "font-style-italic": "Italic",
     "font-family":"Font Family",
     "manual-weight-number": "Set quantity",
     "manual-weight-number-tooltip": "Quantity Limitation of this weight class",