From 1504f1d4bbda6d329152dea6a757fe17fe38acbb Mon Sep 17 00:00:00 2001
From: Jan-Hendrik Willms <tleilax+studip@gmail.com>
Date: Thu, 20 Jun 2024 12:27:18 +0000
Subject: [PATCH] don't html escape title attributes in vue, fixes #3050

Closes #3050

Merge request studip/studip!3135
---
 resources/vue/components/ActiveFilter.vue            |  2 +-
 resources/vue/components/AdminCourses.vue            |  2 +-
 resources/vue/components/ContentModulesControl.vue   |  2 +-
 resources/vue/components/ContentModulesEditTiles.vue |  9 ++++++---
 resources/vue/components/ContentmodulesEditTable.vue |  8 +++++---
 resources/vue/components/EditableList.vue            |  2 +-
 resources/vue/components/FilesTable.vue              | 12 ++++++------
 .../courseware/CoursewareContentPermissions.vue      |  6 +++---
 .../tasks/CoursewareTasksDialogDistribute.vue        |  4 ++--
 .../courseware/tasks/TaskGroupsAddSolversDialog.vue  |  4 ++--
 .../courseware/unit/CoursewareUnitItem.vue           |  2 +-
 .../courseware/unit/CoursewareUnitProgress.vue       |  2 +-
 .../form_inputs/CalendarPermissionsTable.vue         |  6 ++++--
 .../form_inputs/MyCoursesColouredTable.vue           |  2 +-
 .../vue/components/questionnaires/InputArray.vue     |  6 +++---
 resources/vue/components/tree/StudipTreeList.vue     | 11 +++++++----
 resources/vue/components/tree/StudipTreeTable.vue    | 11 +++++++----
 resources/vue/components/tree/TreeBreadcrumb.vue     |  2 +-
 resources/vue/components/tree/TreeCourseDetails.vue  |  2 +-
 resources/vue/components/tree/TreeNodeTile.vue       |  2 +-
 resources/vue/components/tree/TreeSearchResult.vue   |  2 +-
 21 files changed, 56 insertions(+), 43 deletions(-)

diff --git a/resources/vue/components/ActiveFilter.vue b/resources/vue/components/ActiveFilter.vue
index d4654faa9f4..5394bce50a0 100644
--- a/resources/vue/components/ActiveFilter.vue
+++ b/resources/vue/components/ActiveFilter.vue
@@ -4,7 +4,7 @@
         <button
             @click="onRemoveActiveFilter"
             type="button"
-            :title="$gettextInterpolate($gettext('Filter \'%{name}\' entfernen'), { name })"
+            :title="$gettextInterpolate($gettext('Filter \'%{name}\' entfernen'), { name }, true)"
         >
             <StudipIcon class="text-bottom" shape="decline" role="presentation" alt="" />
         </button>
diff --git a/resources/vue/components/AdminCourses.vue b/resources/vue/components/AdminCourses.vue
index 23f93755365..d24a9004281 100644
--- a/resources/vue/components/AdminCourses.vue
+++ b/resources/vue/components/AdminCourses.vue
@@ -23,7 +23,7 @@
                 <th v-for="activeField in sortedActivatedFields" :key="`field-${activeField}`" :class="sort.by === activeField ? 'sort' + sort.direction.toLowerCase() : ''">
                     <a href="#"
                        @click.prevent="changeSort(activeField)"
-                       :title="sort.by === activeField && sort.direction === 'ASC' ? $gettextInterpolate('Sortiert aufsteigend nach %{field}', {field: fields[activeField]}) : (sort.by === activeField && sort.direction === 'DESC' ? $gettextInterpolate('Sortiert absteigend nach %{ field } ', { field: fields[activeField]}) : $gettextInterpolate('Sortieren nach %{ field }', { field: fields[activeField]}))"
+                       :title="sort.by === activeField && sort.direction === 'ASC' ? $gettextInterpolate('Sortiert aufsteigend nach %{field}', {field: fields[activeField]}, true) : (sort.by === activeField && sort.direction === 'DESC' ? $gettextInterpolate('Sortiert absteigend nach %{ field } ', { field: fields[activeField]}, true) : $gettextInterpolate('Sortieren nach %{ field }', { field: fields[activeField]}, true))"
                        v-if="!unsortableFields.includes(activeField)"
                     >
                         {{ fields[activeField] }}
