diff --git a/composer.json b/composer.json
index 7a7d7fdde1791e84a764bb5a3720eeb710b902f6..f551d644fc4b2341401230f745675bf5acd7ee3f 100644
--- a/composer.json
+++ b/composer.json
@@ -77,7 +77,8 @@
         "phpmd/phpmd": "2.6.0",
         "phpunit/phpunit": "6.5.13",
         "sebastian/phpcpd": "3.0.1",
-        "squizlabs/php_codesniffer": "3.4.0"
+        "squizlabs/php_codesniffer": "3.4.0",
+        "exussum12/coverage-checker": "^1.0"
     },
     "extra": {
         "merge-plugin": {
diff --git a/composer.lock b/composer.lock
index 6f155678386dad4ef2f1627d18e0d3645e8390d5..a3e867e8b1a46199234dc1cc6e831d36f4e9d73d 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "8f632938475a6265104ca49d4fe4539a",
+    "content-hash": "8912fd5b6c4ad5d520c1a17bbc17f289",
     "packages": [
         {
             "name": "ahand/mobileesp",
@@ -7137,6 +7137,106 @@
             ],
             "time": "2015-06-14T21:17:01+00:00"
         },
+        {
+            "name": "doctrine/lexer",
+            "version": "v1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/lexer.git",
+                "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
+                "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Doctrine\\Common\\Lexer\\": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
+                {
+                    "name": "Guilherme Blanco",
+                    "email": "guilhermeblanco@gmail.com"
+                },
+                {
+                    "name": "Johannes Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
+            "homepage": "http://www.doctrine-project.org",
+            "keywords": [
+                "lexer",
+                "parser"
+            ],
+            "time": "2014-09-09T13:34:57+00:00"
+        },
+        {
+            "name": "exussum12/coverage-checker",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/exussum12/coverageChecker.git",
+                "reference": "495c9cb512cdb057cd2c63e6bda0efee4838bb3a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/exussum12/coverageChecker/zipball/495c9cb512cdb057cd2c63e6bda0efee4838bb3a",
+                "reference": "495c9cb512cdb057cd2c63e6bda0efee4838bb3a",
+                "shasum": ""
+            },
+            "require": {
+                "ext-json": "*",
+                "ext-xmlreader": "*",
+                "nikic/php-parser": "^3.1||^4.0",
+                "php": ">=7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0"
+            },
+            "bin": [
+                "bin/diffFilter"
+            ],
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "exussum12\\CoverageChecker\\": "src/",
+                    "exussum12\\CoverageChecker\\tests\\": "tests/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Scott Dutton",
+                    "email": "scott@exussum.co.uk"
+                }
+            ],
+            "description": "Allows checking the code coverage of a single pull request",
+            "time": "2020-10-27T22:49:24+00:00"
+        },
         {
             "name": "friendsofphp/php-cs-fixer",
             "version": "v2.14.0",
@@ -7337,6 +7437,58 @@
             ],
             "time": "2017-10-19T19:58:43+00:00"
         },
+        {
+            "name": "nikic/php-parser",
+            "version": "v4.13.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/nikic/PHP-Parser.git",
+                "reference": "210577fe3cf7badcc5814d99455df46564f3c077"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077",
+                "reference": "210577fe3cf7badcc5814d99455df46564f3c077",
+                "shasum": ""
+            },
+            "require": {
+                "ext-tokenizer": "*",
+                "php": ">=7.0"
+            },
+            "require-dev": {
+                "ircmaxell/php-yacc": "^0.0.7",
+                "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
+            },
+            "bin": [
+                "bin/php-parse"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "4.9-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "PhpParser\\": "lib/PhpParser"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Nikita Popov"
+                }
+            ],
+            "description": "A PHP parser written in PHP",
+            "keywords": [
+                "parser",
+                "php"
+            ],
+            "time": "2021-11-30T19:35:32+00:00"
+        },
         {
             "name": "pdepend/pdepend",
             "version": "2.5.2",
@@ -9636,6 +9788,57 @@
             ],
             "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
             "time": "2017-04-07T12:08:54+00:00"
+        },
+        {
+            "name": "webmozart/assert",
+            "version": "1.4.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/webmozarts/assert.git",
+                "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/webmozarts/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9",
+                "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.3.3 || ^7.0",
+                "symfony/polyfill-ctype": "^1.8"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.6",
+                "sebastian/version": "^1.0.1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.3-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Webmozart\\Assert\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Bernhard Schussek",
+                    "email": "bschussek@gmail.com"
+                }
+            ],
+            "description": "Assertions to validate method input/output with nice error messages.",
+            "keywords": [
+                "assert",
+                "check",
+                "validate"
+            ],
+            "time": "2018-12-25T11:19:39+00:00"
         }
     ],
     "aliases": [],
