From dc790e93a81f68071137a618aadfe33d8b5c9697 Mon Sep 17 00:00:00 2001
From: Patrick Kollodzik <patrick.kollodzik@gmail.com>
Date: Sat, 3 Sep 2016 00:27:43 +0200
Subject: [PATCH] [TASK] Fluidification of ShortcutToolbarItem

Because the ShortcutToolbarItem has three different actions,
every action has its own template.

Resolves: #77800
Releases: master
Change-Id: I054569376a0a5f62bb40e7d77f675350e0464423
Reviewed-on: https://review.typo3.org/49810
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Alexander Stehlik <alexander.stehlik@gmail.com>
Tested-by: Alexander Stehlik <alexander.stehlik@gmail.com>
Reviewed-by: Joerg Boesche <typo3@joergboesche.de>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
---
 .../ToolbarItems/ShortcutToolbarItem.php      | 161 +++++++-----------
 .../ShortcutToolbarItem/Shortcut.html         |  31 ++++
 .../ShortcutToolbarItem/DropDown.html         |  33 ++++
 .../ShortcutToolbarItem/EditForm.html         |  19 +++
 .../Templates/ShortcutToolbarItem/Item.html   |   7 +
 .../Private/Language/locallang_misc.xlf       |   2 +-
 6 files changed, 154 insertions(+), 99 deletions(-)
 create mode 100644 typo3/sysext/backend/Resources/Private/Partials/ShortcutToolbarItem/Shortcut.html
 create mode 100644 typo3/sysext/backend/Resources/Private/Templates/ShortcutToolbarItem/DropDown.html
 create mode 100644 typo3/sysext/backend/Resources/Private/Templates/ShortcutToolbarItem/EditForm.html
 create mode 100644 typo3/sysext/backend/Resources/Private/Templates/ShortcutToolbarItem/Item.html

diff --git a/typo3/sysext/backend/Classes/Backend/ToolbarItems/ShortcutToolbarItem.php b/typo3/sysext/backend/Classes/Backend/ToolbarItems/ShortcutToolbarItem.php
index cf8151999c21..e089707d2ad6 100644
--- a/typo3/sysext/backend/Classes/Backend/ToolbarItems/ShortcutToolbarItem.php
+++ b/typo3/sysext/backend/Classes/Backend/ToolbarItems/ShortcutToolbarItem.php
@@ -29,6 +29,7 @@ use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
 use TYPO3\CMS\Core\Resource\ResourceFactory;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