diff --git a/resources/vue/components/ContentModulesControl.vue b/resources/vue/components/ContentModulesControl.vue
index f403bddb8c1..34f4125624c 100644
--- a/resources/vue/components/ContentModulesControl.vue
+++ b/resources/vue/components/ContentModulesControl.vue
@@ -15,7 +15,7 @@
                @click.prevent="toggleModuleVisibility(module)">
                 <studip-icon :shape="module.visibility !== 'tutor' ? 'visibility-visible' : 'visibility-invisible'"
                              class="text-bottom"
-                             :title="$gettextInterpolate($gettext('Inhaltsmodul %{ name } für Teilnehmende unsichtbar bzw. sichtbar schalten'), { name: module.displayname})"></studip-icon>
+                             :title="$gettextInterpolate($gettext('Inhaltsmodul %{ name } für Teilnehmende unsichtbar bzw. sichtbar schalten'), { name: module.displayname}, true)"></studip-icon>
             </a>
         </div>
     </div>
diff --git a/resources/vue/components/ContentModulesEditTiles.vue b/resources/vue/components/ContentModulesEditTiles.vue
index 383c6ab4cb6..7407632c40a 100644
--- a/resources/vue/components/ContentModulesEditTiles.vue
+++ b/resources/vue/components/ContentModulesEditTiles.vue
@@ -35,7 +35,8 @@
                                             $gettext(
                                                 'Sortierelement für Werkzeug %{module}. Drücken Sie die Tasten Pfeil-nach-oben oder Pfeil-nach-unten, um dieses Element in der Liste zu verschieben.'
                                             ),
-                                            { module: module.displayname }
+                                            { module: module.displayname },
+                                            true
                                         )
                                     "
                                     @keydown="keyboardHandler($event, module)"
@@ -76,7 +77,8 @@
                                                 $gettext(
                                                     'Inhaltsmodul %{ name } für Teilnehmende unsichtbar bzw. sichtbar schalten'
                                                 ),
-                                                { name: module.displayname }
+                                                { name: module.displayname },
+                                                true
                                             )
                                         "
                                     ></studip-icon>
@@ -90,7 +92,8 @@
                                                 $gettext(
                                                     'Umbenennen des Inhaltsmoduls %{ name }'
                                                 ),
-                                                { name: module.displayname }
+                                                { name: module.displayname },
+                                                true
                                             )
                                         "
                                     ></studip-icon>
diff --git a/resources/vue/components/ContentmodulesEditTable.vue b/resources/vue/components/ContentmodulesEditTable.vue
index 8724a24ed92..0a8a0aa6f38 100644
--- a/resources/vue/components/ContentmodulesEditTable.vue
+++ b/resources/vue/components/ContentmodulesEditTable.vue
@@ -25,7 +25,8 @@
                                 $gettext(
                                     'Sortierelement für Module %{module}. Drücken Sie die Tasten Pfeil-nach-oben oder Pfeil-nach-unten, um dieses Element in der Liste zu verschieben.'
                                 ),
-                                { module: module.displayname }
+                                { module: module.displayname },
+                                true
                             )
                         "
                         @keydown="keyboardHandler($event, module)"
@@ -71,7 +72,8 @@
                                     $gettext(
                                         'Inhaltsmodul %{ name } für Teilnehmende unsichtbar bzw. sichtbar schalten'
                                     ),
-                                    { name: module.displayname }
+                                    { name: module.displayname },
+                                    true
                                 )
                             "
                         ></studip-icon>
@@ -83,7 +85,7 @@
                             :title="
                                 $gettextInterpolate($gettext('Umbenennen des Inhaltsmoduls %{ name }'), {
                                     name: module.displayname,
-                                })
+                                }, true)
                             "
                         ></studip-icon>
                     </a>