diff --git a/fid/config/vufind/iconMapping.ini b/fid/config/vufind/iconMapping.ini
new file mode 100644
index 0000000000000000000000000000000000000000..dd04c4b4e5607da9f0efdf93c53c5bb1ad9031b7
--- /dev/null
+++ b/fid/config/vufind/iconMapping.ini
@@ -0,0 +1,23 @@
+;####################################################################
+;##################### DO NOT DELETE THIS HEADER ####################
+;################### Leipzig University Library © 2015 ##############
+;
+; This is the ISIL-instance-specific default INI-file and inherits
+; all the settings from the INI-file defined in [Parent_Config] which
+; points to the default INI-file located in the folder vufind2/local
+;
+
+[Parent_Config]
+relative_path = ../../../local/config/vufind/iconMapping.ini
+
+; A comma-separated list of config sections from the parent which should be
+; completely overwritten by the equivalent sections in this configuration;
+; any sections not listed here will be merged on a section-by-section basis.
+; override_full_sections = "InstitutionInfo,Export"
+
+;
+;       Add instance-specific customization after this header.
+;
+;##################### DO NOT DELETE THIS HEADER ####################
+;####################################################################
+
diff --git a/install-codestylechecker.sh b/install-codestylechecker.sh
new file mode 100755
index 0000000000000000000000000000000000000000..02c158a41dea4e66994f1113479eaa3634e22062
--- /dev/null
+++ b/install-codestylechecker.sh
@@ -0,0 +1,90 @@
+#!/bin/bash
+
+red="\e[0;91m"
+green="\e[0;92m"
+clean="\e[0m"
+
+if [ -z $1 ] 
+then
+    echo -e "\n${red}Nicht genau angegeben was ich tun soll.${clean}\n"
+    echo -e "---------------------------------------------------------------------------"
+    echo -e "\n ./install-codestylechecker.sh install - install the checker and hooks\n"
+    echo -e "\n ./install-codestylechecker.sh update  - update the checker and hooks\n"
+    echo -e "--------------------------------------------------------------------------\n"
+
+    exit 1
+fi
+
+if [ $(which curl) != "/usr/bin/curl" ] 
+then
+	echo -e "\n${red}Benötigt curl.\n"
+	exit 1
+fi
+
+gitdir=$(pwd)
+
+reset
+
+if [ $1 = "install" ]
+then
+
+    gitdir=$(pwd)
+
+    echo -e "${green}Install...${clean}\n"
+
+    mkdir -p $HOME/bin/codestylechecker
+
+    cd $HOME/bin/codestylechecker
+
+    curl -OL https://squizlabs.github.io/PHP_CodeSniffer/phpcs.phar
+    curl -OL https://alpha.finc.info/vufind2/logs/alpha/CodeSniffer.conf
+
+    chmod +x $HOME/bin/codestylechecker/phpcs.phar
+
+    echo -e "\n${green}Kopiere Hooks nach ${gitdir}/.git/hooks\n${clean}"
+
+    cd $gitdir/.git/hooks/
+
+    mv pre-commit pre-commit.old.$(date +%Y-%m-%d)
+    mv pre-push pre-push.old.$(date +%Y-%m-%d)
+
+    curl -OL https://alpha.finc.info/vufind2/logs/alpha/pre-commit
+    curl -OL https://alpha.finc.info/vufind2/logs/alpha/pre-push
+
+    chmod +x $gitdir/.git/hooks/pre-commit
+    chmod +x $gitdir/.git/hooks/pre-push
+
+    echo -e "\n${green}Ready${clean}\n"
+    exit 0
+
+    elif [ $1 = "update" ]
+    then
+
+    echo -e "\n${green}Update...${clean}\n"
+
+    cd $HOME/bin/codestylechecker
+
+    curl -OL https://squizlabs.github.io/PHP_CodeSniffer/phpcs.phar
+
+    chmod +x $HOME/bin/codestylechecker/phpcs.phar
+
+    cd $gitdir/.git/hooks/
+
+    mv pre-commit pre-commit.old.$(date +%Y-%m-%d)
+    mv pre-push pre-push.old.$(date +%Y-%m-%d)
+
+    curl -OL https://alpha.finc.info/vufind2/logs/alpha/pre-commit
+    curl -OL https://alpha.finc.info/vufind2/logs/alpha/pre-push
+
+    chmod +x $gitdir/.git/hooks/pre-commit
+    chmod +x $gitdir/.git/hooks/pre-push
+
+    echo -e "\n${green}Ready.${clean}\n"
+    exit 0
+    fi
+
+echo -e "\n${red}Nix ist passiert.${clean}\n"
+
+exit 1
+
+#heiko.wolf@uni-leipzig.de, 2021
diff --git a/local/config/vufind/iconMapping.ini b/local/config/vufind/iconMapping.ini
new file mode 100644
index 0000000000000000000000000000000000000000..892e76ad27f7e134956d10e88b428d431b7da486
--- /dev/null
+++ b/local/config/vufind/iconMapping.ini
@@ -0,0 +1,119 @@
+;####################################################################
+;##################### DO NOT DELETE THIS HEADER ####################
+;################### Leipzig University Library © 2021 ##############
+;
+; This is the SIGEL-instance-specific default INI-file and inherits
+; all the settings from the INI-file defined in [Parent_Config] which
+; points to the default INI-file located in the folder vufind2/local
+;
+
+[StyleBasedIcons]
+; use facet_avail facet as key and FacetAvail-Array as Mapping
+type = "FacetAvail"
+; combine format and facet_avail, for example AudioLocal
+; type = "Formats_FacetAvail"
+; use true to combine entries or false to use first entries as key
+concatenateKeys = false
+; default icons for field format: Formats | getFacetAvail
+; Formats[default] = ""
+; Formats[unknown] = ""
+
+; finc default mapping for facet_avail
+FacetAvail[marcfincpda] = "fa-home passive"
+FacetAvail[object] = "fa-home object"
+FacetAvail[local] = "fa-home"
+FacetAvail[online] = "fa-globe"
+FacetAvail[free] = "fa-globe"
+FacetAvail[missing] = "fa-question"
+FacetAvail[default] = "fa-book"
+FacetAvail[unknown] = "fa-book"
+
+; finc default mapping for format
+Formats[article] = "fa-file-text-o"
+Formats[preprint] = "fa-file-text-o"
+Formats[book] = "fa-book"
+Formats[notatedmusic] = "fa-music"
+Formats[ebook] = "fa-globe"
+Formats[electronicarticle] = "fa-globe"
+Formats[map] = "fa-map"
+Formats[conferenceproceedings] = "fa-file-text-o"
+Formats[bookcomponentpart] = "fa-book"
+Formats[thesis] = "fa-file-text-o"
+Formats[serialcomponentpart] = "fa-file-text-o"
+Formats[journal] = "fa-file-text"
+Formats[electronicserialcomponentpart] = "fa-globe"
+Formats[electronicjournal] = "fa-globe"
+Formats[bibliography] = "fa-book"
+Formats[exhibitioncatalogue] = "fa-file-text"
+Formats[stillimage] = "fa-picture-o"
+Formats[microfiche] = "fa-floppy-o"
+Formats[electronicbook] = "fa-globe"
+Formats[serial] = "fa-newspaper-o"
+Formats[electronicthesis] = "fa-globe"
+Formats[electronicmanuscript] = "fa-globe"
+Formats[illustratedbook] = "fa-book"
+Formats[monographseries] = "fa-book"
+Formats[electronicbookcomponentpart] = "fa-globe"
+Formats[biography] = "fa-book"
+Formats[cdrom] = "fa-floppy-o"
+Formats[commemorativepublication] = "fa-file-text"
+Formats[manuscript] = "fa-file-text"
+Formats[electronicmusicrecording] = "fa-music"
+Formats[mixedmaterials] = "fa-cube"
+Formats[kit] = "fa-cube"
+Formats[specialprint] = "fa-file-text"
+Formats[electronicserial] = "fa-globe"
+Formats[autobiography] = "fa-book"
+Formats[twodimensionalmovingimage] = "fa-file-video-o"
+Formats[microfilmreel] = "fa-film"
+Formats[video] = "fa-file-video-o"
+Formats[photo] = "fa-picture-o"
+Formats[othercomputercarrier] = "fa-floppy-o"
+Formats[othermicroformcarrier] = "fa-floppy-o"
+Formats[volume] = "fa-book"
+Formats[newspaper] = "fa-newspaper-o"
+Formats[dvdrom] = "fa-floppy-o"
+Formats[dvdvideo] = "fa-file-video-o"
+Formats[onlineresource] = "fa-globe"
+Formats[database] = "fa-database"
+Formats[performedmusic] = "fa-music"
+Formats[musicalscore] = "fa-music"
+Formats[computerdataset] = "fa-file-code-o"
+Formats[textbook] = "fa-book"
+Formats[cartographicimage] = "fa-picture-o"
+Formats[electronicnewspaper] = "fa-globe"
+Formats[computerdisccartridge] = "fa-floppy-o"
+Formats[videocassette] = "fa-file-video-o"
+Formats[microfilmroll] = "fa-film"
+Formats[spokenword] = "fa-file-audio-o"
+Formats[videodisc] = "fa-file-video-o"
+Formats[comicbook] = "fa-book"
+Formats[sheet] = "fa-file-text-o"
+Formats[floppydisc] = "fa-floppy-o"
+Formats[cd] = "fa-floppy-o"
+Formats[website] = "fa-globe"
+Formats[object] = "fa-cube"
+Formats[serialpart] = "fa-file-text"
+Formats[threedimensionalform] = "fa-cube"
+Formats[otheraudiocarrier] = "fa-file-audio-o"
+Formats[computerchipcartridge] = "fa-floppy-o"
+Formats[electronicschoolpublication] = "fa-globe"
+Formats[dvdaudio] = "fa-file-audio-o"
+Formats[audiobook] = "fa-file-audio-o"
+Formats[audiodisc] = "fa-file-audio-o"
+Formats[audiocassette] = "fa-file-audio-o"
+Formats[weblog] = "fa-globe"
+Formats[tactileimage] = "fa-picture-o"
+Formats[threedimensionalmovingimage] = "fa-picture-o"
+Formats[software] = "fa-file-code-o"
+Formats[usbflashdrive] = "fa-floppy-o"
+Formats[vhs] = "fa-file-video-o"
+Formats[dvd] = "fa-file-video-o"
+Formats[othervideocarrier] = "fa-file-video-o"
+Formats[audiocartridge] = "fa-file-audio-o"
+Formats[default] = "fa-question"
+Formats[electronicintegratingresource] = "fa-globe"
+Formats[electronicbookpart] = "fa-globe"
+Formats[electronicbookcomponentpart] = "fa-globe"
+Formats[electronicproceeding] = "fa-globe"
+Formats[norm] = "fa-balance-scale"
diff --git a/local/languages/de.ini b/local/languages/de.ini
index 6428ea9568274ecf180264ac9f35778dece09cc1..43e56bfa00b0e74417949d16562cc638d6d70e5d 100644
--- a/local/languages/de.ini
+++ b/local/languages/de.ini
@@ -1973,7 +1973,21 @@ support_by_dfg = "Die Nationallizenzen wurden gefördert durch die"
 (fa-home object) = "Online-Ressource"
 (fa-globe) = "Online-Ressource"
 (fa-home passive) = "beschaffbar"
