diff --git a/assets/js/misc/active-link-trail.js b/assets/js/misc/active-link-trail.js
new file mode 100644
index 0000000000000000000000000000000000000000..1feb460a9e17315ad1af4ef234201116b7104d19
--- /dev/null
+++ b/assets/js/misc/active-link-trail.js
@@ -0,0 +1,62 @@
+/**
+ * @file
+ * Attaches behaviors for Drupal's active trail link marking.
+ */
+
+((Drupal, drupalSettings) => {
+  const activeClass = 'active';
+
+  /**
+   * Append active class.
+   *
+   * The link is only active if it has data-drupal-active-trail=true.
+   *
+   * Does not discriminate based on element type, so allows you to set the
+   * active class on any element: a, li…
+   *
+   * @type {Drupal~behavior}
+   */
+  Drupal.behaviors.ui_suite_bootstrap_activeTrailLinks = {
+    attach(context) {
+      // Start by finding all potentially active links.
+      const { path } = drupalSettings;
+      const queryString = JSON.stringify(path.currentQuery);
+      const querySelector = queryString
+        ? `[data-drupal-link-query="${CSS.escape(queryString)}"]`
+        : ':not([data-drupal-link-query])';
+      const originalSelectors = [`[data-drupal-active-trail=true]`];
+      let selectors;
+
+      // Add language filtering.
+      selectors = [].concat(
+        // Links without any hreflang attributes (most of them).
+        originalSelectors.map((selector) => `${selector}:not([hreflang])`),
+        // Links with hreflang equals to the current language.
+        originalSelectors.map(
+          (selector) => `${selector}[hreflang="${path.currentLanguage}"]`,
+        ),
+      );
+
+      // Add query string selector for pagers, exposed filters.
+      selectors = selectors.map((current) => current + querySelector);
+
+      // Query the DOM.
+      const activeLinks = context.querySelectorAll(selectors.join(','));
+      const il = activeLinks.length;
+      for (let i = 0; i < il; i++) {
+        activeLinks[i].classList.add(activeClass);
+      }
+    },
+    detach(context, settings, trigger) {
+      if (trigger === 'unload') {
+        const activeLinks = context.querySelectorAll(
+          `[data-drupal-active-trail=true]`,
+        );
+        const il = activeLinks.length;
+        for (let i = 0; i < il; i++) {
+          activeLinks[i].classList.remove(activeClass);
+        }
+      }
+    },
+  };
+})(Drupal, drupalSettings);
diff --git a/assets/js/misc/active-link.js b/assets/js/misc/active-link.js
index ff094246c18e86e83a1ffa2de7d87be4be46b00b..b40b7739c4d3110705c0759a10ff3c99b66c1991 100644
--- a/assets/js/misc/active-link.js
+++ b/assets/js/misc/active-link.js
@@ -25,12 +25,11 @@
       // Start by finding all potentially active links.
       const { path } = drupalSettings;
       const queryString = JSON.stringify(path.currentQuery);
-      const querySelector = path.currentQuery
-        ? `[data-drupal-link-query='${queryString}']`
+      const querySelector = queryString
+        ? `[data-drupal-link-query="${CSS.escape(queryString)}"]`
         : ':not([data-drupal-link-query])';
       const originalSelectors = [
-        `[data-drupal-link-system-path="${path.currentPath}"]`,
-        `[data-drupal-active-trail=true]`,
+        `[data-drupal-link-system-path="${CSS.escape(path.currentPath)}"]`,
       ];
       let selectors;
 
@@ -58,17 +57,18 @@
       const il = activeLinks.length;
       for (let i = 0; i < il; i++) {
         activeLinks[i].classList.add(activeClass);
+        activeLinks[i].setAttribute('aria-current', 'page');
       }
     },
     detach(context, settings, trigger) {
       if (trigger === 'unload') {
         const activeLinks = context.querySelectorAll(
           `[data-drupal-link-system-path].${activeClass}`,
-          `[data-drupal-active-trail=true]`,
         );
         const il = activeLinks.length;
         for (let i = 0; i < il; i++) {
           activeLinks[i].classList.remove(activeClass);
+          activeLinks[i].removeAttribute('aria-current');
         }
       }
     },
diff --git a/ui_suite_bootstrap.info.yml b/ui_suite_bootstrap.info.yml
index 1da0622b0f17c28ce36fa186f24b1d4d04bcf2e3..45c9bb7f6e6afa34f77ee946e07afe2fc051dd66 100644
--- a/ui_suite_bootstrap.info.yml
+++ b/ui_suite_bootstrap.info.yml
@@ -101,6 +101,8 @@ libraries-override:
         css/icon.autocomplete.css: false
 
 libraries-extend:
+  core/drupal.active-link:
+    - ui_suite_bootstrap/drupal.active-link
   core/drupal.ajax:
     - ui_suite_bootstrap/drupal.ajax
   core/drupal.autocomplete:
diff --git a/ui_suite_bootstrap.libraries.yml b/ui_suite_bootstrap.libraries.yml
index a08104b2f53831e840f6b25910af1663d2c60bee..0b6bdce97a64bb0f663c624620994837865f931f 100644
--- a/ui_suite_bootstrap.libraries.yml
+++ b/ui_suite_bootstrap.libraries.yml
@@ -23,6 +23,13 @@ component_placeholder:
     theme:
       assets/css/component/placeholder.css: {}
 
+drupal.active-link:
+  js:
+    assets/js/misc/active-link-trail.js: { }
+  dependencies:
+    - core/drupal
+    - core/drupalSettings
+
 drupal.ajax:
   js:
     assets/js/misc/ajax.js: {}