diff --git a/resources/vue/components/EditableList.vue b/resources/vue/components/EditableList.vue
index cf1716b6357..39c32ace231 100644
--- a/resources/vue/components/EditableList.vue
+++ b/resources/vue/components/EditableList.vue
@@ -12,7 +12,7 @@
                     <studip-icon v-if="item.icon" :shape="item.icon" role="info" :size="20" class="text-bottom" alt=""></studip-icon>
                     <input v-if="name" type="hidden" :name="name + '[]'" :value="item.value">
                     <span>{{item.name}}</span>
-                    <button v-if="item.deletable" @click.prevent="deleteItem(item)" :title="$gettextInterpolate($gettext('%{ name } löschen'), {name: item.name})" class="undecorated">
+                    <button v-if="item.deletable" @click.prevent="deleteItem(item)" :title="$gettextInterpolate($gettext('%{ name } löschen'), {name: item.name}, true)" class="undecorated">
                         <studip-icon shape="trash" role="clickable" :size="20" class="text-bottom"></studip-icon>
                     </button>
                 </li>
diff --git a/resources/vue/components/FilesTable.vue b/resources/vue/components/FilesTable.vue
index 0c9dbdaeeeb..1e19cc9f948 100644
--- a/resources/vue/components/FilesTable.vue
+++ b/resources/vue/components/FilesTable.vue
@@ -132,7 +132,7 @@
                     >
                         <a href="#"
                            @click.prevent
-                           :title="$gettextInterpolate($gettext('Nach %{ colName } sortieren'), {colName: name})">
+                           :title="$gettextInterpolate($gettext('Nach %{ colName } sortieren'), {colName: name}, true)">
                             {{name}}
                         </a>
                     </th>
@@ -170,14 +170,14 @@
                         <a :href="folder.url"
                            :id="`folder-${folder.id}`"
                            :title="$gettextInterpolate($gettext('Ordner %{foldername} öffnen'),
-                           { foldername: folder.name})">
+                           { foldername: folder.name}, true)">
                             <studip-icon :shape="folder.icon" :size="26" class="text-bottom" alt=""></studip-icon>
                         </a>
                     </td>
                     <td :class="{'filter-match': valueMatchesFilter(folder.name)}">
                         <a :href="folder.url"
                            :title="$gettextInterpolate($gettext('Ordner %{foldername} öffnen'),
-                           { foldername: folder.name})">
+                           { foldername: folder.name}, true)">
                             <span v-html="highlightString(folder.name)"></span>
                         </a>
                     </td>
@@ -228,7 +228,7 @@
                            :href="file.download_url"
                            target="_blank" rel="noopener noreferrer"
                            :title="$gettextInterpolate($gettext('Datei %{filename} herunterladen'),
-                            { filename: file.name })">
+                            { filename: file.name }, true)">
                             <studip-icon :shape="file.icon" :size="24" class="text-bottom"></studip-icon>
                         </a>
                         <studip-icon v-else :shape="file.icon" :size="24"></studip-icon>
@@ -238,14 +238,14 @@
                            class="lightbox-image"
                            data-lightbox="gallery"
                            :title="$gettextInterpolate($gettext('Datei %{filename} anzeigen'),
-                            { filename: file.name })"></a>
+                            { filename: file.name }, true)"></a>
                     </td>
                     <td :class="{'filter-match': valueMatchesFilter(file.name)}">
                         <a :href="file.details_url"
                            data-dialog
                            :id="`file-${file.id}`"
                            :title="$gettextInterpolate($gettext('Details zur Datei %{filename} anzeigen'),
-                            { filename: file.name })">
+                            { filename: file.name }, true)">
                             <span v-html="highlightString(file.name)"></span>
                             <studip-icon v-if="file.isAccessible"
                                          shape="accessibility"
diff --git a/resources/vue/components/courseware/CoursewareContentPermissions.vue b/resources/vue/components/courseware/CoursewareContentPermissions.vue
index d2412ef26c4..60f09644471 100644
--- a/resources/vue/components/courseware/CoursewareContentPermissions.vue
+++ b/resources/vue/components/courseware/CoursewareContentPermissions.vue
@@ -42,7 +42,7 @@
                     <td class="perm">
                         <input
                             class="right"