-(fa-question) = "entfernt / ersetzt"
+(fa-question) = "unbekannt"
+(fa-file-text-o) = "Artikel"
+(fa-file-text) = "Zeitschrift"
+(fa-book) = "Buch"
+(fa-music) = "Musik"
+(fa-file-video-o) = "Video"
+(fa-floppy-o) = "Datenträger"
+(fa-newspaper-o) = "Schriftenreihe"
+(fa-picture-o) = "Bild"
+(fa-cube) = "Vermischtes"
+(fa-film) = "Film"
+(fa-database) = "Datenbank"
+(fa-file-code-o) = "Software"
+(fa-file-audio-o) = "Audio"
+(fa-balance-scale) = "Norm"
 
 ; HierarchyTree select
 hierarchyTreeSelect = "Ãœbergeordnete Werke:"
@@ -2081,3 +2095,6 @@ Unknown Electronic = "Titel ist beim Resolver-Service nicht bekannt"
 title_wrapper = "%%pageTitle%% %%titleSeparator%% %%siteTitle%%"
 
 load_tab_content_hint = "Klicken Sie hier, um den Inhalt der Registerkarte zu laden."
+
+; #20266
+Additional Titles = "Weitere Titel"
diff --git a/local/languages/en.ini b/local/languages/en.ini
index f1aa7b7cf478120dce8ec464464eec64899cca2b..d52e85f5cd4ccd89bc9c5507b1c997349dd45f9b 100644
--- a/local/languages/en.ini
+++ b/local/languages/en.ini
@@ -2074,7 +2074,21 @@ support_by_dfg = "National licenses were sponsored by "
 (fa-home object) = "online resource"
 (fa-globe) = "online resource"
 (fa-home passive) = "available on request"