+use TYPO3\CMS\Fluid\View\StandaloneView;
 
 /**
  * Class to render the shortcut menu
@@ -127,79 +128,37 @@ class ShortcutToolbarItem implements ToolbarItemInterface
      * Render shortcut icon
      *
      * @return string HTML
+     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidExtensionNameException
+     * @throws \InvalidArgumentException
      */
     public function getItem()
     {
-        $title = htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.bookmarks'));
-        $icon = $this->iconFactory->getIcon('apps-toolbar-menu-shortcut', Icon::SIZE_SMALL)->render('inline');
-        return '
-            <span class="toolbar-item-icon" title="' . $title . '">' . $icon . '</span>
-            <span class="toolbar-item-title">' . $title . '</span>
-            ';
+        return $this->getFluidTemplateObject('Item.html')->render();
     }
 
     /**
      * Render drop down content
      *
      * @return string HTML
+     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidExtensionNameException
+     * @throws \InvalidArgumentException
      */
     public function getDropDown()
     {
-        $languageService = $this->getLanguageService();
-        $shortcutEdit = htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.bookmarksEdit'));
-        $shortcutDelete = htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.bookmarksDelete'));
-        $editIcon = '<a href="#" class="dropdown-table-actions-btn dropdown-table-actions-btn-edit t3js-shortcut-edit" title="' . $shortcutEdit . '">'
-            . $this->iconFactory->getIcon('actions-open', Icon::SIZE_SMALL)->render('inline') . '</a>';
-        $deleteIcon = '<a href="#" class="dropdown-table-actions-btn dropdown-table-actions-btn-delete t3js-shortcut-delete" title="' . $shortcutDelete . '">'
-            . $this->iconFactory->getIcon('actions-delete', Icon::SIZE_SMALL)->render('inline') . '</a>';
-
         $shortcutMenu = [];
-        $shortcutMenu[] = '<h3 class="dropdown-headline">' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.bookmarks')) . '</h3>';
-        $shortcutMenu[] = '<hr>';
-
-        // Render groups and the contained shortcuts
         $groups = $this->getGroupsFromShortcuts();
-        $groupCount = 0;
         arsort($groups, SORT_NUMERIC);
         foreach ($groups as $groupId => $groupLabel) {
-            $shortcuts = $this->getShortcutsByGroup($groupId);
-            if (count($shortcuts) > 0) {
-                if ($groupCount !== 0) {
-                    $shortcutMenu[] = '<hr>';
-                }
-                $groupCount++;
-                if ($groupLabel) {
-                    $shortcutMenu[] = '<h3 class="dropdown-headline" id="shortcut-group-' . (int)$groupId . '">' . $groupLabel . '</h3>';
-                }
-                $shortcutMenu[] = '<div class="dropdown-table" data-shortcutgroup="' . (int)$groupId . '">';
-                foreach ($shortcuts as $shortcut) {
-                    $shortcutItem  = '<div class="dropdown-table-row t3js-topbar-shortcut" data-shortcutid="' . (int)$shortcut['raw']['uid'] . '" data-shortcutgroup="' . (int)$groupId . '">';
-                    $shortcutItem .= '<div class="dropdown-table-column dropdown-table-icon">';
-                    $shortcutItem .= $shortcut['icon'];
-                    $shortcutItem .= '</div>';
-                    $shortcutItem .= '<div class="dropdown-table-column dropdown-table-title">';
-                    $shortcutItem .= '<a class="dropdown-table-title-ellipsis" href="#" onclick="' . htmlspecialchars($shortcut['action']) . ' return false;">';
-                    $shortcutItem .= htmlspecialchars($shortcut['label']);
-                    $shortcutItem .= '</a>';
-                    $shortcutItem .= '</div>';
-                    $shortcutItem .= '<div class="dropdown-table-column dropdown-table-actions">' . $editIcon . $deleteIcon . '</div>';
-                    $shortcutItem .= '</div>';
-                    $shortcutMenu[] = $shortcutItem;
-                }
-                $shortcutMenu[] = '</div>';
-            }
+            $shortcutMenu[] = [
+                'id' => (int)$groupId,
+                'title' => $groupLabel,
+                'shortcuts' => $this->getShortcutsByGroup($groupId)
+            ];
         }
 
-        $compiledShortcutMenu = implode(LF, $shortcutMenu);
-        if (count($shortcutMenu) === 2) {
-            // No shortcuts added yet, show a small help message how to add shortcuts
-            $title = htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.bookmarks'));
-            $icon = '<span title="' . $title . '">' . $this->iconFactory->getIcon('actions-system-shortcut-new', Icon::SIZE_SMALL)->render('inline') . '</span>';
-            $label = str_replace('%icon%', $icon, htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:bookmarkDescription')));
-            $compiledShortcutMenu .= '<p>' . $label . '</p>';
-        }
-
-        return $compiledShortcutMenu;
+        $dropDownView = $this->getFluidTemplateObject('DropDown.html');
+        $dropDownView->assign('shortcutMenu', $shortcutMenu);
+        return $dropDownView->render();
     }
 
     /**
@@ -476,6 +435,7 @@ class ShortcutToolbarItem implements ToolbarItemInterface
             }
             $this->shortcutGroups[$groupId] = $label;
         }
+
         return $this->shortcutGroups;
     }
 
@@ -485,17 +445,18 @@ class ShortcutToolbarItem implements ToolbarItemInterface
      * @param ServerRequestInterface $request
      * @param ResponseInterface $response
      * @return ResponseInterface the full HTML for the form
+     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidExtensionNameException
+     * @throws \RuntimeException
+     * @throws \InvalidArgumentException
      */
     public function editFormAction(ServerRequestInterface $request, ResponseInterface $response)
     {
-        $languageService = $this->getLanguageService();
         $parsedBody = $request->getParsedBody();
         $queryParams = $request->getQueryParams();
 
-        $selectedShortcutId = (int)(isset($parsedBody['shortcutId']) ? $parsedBody['shortcutId'] : $queryParams['shortcutId']);
-        $selectedShortcutGroupId = (int)(isset($parsedBody['shortcutGroup']) ? $parsedBody['shortcutGroup'] : $queryParams['shortcutGroup']);
+        $selectedShortcutId = (int)($parsedBody['shortcutId'] ?? $queryParams['shortcutId']);
+        $selectedShortcutGroupId = (int)($parsedBody['shortcutGroup'] ?? $queryParams['shortcutGroup']);
         $selectedShortcut = $this->getShortcutById($selectedShortcutId);
-
         $shortcutGroups = $this->shortcutGroups;
         if (!$this->getBackendUser()->isAdmin()) {
             foreach ($shortcutGroups as $groupId => $groupName) {
@@ -505,33 +466,14 @@ class ShortcutToolbarItem implements ToolbarItemInterface
             }
         }
 
-        // build the form
-        $content = '
-			<form class="shortcut-form" role="form" data-shortcutid="' . (int)$selectedShortcutId . '">
-                <h3 class="dropdown-headline">
-                    ' . htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.bookmarksEdit')) . '
-                </h3>
-                <hr>
-				<div class="form-group">
-					<input type="text" class="form-control" name="shortcut-title" value="' . htmlspecialchars($selectedShortcut['label']) . '">
-				</div>';
-        $content .= '
-				<div class="form-group">
-					<select class="form-control" name="shortcut-group">';
-        foreach ($shortcutGroups as $shortcutGroupId => $shortcutGroupTitle) {
-            $content .= '<option value="' . (int)$shortcutGroupId . '"' . ($selectedShortcutGroupId == $shortcutGroupId ? ' selected="selected"' : '') . '>' . htmlspecialchars($shortcutGroupTitle) . '</option>';
-        }
-        $content .= '
-					</select>
-				</div>
-                <hr>
-				<input type="button" class="btn btn-default shortcut-form-cancel" value="Cancel">
-				<input type="button" class="btn btn-success shortcut-form-save" value="Save">
-			</form>';
-
-        $response->getBody()->write($content);
-        $response = $response->withHeader('Content-Type', 'text/html; charset=utf-8');
-        return $response;
+        $editFormView = $this->getFluidTemplateObject('EditForm.html');
+        $editFormView->assign('selectedShortcutId', $selectedShortcutId);
+        $editFormView->assign('selectedShortcutGroupId', $selectedShortcutGroupId);
+        $editFormView->assign('selectedShortcut', $selectedShortcut);
+        $editFormView->assign('shortcutGroups', $shortcutGroups);
+
+        $response->getBody()->write($editFormView->render());
+        return $response->withHeader('Content-Type', 'text/html; charset=utf-8');
     }
 
     /**
@@ -660,6 +602,7 @@ class ShortcutToolbarItem implements ToolbarItemInterface
      * @param string $url
      * @param string $shortcutName
      * @return ResponseInterface
+     * @throws \InvalidArgumentException
      */
     protected function tryAddingTheShortcut(ResponseInterface $response, $url, $shortcutName)
     {
@@ -675,8 +618,7 @@ class ShortcutToolbarItem implements ToolbarItemInterface
         }
 
         $response->getBody()->write($shortcutCreated);