-                            :title="$gettextInterpolate($gettext('Leserechte für %{ userName }'), { userName: user_perm.username })"
+                            :title="$gettextInterpolate($gettext('Leserechte für %{ userName }'), { userName: user_perm.username }, true)"
                             type="radio"
                             :name="`${user_perm.id}_right`"
                             value="read"
@@ -53,7 +53,7 @@
                     <td class="perm">
                         <input
                             class="right"
-                            :title="$gettextInterpolate($gettext('Lese- und Schreibrechte für %{ userName }'), { userName: user_perm.username })"
+                            :title="$gettextInterpolate($gettext('Lese- und Schreibrechte für %{ userName }'), { userName: user_perm.username }, true)"
                             type="radio"
                             :name="`${user_perm.id}_right`"
                             value="write"
@@ -75,7 +75,7 @@
                     <td class="actions">
                         <button
                             class="cw-permission-delete"
-                            :title="$gettextInterpolate($gettext('Entfernen der Rechte von %{ userName }'), { userName: user_perm.username })"
+                            :title="$gettextInterpolate($gettext('Entfernen der Rechte von %{ userName }'), { userName: user_perm.username }, true)"
                             @click.prevent="confirmDeleteUserPerm(index)"
                         >
                         </button>
diff --git a/resources/vue/components/courseware/tasks/CoursewareTasksDialogDistribute.vue b/resources/vue/components/courseware/tasks/CoursewareTasksDialogDistribute.vue
index 1e076c752fa..7680167cd2e 100644
--- a/resources/vue/components/courseware/tasks/CoursewareTasksDialogDistribute.vue
+++ b/resources/vue/components/courseware/tasks/CoursewareTasksDialogDistribute.vue
@@ -179,7 +179,7 @@
                                         :aria-label="
                                             $gettextInterpolate($gettext('%{userName} auswählen'), {
                                                 userName: user.formattedname,
-                                            })
+                                            }, true)
                                         "
                                     />
                                 </td>
@@ -217,7 +217,7 @@
                                         :aria-label="
                                             $gettextInterpolate($gettext('%{groupName} auswählen'), {
                                                 groupName: group.name,
-                                            })
+                                            }, true)
                                         "
                                     />
                                 </td>
diff --git a/resources/vue/components/courseware/tasks/TaskGroupsAddSolversDialog.vue b/resources/vue/components/courseware/tasks/TaskGroupsAddSolversDialog.vue
index a84334169a2..d7db6e19963 100644
--- a/resources/vue/components/courseware/tasks/TaskGroupsAddSolversDialog.vue
+++ b/resources/vue/components/courseware/tasks/TaskGroupsAddSolversDialog.vue
@@ -44,7 +44,7 @@
                                         :aria-label="
                                             $gettextInterpolate($gettext('%{userName} auswählen'), {
                                                 userName: user.formattedname,
-                                            })
+                                            }, true)
                                         "
                                     />
                                 </td>
@@ -77,7 +77,7 @@
                                         :aria-label="
                                             $gettextInterpolate($gettext('%{groupName} auswählen'), {
                                                 groupName: group.name,
-                                            })
+                                            }, true)
                                         "
                                     />
                                 </td>
diff --git a/resources/vue/components/courseware/unit/CoursewareUnitItem.vue b/resources/vue/components/courseware/unit/CoursewareUnitItem.vue
index f09601e94d7..dc68225f873 100644
--- a/resources/vue/components/courseware/unit/CoursewareUnitItem.vue
+++ b/resources/vue/components/courseware/unit/CoursewareUnitItem.vue
@@ -63,7 +63,7 @@
             :question="
                 $gettextInterpolate($gettext('Möchten Sie das Lernmaterial %{ unitTitle } wirklich löschen?'), {
                     unitTitle: title,
-                })
+                }, true)
             "
             height="200"
             @confirm="executeDelete"
diff --git a/resources/vue/components/courseware/unit/CoursewareUnitProgress.vue b/resources/vue/components/courseware/unit/CoursewareUnitProgress.vue
index 7c9de011ea1..31c6c01d3a7 100644
--- a/resources/vue/components/courseware/unit/CoursewareUnitProgress.vue
+++ b/resources/vue/components/courseware/unit/CoursewareUnitProgress.vue
@@ -17,7 +17,7 @@
             <h1>
                 <a
                     :href="chapterUrl"