-(fa-question) = "removed or replaced"
+(fa-question) = "unknown"
+(fa-file-text-o) = "article"
+(fa-file-text) = "journal"
+(fa-book) = "book"
+(fa-music) = "music"
+(fa-file-video-o) = "video"
+(fa-floppy-o) = "data carrier"
+(fa-newspaper-o) = "Serial"
+(fa-picture-o) = "picture"
+(fa-cube) = "mixed"
+(fa-film) = "movie"
+(fa-database) = "database"
+(fa-file-code-o) = "software"
+(fa-file-audio-o) = "audio"
+(fa-balance-scale) = "norm"
 
 ; HierarchyTree select
 hierarchyTreeSelect = "Parent items:"
@@ -2168,3 +2182,6 @@ Unknown Electronic = "Record is unknown to the resolver service"
 title_wrapper = "%%pageTitle%% %%titleSeparator%% %%siteTitle%%"
 
 load_tab_content_hint = "Click to load tab content."
+
+; #20266
+Additional Titles = "Additional Titles"
\ No newline at end of file
diff --git a/module/finc/src/finc/RecordDriver/SolrMarcFincTrait.php b/module/finc/src/finc/RecordDriver/SolrMarcFincTrait.php
index ba947ac8b20434c701bdd108c0dce3e71c53ee69..fd921067791bc71bb7c91e914ec67f5ff0c780ee 100644
--- a/module/finc/src/finc/RecordDriver/SolrMarcFincTrait.php
+++ b/module/finc/src/finc/RecordDriver/SolrMarcFincTrait.php
@@ -572,6 +572,26 @@ trait SolrMarcFincTrait
         return count($array) ? array_pop($array) : '';
     }
 