-        $response = $response->withHeader('Content-Type', 'text/html; charset=utf-8');
-        return $response;
+        return $response->withHeader('Content-Type', 'text/html; charset=utf-8');
     }
 
     /**
@@ -843,22 +785,21 @@ class ShortcutToolbarItem implements ToolbarItemInterface
      * @param array $row
      * @param array $shortcut
      * @return string Shortcut icon as img tag
+     * @throws \InvalidArgumentException
      */
     protected function getShortcutIcon($row, $shortcut)
     {
-        $languageService = $this->getLanguageService();
-        $titleAttribute = htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.shortcut'));
         switch ($row['module_name']) {
             case 'xMOD_alt_doc.php':
                 $table = $shortcut['table'];
                 $recordid = $shortcut['recordid'];
                 $icon = '';
-                if ($shortcut['type'] == 'edit') {
+                if ($shortcut['type'] === 'edit') {
                     // Creating the list of fields to include in the SQL query:
                     $selectFields = $this->fieldArray;
                     $selectFields[] = 'uid';
                     $selectFields[] = 'pid';
-                    if ($table == 'pages') {
+                    if ($table === 'pages') {
                         $selectFields[] = 'module';
                         $selectFields[] = 'extendToSubpages';
                         $selectFields[] = 'doktype';
@@ -893,16 +834,16 @@ class ShortcutToolbarItem implements ToolbarItemInterface
 
                     $row = $queryBuilder->execute()->fetch();
 
-                    $icon = '<span title="' . $titleAttribute . '">' . $this->iconFactory->getIconForRecord($table, (array)$row, Icon::SIZE_SMALL)->render() . '</span>';
-                } elseif ($shortcut['type'] == 'new') {
-                    $icon = '<span title="' . $titleAttribute . '">' . $this->iconFactory->getIconForRecord($table, [], Icon::SIZE_SMALL)->render() . '</span>';
+                    $icon = $this->iconFactory->getIconForRecord($table, (array)$row, Icon::SIZE_SMALL)->render();
+                } elseif ($shortcut['type'] === 'new') {
+                    $icon = $this->iconFactory->getIconForRecord($table, [], Icon::SIZE_SMALL)->render();
                 }
                 break;
             case 'file_edit':
-                $icon = '<span title="' . $titleAttribute . '">' . $this->iconFactory->getIcon('mimetypes-text-html', Icon::SIZE_SMALL)->render() . '</span>';
+                $icon = $this->iconFactory->getIcon('mimetypes-text-html', Icon::SIZE_SMALL)->render();
                 break;
             case 'wizard_rte':
-                $icon = '<span title="' . $titleAttribute . '">' . $this->iconFactory->getIcon('mimetypes-word', Icon::SIZE_SMALL)->render() . '</span>';
+                $icon = $this->iconFactory->getIcon('mimetypes-word', Icon::SIZE_SMALL)->render();
                 break;
             default:
                 $iconIdentifier = '';
@@ -916,8 +857,9 @@ class ShortcutToolbarItem implements ToolbarItemInterface
                 if (!$iconIdentifier) {
                     $iconIdentifier = 'empty-empty';
                 }
-                $icon = '<span title="' . $titleAttribute . '">' . $this->iconFactory->getIcon($iconIdentifier, Icon::SIZE_SMALL)->render() . '</span>';
+                $icon = $this->iconFactory->getIcon($iconIdentifier, Icon::SIZE_SMALL)->render();
         }
+
         return $icon;
     }
 
@@ -1000,4 +942,27 @@ class ShortcutToolbarItem implements ToolbarItemInterface
     {
         return $GLOBALS['LANG'];
     }
+
+    /**
+     * returns a new standalone view, shorthand function
+     *
+     * @param string $templateFilename
+     * @return StandaloneView
+     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidExtensionNameException
+     * @throws \InvalidArgumentException
+     * @internal param string $templateFile
+     */
+    protected function getFluidTemplateObject(string $templateFilename)
+    {
+        /** @var StandaloneView $view */
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $view->setLayoutRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Layouts')]);
+        $view->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Partials')]);
+        $view->setTemplateRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates')]);
+
+        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/ShortcutToolbarItem/' . $templateFilename));
+
+        $view->getRequest()->setControllerExtensionName('Backend');
+        return $view;
+    }
 }
diff --git a/typo3/sysext/backend/Resources/Private/Partials/ShortcutToolbarItem/Shortcut.html b/typo3/sysext/backend/Resources/Private/Partials/ShortcutToolbarItem/Shortcut.html
new file mode 100644
index 000000000000..501c48febf7b
--- /dev/null
+++ b/typo3/sysext/backend/Resources/Private/Partials/ShortcutToolbarItem/Shortcut.html
@@ -0,0 +1,31 @@
+{namespace core = TYPO3\CMS\Core\ViewHelpers}
+<div class="dropdown-table-row t3js-topbar-shortcut" data-shortcutid="{shortcut.raw.uid}" data-shortcutgroup="{group.id}">
+	<div class="dropdown-table-column dropdown-table-icon">
+		<span title="{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.shortcut')}">
+			<f:format.raw>{shortcut.icon}</f:format.raw>
+		</span>
+	</div>
+	<div class="dropdown-table-column dropdown-table-title">
+		<f:link.external uri="#" class="dropdown-table-title-ellipsis" onclick="{shortcut.action} return false;" defaultScheme="">{shortcut.label}</f:link.external>
+	</div>
+	<div class="dropdown-table-column dropdown-table-actions">
+		<f:render section="Edit"/>
+		<f:render section="Delete"/>
+	</div>
+</div>
+
+<f:section name="Edit">
+	<f:link.external uri="#" class="dropdown-table-actions-btn dropdown-table-actions-btn-edit t3js-shortcut-edit"
+									 title="{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.bookmarksEdit')}"
+									 defaultScheme="">
+		<core:icon identifier="actions-open" alternativeMarkupIdentifier="inline"/>
+	</f:link.external>
+</f:section>
+
+<f:section name="Delete">
+	<f:link.external uri="#" class="dropdown-table-actions-btn dropdown-table-actions-btn-delete t3js-shortcut-delete"
+									 title="{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.bookmarksDelete')}"
+									 defaultScheme="">
+		<core:icon identifier="actions-delete" alternativeMarkupIdentifier="inline"/>
+	</f:link.external>
+</f:section>
diff --git a/typo3/sysext/backend/Resources/Private/Templates/ShortcutToolbarItem/DropDown.html b/typo3/sysext/backend/Resources/Private/Templates/ShortcutToolbarItem/DropDown.html
new file mode 100644
index 000000000000..2754bc6be705
--- /dev/null
+++ b/typo3/sysext/backend/Resources/Private/Templates/ShortcutToolbarItem/DropDown.html
@@ -0,0 +1,33 @@
+{namespace core = TYPO3\CMS\Core\ViewHelpers}
+<h3 class="dropdown-headline">
+	{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.bookmarks')}
+</h3>
+<hr>
+<f:if condition="{f:count(subject: '{shortcutMenu}')} == 0">
+	<f:then>
+		<f:render section="helpMessage"/>
+	</f:then>
+	<f:else>
+		<f:for each="{shortcutMenu}" as="group" iteration="iterator">
+			<f:if condition="!{iterator.isFirst}">
+				<hr>
+			</f:if>
+			<f:if condition="{group.title}">
+				<h3 class="dropdown-headline" id="shortcut-group-{group.id}">{group.title}</h3>
+			</f:if>
+			<div class="dropdown-table" data-shortcutgroup="{group.id}">
+				<f:for each="{group.shortcuts}" as="shortcut">
+					<f:render partial="ShortcutToolbarItem/Shortcut" arguments="{group : group, shortcut : shortcut}" />
+				</f:for>
+			</div>
+		</f:for>
+	</f:else>
+</f:if>
+
+<f:section name="helpMessage">
+	<f:comment>No shortcuts added yet, show a small help message how to add shortcuts</f:comment>
+	<f:alias
+		map="{inlineIcon: '{core:icon(identifier: \'actions-system-shortcut-new\', alternativeMarkupIdentifier: \'inline\')}', inlineIconTitle: '{f:translate(key: \'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.bookmarks\')}'}">
+		<p>{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:bookmarkDescription', arguments:'{0: \'<span title="{inlineIconTitle}">{inlineIcon -> f:format.raw()}</span>\'}') -> f:format.raw()}</p>
+	</f:alias>
+</f:section>
diff --git a/typo3/sysext/backend/Resources/Private/Templates/ShortcutToolbarItem/EditForm.html b/typo3/sysext/backend/Resources/Private/Templates/ShortcutToolbarItem/EditForm.html
new file mode 100644
index 000000000000..9a6728375cdc
--- /dev/null
+++ b/typo3/sysext/backend/Resources/Private/Templates/ShortcutToolbarItem/EditForm.html
@@ -0,0 +1,19 @@
+<form class="shortcut-form" role="form" data-shortcutid="{selectedShortcutId}">
+	<h3 class="dropdown-headline">
+		{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.bookmarksEdit')}
+	</h3>
+	<hr>
+	<div class="form-group">
+		<input type="text" class="form-control" name="shortcut-title" value="{selectedShortcut.label}"/>
+	</div>
+	<div class="form-group">
+		<select class="form-control" name="shortcut-group">
+			<f:for each="{shortcutGroups}" key="shortcutGroupId" as="shortcutGroupTitle">
+				<option value="{shortcutGroupId}" {f:if(condition: '{selectedShortcutGroupId} == {shortcutGroupId}', then: 'selected="selected"')}>{shortcutGroupTitle}</option>
+			</f:for>
+		</select>
+	</div>
+	<hr>
+	<input type="button" class="btn btn-default shortcut-form-cancel" value="Cancel"/>
+	<input type="button" class="btn btn-success shortcut-form-save" value="Save"/>
+</form>
diff --git a/typo3/sysext/backend/Resources/Private/Templates/ShortcutToolbarItem/Item.html b/typo3/sysext/backend/Resources/Private/Templates/ShortcutToolbarItem/Item.html
new file mode 100644
index 000000000000..9cf9b95a527a
--- /dev/null
+++ b/typo3/sysext/backend/Resources/Private/Templates/ShortcutToolbarItem/Item.html
@@ -0,0 +1,7 @@
+{namespace core = TYPO3\CMS\Core\ViewHelpers}
+<span class="toolbar-item-icon" title="{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.bookmarks')}">
+	<core:icon identifier="apps-toolbar-menu-shortcut" alternativeMarkupIdentifier="inline" />
+</span>
+<span class="toolbar-item-title">
+	<f:translate key="LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.bookmarks"/>
+</span>
diff --git a/typo3/sysext/lang/Resources/Private/Language/locallang_misc.xlf b/typo3/sysext/lang/Resources/Private/Language/locallang_misc.xlf
index afed89ddf837..291a1a4e7507 100644
--- a/typo3/sysext/lang/Resources/Private/Language/locallang_misc.xlf
+++ b/typo3/sysext/lang/Resources/Private/Language/locallang_misc.xlf
@@ -91,7 +91,7 @@
 				<source>Go to Workspace Module</source>
 			</trans-unit>
 			<trans-unit id="bookmarkDescription">
-				<source>This is the bookmarks menu. You do not have any bookmarks added yet, you can do so by clicking the bookmark icon %icon%, which you can find on each page in the backend.</source>
+				<source>This is the bookmarks menu. You do not have any bookmarks added yet, you can do so by clicking the bookmark icon %s, which you can find on each page in the backend.</source>
 			</trans-unit>
 			<trans-unit id="bookmark_edit">
 				<source>Edit</source>
-- 
GitLab