-                    :title="$gettextInterpolate('%{ pageTitle } öffnen', { pageTitle: selected.name })"
+                    :title="$gettextInterpolate('%{ pageTitle } öffnen', { pageTitle: selected.name }, true)"
                 >
                     {{ selected.name }}
                 </a>
diff --git a/resources/vue/components/form_inputs/CalendarPermissionsTable.vue b/resources/vue/components/form_inputs/CalendarPermissionsTable.vue
index a0a76a2897a..e507adce1e3 100644
--- a/resources/vue/components/form_inputs/CalendarPermissionsTable.vue
+++ b/resources/vue/components/form_inputs/CalendarPermissionsTable.vue
@@ -30,14 +30,16 @@
                                v-model="user.write_permissions"
                                :aria-label="$gettextInterpolate(
                                    $gettext('Schreibzugriff für %{name}'),
-                                   {name: user.name}
+                                   {name: user.name},
+                                   true
                                )">
                     </td>
                     <td class="actions">
                         <studip-icon shape="trash" aria-role="button" @click="removeContact(user.id)"
                                      :title="$gettextInterpolate(
                                          $gettext('Kalender nicht mehr mit %{name} teilen'),
-                                         {name: user.name}
+                                         {name: user.name},
+                                         true
                                      )"></studip-icon>
                     </td>
                 </tr>
diff --git a/resources/vue/components/form_inputs/MyCoursesColouredTable.vue b/resources/vue/components/form_inputs/MyCoursesColouredTable.vue
index d2cc2f1aa3f..fe67db55661 100644
--- a/resources/vue/components/form_inputs/MyCoursesColouredTable.vue
+++ b/resources/vue/components/form_inputs/MyCoursesColouredTable.vue
@@ -42,7 +42,7 @@
                         <input type="hidden" :name="`${name}_course_ids[${course.id}]`" value="0">
                         <input type="checkbox" :name="`${name}_course_ids[${course.id}]`"
                                value="1" :checked="selected_course_id_list.includes(course.id)"
-                               :title="$gettextInterpolate($gettext('%{course} auswählen'), {course: course.name})">
+                               :title="$gettextInterpolate($gettext('%{course} auswählen'), {course: course.name}, true)">
                     </td>
                 </tr>
                 <tr v-if="loadedSemesters.includes(semester_id) && courses.length === 0">
diff --git a/resources/vue/components/questionnaires/InputArray.vue b/resources/vue/components/questionnaires/InputArray.vue
index f57ca58d33a..896418f425d 100644
--- a/resources/vue/components/questionnaires/InputArray.vue
+++ b/resources/vue/components/questionnaires/InputArray.vue
@@ -22,7 +22,7 @@
                     <td class="dragcolumn">
                         <a class="dragarea"
                            tabindex="0"
-                           :title="$gettextInterpolate($gettext(`Sortierelement für %{label} %{option}. Drücken Sie die Tasten Pfeil-nach-oben oder Pfeil-nach-unten, um dieses Element in der Liste zu verschieben.`), {option, label})"
+                           :title="$gettextInterpolate($gettext(`Sortierelement für %{label} %{option}. Drücken Sie die Tasten Pfeil-nach-oben oder Pfeil-nach-unten, um dieses Element in der Liste zu verschieben.`), {option, label}, true)"
                            @keydown="keyHandler($event, index)"
                            ref="draghandle">
                             <span class="drag-handle"></span>
@@ -41,7 +41,7 @@
                                      shape="trash"
                                      :size="20"
                                      @click.prevent="deleteOption(index)"
-                                     :title="$gettextInterpolate($gettext('%{label} löschen'), {label})"
+                                     :title="$gettextInterpolate($gettext('%{label} löschen'), {label}, true)"
                         />
                     </td>
                 </tr>
@@ -50,7 +50,7 @@
                 <tr>
                     <td :colspan="3 + additionalColspan">
                         <button class="as-link"