+    /**
+     * Get an array of title details with information from MARC field 249a.
+     *
+     * @return array
+     */
+    public function getTitleDetails249a()
+    {
+        $titleDetails = [];
+
+        if ($field = $this->getMarcRecord()->getField('249')) {
+            if ($subfields = $field->getSubfields('a')) {
+                foreach ($subfields as $subfield) {
+                    $titleDetails[] = $subfield->getData();
+                }
+            }
+        }
+
+        return array_unique($titleDetails);
+    }
+
     /**
      * Get an array of title detail lines with original notations combining
      * information from MARC field 245 and linked content in 880.
diff --git a/module/finc/src/finc/View/Helper/Root/Factory.php b/module/finc/src/finc/View/Helper/Root/Factory.php
index 82c343ba186660ec99e903001f73c65ed609594d..cefff99a0a9776e86830d915d1fa23799e1fc473 100644
--- a/module/finc/src/finc/View/Helper/Root/Factory.php
+++ b/module/finc/src/finc/View/Helper/Root/Factory.php
@@ -72,7 +72,8 @@ class Factory
             $container->get('ViewHelperManager')->get('url'),
             $container->get('VuFind\AuthManager'),
             $container->get(EblRewrite::class),
-            $container->get('VuFind\Config')->get('Resolver')
+            $container->get('VuFind\Config')->get('Resolver'),
+            $container->get('VuFind\Config')->get('iconMapping')
         );
 
         //due to https://github.com/vufind-org/vufind/pull/718
diff --git a/module/finc/src/finc/View/Helper/Root/Record.php b/module/finc/src/finc/View/Helper/Root/Record.php
index 340f8980884318fa5765bd0b95292d4f85259f3e..25544d9da640c2b9cf132bf25fef5c1981fd042e 100644
--- a/module/finc/src/finc/View/Helper/Root/Record.php
+++ b/module/finc/src/finc/View/Helper/Root/Record.php
@@ -28,7 +28,6 @@
 namespace finc\View\Helper\Root;
 
 use finc\Rewrite\EblRewrite;
-use Symfony\Component\Config\Definition\Exception\Exception;
 
 /**
  * Record driver view helper
@@ -76,6 +75,37 @@ class Record extends \VuFind\View\Helper\Root\Record
      */
     protected $resolverConfig;
 
+    /**
+     * mapping for facets on style based icons
+     *
+     * @var \Zend\Config\Config
+     */
+    protected $iconConfig;
+
+    /**
+     * Type of Mapping for record on its icon
+     *
+     * @var string
+     */
+    protected $iconMappingType;
+
+    /**
+     * Mapping for style based record icons
+     *
+     * @var array
+     */
+    protected $iconMappings = [];
+
+    /**
+     * Handling for array of entry keys
+     *
+     * true  => concatenate keys for mapping
+     * false => use first key only for mapping
+     *
+     * @var string
+     */
+    protected $concatKeysForIconMapping;
+
     /**
      * Constructor
      *
@@ -91,13 +121,20 @@ class Record extends \VuFind\View\Helper\Root\Record
         \Zend\View\Helper\Url $helper,
         \VuFind\Auth\Manager $manager,
         $rewrite,
-        $resolverConfig
+        $resolverConfig,
+        $iconConfig
     ) {
         parent::__construct($config);
         $this->url = $helper;
         $this->manager = $manager;
         $this->rewrite = $rewrite;
         $this->resolverConfig = $resolverConfig;
+        $this->iconConfig = $iconConfig;
+
+        $this->iconMappingType = $this->iconConfig->StyleBasedIcons->type ?? 'None';
+        $this->iconMappings = isset($this->iconConfig->StyleBasedIcons->{$this->iconMappingType})
+            ? $this->iconConfig->StyleBasedIcons->{$this->iconMappingType}->toArray() : [];
+        $this->concatKeysForIconMapping = $this->iconConfig->StyleBasedIcons->concatenateKeys ? true : false;
     }
 
     /**
@@ -113,28 +150,19 @@ class Record extends \VuFind\View\Helper\Root\Record
         $iconType = $this->getRecordIconType();
         $iconClass = $this->getRecordIconClass($iconType);
         return $this->renderTemplate($tpl . '.phtml', ['iconClass' => $iconClass])
-            . ($addText ? $this->getRecordIconText($iconType,$iconClass) : '');
+            . ($addText ? $this->getRecordIconText($iconType, $iconClass) : '');
     }
 
     /**
      * Get the CSS class used to properly render an icon for given value
      *
-     * @param string $value (identifier) Value to convert into CSS class. Default: null
-     * @param string $classfile Define alternative file for icon class without
-     *                              suffix. Default: record-icon-class.phtml
+     * @param string $key (identifier) Value to convert into CSS class. Default: null
      *
      * @return string
      */
