diff --git a/Module.php b/Module.php
index feed5874ec883a3b86e2a0064f85051abd695a2c..7e8ce144fddd94a3fd6340816ff85b07a1edd6d8 100644
--- a/Module.php
+++ b/Module.php
@@ -207,6 +207,14 @@ SQL;
             'view.browse.after',
             [$this, 'filterAdminDashboardPanels']
         );
+
+        // The AbstractMetadata class is used in order to manage all formats,
+        // even if OaiDcTerms doesn't require it.
+        $sharedEventManager->attach(
+            \OaiPmhRepository\OaiPmh\Metadata\AbstractMetadata::class,
+            'oaipmhrepository.values',
+            [$this, 'filterOaiPmhRepositoryValues']
+        );
     }
 
     public function getConfigForm(PhpRenderer $renderer)
@@ -276,6 +284,57 @@ SQL;
         ]);
     }
 
+    public function filterOaiPmhRepositoryValues(Event $event)
+    {
+        static $genericDcterms;
+
+        if (is_null($genericDcterms)) {
+            $services = $this->getServiceLocator();
+            $settings = $services->get('Omeka\Settings');
+            $genericDcterms = $settings->get('oaipmhrepository_generic_dcterms', false);
+        }
+        if (!$genericDcterms) {
+            return;
+        }
+
+        $prefix = $event->getParam('prefix');
+        if ($prefix === 'oai_dcterms') {
+            return;
+        }
+
+        $map = include __DIR__ . '/data/mappings/dc_generic.php';
+        $term = $event->getParam('term');
+        if (empty($map[$term])) {
+            return;
+        }
+
+        $resource = $event->getParam('resource');
+        $values = $event->getParam('values');
+
+        $single = !is_array($values);
+        if ($single) {
+            if (count($values)) {
+                return;
+            }
+
+            foreach ($map[$term] as $refinedTerm) {
+                $refinedValue = $resource->value($refinedTerm);
+                if ($refinedValue) {
+                    $event->setParam('values', $refinedValue);
+                    return;
+                }
+            }
+
+            return;
+        }
+
+        foreach ($map[$term] as $refinedTerm) {
+            $refinedValues = $resource->value($refinedTerm, ['all' => true, 'default' => []]);
+            $values = array_merge($values, $refinedValues);
+        }
+        $event->setParam('values', $values);
+    }
+
     protected function getServerNameWithoutProtocol($serviceLocator)
     {
         $viewHelpers = $serviceLocator->get('ViewHelperManager');
diff --git a/README.md b/README.md
index 1ad0a0a6083fe86f753bb4b668b790d5ec33dc08..c47f850c05f19ede3eecf208438974c0454fb5c9 100644
--- a/README.md
+++ b/README.md
@@ -86,6 +86,14 @@ items and the attached item sets as oai sets.
 There is only one format currently, but new ones can be added, for example when
 the resource have a unique standard identifier.
 
+### Genericize Dublin Core terms
+
+This option allows to expose all metadata in the standard oai_dc and use refined
+terms for Dublin Core elements, for example "dcterms:abstract" will be merged
+with "dc:description". For other merges, the event `oaipmhrepository.values` can
+be used. For a quick hack, the file `data/mapping/generic_dcterms.php` can be
+used.
+
 ### Human interface
 
 The OAI-PMH pages can be displayed and browsed with a themable responsive human
diff --git a/config/module.config.php b/config/module.config.php
index a713c0cd532d1585f8291e9c573bf03c4c8ed9f2..3d5cd20d02535e66c9e477585b46310cef14af40 100644
--- a/config/module.config.php
+++ b/config/module.config.php
@@ -103,6 +103,7 @@ return [
             'oaipmhrepository_append_identifier_global' => 'api_url',
             'oaipmhrepository_append_identifier_site' => 'absolute_site_url',
             'oaipmhrepository_oai_set_format' => 'basic',
+            'oaipmhrepository_generic_dcterms' => true,
             'oaipmhrepository_human_interface' => true,
             'oaipmhrepository_redirect_route' => '',
             'oaipmhrepository_list_limit' => 50,
diff --git a/data/mappings/dc_generic.php b/data/mappings/dc_generic.php
new file mode 100644
index 0000000000000000000000000000000000000000..af32bfcff62e8f48e96512762b26c14cb80c9cad
--- /dev/null
+++ b/data/mappings/dc_generic.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * Refinements of Dublin Core.
+ *
+ * Dublin Core properties and property refinements. See DCMI Metadata Terms:
+ * http://dublincore.org/documents/dcmi-terms/
+ * The order is the Omeka one.
+ *
+ * This mapping may be used by the filter `oaipmhrepository.values`.
+ * @todo Use the rdf relations directly.
+ */
+return [
+    'dcterms:title' => [
+        'dcterms:alternative',
+    ],
+    'dcterms:creator' => [
+    ],
+    'dcterms:subject' => [
+    ],
+    'dcterms:description' => [
+        'dcterms:tableOfContents',
+        'dcterms:abstract',
+    ],
+    'dcterms:publisher' => [
+    ],
+    'dcterms:contributor' => [
+    ],
+    'dcterms:date' => [
+        'dcterms:created',
+        'dcterms:valid',
+        'dcterms:available',
+        'dcterms:issued',
+        'dcterms:modified',
+        'dcterms:dateAccepted',
+        'dcterms:dateCopyrighted',
+        'dcterms:dateSubmitted',
+    ],
+    'dcterms:type' => [
+    ],
+    'dcterms:format' => [
+        'dcterms:extent',
+        'dcterms:medium',
+    ],
+    'dcterms:identifier' => [
+        'dcterms:bibliographicCitation',
+    ],
+    // Source is a refinement of Relation too.
+    'dcterms:source' => [
+    ],
+    'dcterms:language' => [
+    ],
+    'dcterms:relation' => [
+        'dcterms:isVersionOf',
+        'dcterms:hasVersion',
+        'dcterms:isReplacedBy',
+        'dcterms:replaces',
+        'dcterms:isRequiredBy',
+        'dcterms:requires',
+        'dcterms:isPartOf',
+        'dcterms:hasPart',
+        'dcterms:isReferencedBy',
+        'dcterms:references',
+        'dcterms:isFormatOf',
+        'dcterms:hasFormat',
+        'dcterms:conformsTo',
+    ],
+    'dcterms:coverage' => [
+        'dcterms:spatial',
+        'dcterms:temporal',
+    ],
+    'dcterms:rights' => [
+        'dcterms:accessRights',
+        'dcterms:license',
+    ],
+    // Ungenerized terms.
+    // 'dcterms:audience',
+        // 'dcterms:mediator',
+        // 'dcterms:educationLevel',
+    // 'dcterms:rightsHolder',
+    // 'dcterms:provenance',
+    // 'dcterms:instructionalMethod',
+    // 'dcterms:accrualMethod',
+    // 'dcterms:accrualPeriodicity',
+    // 'dcterms:accrualPolicy',
+];
diff --git a/src/Form/ConfigForm.php b/src/Form/ConfigForm.php
index 531ca8f7c53a4c1c9ac81b73161b396ab646ba39..2ae6b8ccd5c3b4e2ee75c707e8656350a000612c 100644
--- a/src/Form/ConfigForm.php
+++ b/src/Form/ConfigForm.php
@@ -141,6 +141,17 @@ class ConfigForm extends Form implements TranslatorAwareInterface
             ],
         ]);
 
+        $this->add([
+            'name' => 'oaipmhrepository_generic_dcterms',
+            'type' => Element\Checkbox::class,
+            'options' => [
+                'label' => 'Genericize dcterms', // @translate
+                'info' => $this->translate('Use refined terms for Dublin Core elements, for example dcterms:abstract will be merged with dc:description.') // @translate
+                    . $this->translate('It allows to expose all metadata in the standard oai_dc.') // @translate
+                    . $this->translate('For other merges, the event "oaipmhrepository.values" can be used.'), // @translate
+            ],
+        ]);
+
         $this->add([
             'name' => 'oaipmhrepository_human_interface',
             'type' => Element\Checkbox::class,