-                                :title="$gettextInterpolate($gettext('%{label} hinzufügen'),  {label})"
+                                :title="$gettextInterpolate($gettext('%{label} hinzufügen'),  {label}, true)"
                                 @click.prevent="addOption()">
                             <StudipIcon shape="add" :size="20" alt="" />
                         </button>
diff --git a/resources/vue/components/tree/StudipTreeList.vue b/resources/vue/components/tree/StudipTreeList.vue
index 2ab489c62a4..6214234c3e9 100644
--- a/resources/vue/components/tree/StudipTreeList.vue
+++ b/resources/vue/components/tree/StudipTreeList.vue
@@ -15,7 +15,7 @@
                 <a v-if="editable && currentNode.attributes.id !== 'root'"
                    :href="editUrl + '/' + currentNode.attributes.id"
                    @click.prevent="editNode(editUrl, currentNode.id)" data-dialog="size=medium"
-                   :title="$gettextInterpolate($gettext('%{name} bearbeiten'), {name: currentNode.attributes.name})">
+                   :title="$gettextInterpolate($gettext('%{name} bearbeiten'), {name: currentNode.attributes.name}, true)">
                     <studip-icon shape="edit" :size="20"></studip-icon>
                 </a>
 
@@ -36,7 +36,7 @@
                 <li v-for="(child, index) in children" :key="index" class="studip-tree-child">
                     <a v-if="editable && children.length > 1" class="drag-link"
                        tabindex="0"
-                       :title="$gettextInterpolate($gettext('Sortierelement für Element %{node}. Drücken Sie die Tasten Pfeil-nach-oben oder Pfeil-nach-unten, um dieses Element in der Liste zu verschieben.'), {node: child.attributes.name})"
+                       :title="$gettextInterpolate($gettext('Sortierelement für Element %{node}. Drücken Sie die Tasten Pfeil-nach-oben oder Pfeil-nach-unten, um dieses Element in der Liste zu verschieben.'), {node: child.attributes.name}, true)"
                        @keydown="keyHandler($event, index)"
                        :ref="'draghandle-' + index">
                         <span class="drag-handle"></span>
@@ -92,8 +92,11 @@
                 <tr v-for="(course) in courses" :key="course.id" class="studip-tree-child studip-tree-course">
                     <td>
                         <a :href="courseUrl(course.id)" tabindex="0"
-                           :title="$gettextInterpolate($gettext('Zur Veranstaltung %{ title }'),
-                                { title: course.attributes.title })">
+                           :title="$gettextInterpolate(
+                               $gettext('Zur Veranstaltung %{ title }'),
+                               { title: course.attributes.title },
+                               true
+                           )">
                             <studip-icon shape="seminar" :size="26"></studip-icon>
                             <template v-if="course.attributes['course-number']">
                                 {{ course.attributes['course-number'] }}
diff --git a/resources/vue/components/tree/StudipTreeTable.vue b/resources/vue/components/tree/StudipTreeTable.vue
index 4cfa7d59fd8..093dd9c7a4c 100644
--- a/resources/vue/components/tree/StudipTreeTable.vue
+++ b/resources/vue/components/tree/StudipTreeTable.vue
@@ -79,7 +79,7 @@
                     <td>
                         <a v-if="editable && children.length > 1" class="drag-link" role="option"
                            tabindex="0"
-                           :title="$gettextInterpolate($gettext('Sortierelement für Element %{node}. Drücken Sie die Tasten Pfeil-nach-oben oder Pfeil-nach-unten, um dieses Element in der Liste zu verschieben.'), {node: child.attributes.name})"
+                           :title="$gettextInterpolate($gettext('Sortierelement für Element %{node}. Drücken Sie die Tasten Pfeil-nach-oben oder Pfeil-nach-unten, um dieses Element in der Liste zu verschieben.'), {node: child.attributes.name}, true)"
                            @keydown="keyHandler($event, index)"
                            :ref="'draghandle-' + index">
                             <span class="drag-handle"></span>
@@ -93,7 +93,7 @@
                         <a :href="nodeUrl(child.id, semester !== 'all' ? semester : null)" tabindex="0"
                            @click.prevent="openNode(child)"
                            :title="$gettextInterpolate($gettext('Unterebene %{ node } öffnen'),