-    public function getRecordIconClass(string $value = null, string $classfile = 'record-icon-class'): string
+    public function getRecordIconClass(string $key = "default"): string
     {
-        if ($value === null) {
-            $value = $this->getRecordIconType();
-        }
-
-        return $this->renderTemplate(
-            $classfile . '.phtml',
-            ['value' => $value]
-        );
+        return $this->iconMappings[$key] ?? $this->iconMappings["default"] ?? "unknown";
     }
 
     /**
@@ -153,13 +181,11 @@ class Record extends \VuFind\View\Helper\Root\Record
             $iconClass = $this->getRecordIconClass($iconType);
         }
         return $this->renderTemplate(
-            $classfile . '.phtml', compact('iconType','iconClass')
+            $classfile . '.phtml', compact('iconType', 'iconClass')
         );
     }
 
-    function getRecordIconType() {
-
-        /* block copied from record-icon - RL */
+    protected function getRecordIconType() {
         $recordType = $this->driver->getRecordType();
         switch ($recordType) {
             case 'lido':
@@ -168,7 +194,14 @@ class Record extends \VuFind\View\Helper\Root\Record
             case 'marcfincpda':
                 return $recordType;
             default:
-                return implode('', $this->driver->getFacetAvail());
+                $types = explode('_', $this->iconMappingType);
+                $recordType = '';
+                foreach ($types as $type) {
+                    $recordTypes = $this->driver->tryMethod("get{$type}") ?? ['default'];
+                    $recordTypes = $this->concatKeysForIconMapping ? implode('', $recordTypes) : $recordTypes[0] ?? 'default';
+                    $recordType .= strtolower(str_replace([' ','-',','], '', $recordTypes));
+                }
+                return $recordType;
         }
     }
 
@@ -197,7 +230,8 @@ class Record extends \VuFind\View\Helper\Root\Record
             $type == 'author'
                 ? $this->removeAuthorDates($lookfor) : $lookfor
         );
-        return parent::getLink($type, $lookfor);
+        /* remove invalid new line in link templates, remove after fixed in templates or VuFind parent */
+        return str_replace(["\n"], '', parent::getLink($type, $lookfor) ?? '');
     }
 
     /**
diff --git a/themes/fid/templates/ajax/resolverLinks.phtml b/themes/fid/templates/ajax/resolverLinks.phtml
index 4b19b271ad482b1eee1fc5b5f97ea86420d6b977..8f795e48db9f968b50665cd8e06b8e657e7270de 100644
--- a/themes/fid/templates/ajax/resolverLinks.phtml
+++ b/themes/fid/templates/ajax/resolverLinks.phtml
@@ -12,9 +12,17 @@
             <li>
               <?php if (!empty($link['href'])): ?>
               <?php /* fid: #16136 remove traffic light - GG */?>
-                  <a href="<?=$this->escapeHtmlAttr($link['href'])?>" target="_blank" title="<?=isset($link['service_type'])?$this->escapeHtmlAttr($link['service_type']):''?>"<?=!empty($link['access'])?' class="access-'.$link['access'].'"':''?>>
-                      <i class="icon icon-external-link" aria-hidden="true"></i><?=isset($link['title'])?$this->escapeHtml($this->transEsc($link['title'])):''?>
-                  </a> <br />
+                  <?= $this->externalLink(
+                      $this->escapeHtmlAttr($link['href']),
+                      '<i class="icon icon-external-link" aria-hidden="true"></i>'
+                        . (isset($link['title']) ? $this->escapeHtml($this->transEsc($link['title'])) : ''),
+                      [
+                          'title' => isset($link['service_type']) ? $this->escapeHtmlAttr($link['service_type']) : '',
+                          'class' => !empty($link['access']) ? 'access-' . $link['access'] : ''
+                      ],
+                      true
+                  ); ?>
+                  <br />
                   <?php /* fid: #16136 remove coverage - GG */?>
               <?php else: ?>
                 <?=isset($link['title'])?$this->escapeHtml($this->transEsc($link['title'])):''?>
diff --git a/themes/fid/templates/footer.phtml b/themes/fid/templates/footer.phtml
index 29c511c5b11555f96cef52d3e6f0629411f2baf0..f8243b8f6d6ef0d0c89e09a173383a935a5a4ad2 100644
--- a/themes/fid/templates/footer.phtml
+++ b/themes/fid/templates/footer.phtml
@@ -37,12 +37,18 @@
       <div class="footer-column">
         <?=$this->layout()->poweredBy?>
         <span lang="en">Powered by</span>
-        <a href="https://vufind.org/" title="<?=$this->transEsc('vufind-logo_title')?>" target="_blank">
-          <img src="<?=$this->imageLink('vufind_logo.png')?>" alt="<?=$this->transEsc('vufind-logo_alt')?>"/>
-        </a>
-        <a href="http://blog.finc.info" title="<?=$this->transEsc('finc-logo_title')?>" target="_blank">
-          <img src="<?=$this->imageLink('finc_logo.png')?>" alt="<?=$this->transEsc('finc-logo_alt')?>"/>
-        </a>
+        <?= $this->externalLink(
+              "https://vufind.org",
+              '<img src="' . $this->imageLink('vufind_logo.png') . '" alt="' . $this->translate('vufind-logo_alt') . '" aria-hidden="true"/>',
+              ['title' => $this->translate('vufind-logo_title')],
+              true
+        ) ?>
+        <?= $this->externalLink(
+              "https://blog.finc.info",
+              '<img src="' . $this->imageLink('finc_logo.png') . '" alt="' . $this->translate('finc-logo_alt') . '" aria-hidden="true"/>',
+              ['title' => $this->translate('finc-logo_title')],
+              true
+        ) ?>
       </div>
     </div>
 </footer>