-                                { node: node.attributes.name })">
+                                { node: node.attributes.name }, true)">
                             {{ child.attributes.name }}
                         </a>
                     </td>
@@ -112,8 +112,11 @@
                     </td>
                     <td>
                         <a :href="courseUrl(course.id)" tabindex="0"
-                           :title="$gettextInterpolate($gettext('Zur Veranstaltung %{ title }'),
-                                { title: course.attributes.title })">
+                           :title="$gettextInterpolate(
+                               $gettext('Zur Veranstaltung %{ title }'),
+                               { title: course.attributes.title },
+                               true
+                           )">
                             <template v-if="course.attributes['course-number']">
                                 {{ course.attributes['course-number'] }}
                             </template>
diff --git a/resources/vue/components/tree/TreeBreadcrumb.vue b/resources/vue/components/tree/TreeBreadcrumb.vue
index 33b04b3c0a2..a8c3dd5e36a 100644
--- a/resources/vue/components/tree/TreeBreadcrumb.vue
+++ b/resources/vue/components/tree/TreeBreadcrumb.vue
@@ -10,7 +10,7 @@
                     <a :href="nodeUrl(ancestor.classname + '_' + ancestor.id)" :ref="ancestor.id"
                        @click.prevent="openNode(ancestor.id, ancestor.classname)" tabindex="0"
                        :id="'tree-breadcrumb-' + ancestor.id"
-                       :title="$gettextInterpolate($gettext('%{ node } öffnen'), { node: ancestor.name})">
+                       :title="$gettextInterpolate($gettext('%{ node } öffnen'), { node: ancestor.name}, true)">
                         {{ ancestor.name }}
                     </a>
                     <template v-if="index !== node.attributes.ancestors.length - 1">
diff --git a/resources/vue/components/tree/TreeCourseDetails.vue b/resources/vue/components/tree/TreeCourseDetails.vue
index 6f3e056cdb1..020cc330c0d 100644
--- a/resources/vue/components/tree/TreeCourseDetails.vue
+++ b/resources/vue/components/tree/TreeCourseDetails.vue
@@ -12,7 +12,7 @@
             <span v-for="(lecturer, index) in details.lecturers" :key="index">
                 <a :href="profileUrl(lecturer.username)"
                    :title="$gettextInterpolate($gettext('Zum Profil von %{ user }'),
-                        { user: lecturer.name })"
+                        { user: lecturer.name }, true)"
                    tabindex="0">
                     {{ lecturer.name }}
                 </a><template v-if="details.lecturers.length > 1 && index < details.lecturers.length - 1">, </template>
diff --git a/resources/vue/components/tree/TreeNodeTile.vue b/resources/vue/components/tree/TreeNodeTile.vue
index dab2bdf9ff6..698cc25c024 100644
--- a/resources/vue/components/tree/TreeNodeTile.vue
+++ b/resources/vue/components/tree/TreeNodeTile.vue
@@ -1,6 +1,6 @@
 <template>
     <a :href="url" @click.prevent="openNode" :title="$gettextInterpolate($gettext('Unterebene %{ node } öffnen'),
-                                { node: node.attributes.name })">
+                                { node: node.attributes.name }, true)">
         <p class="studip-tree-child-title">
             {{ node.attributes.name }}
         </p>
diff --git a/resources/vue/components/tree/TreeSearchResult.vue b/resources/vue/components/tree/TreeSearchResult.vue
index 1943dd355fe..9799dae1f4c 100644
--- a/resources/vue/components/tree/TreeSearchResult.vue
+++ b/resources/vue/components/tree/TreeSearchResult.vue
@@ -31,7 +31,7 @@
                     </td>
                     <td>
                         <a :href="courseUrl(course.id)"
-                           :title="$gettextInterpolate($gettext('Zur Veranstaltung %{title}'), {title: course.attributes.title})"
+                           :title="$gettextInterpolate($gettext('Zur Veranstaltung %{title}'), {title: course.attributes.title}, true)"
                            tabindex="0">
                             <template v-if="course.attributes['course-number']">
                                 {{ course.attributes['course-number'] }}
-- 
GitLab