diff --git a/themes/fid/templates/myresearch/databases.phtml b/themes/fid/templates/myresearch/databases.phtml
index a50765777df515d60444de9501ede77b0afdac48..db0bc701b7d3514ee2f98ae6da79a9f5bc6f14b7 100644
--- a/themes/fid/templates/myresearch/databases.phtml
+++ b/themes/fid/templates/myresearch/databases.phtml
@@ -37,7 +37,7 @@ $account = $this->auth()->getManager();
     <ul class="licenses">
       <?php foreach ($licenses as $license): ?>
         <li>
-          <a href="<?= $license['url'] ?>" target="_blank"><?= $this->translate('licenses_' . $license['name']) ?></a><br/>
+          <?= $this->externalLink($license['url'], $this->translate('licenses_' . $license['name'])) ?><br/>
           <span><?= $license['desc'] ?></span>
           <br/><br/>
         </li>
diff --git a/themes/finc/scss/compiled.scss b/themes/finc/scss/compiled.scss
index 7b324eb9c6768c30ea9fc2a22f7d654a92f50f31..63d611713d1b280e05568037f2dab084e5e6765d 100644
--- a/themes/finc/scss/compiled.scss
+++ b/themes/finc/scss/compiled.scss
@@ -1265,11 +1265,23 @@ table.collapse.in {
   margin-top: ($grid-gutter-width / 2);
 }
 
+.margin-t-half {
+  margin-top: ($grid-gutter-width / 4);
+}
+
 ////// NO margin bottom
 .no-margin-btm {
   margin-bottom: 0;
 }
 
+.margin-btm {
+  margin-bottom: ($grid-gutter-width / 2);
+}
+
+.margin-btm-half {
+  margin-bottom: ($grid-gutter-width / 4);
+}
+
 ////// NO margin left
 .no-margin-l {
   margin-left: 0;
diff --git a/themes/finc/templates/RecordDriver/DefaultRecord/data-multiline.phtml b/themes/finc/templates/RecordDriver/DefaultRecord/data-multiline.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..0e1ea67853047559d0e7c9d1588a9cf7a84f7047
--- /dev/null
+++ b/themes/finc/templates/RecordDriver/DefaultRecord/data-multiline.phtml
@@ -0,0 +1,7 @@
+<!-- finc: RecordDriver - DefaultRecord - data-multiline -->
+<?php if (is_array($data)): ?>
+  <?=implode('<hr class="margin-t-half margin-btm-half" />', $data) ?>
+<?php else: ?>
+  <?= $data ?>
+<?php endif; ?>
+<!-- finc: RecordDriver - DefaultRecord - data-multiline - END -->
diff --git a/themes/finc/templates/RecordDriver/DefaultRecord/record-icon-class.phtml b/themes/finc/templates/RecordDriver/DefaultRecord/record-icon-class.phtml
deleted file mode 100644
index c665701859e2e522a6d8516918ad73c3656a7231..0000000000000000000000000000000000000000
--- a/themes/finc/templates/RecordDriver/DefaultRecord/record-icon-class.phtml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-$normalizedValue = preg_replace('/[^a-z0-9]/', '', strtolower($this->value));
-
-// Convert normalizedValue to styles
-switch ($normalizedValue) {
-  case 'local':
-    echo 'fa-home';
-    break;
-  case 'freeonline':
-  case 'onlinefree':
-  case 'online':
-  case 'free':
-    echo 'fa-globe';
-    break;
-  case 'missing':
-    echo 'fa-question';
-    break;
-  default:
-    echo 'fa-book';
-    break;
-}
-?>
diff --git a/themes/finc/templates/RecordDriver/DefaultRecord/record-icon-sprite-class.phtml b/themes/finc/templates/RecordDriver/DefaultRecord/record-icon-sprite-class.phtml
deleted file mode 100644
index 118bd36bdfb8b84448a4f98e89813fa6bb9594ab..0000000000000000000000000000000000000000
--- a/themes/finc/templates/RecordDriver/DefaultRecord/record-icon-sprite-class.phtml
+++ /dev/null
@@ -1,176 +0,0 @@
-<?php
-$normalizedValue = preg_replace('/[^a-z0-9]/', '', strtolower($this->value));
-// Convert normalizedValue to styles
-switch ($normalizedValue) {
-
-  //block book
-  case 'book':
-  case 'articles':
-    echo 'book';
-    break;
-  //block general audio
-  case 'audio':
-  case 'musicrecording':
-  case 'record':
-  case 'soundrecordingmedium':
-  case 'electronicsoundrecordingmedium':
-  case 'soundrecording':
-    echo 'audio';
-    break;
-  //block tape audio
-  case 'audiotape':
-  case 'cassette':
-  case 'soundcassette':
-    echo 'audiotape';
-    break;
-  //block braille
-  case 'braille':
-    echo 'braille';
-    break;
-  //block digital audio
-  case 'cd':
-  case 'dvdaudio':
-  case 'sounddisc':
-    echo 'cd';
-    break;
-  //block digital video
-  case 'dvd':
-  case 'blueraydisc':
-  case 'dvdvideo':
-  case 'videodisc':
-    echo 'dvd';
-    break;
-  //block ebook
-  case 'ebook':
-    echo 'ebook';
-    break;
-  //block digital non-book
-  case 'electronicnewspaper':
-  case 'newspaperarticle':
-  case 'newspaper':
-  case 'textresource':
-    echo 'newspaper';
-    break;
-  //block manuscripts
-  case 'manuscript':
-  case 'nachlass':
-    echo 'manuscript';
-    break;
-  //block articles
-  case 'article':
-  case 'articlearticle':
-  case 'electronic':
-  case 'electronicarticle':
-  case 'electronicresourcedatacarrier':
-  case 'electronicresourceremoteaccess':
-    echo 'electronic';
-    break;
-  //block globe
-  case 'globe':
-    echo 'globe';
-    break;
-  //block kit
-  case 'kit':
-    echo 'kit';
-    break;
-  //block journal
-  case 'journal':
-  case 'journalnewspaper':
-  case 'serial':
-    echo 'journal';
-    break;
-  //block ejournal
-  case 'electronicjournal':
-  case 'electronicserial':
-    echo 'electronicjournal';
-    break;
-  //block map
-  case 'map':
-  case 'atlas':
-    echo 'map';
-    break;
-  //block microfilm
-  case 'microfilm':
-  case 'microfiche':
-  case 'microform':
-    echo 'microfilm';
-    break;
-  //block musical score
-  case 'musicalscore':
-  case 'notatedmusic':
-  case 'electronicmusicalscore':
-    echo 'musicalscore';
-    break;
-  //block images
-  case 'photo':
-  case 'artprint':
-  case 'collage':
-  case 'drawing':
-  case 'flashcard':
-  case 'painting':
-  case 'photonegative':
-  case 'placard':
-  case 'print':
-  case 'sensorimage':
-  case 'transparency':
-    echo 'image';
-    break;
-  //block physical object
-  case 'physicalobject':
-    echo 'physicalobject';
-    break;
-  //block othe rimages
-  case 'sensorimage':
-  case 'chart':
-    echo 'chart';
-    break;
-  //block sets
-  case 'sets':
-    echo 'sets';
-    break;
-  //block slide
-  case 'slide':
-    echo 'slide';
-    break;
-  //block software
-  case 'software':
-  case 'cdrom':
-  case 'chipcartridge':
-  case 'disccartridge':
-  case 'dvdrom':
-  case 'floppydisk':
-  case 'tapecartridge':
-  case 'tapecassette':
-  case 'tapereel':
-    echo 'software';
-    break;
-  //block thesis
-  case 'thesis':
-  case 'electronicthesis':
-    echo 'thesis';
-    break;
-
-  //block unknown
-  case 'unknown':
-    echo 'unknown';
-    break;
-  //block analog video
-  case 'vhs':
-  case 'video':
-  case 'videotape':
-  case 'videocartridge':
-  case 'videocassette':
-    echo 'video';
-    break;
-  //block film
-  case 'audiovisualmedia':
-  case 'filmstrip':
-  case 'motionpicture':
-  case 'videoreel':
-    echo 'film';
-    break;
-  //default
-  default:
-    echo 'unknown';
-    break;
-}
\ No newline at end of file
diff --git a/themes/finc/templates/RecordDriver/DefaultRecord/record-icon-sprite.phtml b/themes/finc/templates/RecordDriver/DefaultRecord/record-icon-sprite.phtml
deleted file mode 100644
index 279b1a67b82f98758a2450897594c432a7d017d8..0000000000000000000000000000000000000000
--- a/themes/finc/templates/RecordDriver/DefaultRecord/record-icon-sprite.phtml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php
-$formats = [];
-foreach ($this->driver->getFormats() as $format) {
-  $formats[] = $this->record($this->driver)->getRecordIconClass(
-    $format, 'record-icon-sprite-class'
-  );
-}
-$formats = array_unique($formats);
-asort($formats);
-?>
-<span class="sprite-media-icon <?=array_pop($formats)?>"></span>
\ No newline at end of file
diff --git a/themes/finc/templates/RecordTab/holdingsils.phtml b/themes/finc/templates/RecordTab/holdingsils.phtml
index ed99f581cf84e3bd1f396fba374371e32315551f..392dd55a860ef27148f0782b7d3ea375283f8c8c 100644
--- a/themes/finc/templates/RecordTab/holdingsils.phtml
+++ b/themes/finc/templates/RecordTab/holdingsils.phtml
@@ -179,7 +179,7 @@ if (!empty($holdingTitleHold)): ?>
   <h2><?=$this->transEsc("external_access")?></h2>
   <?php if (!empty($extUrls)): ?>
     <?php foreach ($extUrls as $current): ?>
-      <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>"><?=$this->translate($current['desc'])?></a>
+      <?=$this->externalLink($this->escapeHtmlAttr($this->proxyUrl($current['url'])), $this->translate($current['desc']))?>
       <br/>
     <?php endforeach; ?>
   <?php endif; ?>