diff --git a/composer.json b/composer.json
index 83b40ee335111e7a55d8a284e237c00b013c344e..989c03fbc4536a184c4ff6e53e87ae1e7abf005d 100644
--- a/composer.json
+++ b/composer.json
@@ -90,8 +90,8 @@
         "drupal/admin_toolbar": "3.1.0",
         "drupal/administerusersbyrole": "3.0",
         "drupal/allowed_formats": "1.3",
-        "drupal/anchor_link": "1.7",
-        "drupal/better_exposed_filters": "5.0-beta3",
+        "drupal/anchor_link": "1.9",
+        "drupal/better_exposed_filters": "5.0",
         "drupal/block_field": "1.0.0-rc2",
         "drupal/block_permissions": "1.2",
         "drupal/block_region_permissions": "1.4",
diff --git a/composer.lock b/composer.lock
index dd6dcc645145ab24db8bfae5dc17176ae0c3d504..411141915e4b2dc1eb8875b84ea5df368d9c57ff 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": "48d56c2b2219d32e7748e0c8de599e83",
+    "content-hash": "2ac8b205c44d2a74f0a1053fecd19f48",
     "packages": [
         {
             "name": "alchemy/zippy",
@@ -1732,7 +1732,7 @@
             "extra": {
                 "drupal": {
                     "version": "3.1.0",
-                    "datestamp": "1643097060",
+                    "datestamp": "1643742891",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
@@ -1891,17 +1891,17 @@
         },
         {
             "name": "drupal/anchor_link",
-            "version": "1.7.0",
+            "version": "1.9.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/anchor_link.git",
-                "reference": "8.x-1.7"
+                "reference": "8.x-1.9"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/anchor_link-8.x-1.7.zip",
-                "reference": "8.x-1.7",
-                "shasum": "625c209245779377beede4d6eb7f87c7eac75dd0"
+                "url": "https://ftp.drupal.org/files/projects/anchor_link-8.x-1.9.zip",
+                "reference": "8.x-1.9",
+                "shasum": "48d343f29dc034bf2deb7de858498fb80d558ca8"
             },
             "require": {
                 "drupal/core": "^8 || ^9"
@@ -1909,8 +1909,8 @@
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "8.x-1.7",
-                    "datestamp": "1582013628",
+                    "version": "8.x-1.9",
+                    "datestamp": "1643826959",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
@@ -1927,11 +1927,11 @@
                     "homepage": "https://www.drupal.org/user/255384"
                 },
                 {
-                    "name": "RajabNatshah",
+                    "name": "Rajab Natshah",
                     "homepage": "https://www.drupal.org/user/1414312"
                 }
             ],
-            "description": "This plugin module adds the better link dialog and anchor related features to CKEditor in Drupal 8",
+            "description": "This plugin module adds the better link dialog and anchor related features to CKEditor in Drupal 9",
             "homepage": "https://www.drupal.org/project/anchor_link",
             "support": {
                 "source": "https://git.drupalcode.org/project/anchor_link"
@@ -1939,17 +1939,17 @@
         },
         {
             "name": "drupal/better_exposed_filters",
-            "version": "5.0.0-beta3",
+            "version": "5.0.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/better_exposed_filters.git",
-                "reference": "8.x-5.0-beta3"
+                "reference": "8.x-5.0"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/better_exposed_filters-8.x-5.0-beta3.zip",
-                "reference": "8.x-5.0-beta3",
-                "shasum": "23f00fe898cd9e4f2278ef790bc9f1d197312ac3"
+                "url": "https://ftp.drupal.org/files/projects/better_exposed_filters-8.x-5.0.zip",
+                "reference": "8.x-5.0",
+                "shasum": "ef575591af202b5c6867841ce58e1f447455e502"
             },
             "require": {
                 "drupal/core": "^8.8 || ^9",
@@ -1961,11 +1961,11 @@
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "8.x-5.0-beta3",
-                    "datestamp": "1625665853",
+                    "version": "8.x-5.0",
+                    "datestamp": "1634748760",
                     "security-coverage": {
-                        "status": "not-covered",
-                        "message": "Beta releases are not covered by Drupal security advisories."
+                        "status": "covered",
+                        "message": "Covered by Drupal's security advisory policy"
                     }
                 }
             },
@@ -2280,17 +2280,17 @@
         },
         {
             "name": "drupal/captcha",
-            "version": "1.1.0",
+            "version": "1.2.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/captcha.git",
-                "reference": "8.x-1.1"
+                "reference": "8.x-1.2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/captcha-8.x-1.1.zip",
-                "reference": "8.x-1.1",
-                "shasum": "2eaf6f00ea256652c09f785b26dc933cc5b3dd26"
+                "url": "https://ftp.drupal.org/files/projects/captcha-8.x-1.2.zip",
+                "reference": "8.x-1.2",
+                "shasum": "e35a2ce42b652f833d140f7571d1eef0e06b0edc"
             },
             "require": {
                 "drupal/core": "^8.8 || ^9"
@@ -2298,8 +2298,8 @@
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "8.x-1.1",
-                    "datestamp": "1591160977",
+                    "version": "8.x-1.2",
+                    "datestamp": "1619673374",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
@@ -3513,7 +3513,7 @@
                 "drupal/core": "^8.8 || ^9"
             },
             "require-dev": {
-                "drupal/entity_browser": "^2.5"
+                "drupal/entity_browser": "*"
             },
             "suggest": {
                 "enyo/dropzone": "Required to use drupal/dropzonejs. DropzoneJS is an open source library that provides drag’n’drop file uploads with image previews."
@@ -4670,6 +4670,10 @@
                 "GPL-2.0-or-later"
             ],
             "authors": [
+                {
+                    "name": "Centarro",
+                    "homepage": "https://www.drupal.org/user/3661446"
+                },
                 {
                     "name": "bojanz",
                     "homepage": "https://www.drupal.org/user/86106"
@@ -5674,6 +5678,10 @@
                     "name": "Lucas Hedding",
                     "homepage": "https://www.drupal.org/u/heddn",
                     "role": "Maintainer"
+                },
+                {
+                    "name": "mikeryan",
+                    "homepage": "https://www.drupal.org/user/4420"
                 }
             ],
             "description": "Enhancements to core migration support.",
@@ -9538,12 +9546,12 @@
             },
             "type": "library",
             "autoload": {
-                "classmap": [
-                    "Mobile_Detect.php"
-                ],
                 "psr-0": {
                     "Detection": "namespaced/"
-                }
+                },
+                "classmap": [
+                    "Mobile_Detect.php"
+                ]
             },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
@@ -10704,12 +10712,12 @@
             },
             "type": "project",
             "autoload": {
-                "psr-4": {
-                    "SimpleSAML\\": "lib/SimpleSAML"
-                },
                 "files": [
                     "lib/_autoload_modules.php"
-                ]
+                ],
+                "psr-4": {
+                    "SimpleSAML\\": "lib/SimpleSAML"
+                }
             },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
index 8bdfb0c588bd4591ad7b4d9232f2e06ca93e080c..95ebedfe9f580447863634ac40d8208dcdcc55da 100644
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -2278,8 +2278,6 @@
     'Drupal\\Core\\Language\\LanguageManager' => $baseDir . '/web/core/lib/Drupal/Core/Language/LanguageManager.php',
     'Drupal\\Core\\Language\\LanguageManagerInterface' => $baseDir . '/web/core/lib/Drupal/Core/Language/LanguageManagerInterface.php',
     'Drupal\\Core\\Layout\\Annotation\\Layout' => $baseDir . '/web/core/lib/Drupal/Core/Layout/Annotation/Layout.php',
-    'Drupal\\Core\\Layout\\Icon\\IconBuilderInterface' => $baseDir . '/web/core/lib/Drupal/Core/Layout/Icon/IconBuilderInterface.php',
-    'Drupal\\Core\\Layout\\Icon\\SvgIconBuilder' => $baseDir . '/web/core/lib/Drupal/Core/Layout/Icon/SvgIconBuilder.php',
     'Drupal\\Core\\Layout\\LayoutDefault' => $baseDir . '/web/core/lib/Drupal/Core/Layout/LayoutDefault.php',
     'Drupal\\Core\\Layout\\LayoutDefinition' => $baseDir . '/web/core/lib/Drupal/Core/Layout/LayoutDefinition.php',
     'Drupal\\Core\\Layout\\LayoutInterface' => $baseDir . '/web/core/lib/Drupal/Core/Layout/LayoutInterface.php',
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index 3ff8bd2803e682a074cea0fc1363d27ed9a03600..13f2b32f3a243cc9f1ec9c0d22e0a0fe6ce968aa 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -3064,8 +3064,6 @@ class ComposerStaticInit5c689ffcd54b9e495ed983fdce09b530
         'Drupal\\Core\\Language\\LanguageManager' => __DIR__ . '/../..' . '/web/core/lib/Drupal/Core/Language/LanguageManager.php',
         'Drupal\\Core\\Language\\LanguageManagerInterface' => __DIR__ . '/../..' . '/web/core/lib/Drupal/Core/Language/LanguageManagerInterface.php',
         'Drupal\\Core\\Layout\\Annotation\\Layout' => __DIR__ . '/../..' . '/web/core/lib/Drupal/Core/Layout/Annotation/Layout.php',
-        'Drupal\\Core\\Layout\\Icon\\IconBuilderInterface' => __DIR__ . '/../..' . '/web/core/lib/Drupal/Core/Layout/Icon/IconBuilderInterface.php',
-        'Drupal\\Core\\Layout\\Icon\\SvgIconBuilder' => __DIR__ . '/../..' . '/web/core/lib/Drupal/Core/Layout/Icon/SvgIconBuilder.php',
         'Drupal\\Core\\Layout\\LayoutDefault' => __DIR__ . '/../..' . '/web/core/lib/Drupal/Core/Layout/LayoutDefault.php',
         'Drupal\\Core\\Layout\\LayoutDefinition' => __DIR__ . '/../..' . '/web/core/lib/Drupal/Core/Layout/LayoutDefinition.php',
         'Drupal\\Core\\Layout\\LayoutInterface' => __DIR__ . '/../..' . '/web/core/lib/Drupal/Core/Layout/LayoutInterface.php',
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index 24aec2af9b9beb90bf6c1f2e69475efb03d22a93..2e5e42249ce69ab2303994280210bdf1c465f924 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -1937,30 +1937,27 @@
         },
         {
             "name": "drupal/anchor_link",
-            "version": "1.7.0",
-            "version_normalized": "1.7.0.0",
+            "version": "1.9.0",
+            "version_normalized": "1.9.0.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/anchor_link.git",
-                "reference": "8.x-1.7"
+                "reference": "8.x-1.9"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/anchor_link-8.x-1.7.zip",
-                "reference": "8.x-1.7",
-                "shasum": "625c209245779377beede4d6eb7f87c7eac75dd0"
+                "url": "https://ftp.drupal.org/files/projects/anchor_link-8.x-1.9.zip",
+                "reference": "8.x-1.9",
+                "shasum": "48d343f29dc034bf2deb7de858498fb80d558ca8"
             },
             "require": {
                 "drupal/core": "^8 || ^9"
             },
             "type": "drupal-module",
             "extra": {
-                "branch-alias": {
-                    "dev-1.x": "1.x-dev"
-                },
                 "drupal": {
-                    "version": "8.x-1.7",
-                    "datestamp": "1582013628",
+                    "version": "8.x-1.9",
+                    "datestamp": "1643826959",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
@@ -1978,11 +1975,11 @@
                     "homepage": "https://www.drupal.org/user/255384"
                 },
                 {
-                    "name": "RajabNatshah",
+                    "name": "Rajab Natshah",
                     "homepage": "https://www.drupal.org/user/1414312"
                 }
             ],
-            "description": "This plugin module adds the better link dialog and anchor related features to CKEditor in Drupal 8",
+            "description": "This plugin module adds the better link dialog and anchor related features to CKEditor in Drupal 9",
             "homepage": "https://www.drupal.org/project/anchor_link",
             "support": {
                 "source": "https://git.drupalcode.org/project/anchor_link"
@@ -1991,18 +1988,18 @@
         },
         {
             "name": "drupal/better_exposed_filters",
-            "version": "5.0.0-beta3",
-            "version_normalized": "5.0.0.0-beta3",
+            "version": "5.0.0",
+            "version_normalized": "5.0.0.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/better_exposed_filters.git",
-                "reference": "8.x-5.0-beta3"
+                "reference": "8.x-5.0"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/better_exposed_filters-8.x-5.0-beta3.zip",
-                "reference": "8.x-5.0-beta3",
-                "shasum": "23f00fe898cd9e4f2278ef790bc9f1d197312ac3"
+                "url": "https://ftp.drupal.org/files/projects/better_exposed_filters-8.x-5.0.zip",
+                "reference": "8.x-5.0",
+                "shasum": "ef575591af202b5c6867841ce58e1f447455e502"
             },
             "require": {
                 "drupal/core": "^8.8 || ^9",
@@ -2014,11 +2011,11 @@
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "8.x-5.0-beta3",
-                    "datestamp": "1625665853",
+                    "version": "8.x-5.0",
+                    "datestamp": "1634748760",
                     "security-coverage": {
-                        "status": "not-covered",
-                        "message": "Beta releases are not covered by Drupal security advisories."
+                        "status": "covered",
+                        "message": "Covered by Drupal's security advisory policy"
                     }
                 }
             },
@@ -2350,18 +2347,18 @@
         },
         {
             "name": "drupal/captcha",
-            "version": "1.1.0",
-            "version_normalized": "1.1.0.0",
+            "version": "1.2.0",
+            "version_normalized": "1.2.0.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/captcha.git",
-                "reference": "8.x-1.1"
+                "reference": "8.x-1.2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/captcha-8.x-1.1.zip",
-                "reference": "8.x-1.1",
-                "shasum": "2eaf6f00ea256652c09f785b26dc933cc5b3dd26"
+                "url": "https://ftp.drupal.org/files/projects/captcha-8.x-1.2.zip",
+                "reference": "8.x-1.2",
+                "shasum": "e35a2ce42b652f833d140f7571d1eef0e06b0edc"
             },
             "require": {
                 "drupal/core": "^8.8 || ^9"
@@ -2369,8 +2366,8 @@
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "8.x-1.1",
-                    "datestamp": "1591160977",
+                    "version": "8.x-1.2",
+                    "datestamp": "1619673374",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php
index 3b1cc548279fc3b1e3b8a2d28eed856ba84b80a1..ddaecb81f1da58b2609647227367bb645e754639 100644
--- a/vendor/composer/installed.php
+++ b/vendor/composer/installed.php
@@ -5,7 +5,7 @@
         'type' => 'project',
         'install_path' => __DIR__ . '/../../',
         'aliases' => array(),
-        'reference' => '017d554d05ee95263629d62bfe1ad0b3dcb57e47',
+        'reference' => '62ba9430024688ba49b5cf20a6234ce99c9f1ce8',
         'name' => 'osu-asc-webservices/d8-upstream',
         'dev' => true,
     ),
@@ -317,12 +317,12 @@
             'dev_requirement' => false,
         ),
         'drupal/anchor_link' => array(
-            'pretty_version' => '1.7.0',
-            'version' => '1.7.0.0',
+            'pretty_version' => '1.9.0',
+            'version' => '1.9.0.0',
             'type' => 'drupal-module',
             'install_path' => __DIR__ . '/../../web/modules/anchor_link',
             'aliases' => array(),
-            'reference' => '8.x-1.7',
+            'reference' => '8.x-1.9',
             'dev_requirement' => false,
         ),
         'drupal/automated_cron' => array(
@@ -350,12 +350,12 @@
             ),
         ),
         'drupal/better_exposed_filters' => array(
-            'pretty_version' => '5.0.0-beta3',
-            'version' => '5.0.0.0-beta3',
+            'pretty_version' => '5.0.0',
+            'version' => '5.0.0.0',
             'type' => 'drupal-module',
             'install_path' => __DIR__ . '/../../web/modules/better_exposed_filters',
             'aliases' => array(),
-            'reference' => '8.x-5.0-beta3',
+            'reference' => '8.x-5.0',
             'dev_requirement' => false,
         ),
         'drupal/big_pipe' => array(
@@ -434,12 +434,12 @@
             'dev_requirement' => false,
         ),
         'drupal/captcha' => array(
-            'pretty_version' => '1.1.0',
-            'version' => '1.1.0.0',
+            'pretty_version' => '1.2.0',
+            'version' => '1.2.0.0',
             'type' => 'drupal-module',
             'install_path' => __DIR__ . '/../../web/modules/captcha',
             'aliases' => array(),
-            'reference' => '8.x-1.1',
+            'reference' => '8.x-1.2',
             'dev_requirement' => false,
         ),
         'drupal/ckeditor' => array(
@@ -2101,7 +2101,7 @@
             'type' => 'project',
             'install_path' => __DIR__ . '/../../',
             'aliases' => array(),
-            'reference' => '017d554d05ee95263629d62bfe1ad0b3dcb57e47',
+            'reference' => '62ba9430024688ba49b5cf20a6234ce99c9f1ce8',
             'dev_requirement' => false,
         ),
         'pantheon-systems/quicksilver-pushback' => array(
diff --git a/web/modules/anchor_link/README.md b/web/modules/anchor_link/README.md
index ebfc2eec764096a2328f81848789e599d9c122f5..ced859dc956b8ab3e96e8c61a92761fb54ef6b1f 100644
--- a/web/modules/anchor_link/README.md
+++ b/web/modules/anchor_link/README.md
@@ -2,11 +2,17 @@ CKEditor Anchor Link
 --------------------------------------------------------------------------------
 
 This plugin module adds the better link dialog and anchor related features
-to CKEditor in Drupal 8:
+to CKEditor in Drupal 9:
 
 - Dialog to insert links and anchors with some properties.
 - Context menu option to edit or remove links and anchors.
 - Ability to insert a link with the URL using multiple protocols, including an
   external file if a file manager is integrated.
 
+Most text formats limit HTML tags. If this is the case, it will
+ be necessary to whitelist the "name" attribute on the "a" element.
+
+E.g. `<a name href hreflang>`
+
+
 http://ckeditor.com/addon/link
diff --git a/web/modules/anchor_link/anchor_link.info.yml b/web/modules/anchor_link/anchor_link.info.yml
index dd44a773c42d59e32b3c6e11490d17b772ae0fc9..3c1af5c01416fecad4ba6e6c3a9ddca6285838b7 100644
--- a/web/modules/anchor_link/anchor_link.info.yml
+++ b/web/modules/anchor_link/anchor_link.info.yml
@@ -1,15 +1,13 @@
 name: 'CKEditor Anchor Link'
 type: module
-description: 'This plugin module adds the better link dialog and anchor related features to CKEditor in Drupal 8'
-core: 8.x
+description: 'This plugin module adds the better link dialog and anchor related features to CKEditor in Drupal 9'
 package: CKEditor
-# project: anchor_link
 core_version_requirement: ^8 || ^9
 dependencies:
   - drupal:ckeditor
   - drupal:editor
 
-# Information added by Drupal.org packaging script on 2020-02-16
-version: '8.x-1.7'
+# Information added by Drupal.org packaging script on 2022-02-02
+version: '8.x-1.9'
 project: 'anchor_link'
-datestamp: 1581868108
+datestamp: 1643826963
diff --git a/web/modules/anchor_link/anchor_link.module b/web/modules/anchor_link/anchor_link.module
index 58a4b0a59d52f7e6eb69b039533c4c8fb1b5bb73..23d99c875e1635e922bfe07dc3426a6229778a55 100755
--- a/web/modules/anchor_link/anchor_link.module
+++ b/web/modules/anchor_link/anchor_link.module
@@ -16,7 +16,7 @@ function anchor_link_help($route_name, RouteMatchInterface $route_match) {
     case 'help.page.anchor_link':
       $output = '';
       $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('This plugin module adds the better link dialog and anchor related features to CKEditor in Drupal 8') . '</p>';
+      $output .= '<p>' . t('This plugin module adds the better link dialog and anchor related features to CKEditor in Drupal 9') . '</p>';
       $output .= '<p><ul>';
       $output .= '  <li>Dialog to insert links and anchors with some properties.</li>';
       $output .= '  <li>Context menu option to edit or remove links and anchors.</li>';
@@ -42,5 +42,7 @@ function anchor_link_theme() {
  * Implements hook_page_attachments().
  */
 function anchor_link_page_attachments(array &$attachments) {
-  $attachments['#attached']['library'][] = 'anchor_link/drupal.anchor_link';
+  if (\Drupal::currentUser()->isAuthenticated()) {
+    $attachments['#attached']['library'][] = 'anchor_link/drupal.anchor_link';
+  }
 }
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/af.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/af.js
index 27e151cf2a18682d79e2476ddf9037ebbfd2771d..12eee689f95ed36ff39510467ceae0fcb871105f 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/af.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/af.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'af', {
 	anchor: 'Anker',
-	flash: 'Flash animasie',
 	hiddenfield: 'Verborge veld',
 	iframe: 'IFrame',
 	unknown: 'Onbekende objek'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ar.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ar.js
index f4b3fed3c1fbc6cd3ff3253a42f78548fad8e0f4..0552cd9dc1371d87a82bf8915125db4a6ff9272f 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ar.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ar.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'ar', {
 	anchor: 'إرساء',
-	flash: 'رسم متحرك بالفلاش',
 	hiddenfield: 'إدراج حقل خفي',
 	iframe: 'iframe',
 	unknown: 'عنصر غير معروف'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/az.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/az.js
index b31c6cb1ab335d1e1dda4d8a968d170af519a3e3..2319d5d0a9343ff73dbd05ebce92fd3a123bd9a5 100644
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/az.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/az.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'az', {
 	anchor: 'Lövbər',
-	flash: 'Flash animasiya',
 	hiddenfield: 'Gizli xana',
 	iframe: 'IFrame',
 	unknown: 'Tanımamış obyekt'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/bg.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/bg.js
index 11d6e3a3d1b6390788eedcbfd20b8be0af847de9..4bd26f6e1460643ef5c4b2582d899b354c7ed782 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/bg.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/bg.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'bg', {
 	anchor: 'Кука',
-	flash: 'Флаш анимация',
 	hiddenfield: 'Скрито поле',
 	iframe: 'IFrame',
 	unknown: 'Неизвестен обект'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/bn.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/bn.js
index 248fc5e2d033f98ffc2a0d376bdc31197a546f72..a307ad7e81c1e3021f8dc6983c90b9fb4a27d1af 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/bn.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/bn.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'bn', {
 	anchor: 'Anchor', // MISSING
-	flash: 'Flash Animation', // MISSING
 	hiddenfield: 'Hidden Field', // MISSING
 	iframe: 'IFrame', // MISSING
 	unknown: 'Unknown Object' // MISSING
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/bs.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/bs.js
index 77de4c2ab8c7f3b4f882e59af553ab42a1f4e060..ff1923f4c896ff16730760cdcd36e2de193e3bd5 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/bs.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/bs.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'bs', {
 	anchor: 'Anchor',
-	flash: 'Flash Animation', // MISSING
 	hiddenfield: 'Hidden Field', // MISSING
 	iframe: 'IFrame', // MISSING
 	unknown: 'Unknown Object' // MISSING
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ca.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ca.js
index 85af29d1c9dc6bf49efa206cabc8305b22bfc1d1..e0d6e1534c6e1fb8ddd02845d250f329b07222b1 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ca.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ca.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'ca', {
 	anchor: 'Àncora',
-	flash: 'Animació Flash',
 	hiddenfield: 'Camp ocult',
 	iframe: 'IFrame',
 	unknown: 'Objecte desconegut'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/cs.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/cs.js
index aeb9be4b7a697c3aae95a3d822f4cc346a4a7a3a..cf7b54b111838f6ddcb5ab3d0685eae97afcebc5 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/cs.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/cs.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'cs', {
 	anchor: 'Záložka',
-	flash: 'Flash animace',
 	hiddenfield: 'Skryté pole',
 	iframe: 'IFrame',
 	unknown: 'Neznámý objekt'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/cy.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/cy.js
index 3405f1685685d524761ad4d05af29a6ae7650e52..08c867ea320a90f9303a525139fd7221a602ef1f 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/cy.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/cy.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'cy', {
 	anchor: 'Angor',
-	flash: 'Animeiddiant Flash',
 	hiddenfield: 'Maes Cudd',
 	iframe: 'IFrame',
 	unknown: 'Gwrthrych Anhysbys'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/da.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/da.js
index d54846ea3227876de942a03012277fae1893b08a..5a797fe4f86e9b633c2221d8567472d179b31639 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/da.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/da.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'da', {
 	anchor: 'Anker',
-	flash: 'Flashanimation',
 	hiddenfield: 'Skjult felt',
 	iframe: 'Iframe',
 	unknown: 'Ukendt objekt'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/de-ch.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/de-ch.js
index c51ba5abdabcb9b1da32655c526f3e341aed0e9d..682fdd5be743b2557388d1a62153663e3fc70ae4 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/de-ch.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/de-ch.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'de-ch', {
 	anchor: 'Anker',
-	flash: 'Flash-Animation',
 	hiddenfield: 'Verstecktes Feld',
 	iframe: 'IFrame',
 	unknown: 'Unbekanntes Objekt'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/de.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/de.js
index 671e4dd59547a284c773b4e6f8ddd379140b07a4..9ce244182adbb48f257d7c9a49af5cf5714276f6 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/de.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/de.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'de', {
 	anchor: 'Anker',
-	flash: 'Flash-Animation',
 	hiddenfield: 'Verstecktes Feld',
 	iframe: 'IFrame',
 	unknown: 'Unbekanntes Objekt'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/el.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/el.js
index 90e005d81e4eb599dfb14bc59dfef5f4aa8bac73..c7e38d557b308dff48c9454b8a4b2c83329507ca 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/el.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/el.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'el', {
 	anchor: 'Άγκυρα',
-	flash: 'Ταινία Flash',
 	hiddenfield: 'Κρυφό Πεδίο',
 	iframe: 'IFrame',
 	unknown: 'Άγνωστο Αντικείμενο'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/en-au.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/en-au.js
index 3eacb2f214d67b34f7243e54317dba5b8bf68eb6..ae9535861eeb747ad73152fc86c5ca9afba1ff04 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/en-au.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/en-au.js
@@ -1,11 +1,10 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'en-au', {
-	anchor: 'Anchor', // MISSING
-	flash: 'Flash Animation', // MISSING
-	hiddenfield: 'Hidden Field', // MISSING
-	iframe: 'IFrame', // MISSING
-	unknown: 'Unknown Object' // MISSING
+	anchor: 'Anchor',
+	hiddenfield: 'Hidden Field',
+	iframe: 'IFrame',
+	unknown: 'Unknown Object'
 } );
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/en-ca.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/en-ca.js
index 8a0d321c191a736368930b4af1d71bfb930856cf..566d3addecfd8eab2aacacf106f9d9975481f9f6 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/en-ca.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/en-ca.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'en-ca', {
 	anchor: 'Anchor', // MISSING
-	flash: 'Flash Animation', // MISSING
 	hiddenfield: 'Hidden Field', // MISSING
 	iframe: 'IFrame', // MISSING
 	unknown: 'Unknown Object' // MISSING
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/en-gb.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/en-gb.js
index 2273955c2ff9051e50d6d0a426d2200ffa55471b..d617068c6753ffdd1a2c13237d4d2fda8cc1e72f 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/en-gb.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/en-gb.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'en-gb', {
 	anchor: 'Anchor',
-	flash: 'Flash Animation',
 	hiddenfield: 'Hidden Field',
 	iframe: 'IFrame',
 	unknown: 'Unknown Object'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/en.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/en.js
index 17c27b14fbd409d071065935d484d79300d1eeed..c6c66817ce7a68ec6ac90735867417aa9f6f56a6 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/en.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/en.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'en', {
 	anchor: 'Anchor',
-	flash: 'Flash Animation',
 	hiddenfield: 'Hidden Field',
 	iframe: 'IFrame',
 	unknown: 'Unknown Object'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/eo.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/eo.js
index f6f04325b5018aae95447c65a63f68f3edc015dd..d33aa7c0acd22f09db84bd19a9caa63078798a59 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/eo.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/eo.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'eo', {
 	anchor: 'Ankro',
-	flash: 'FlaŝAnimacio',
 	hiddenfield: 'Kaŝita kampo',
 	iframe: 'Enlinia Kadro (IFrame)',
 	unknown: 'Nekonata objekto'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/es-mx.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/es-mx.js
index 6fb115c86213c241026052455d51397e0a0485ae..a768579891a60a610794c9b18b55afd74d486892 100644
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/es-mx.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/es-mx.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'es-mx', {
 	anchor: 'Ancla',
-	flash: 'Animación flash',
 	hiddenfield: 'Campo oculto',
 	iframe: 'IFrame',
 	unknown: 'Objeto desconocido'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/es.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/es.js
index 73d007c12baa390e7adf20fca4fe58c746242baa..c27ee25796ee82e5e54e94e4122e55e249c2a4f1 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/es.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/es.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'es', {
 	anchor: 'Ancla',
-	flash: 'Animación flash',
 	hiddenfield: 'Campo oculto',
 	iframe: 'IFrame',
 	unknown: 'Objeto desconocido'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/et.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/et.js
index 88793067cc7f7b8beba5fcd4cfb3b5fb3cc65bfb..895bb3d9e592f968dbc6bb993fd3a3946a14320c 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/et.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/et.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'et', {
 	anchor: 'Ankur',
-	flash: 'Flashi animatsioon',
 	hiddenfield: 'Varjatud väli',
 	iframe: 'IFrame',
 	unknown: 'Tundmatu objekt'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/eu.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/eu.js
index cd6cfd8cb0981d1b6c5ca8e23993fbd2d378ce20..cdf3b7d4703f2de55336d7bf3b7b71eb45b7b8b1 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/eu.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/eu.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'eu', {
 	anchor: 'Aingura',
-	flash: 'Flash animazioa',
 	hiddenfield: 'Ezkutuko eremua',
 	iframe: 'IFrame-a',
 	unknown: 'Objektu ezezaguna'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/fa.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/fa.js
index 669facc77aa3143bf5d6f6cc127bf167465f947f..1a3586b8a805e66da57d7c95aa4ce7ac0c1f692f 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/fa.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/fa.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'fa', {
 	anchor: 'لنگر',
-	flash: 'انیمشن فلش',
 	hiddenfield: 'فیلد پنهان',
 	iframe: 'IFrame',
 	unknown: 'شیء ناشناخته'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/fi.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/fi.js
index fcee9a7c2d306bfd58b65bd4bbfc65339245316c..359778cd36fdb80438139168c849e20a36dfe3d2 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/fi.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/fi.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'fi', {
 	anchor: 'Ankkuri',
-	flash: 'Flash animaatio',
 	hiddenfield: 'Piilokenttä',
 	iframe: 'IFrame-kehys',
 	unknown: 'Tuntematon objekti'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/fo.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/fo.js
index c475dd3e1a1117d56290e494760f06fcceee0a72..338bcaf5a5c7cd0f34fc303e1faf83ce3a41cb9c 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/fo.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/fo.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'fo', {
 	anchor: 'Anchor',
-	flash: 'Flash Animation',
 	hiddenfield: 'Fjaldur teigur',
 	iframe: 'IFrame',
 	unknown: 'Ókent Object'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/fr-ca.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/fr-ca.js
index 577fa8e5f10ae99275e14d09e01d6eaac5381aa6..ecaf797c1cf5a416ad97789361dadcdbe5ed84c8 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/fr-ca.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/fr-ca.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'fr-ca', {
 	anchor: 'Ancre',
-	flash: 'Animation Flash',
 	hiddenfield: 'Champ caché',
 	iframe: 'IFrame',
 	unknown: 'Objet inconnu'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/fr.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/fr.js
index 27c23bc717f32cac500df2a915ed8de40a4a8714..74748d89f14ec0f23e07b7a00bcac6891b6d8a82 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/fr.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/fr.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'fr', {
 	anchor: 'Ancre',
-	flash: 'Animation Flash',
 	hiddenfield: 'Champ invisible',
 	iframe: 'Cadre de contenu incorporé',
 	unknown: 'Objet inconnu'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/gl.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/gl.js
index 907ba229f32201016c88208d98fc878adf854846..c49f65826b4870ef645df3c574db67f71e26b131 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/gl.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/gl.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'gl', {
 	anchor: 'Ancoraxe',
-	flash: 'Animación «Flash»',
 	hiddenfield: 'Campo agochado',
 	iframe: 'IFrame',
 	unknown: 'Obxecto descoñecido'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/gu.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/gu.js
index 03e1f43c751213f05400c3054be6b154ff291cb2..c95abce0f004b618157be9c6997e96e92ff762ce 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/gu.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/gu.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'gu', {
 	anchor: 'અનકર',
-	flash: 'ફ્લેશ ',
 	hiddenfield: 'હિડન ',
 	iframe: 'IFrame',
 	unknown: 'અનનોન ઓબ્જેક્ટ'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/he.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/he.js
index 88b8d45577f172a68a8201c692a0fd6c45bf4de1..ee5f65cb56846b83e4b379a77fb21aa3438e2544 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/he.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/he.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'he', {
 	anchor: 'עוגן',
-	flash: 'סרטון פלאש',
 	hiddenfield: 'שדה חבוי',
 	iframe: 'חלון פנימי (iframe)',
 	unknown: 'אובייקט לא ידוע'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/hi.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/hi.js
index 6854dc25b23588ab1706a9ab0829870e5344d1b4..7656911d8e68b8a1ee08bc193c742bb8e4d392a9 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/hi.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/hi.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'hi', {
 	anchor: 'ऐंकर इन्सर्ट/संपादन',
-	flash: 'Flash Animation', // MISSING
 	hiddenfield: 'गुप्त फ़ील्ड',
 	iframe: 'IFrame', // MISSING
 	unknown: 'Unknown Object' // MISSING
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/hr.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/hr.js
index bb779d44e10f3cc6007a865266bc9938561b5e4e..c3b2940821465f9b440a2418c096d78c3f4bfb0d 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/hr.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/hr.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'hr', {
 	anchor: 'Sidro',
-	flash: 'Flash animacija',
 	hiddenfield: 'Sakriveno polje',
 	iframe: 'IFrame',
 	unknown: 'Nepoznati objekt'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/hu.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/hu.js
index 10c2dec2fc03c7dad3d82bcea876b4072a8e5f0b..c5f07027d1bafd73b858235bfdcdfb5ea1666eb6 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/hu.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/hu.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'hu', {
 	anchor: 'Horgony',
-	flash: 'Flash animáció',
 	hiddenfield: 'Rejtett mezõ',
 	iframe: 'IFrame',
 	unknown: 'Ismeretlen objektum'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/id.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/id.js
index 46324b083d3bf4a0a384d716749c954b57667e57..deec36c95ca1f746b13aa51981c7114adee41a1b 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/id.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/id.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'id', {
 	anchor: 'Anchor', // MISSING
-	flash: 'Animasi Flash',
 	hiddenfield: 'Kolom Tersembunyi',
 	iframe: 'IFrame',
 	unknown: 'Obyek Tak Dikenal'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/is.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/is.js
index 078558543de40ca63e104a9ae621e317ae411fba..265b4620374767f7ed37a373496b5a4b601b6980 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/is.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/is.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'is', {
 	anchor: 'Anchor', // MISSING
-	flash: 'Flash Animation', // MISSING
 	hiddenfield: 'Hidden Field', // MISSING
 	iframe: 'IFrame', // MISSING
 	unknown: 'Unknown Object' // MISSING
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/it.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/it.js
index 44caa04dfa7ca24c8ad918e26e7cec50094060e7..10087ea13c5f1db9c511da55b4736974054f9874 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/it.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/it.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'it', {
 	anchor: 'Ancora',
-	flash: 'Animazione Flash',
 	hiddenfield: 'Campo Nascosto',
 	iframe: 'IFrame',
 	unknown: 'Oggetto sconosciuto'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ja.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ja.js
index 2d7bceb965afab94d14c30df08a4fb5101cf0f35..f2bf2c2e78297eca74570da0e54c59209d0b743a 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ja.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ja.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'ja', {
 	anchor: 'アンカー',
-	flash: 'Flash Animation',
 	hiddenfield: '不可視フィールド',
 	iframe: 'IFrame',
 	unknown: 'Unknown Object'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ka.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ka.js
index 45075d204bb33e0b4799fd051fa4c10560226bb8..449bfc1fd3425fe0d5b1183272211ca73b2e480a 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ka.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ka.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'ka', {
 	anchor: 'ღუზა',
-	flash: 'Flash ანიმაცია',
 	hiddenfield: 'მალული ველი',
 	iframe: 'IFrame',
 	unknown: 'უცნობი ობიექტი'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/km.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/km.js
index 404bab6fb68dbf4ed4c25df1aa8a97fc76d6c03e..399a9901696721dd4c18172dccae6b92629ebada 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/km.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/km.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'km', {
 	anchor: 'យុថ្កា',
-	flash: 'Flash មាន​ចលនា',
 	hiddenfield: 'វាល​កំបាំង',
 	iframe: 'IFrame',
 	unknown: 'វត្ថុ​មិន​ស្គាល់'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ko.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ko.js
index e677ccffd6d6f310e10da4858c32c9dce7f22df8..e481c57a22e12cea1da016976af5213b63bdf5af 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ko.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ko.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'ko', {
 	anchor: '책갈피',
-	flash: '플래시 애니메이션',
 	hiddenfield: '숨은 입력 칸',
 	iframe: '아이프레임',
 	unknown: '알 수 없는 객체'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ku.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ku.js
index 72eba2386ec52a3c5b6fdddf7eb60627f603f824..6e39dfc503d77cabac28212d2fc4fb6fd98ff8fa 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ku.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ku.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'ku', {
 	anchor: 'لەنگەر',
-	flash: 'فلاش',
 	hiddenfield: 'شاردنەوەی خانه',
 	iframe: 'لەچوارچێوە',
 	unknown: 'بەرکارێکی نەناسراو'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/lt.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/lt.js
index c4d0574741f61f6f93c0432d08d6700ef028c8e1..135b65a4a53deaa29e70d8253505b1774ee869c2 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/lt.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/lt.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'lt', {
 	anchor: 'Žymė',
-	flash: 'Flash animacija',
 	hiddenfield: 'Paslėptas laukas',
 	iframe: 'IFrame',
 	unknown: 'Nežinomas objektas'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/lv.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/lv.js
index 96233f45c451b52bddb24bf197aa21c7f2e4ea66..97f6aeb6a914554f552bee31609e0a55124b29cb 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/lv.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/lv.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'lv', {
 	anchor: 'Iezīme',
-	flash: 'Flash animācija',
 	hiddenfield: 'Slēpts lauks',
 	iframe: 'Iframe',
 	unknown: 'Nezināms objekts'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/mk.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/mk.js
index 39b51e2f4bfbe8b7237ec16fc0873b9f89d6962c..6f93bdaa3602785a721a7f0931612f87eef81a3c 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/mk.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/mk.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'mk', {
 	anchor: 'Anchor',
-	flash: 'Flash Animation', // MISSING
 	hiddenfield: 'Скриено поле',
 	iframe: 'IFrame', // MISSING
 	unknown: 'Unknown Object' // MISSING
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/mn.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/mn.js
index 507e3167979fb2854e0023efb413522ced4ff446..4018243d04fdd254e5e1a520cfbd8808eaae628f 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/mn.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/mn.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'mn', {
 	anchor: 'Зангуу',
-	flash: 'Flash Animation', // MISSING
 	hiddenfield: 'Нууц талбар',
 	iframe: 'IFrame', // MISSING
 	unknown: 'Unknown Object' // MISSING
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ms.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ms.js
index 900cf391a2446b84ae782ae63f3cc60390cd9663..905d7da61765684b5d36d9e196c79f48a3c1ca74 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ms.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ms.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'ms', {
 	anchor: 'Anchor', // MISSING
-	flash: 'Flash Animation', // MISSING
 	hiddenfield: 'Hidden Field', // MISSING
 	iframe: 'IFrame', // MISSING
 	unknown: 'Unknown Object' // MISSING
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/nb.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/nb.js
index 6548eedb7416816dc13a9cd36a9a0fc5e76cce9d..a9b4e8d778bba9e50072eec803bd6dabc5c9547f 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/nb.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/nb.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'nb', {
 	anchor: 'Anker',
-	flash: 'Flash-animasjon',
 	hiddenfield: 'Skjult felt',
 	iframe: 'IFrame',
 	unknown: 'Ukjent objekt'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/nl.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/nl.js
index f4a78cbc1203fbf5af9e3f812da87d06650eed3d..77497278815bd0eb832a7e36ced6f50a1d7383f1 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/nl.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/nl.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'nl', {
 	anchor: 'Interne link',
-	flash: 'Flash animatie',
 	hiddenfield: 'Verborgen veld',
 	iframe: 'IFrame',
 	unknown: 'Onbekend object'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/no.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/no.js
index a140e3d410e0b9255950c2103f74908e5cea4f97..26a194a3171344ce0d54de1a4199ba0201e66a45 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/no.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/no.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'no', {
 	anchor: 'Anker',
-	flash: 'Flash-animasjon',
 	hiddenfield: 'Skjult felt',
 	iframe: 'IFrame',
 	unknown: 'Ukjent objekt'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/oc.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/oc.js
index 5e3d0cda9589d21e5c220ea514440e3eac9e6b7f..8a167f5d2692f19c02546af974d6e0607e3a7b09 100644
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/oc.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/oc.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'oc', {
 	anchor: 'Ancòra',
-	flash: 'Animacion Flash',
 	hiddenfield: 'Camp invisible',
 	iframe: 'Quadre de contengut incorporat',
 	unknown: 'Objècte desconegut'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/pl.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/pl.js
index fa0828bfb6e317f4bf29b0abf97c749ec91864fb..6d16eb1a6121606babafef063141df5eddd600a4 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/pl.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/pl.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'pl', {
 	anchor: 'Kotwica',
-	flash: 'Animacja Flash',
 	hiddenfield: 'Pole ukryte',
 	iframe: 'IFrame',
 	unknown: 'Nieznany obiekt'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/pt-br.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/pt-br.js
index ca6694ce7bb41b27561ca1a3b90bb969030755b3..bd8ac019d63928ff045b32939b3d7acd79e6f899 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/pt-br.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/pt-br.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'pt-br', {
 	anchor: 'Âncora',
-	flash: 'Animação em Flash',
 	hiddenfield: 'Campo Oculto',
 	iframe: 'IFrame',
 	unknown: 'Objeto desconhecido'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/pt.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/pt.js
index b6766c5e7cbe3004001e5fc04df4e5ae05acbf63..cf2720c33caaeb1f00bb35f1b05f4306192c3589 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/pt.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/pt.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'pt', {
 	anchor: ' Inserir/Editar âncora',
-	flash: 'Animação Flash',
 	hiddenfield: 'Campo oculto',
 	iframe: 'IFrame',
 	unknown: 'Objeto desconhecido'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ro.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ro.js
index 470d9912f1cae6a52f69452ad592f302e9078200..f7679e9b9a0cb89f047dce8733caf65ff369be6d 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ro.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ro.js
@@ -1,11 +1,10 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'ro', {
 	anchor: 'Inserează/Editează ancoră',
-	flash: 'Flash Animation', // MISSING
 	hiddenfield: 'Câmp ascuns (HiddenField)',
-	iframe: 'IFrame', // MISSING
-	unknown: 'Unknown Object' // MISSING
+	iframe: 'Fereastră în fereastră (iframe)',
+	unknown: 'Necunoscut'
 } );
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ru.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ru.js
index 4744b6ec117c665817a317734a0dd54d5c6cfc48..f2860b5bd4127d99ba5892ed78343d951baf1c3c 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ru.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ru.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'ru', {
 	anchor: 'Якорь',
-	flash: 'Flash анимация',
 	hiddenfield: 'Скрытое поле',
 	iframe: 'iFrame',
 	unknown: 'Неизвестный объект'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/si.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/si.js
index 139dee05d33826b5d3320be27ac69f4ce3f0185f..037d6299a9b22980df0a28193c2738e0c66779d8 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/si.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/si.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'si', {
 	anchor: 'ආධාරය',
-	flash: 'Flash Animation', // MISSING
 	hiddenfield: 'සැඟවුණු ප්‍රදේශය',
 	iframe: 'IFrame',
 	unknown: 'Unknown Object' // MISSING
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/sk.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/sk.js
index 1b7c43f3a900212a0e4e01b533873e2f592001f8..489a149dbd05f69d19488ed0ddf06c96ead28455 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/sk.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/sk.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'sk', {
 	anchor: 'Kotva',
-	flash: 'Flash animácia',
 	hiddenfield: 'Skryté pole',
 	iframe: 'IFrame',
 	unknown: 'Neznámy objekt'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/sl.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/sl.js
index 3760a04948d97ed8a547d54e635d610504327a95..db11d7fcb3f26e5183a754fa5273c09c95900a56 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/sl.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/sl.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'sl', {
 	anchor: 'Sidro',
-	flash: 'Animacija flash',
 	hiddenfield: 'Skrito polje',
 	iframe: 'IFrame',
 	unknown: 'Neznan objekt'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/sq.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/sq.js
index b6c0d1cc308de06ff9a70b4894b069dd78ca09b8..001a3d97085990946a8aa18e0d188aa83a1e336e 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/sq.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/sq.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'sq', {
 	anchor: 'Spirancë',
-	flash: 'Objekt flash',
 	hiddenfield: 'Fushë e fshehur',
 	iframe: 'IFrame',
 	unknown: 'Objekt i Panjohur'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/sr-latn.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/sr-latn.js
index c9db381e9a0f0c04dd5d26ca212143aa4c53f427..1db018031bb9274d2845f8f944b8ec579a26189f 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/sr-latn.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/sr-latn.js
@@ -1,11 +1,10 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'sr-latn', {
-	anchor: 'Unesi/izmeni sidro',
-	flash: 'Flash Animation', // MISSING
+	anchor: 'Sidro',
 	hiddenfield: 'Skriveno polje',
-	iframe: 'IFrame', // MISSING
-	unknown: 'Unknown Object' // MISSING
+	iframe: 'IFrame',
+	unknown: 'Nepoznat objekat'
 } );
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/sr.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/sr.js
index ce55c96f5dfec2df9a5c2851c8c367b60335e967..9c2a83c7b818ac793b48438285b717f81232eae4 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/sr.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/sr.js
@@ -1,11 +1,10 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'sr', {
-	anchor: 'Anchor', // MISSING
-	flash: 'Flash Animation', // MISSING
-	hiddenfield: 'Hidden Field', // MISSING
-	iframe: 'IFrame', // MISSING
-	unknown: 'Unknown Object' // MISSING
+	anchor: 'Сидро',
+	hiddenfield: 'Скривено полје',
+	iframe: 'IFrame',
+	unknown: 'Непознат објекат'
 } );
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/sv.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/sv.js
index e97dc6d80d8576368dbe839163e5f004efebe449..5ea0ee6aac3754d0574862441543f97bcb7cf718 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/sv.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/sv.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'sv', {
 	anchor: 'Ankare',
-	flash: 'Flashanimation',
 	hiddenfield: 'Gömt fält',
 	iframe: 'iFrame',
 	unknown: 'Okänt objekt'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/th.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/th.js
index b4fcda9de3ca33647b68822bc35132a17e37c748..a57e147952aa9fbdbc8a44147034c2f8721aad37 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/th.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/th.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'th', {
 	anchor: 'แทรก/แก้ไข Anchor',
-	flash: 'ภาพอนิเมชั่นแฟลช',
 	hiddenfield: 'ฮิดเดนฟิลด์',
 	iframe: 'IFrame',
 	unknown: 'วัตถุไม่ทราบชนิด'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/tr.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/tr.js
index b6a1043eb97cd7f2a11d0dd4c5717ed3155ee961..95bd11b32ec1b3296b7f67988d92afb925207bf2 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/tr.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/tr.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'tr', {
 	anchor: 'Bağlantı',
-	flash: 'Flash Animasyonu',
 	hiddenfield: 'Gizli Alan',
 	iframe: 'IFrame',
 	unknown: 'Bilinmeyen Nesne'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/tt.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/tt.js
index 202f7b11ec1e2e4077d46d8732a755495bf1556a..27b1eab4fbaa50c7857907586007e689bb7a457a 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/tt.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/tt.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'tt', {
 	anchor: 'Якорь',
-	flash: 'Флеш анимациясы',
 	hiddenfield: 'Яшерен кыр',
 	iframe: 'IFrame',
 	unknown: 'Танылмаган объект'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ug.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ug.js
index b454d4435c180b418906309b124027fae1a7e000..a9ee84256f8d70fbaba6d4fba8ed4301d2c9326e 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/ug.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/ug.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'ug', {
 	anchor: 'لەڭگەرلىك نۇقتا',
-	flash: 'Flash جانلاندۇرۇم',
 	hiddenfield: 'يوشۇرۇن دائىرە',
 	iframe: 'IFrame',
 	unknown: 'يوچۇن نەڭ'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/uk.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/uk.js
index 651c06cc3e384637f96153000a68e744ae35454f..12a638e4adb7b7d33cf8cdbee133c0a4a6721a21 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/uk.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/uk.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'uk', {
 	anchor: 'Якір',
-	flash: 'Flash-анімація',
 	hiddenfield: 'Приховані Поля',
 	iframe: 'IFrame',
 	unknown: 'Невідомий об\'єкт'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/vi.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/vi.js
index 7cd26ce3416e59c2138fef25f49487bcad13ac0d..6adbe6e6bf9fd9934df190c012cecd6c51b8c8ca 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/vi.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/vi.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'vi', {
 	anchor: 'Điểm neo',
-	flash: 'Flash',
 	hiddenfield: 'Trường ẩn',
 	iframe: 'IFrame',
 	unknown: 'Đối tượng không rõ ràng'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/zh-cn.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/zh-cn.js
index 1349054c12fbff4b46aeed66b415836d8577f482..8e780090de4038f83e0d941d504abddf4a2fbb36 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/zh-cn.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/zh-cn.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'zh-cn', {
 	anchor: '锚点',
-	flash: 'Flash 动画',
 	hiddenfield: '隐藏域',
 	iframe: 'IFrame',
 	unknown: '未知对象'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/lang/zh.js b/web/modules/anchor_link/js/plugins/fakeobjects/lang/zh.js
index d2257ca7d00b34728f3e320592ab393cf53a7039..823503c7ec9a1d103ca5c127da083e9046b5b220 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/lang/zh.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/lang/zh.js
@@ -1,10 +1,9 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'fakeobjects', 'zh', {
 	anchor: '錨點',
-	flash: 'Flash 動畫',
 	hiddenfield: '隱藏欄位',
 	iframe: 'IFrame',
 	unknown: '無法辨識的物件'
diff --git a/web/modules/anchor_link/js/plugins/fakeobjects/plugin.js b/web/modules/anchor_link/js/plugins/fakeobjects/plugin.js
index 945999ef2c58c12dd6e7c70000248ef6c6e1b41b..8ec8848306afab20a9e3d75af22476e40406b644 100755
--- a/web/modules/anchor_link/js/plugins/fakeobjects/plugin.js
+++ b/web/modules/anchor_link/js/plugins/fakeobjects/plugin.js
@@ -1,6 +1,6 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md or http://ckeditor.com/license
+ * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  */
 
 ( function() {
@@ -27,30 +27,6 @@
 		return length2;
 	}
 
-	var htmlFilterRules = {
-		elements: {
-			$: function( element ) {
-				var attributes = element.attributes,
-					realHtml = attributes && attributes[ 'data-cke-realelement' ],
-					realFragment = realHtml && new CKEDITOR.htmlParser.fragment.fromHtml( decodeURIComponent( realHtml ) ),
-					realElement = realFragment && realFragment.children[ 0 ];
-
-				// Width/height in the fake object are subjected to clone into the real element.
-				if ( realElement && element.attributes[ 'data-cke-resizable' ] ) {
-					var styles = new cssStyle( element ).rules,
-						realAttrs = realElement.attributes,
-						width = styles.width,
-						height = styles.height;
-
-					width && ( realAttrs.width = replaceCssLength( realAttrs.width, width ) );
-					height && ( realAttrs.height = replaceCssLength( realAttrs.height, height ) );
-				}
-
-				return realElement;
-			}
-		}
-	};
-
 	CKEDITOR.plugins.add( 'fakeobjects', {
 		// jscs:disable maximumLineLength
 		lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
@@ -67,7 +43,7 @@
 				htmlFilter = dataProcessor && dataProcessor.htmlFilter;
 
 			if ( htmlFilter ) {
-				htmlFilter.addRules( htmlFilterRules, {
+				htmlFilter.addRules( createHtmlFilterRules( editor ), {
 					applyToAll: true
 				} );
 			}
@@ -98,7 +74,7 @@
 			align: realElement.getAttribute( 'align' ) || ''
 		};
 
-		// Do not set "src" on high-contrast so the alt text is displayed. (http://dev.ckeditor.com/ticket/8945)
+		// Do not set "src" on high-contrast so the alt text is displayed. (https://dev.ckeditor.com/ticket/8945)
 		if ( !CKEDITOR.env.hc )
 			attributes.src = CKEDITOR.tools.transparentImageData;
 
@@ -149,7 +125,7 @@
 			align: realElement.attributes.align || ''
 		};
 
-		// Do not set "src" on high-contrast so the alt text is displayed. (http://dev.ckeditor.com/ticket/8945)
+		// Do not set "src" on high-contrast so the alt text is displayed. (https://dev.ckeditor.com/ticket/8945)
 		if ( !CKEDITOR.env.hc )
 			attributes.src = CKEDITOR.tools.transparentImageData;
 
@@ -183,17 +159,81 @@
 		if ( fakeElement.data( 'cke-real-node-type' ) != CKEDITOR.NODE_ELEMENT )
 			return null;
 
-		var element = CKEDITOR.dom.element.createFromHtml( decodeURIComponent( fakeElement.data( 'cke-realelement' ) ), this.document );
+		var realElementHtml = decodeURIComponent( fakeElement.data( 'cke-realelement' ) ),
+			filteredHtml = filterHtml( this, realElementHtml ),
+			realElement = CKEDITOR.dom.element.createFromHtml( filteredHtml, this.document );
 
 		if ( fakeElement.data( 'cke-resizable' ) ) {
 			var width = fakeElement.getStyle( 'width' ),
 				height = fakeElement.getStyle( 'height' );
 
-			width && element.setAttribute( 'width', replaceCssLength( element.getAttribute( 'width' ), width ) );
-			height && element.setAttribute( 'height', replaceCssLength( element.getAttribute( 'height' ), height ) );
+			width && realElement.setAttribute( 'width', replaceCssLength( realElement.getAttribute( 'width' ), width ) );
+			height && realElement.setAttribute( 'height', replaceCssLength( realElement.getAttribute( 'height' ), height ) );
 		}
 
-		return element;
+		return realElement;
 	};
 
+	function createHtmlFilterRules( editor ) {
+		return {
+			elements: {
+				$: function( element ) {
+					var attributes = element.attributes,
+						realHtml = attributes && attributes[ 'data-cke-realelement' ],
+						filteredRealHtml = filterHtml( editor, decodeURIComponent( realHtml ) ),
+						realFragment = realHtml && new CKEDITOR.htmlParser.fragment.fromHtml( filteredRealHtml ),
+						realElement = realFragment && realFragment.children[ 0 ];
+
+					// Width/height in the fake object are subjected to clone into the real element.
+					if ( realElement && element.attributes[ 'data-cke-resizable' ] ) {
+						var styles = new cssStyle( element ).rules,
+							realAttrs = realElement.attributes,
+							width = styles.width,
+							height = styles.height;
+
+						width && ( realAttrs.width = replaceCssLength( realAttrs.width, width ) );
+						height && ( realAttrs.height = replaceCssLength( realAttrs.height, height ) );
+					}
+
+					return realElement;
+				}
+			}
+		};
+	}
+
+	// Content stored inside fake element is raw and should be explicitly
+	// passed to ACF filter. Additionally some elements can have prefixes in tag names,
+	// which should be removed before filtering and added after it.
+	function filterHtml( editor, html ) {
+		var unprefixedElements = [],
+			prefixRegex = /^cke:/i,
+			dataFilter =  new CKEDITOR.htmlParser.filter( {
+				elements: {
+					'^': function( element ) {
+						if ( prefixRegex.test( element.name ) ) {
+							element.name = element.name.replace( prefixRegex, '' );
+
+							unprefixedElements.push( element );
+						}
+					},
+					iframe: function( element ) {
+						element.children = [];
+					}
+				}
+			} ),
+			acfFilter = editor.activeFilter,
+			writer = new CKEDITOR.htmlParser.basicWriter(),
+			fragment = CKEDITOR.htmlParser.fragment.fromHtml( html );
+
+		dataFilter.applyTo( fragment );
+		acfFilter.applyTo( fragment );
+
+		CKEDITOR.tools.array.forEach( unprefixedElements, function( element ) {
+			element.name = 'cke:' + element.name;
+		} );
+
+		fragment.writeHtml( writer );
+
+		return writer.getHtml();
+	}
 } )();
diff --git a/web/modules/anchor_link/js/plugins/link/dialogs/anchor.js b/web/modules/anchor_link/js/plugins/link/dialogs/anchor.js
index 06ea90d0f162a177a42fc29e551d2003dedff594..f86c1e81388f0b511ca581b544e57d3b01d5da6c 100755
--- a/web/modules/anchor_link/js/plugins/link/dialogs/anchor.js
+++ b/web/modules/anchor_link/js/plugins/link/dialogs/anchor.js
@@ -1,13 +1,11 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md or http://ckeditor.com/license
+ * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  */
 
 CKEDITOR.dialog.add( 'anchor', function( editor ) {
 	// Function called in onShow to load selected element.
 	var loadElements = function( element ) {
-			this._.selectedElement = element;
-
 			var attributeValue = element.data( 'cke-saved-name' );
 			this.setValueOf( 'info', 'txtName', attributeValue || '' );
 		};
@@ -27,35 +25,69 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) {
 		range.shrink( CKEDITOR.SHRINK_ELEMENT );
 		element = range.getEnclosedNode();
 
+		// If selection is inside text, get its parent element (#3437).
+		if ( element && element.type === CKEDITOR.NODE_TEXT ) {
+			element = element.getParent();
+		}
+
+		// If anchor exists and has any styles find the closest parent <a> tag. (#3863)
+		if ( element && !element.is( 'a' ) ) {
+			element = element.getAscendant( 'a' ) || element;
+		}
+
 		if ( element && element.type === CKEDITOR.NODE_ELEMENT &&
 			( element.data( 'cke-real-element-type' ) === 'anchor' || element.is( 'a' ) ) ) {
 			return element;
 		}
 	}
 
+	function removeAnchorsWithinRange( range ) {
+		var newRange = range.clone();
+		newRange.enlarge( CKEDITOR.ENLARGE_ELEMENT );
+
+		var walker = new CKEDITOR.dom.walker( newRange ),
+			element = newRange.collapsed ? newRange.startContainer : walker.next(),
+			bookmark = range.createBookmark();
+
+		while ( element ) {
+			if ( element.type === CKEDITOR.NODE_ELEMENT && element.getAttribute( 'data-cke-saved-name' ) ) {
+				element.remove( true );
+				// Reset the walker and start from beginning, to check if element has more nested anchors.
+				// Without it, next element is null, so there might be space to more nested elements.
+				walker.reset();
+			}
+			element = walker.next();
+		}
+		range.moveToBookmark( bookmark );
+	}
+
 	return {
 		title: editor.lang.link.anchor.title,
 		minWidth: 300,
 		minHeight: 60,
+		getModel: function( editor ) {
+			return getSelectedAnchor( editor.getSelection() ) || null;
+		},
 		onOk: function() {
-			var name = CKEDITOR.tools.trim( this.getValueOf( 'info', 'txtName' ) );
-			var attributes = {
-				id: name,
-				name: name,
-				'data-cke-saved-name': name
-			};
-
-			if ( this._.selectedElement ) {
-				if ( this._.selectedElement.data( 'cke-realelement' ) ) {
+			var name = CKEDITOR.tools.trim( this.getValueOf( 'info', 'txtName' ) ),
+				attributes = {
+					id: name,
+					name: name,
+					'data-cke-saved-name': name
+				},
+				selectedElement = this.getModel( editor );
+
+			if ( selectedElement ) {
+				if ( selectedElement.data( 'cke-realelement' ) ) {
 					var newFake = createFakeAnchor( editor, attributes );
-					newFake.replace( this._.selectedElement );
+					newFake.replace( selectedElement );
 
-					// Selecting fake element for IE. (http://dev.ckeditor.com/ticket/11377)
+					// Selecting fake element for IE. (https://dev.ckeditor.com/ticket/11377)
 					if ( CKEDITOR.env.ie ) {
 						editor.getSelection().selectElement( newFake );
 					}
 				} else {
-					this._.selectedElement.setAttributes( attributes );
+					selectedElement.setAttributes( attributes );
 				}
 			} else {
 				var sel = editor.getSelection(),
@@ -69,6 +101,8 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) {
 					if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 )
 						attributes[ 'class' ] = 'cke_anchor';
 
+					// (#4728)
+					removeAnchorsWithinRange( range );
 					// Apply style.
 					var style = new CKEDITOR.style( { element: 'a', attributes: attributes } );
 					style.type = CKEDITOR.STYLE_INLINE;
@@ -77,13 +111,9 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) {
 			}
 		},
 
-		onHide: function() {
-			delete this._.selectedElement;
-		},
-
 		onShow: function() {
 			var sel = editor.getSelection(),
-				fullySelected = getSelectedAnchor( sel ),
+				fullySelected = this.getModel( editor ),
 				fakeSelected = fullySelected && fullySelected.data( 'cke-realelement' ),
 				linkElement = fakeSelected ?
 					CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, fullySelected ) :
@@ -92,10 +122,6 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) {
 			if ( linkElement ) {
 				loadElements.call( this, linkElement );
 				!fakeSelected && sel.selectElement( linkElement );
-
-				if ( fullySelected ) {
-					this._.selectedElement = fullySelected;
-				}
 			}
 
 			this.getContentElement( 'info', 'txtName' ).focus();
diff --git a/web/modules/anchor_link/js/plugins/link/dialogs/link.js b/web/modules/anchor_link/js/plugins/link/dialogs/link.js
index 78cc6478317a4e6cabde7591796df0a195afde5b..b6fc45eb8ffce5038734768744bbc22f39b6cd72 100755
--- a/web/modules/anchor_link/js/plugins/link/dialogs/link.js
+++ b/web/modules/anchor_link/js/plugins/link/dialogs/link.js
@@ -1,6 +1,6 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md or http://ckeditor.com/license
+ * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  */
 
 'use strict';
@@ -40,7 +40,7 @@
 
 				// Use link URL as text with a collapsed cursor.
 				if ( range.collapsed ) {
-					// Short mailto link text view (http://dev.ckeditor.com/ticket/5736).
+					// Short mailto link text view (https://dev.ckeditor.com/ticket/5736).
 					text = new CKEDITOR.dom.text( data.linkText || ( data.type == 'email' ?
 						data.email.address : attributes.set[ 'data-cke-saved-href' ] ), editor.document );
 					range.insertNode( text );
@@ -65,7 +65,6 @@
 					nestedLinks[ j ].remove( true );
 				}
 
-
 				// Apply style.
 				style.applyToRange( range, editor );
 
@@ -78,9 +77,11 @@
 		function editLinksInSelection( editor, selectedElements, data ) {
 			var attributes = plugin.getLinkAttributes( editor, data ),
 				ranges = [],
+				isDisplayChanged,
+				isEmailEqualDisplay,
+				isURLEqualDisplay,
 				element,
 				href,
-				textView,
 				newText,
 				i;
 
@@ -88,18 +89,19 @@
 				// We're only editing an existing link, so just overwrite the attributes.
 				element = selectedElements[ i ];
 				href = element.data( 'cke-saved-href' );
-				textView = element.getHtml();
+				isDisplayChanged = data.linkText && initialLinkText != data.linkText;
+				isURLEqualDisplay = href == initialLinkText;
+				isEmailEqualDisplay = data.type == 'email' && href == 'mailto:' + initialLinkText;
 
 				element.setAttributes( attributes.set );
 				element.removeAttributes( attributes.removed );
 
-
-				if ( data.linkText && initialLinkText != data.linkText ) {
+				if ( isDisplayChanged ) {
 					// Display text has been changed.
 					newText = data.linkText;
-				} else if ( href == textView || data.type == 'email' && textView.indexOf( '@' ) != -1 ) {
-					// Update text view when user changes protocol (http://dev.ckeditor.com/ticket/4612).
-					// Short mailto link text view (http://dev.ckeditor.com/ticket/5736).
+				} else if ( isURLEqualDisplay || isEmailEqualDisplay ) {
+					// Update text view when user changes protocol (https://dev.ckeditor.com/ticket/4612).
+					// Short mailto link text view (https://dev.ckeditor.com/ticket/5736).
 					newText = data.type == 'email' ? data.email.address : attributes.set[ 'data-cke-saved-href' ];
 				}
 
@@ -116,97 +118,105 @@
 
 		// Handles the event when the "Target" selection box is changed.
 		var targetChanged = function() {
-				var dialog = this.getDialog(),
-					popupFeatures = dialog.getContentElement( 'target', 'popupFeatures' ),
-					targetName = dialog.getContentElement( 'target', 'linkTargetName' ),
-					value = this.getValue();
-
-				if ( !popupFeatures || !targetName )
-					return;
-
-				popupFeatures = popupFeatures.getElement();
-				popupFeatures.hide();
-				targetName.setValue( '' );
-
-				switch ( value ) {
-					case 'frame':
-						targetName.setLabel( editor.lang.link.targetFrameName );
-						targetName.getElement().show();
-						break;
-					case 'popup':
-						popupFeatures.show();
-						targetName.setLabel( editor.lang.link.targetPopupName );
-						targetName.getElement().show();
-						break;
-					default:
-						targetName.setValue( value );
-						targetName.getElement().hide();
-						break;
-				}
+			var dialog = this.getDialog(),
+				popupFeatures = dialog.getContentElement( 'target', 'popupFeatures' ),
+				targetName = dialog.getContentElement( 'target', 'linkTargetName' ),
+				value = this.getValue();
+
+			if ( !popupFeatures || !targetName ) {
+				return;
+			}
+
+			popupFeatures = popupFeatures.getElement();
+			popupFeatures.hide();
+			targetName.setValue( '' );
+
+			switch ( value ) {
+				case 'frame':
+					targetName.setLabel( editor.lang.link.targetFrameName );
+					targetName.getElement().show();
+					break;
+				case 'popup':
+					popupFeatures.show();
+					targetName.setLabel( editor.lang.link.targetPopupName );
+					targetName.getElement().show();
+					break;
+				default:
+					targetName.setValue( value );
+					targetName.getElement().hide();
+					break;
+			}
 
-			};
+		};
 
 		// Handles the event when the "Type" selection box is changed.
 		var linkTypeChanged = function() {
-				var dialog = this.getDialog(),
-					partIds = [ 'urlOptions', 'anchorOptions', 'emailOptions' ],
-					typeValue = this.getValue(),
-					uploadTab = dialog.definition.getContents( 'upload' ),
-					uploadInitiallyHidden = uploadTab && uploadTab.hidden;
-
-				if ( typeValue == 'url' ) {
-					if ( editor.config.linkShowTargetTab )
-						dialog.showPage( 'target' );
-					if ( !uploadInitiallyHidden )
-						dialog.showPage( 'upload' );
-				} else {
-					dialog.hidePage( 'target' );
-					if ( !uploadInitiallyHidden )
-						dialog.hidePage( 'upload' );
+			var dialog = this.getDialog(),
+				partIds = [ 'urlOptions', 'anchorOptions', 'emailOptions', 'telOptions' ],
+				typeValue = this.getValue(),
+				uploadTab = dialog.definition.getContents( 'upload' ),
+				uploadInitiallyHidden = uploadTab && uploadTab.hidden;
+
+			if ( typeValue == 'url' ) {
+				if ( editor.config.linkShowTargetTab ) {
+					dialog.showPage( 'target' );
+				}
+				if ( !uploadInitiallyHidden ) {
+					dialog.showPage( 'upload' );
+				}
+			} else {
+				dialog.hidePage( 'target' );
+				if ( !uploadInitiallyHidden ) {
+					dialog.hidePage( 'upload' );
 				}
+			}
 
-				for ( var i = 0; i < partIds.length; i++ ) {
-					var element = dialog.getContentElement( 'info', partIds[ i ] );
-					if ( !element )
-						continue;
+			for ( var i = 0; i < partIds.length; i++ ) {
+				var element = dialog.getContentElement( 'info', partIds[ i ] );
+				if ( !element ) {
+					continue;
+				}
 
-					element = element.getElement().getParent().getParent();
-					if ( partIds[ i ] == typeValue + 'Options' )
-						element.show();
-					else
-						element.hide();
+				element = element.getElement().getParent().getParent();
+				if ( partIds[ i ] == typeValue + 'Options' ) {
+					element.show();
+				} else {
+					element.hide();
 				}
+			}
 
-				dialog.layout();
-			};
+			dialog.layout();
+		};
 
 		var setupParams = function( page, data ) {
-				if ( data[ page ] )
-					this.setValue( data[ page ][ this.id ] || '' );
-			};
+			if ( data[ page ] ) {
+				this.setValue( data[ page ][ this.id ] || '' );
+			}
+		};
 
 		var setupPopupParams = function( data ) {
-				return setupParams.call( this, 'target', data );
-			};
+			return setupParams.call( this, 'target', data );
+		};
 
 		var setupAdvParams = function( data ) {
-				return setupParams.call( this, 'advanced', data );
-			};
+			return setupParams.call( this, 'advanced', data );
+		};
 
 		var commitParams = function( page, data ) {
-				if ( !data[ page ] )
-					data[ page ] = {};
+			if ( !data[ page ] ) {
+				data[ page ] = {};
+			}
 
-				data[ page ][ this.id ] = this.getValue() || '';
-			};
+			data[ page ][ this.id ] = this.getValue() || '';
+		};
 
 		var commitPopupParams = function( data ) {
-				return commitParams.call( this, 'target', data );
-			};
+			return commitParams.call( this, 'target', data );
+		};
 
 		var commitAdvParams = function( data ) {
-				return commitParams.call( this, 'advanced', data );
-			};
+			return commitParams.call( this, 'advanced', data );
+		};
 
 		var commonLang = editor.lang.common,
 			linkLang = editor.lang.link,
@@ -216,6 +226,12 @@
 			title: linkLang.title,
 			minWidth: ( CKEDITOR.skinName || editor.config.skin ) == 'moono-lisa' ? 450 : 350,
 			minHeight: 240,
+			getModel: function( editor ) {
+				var elements = plugin.getSelectedLink( editor, true ),
+					firstLink = elements[ 0 ] || null;
+
+				return firstLink;
+			},
 			contents: [ {
 				id: 'info',
 				label: linkLang.info,
@@ -245,7 +261,8 @@
 					items: [
 						[ linkLang.toUrl, 'url' ],
 						[ linkLang.toAnchor, 'anchor' ],
-						[ linkLang.toEmail, 'email' ]
+						[ linkLang.toEmail, 'email' ],
+						[ linkLang.toPhone, 'tel' ]
 					],
 					onChange: linkTypeChanged,
 					setup: function( data ) {
@@ -265,22 +282,24 @@
 							id: 'protocol',
 							type: 'select',
 							label: commonLang.protocol,
-							'default': 'http://',
 							items: [
-								// Force 'ltr' for protocol names in BIDI. (http://dev.ckeditor.com/ticket/5433)
+								// Force 'ltr' for protocol names in BIDI. (https://dev.ckeditor.com/ticket/5433)
 								[ 'http://\u200E', 'http://' ],
 								[ 'https://\u200E', 'https://' ],
 								[ 'ftp://\u200E', 'ftp://' ],
 								[ 'news://\u200E', 'news://' ],
 								[ linkLang.other, '' ]
 							],
+							'default': editor.config.linkDefaultProtocol,
 							setup: function( data ) {
-								if ( data.url )
+								if ( data.url ) {
 									this.setValue( data.url.protocol || '' );
+								}
 							},
 							commit: function( data ) {
-								if ( !data.url )
+								if ( !data.url ) {
 									data.url = {};
+								}
 
 								data.url.protocol = this.getValue();
 							}
@@ -298,9 +317,9 @@
 								var protocolCmb = this.getDialog().getContentElement( 'info', 'protocol' ),
 									url = this.getValue(),
 									urlOnChangeProtocol = /^(http|https|ftp|news):\/\/(?=.)/i,
-									urlOnChangeTestOther = /^((javascript:)|[#\/\.\?])/i;
+									urlOnChangeTestOther = /^((javascript:)|[#\/\.\?])/i,
+									protocol = urlOnChangeProtocol.exec( url );
 
-								var protocol = urlOnChangeProtocol.exec( url );
 								if ( protocol ) {
 									this.setValue( url.substr( protocol[ 0 ].length ) );
 									protocolCmb.setValue( protocol[ 0 ].toLowerCase() );
@@ -311,48 +330,56 @@
 								this.allowOnChange = true;
 							},
 							onChange: function() {
-								if ( this.allowOnChange ) // Dont't call on dialog load.
-								this.onKeyUp();
+								// Dont't call on dialog load.
+								if ( this.allowOnChange ) {
+									this.onKeyUp();
+								}
 							},
 							validate: function() {
 								var dialog = this.getDialog();
 
-								if ( dialog.getContentElement( 'info', 'linkType' ) && dialog.getValueOf( 'info', 'linkType' ) != 'url' )
+								if ( dialog.getContentElement( 'info', 'linkType' ) && dialog.getValueOf( 'info', 'linkType' ) != 'url' ) {
 									return true;
+								}
 
 								if ( !editor.config.linkJavaScriptLinksAllowed && ( /javascript\:/ ).test( this.getValue() ) ) {
 									alert( commonLang.invalidValue ); // jshint ignore:line
 									return false;
 								}
 
-								if ( this.getDialog().fakeObj ) // Edit Anchor.
-								return true;
+								// Edit Anchor.
+								if ( this.getDialog().fakeObj ) {
+									return true;
+								}
 
 								var func = CKEDITOR.dialog.validate.notEmpty( linkLang.noUrl );
 								return func.apply( this );
 							},
 							setup: function( data ) {
 								this.allowOnChange = false;
-								if ( data.url )
+								if ( data.url ) {
 									this.setValue( data.url.url );
+								}
 								this.allowOnChange = true;
 
 							},
 							commit: function( data ) {
 								// IE will not trigger the onChange event if the mouse has been used
-								// to carry all the operations http://dev.ckeditor.com/ticket/4724
+								// to carry all the operations https://dev.ckeditor.com/ticket/4724
 								this.onChange();
 
-								if ( !data.url )
+								if ( !data.url ) {
 									data.url = {};
+								}
 
 								data.url.url = this.getValue();
 								this.allowOnChange = false;
 							}
 						} ],
 						setup: function() {
-							if ( !this.getDialog().getContentElement( 'info', 'linkType' ) )
+							if ( !this.getDialog().getContentElement( 'info', 'linkType' ) ) {
 								this.getElement().show();
+							}
 						}
 					},
 					{
@@ -396,21 +423,25 @@
 
 									if ( anchors ) {
 										for ( var i = 0; i < anchors.length; i++ ) {
-											if ( anchors[ i ].name )
+											if ( anchors[ i ].name ) {
 												this.add( anchors[ i ].name );
+											}
 										}
 									}
 
-									if ( data.anchor )
+									if ( data.anchor ) {
 										this.setValue( data.anchor.name );
+									}
 
 									var linkType = this.getDialog().getContentElement( 'info', 'linkType' );
-									if ( linkType && linkType.getValue() == 'email' )
+									if ( linkType && linkType.getValue() == 'email' ) {
 										this.focus();
+									}
 								},
 								commit: function( data ) {
-									if ( !data.anchor )
+									if ( !data.anchor ) {
 										data.anchor = {};
+									}
 
 									data.anchor.name = this.getValue();
 								}
@@ -430,17 +461,20 @@
 
 									if ( anchors ) {
 										for ( var i = 0; i < anchors.length; i++ ) {
-											if ( anchors[ i ].id )
+											if ( anchors[ i ].id ) {
 												this.add( anchors[ i ].id );
+											}
 										}
 									}
 
-									if ( data.anchor )
+									if ( data.anchor ) {
 										this.setValue( data.anchor.id );
+									}
 								},
 								commit: function( data ) {
-									if ( !data.anchor )
+									if ( !data.anchor ) {
 										data.anchor = {};
+									}
 
 									data.anchor.id = this.getValue();
 								}
@@ -462,8 +496,9 @@
 						}
 					} ],
 					setup: function() {
-						if ( !this.getDialog().getContentElement( 'info', 'linkType' ) )
+						if ( !this.getDialog().getContentElement( 'info', 'linkType' ) ) {
 							this.getElement().hide();
+						}
 					}
 				},
 				{
@@ -478,23 +513,27 @@
 						validate: function() {
 							var dialog = this.getDialog();
 
-							if ( !dialog.getContentElement( 'info', 'linkType' ) || dialog.getValueOf( 'info', 'linkType' ) != 'email' )
+							if ( !dialog.getContentElement( 'info', 'linkType' ) || dialog.getValueOf( 'info', 'linkType' ) != 'email' ) {
 								return true;
+							}
 
 							var func = CKEDITOR.dialog.validate.notEmpty( linkLang.noEmail );
 							return func.apply( this );
 						},
 						setup: function( data ) {
-							if ( data.email )
+							if ( data.email ) {
 								this.setValue( data.email.address );
+							}
 
 							var linkType = this.getDialog().getContentElement( 'info', 'linkType' );
-							if ( linkType && linkType.getValue() == 'email' )
+							if ( linkType && linkType.getValue() == 'email' ) {
 								this.select();
+							}
 						},
 						commit: function( data ) {
-							if ( !data.email )
+							if ( !data.email ) {
 								data.email = {};
+							}
 
 							data.email.address = this.getValue();
 						}
@@ -504,12 +543,14 @@
 						id: 'emailSubject',
 						label: linkLang.emailSubject,
 						setup: function( data ) {
-							if ( data.email )
+							if ( data.email ) {
 								this.setValue( data.email.subject );
+							}
 						},
 						commit: function( data ) {
-							if ( !data.email )
+							if ( !data.email ) {
 								data.email = {};
+							}
 
 							data.email.subject = this.getValue();
 						}
@@ -521,19 +562,52 @@
 						rows: 3,
 						'default': '',
 						setup: function( data ) {
-							if ( data.email )
+							if ( data.email ) {
 								this.setValue( data.email.body );
+							}
 						},
 						commit: function( data ) {
-							if ( !data.email )
+							if ( !data.email ) {
 								data.email = {};
+							}
 
 							data.email.body = this.getValue();
 						}
 					} ],
 					setup: function() {
-						if ( !this.getDialog().getContentElement( 'info', 'linkType' ) )
+						if ( !this.getDialog().getContentElement( 'info', 'linkType' ) ) {
+							this.getElement().hide();
+						}
+					}
+				},
+				{
+					type: 'vbox',
+					id: 'telOptions',
+					padding: 1,
+					children: [ {
+						type: 'tel',
+						id: 'telNumber',
+						label: linkLang.phoneNumber,
+						required: true,
+						validate: validateTelNumber,
+						setup: function( data ) {
+							if ( data.tel ) {
+								this.setValue( data.tel );
+							}
+
+							var linkType = this.getDialog().getContentElement( 'info', 'linkType' );
+							if ( linkType && linkType.getValue() == 'tel' ) {
+								this.select();
+							}
+						},
+						commit: function( data ) {
+							data.tel = this.getValue();
+						}
+					} ],
+					setup: function() {
+						if ( !this.getDialog().getContentElement( 'info', 'linkType' ) ) {
 							this.getElement().hide();
+						}
 					}
 				} ]
 			},
@@ -562,13 +636,15 @@
 						],
 						onChange: targetChanged,
 						setup: function( data ) {
-							if ( data.target )
+							if ( data.target ) {
 								this.setValue( data.target.type || 'notSet' );
+							}
 							targetChanged.call( this );
 						},
 						commit: function( data ) {
-							if ( !data.target )
+							if ( !data.target ) {
 								data.target = {};
+							}
 
 							data.target.type = this.getValue();
 						}
@@ -579,12 +655,14 @@
 						label: linkLang.targetFrameName,
 						'default': '',
 						setup: function( data ) {
-							if ( data.target )
+							if ( data.target ) {
 								this.setValue( data.target.name );
+							}
 						},
 						commit: function( data ) {
-							if ( !data.target )
+							if ( !data.target ) {
 								data.target = {};
+							}
 
 							data.target.name = this.getValue().replace( /([^\x00-\x7F]|\s)/gi, '' );
 						}
@@ -614,7 +692,6 @@
 								label: linkLang.popupStatusBar,
 								setup: setupPopupParams,
 								commit: commitPopupParams
-
 							} ]
 						},
 						{
@@ -625,7 +702,6 @@
 								label: linkLang.popupLocationBar,
 								setup: setupPopupParams,
 								commit: commitPopupParams
-
 							},
 							{
 								type: 'checkbox',
@@ -633,7 +709,6 @@
 								label: linkLang.popupToolbar,
 								setup: setupPopupParams,
 								commit: commitPopupParams
-
 							} ]
 						},
 						{
@@ -644,7 +719,6 @@
 								label: linkLang.popupMenuBar,
 								setup: setupPopupParams,
 								commit: commitPopupParams
-
 							},
 							{
 								type: 'checkbox',
@@ -652,7 +726,6 @@
 								label: linkLang.popupFullScreen,
 								setup: setupPopupParams,
 								commit: commitPopupParams
-
 							} ]
 						},
 						{
@@ -663,7 +736,6 @@
 								label: linkLang.popupScrollBars,
 								setup: setupPopupParams,
 								commit: commitPopupParams
-
 							},
 							{
 								type: 'checkbox',
@@ -671,7 +743,6 @@
 								label: linkLang.popupDependent,
 								setup: setupPopupParams,
 								commit: commitPopupParams
-
 							} ]
 						},
 						{
@@ -684,7 +755,6 @@
 								id: 'width',
 								setup: setupPopupParams,
 								commit: commitPopupParams
-
 							},
 							{
 								type: 'text',
@@ -694,7 +764,6 @@
 								id: 'left',
 								setup: setupPopupParams,
 								commit: commitPopupParams
-
 							} ]
 						},
 						{
@@ -707,7 +776,6 @@
 								id: 'height',
 								setup: setupPopupParams,
 								commit: commitPopupParams
-
 							},
 							{
 								type: 'text',
@@ -717,7 +785,6 @@
 								id: 'top',
 								setup: setupPopupParams,
 								commit: commitPopupParams
-
 							} ]
 						} ]
 					} ]
@@ -786,7 +853,6 @@
 							maxLength: 1,
 							setup: setupAdvParams,
 							commit: commitAdvParams
-
 						} ]
 					},
 					{
@@ -799,7 +865,6 @@
 							requiredContent: 'a[name]',
 							setup: setupAdvParams,
 							commit: commitAdvParams
-
 						},
 						{
 							type: 'text',
@@ -810,7 +875,6 @@
 							'default': '',
 							setup: setupAdvParams,
 							commit: commitAdvParams
-
 						},
 						{
 							type: 'text',
@@ -821,7 +885,6 @@
 							maxLength: 5,
 							setup: setupAdvParams,
 							commit: commitAdvParams
-
 						} ]
 					} ]
 				},
@@ -839,7 +902,6 @@
 							id: 'advTitle',
 							setup: setupAdvParams,
 							commit: commitAdvParams
-
 						},
 						{
 							type: 'text',
@@ -849,7 +911,6 @@
 							id: 'advContentType',
 							setup: setupAdvParams,
 							commit: commitAdvParams
-
 						} ]
 					},
 					{
@@ -863,7 +924,6 @@
 							id: 'advCSSClasses',
 							setup: setupAdvParams,
 							commit: commitAdvParams
-
 						},
 						{
 							type: 'text',
@@ -873,7 +933,6 @@
 							id: 'advCharset',
 							setup: setupAdvParams,
 							commit: commitAdvParams
-
 						} ]
 					},
 					{
@@ -908,8 +967,9 @@
 							requiredContent: 'a[download]',
 							label: linkLang.download,
 							setup: function( data ) {
-								if ( data.download !== undefined )
+								if ( data.download !== undefined ) {
 									this.setValue( 'checked', 'checked' );
+								}
 							},
 							commit: function( data ) {
 								if ( this.getValue() ) {
@@ -965,11 +1025,13 @@
 				}
 			},
 			onLoad: function() {
-				if ( !editor.config.linkShowAdvancedTab )
+				if ( !editor.config.linkShowAdvancedTab ) {
 					this.hidePage( 'advanced' ); //Hide Advanded tab.
+				}
 
-				if ( !editor.config.linkShowTargetTab )
+				if ( !editor.config.linkShowTargetTab ) {
 					this.hidePage( 'target' ); //Hide Target tab.
+				}
 			},
 			// Inital focus on 'url' field if link is of type URL.
 			onFocus: function() {
@@ -983,6 +1045,27 @@
 			}
 		};
 	} );
+
+	function validateTelNumber() {
+		var dialog = this.getDialog(),
+			editor = dialog._.editor,
+			regExp =  editor.config.linkPhoneRegExp,
+			msg = editor.config.linkPhoneMsg,
+			linkLang = editor.lang.link,
+			messageWhenEmpty = CKEDITOR.dialog.validate.notEmpty( linkLang.noTel ).apply( this );
+
+		if ( !dialog.getContentElement( 'info', 'linkType' ) || dialog.getValueOf( 'info', 'linkType' ) != 'tel' ) {
+			return true;
+		}
+
+		if ( messageWhenEmpty !== true ) {
+			return messageWhenEmpty;
+		}
+
+		if ( regExp ) {
+			return CKEDITOR.dialog.validate.regex( regExp, msg ).call( this );
+		}
+	}
 } )();
 // jscs:disable maximumLineLength
 /**
@@ -1009,7 +1092,7 @@
  *		// href="javascript:mt('tester','ckeditor.com','subject','body')"
  *		config.emailProtection = 'mt(NAME,DOMAIN,SUBJECT,BODY)';
  *
- * @since 3.1
+ * @since 3.1.0
  * @cfg {String} [emailProtection='' (empty string = disabled)]
  * @member CKEDITOR.config
  */
diff --git a/web/modules/anchor_link/js/plugins/link/lang/af.js b/web/modules/anchor_link/js/plugins/link/lang/af.js
index 1e3f943c8b5a636ad6d1a064a9e05b725b252847..532e1ddd77f2be35ef7530345f94a43b8ec90231 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/af.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/af.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'af', {
 	acccessKey: 'Toegangsleutel',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'af', {
 	noAnchors: '(Geen ankers beskikbaar in dokument)',
 	noEmail: 'Gee die e-posadres',
 	noUrl: 'Gee die skakel se URL',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<ander>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Afhanklik (Netscape)',
 	popupFeatures: 'Eienskappe van opspringvenster',
 	popupFullScreen: 'Volskerm (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'af', {
 	toAnchor: 'Anker in bladsy',
 	toEmail: 'E-pos',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Skakel invoeg/wysig',
 	type: 'Skakelsoort',
 	unlink: 'Verwyder skakel',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/ar.js b/web/modules/anchor_link/js/plugins/link/lang/ar.js
index cfd0b486b1690a16d431f62c546ca730e48f08cf..eb99f8210742d240212995591486c12640e80a02 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/ar.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/ar.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'ar', {
 	acccessKey: 'مفاتيح الإختصار',
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'ar', {
 	anchorName: 'حسب إسم الإشارة المرجعية',
 	charset: 'ترميز المادة المطلوبة',
 	cssClasses: 'فئات التنسيق',
-	download: 'Force Download', // MISSING
-	displayText: 'Display Text', // MISSING
+	download: 'فرض التحميل',
+	displayText: 'نص العرض',
 	emailAddress: 'البريد الإلكتروني',
 	emailBody: 'محتوى الرسالة',
 	emailSubject: 'موضوع الرسالة',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'ar', {
 	noAnchors: '(لا توجد علامات مرجعية في هذا المستند)',
 	noEmail: 'الرجاء كتابة الريد الإلكتروني',
 	noUrl: 'الرجاء كتابة رابط الموقع',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<أخرى>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'تابع (Netscape)',
 	popupFeatures: 'خصائص النافذة المنبثقة',
 	popupFullScreen: 'ملئ الشاشة (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'ar', {
 	toAnchor: 'مكان في هذا المستند',
 	toEmail: 'بريد إلكتروني',
 	toUrl: 'الرابط',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'رابط',
 	type: 'نوع الربط',
 	unlink: 'إزالة رابط',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/az.js b/web/modules/anchor_link/js/plugins/link/lang/az.js
index ff78d0e9c752eae3061dc667f42fb87f4a28edbd..da3ade1c8cea7c4829dad296b94cb753573d12e7 100644
--- a/web/modules/anchor_link/js/plugins/link/lang/az.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/az.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'az', {
 	acccessKey: 'Qısayol düyməsi',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'az', {
 	noAnchors: '(heç bir xeş tapılmayıb)',
 	noEmail: 'E-poçt ünvanı daxil edin',
 	noUrl: 'Linkin URL-ı daxil edin',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<digər>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Asılı (Netscape)',
 	popupFeatures: 'Pəncərənin xüsusiyyətləri',
 	popupFullScreen: 'Tam ekran rejimi (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'az', {
 	toAnchor: 'Xeş',
 	toEmail: 'E-poçt',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Link',
 	type: 'Linkin növü',
 	unlink: 'Linki sil',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/bg.js b/web/modules/anchor_link/js/plugins/link/lang/bg.js
index f0db4c462ef8fe8b895dc09d4ca2cf386d20501f..1a331c4fd187d5b318fc7dc7b5242e84fc86827f 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/bg.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/bg.js
@@ -1,12 +1,12 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'bg', {
-	acccessKey: 'Ключ за достъп',
+	acccessKey: 'Клавиш за достъп',
 	advanced: 'Разширено',
-	advisoryContentType: 'Препоръчителен тип на съдържанието',
-	advisoryTitle: 'Препоръчително заглавие',
+	advisoryContentType: 'Тип на съдържанието',
+	advisoryTitle: 'Заглавие',
 	anchor: {
 		toolbar: 'Котва',
 		menu: 'Промяна на котва',
@@ -17,25 +17,27 @@ CKEDITOR.plugins.setLang( 'link', 'bg', {
 	},
 	anchorId: 'По ID на елемент',
 	anchorName: 'По име на котва',
-	charset: 'Тип на свързания ресурс',
-	cssClasses: 'Класове за CSS',
-	download: 'Force Download', // MISSING
-	displayText: 'Display Text', // MISSING
-	emailAddress: 'E-mail aдрес',
+	charset: 'Езиков код на свързания ресурс',
+	cssClasses: 'CSS класове',
+	download: 'Укажи изтегляне',
+	displayText: 'Текст за показване',
+	emailAddress: 'Имейл aдрес',
 	emailBody: 'Съдържание',
 	emailSubject: 'Тема',
-	id: 'ID',
-	info: 'Инфо за връзката',
-	langCode: 'Код за езика',
+	id: 'Id',
+	info: 'Връзка',
+	langCode: 'Езиков код',
 	langDir: 'Посока на езика',
-	langDirLTR: 'Ляво на Дясно (ЛнД)',
-	langDirRTL: 'Дясно на Ляво (ДнЛ)',
+	langDirLTR: 'От ляво надясно (LTR)',
+	langDirRTL: 'От дясно наляво (RTL)',
 	menu: 'Промяна на връзка',
 	name: 'Име',
 	noAnchors: '(Няма котви в текущия документ)',
-	noEmail: 'Моля въведете e-mail aдрес',
-	noUrl: 'Моля въведете URL адреса',
+	noEmail: 'Моля въведете имейл адрес',
+	noUrl: 'Моля въведете URL адрес',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<друго>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Зависимост (Netscape)',
 	popupFeatures: 'Функции на изкачащ прозорец',
 	popupFullScreen: 'Цял екран (IE)',
@@ -43,23 +45,24 @@ CKEDITOR.plugins.setLang( 'link', 'bg', {
 	popupLocationBar: 'Лента с локацията',
 	popupMenuBar: 'Лента за меню',
 	popupResizable: 'Оразмеряем',
-	popupScrollBars: 'Скролери',
+	popupScrollBars: 'Ленти за прелистване',
 	popupStatusBar: 'Статусна лента',
 	popupToolbar: 'Лента с инструменти',
 	popupTop: 'Горна позиция',
-	rel: 'Връзка',
+	rel: 'Свързаност (rel атрибут)',
 	selectAnchor: 'Изберете котва',
 	styles: 'Стил',
 	tabIndex: 'Ред на достъп',
 	target: 'Цел',
 	targetFrame: '<frame>',
-	targetFrameName: 'Име на целевият прозорец',
+	targetFrameName: 'Име на целевия прозорец',
 	targetPopup: '<изкачащ прозорец>',
 	targetPopupName: 'Име на изкачащ прозорец',
 	title: 'Връзка',
 	toAnchor: 'Връзка към котва в текста',
-	toEmail: 'E-mail',
+	toEmail: 'Имейл',
 	toUrl: 'Уеб адрес',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Връзка',
 	type: 'Тип на връзката',
 	unlink: 'Премахни връзката',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/bn.js b/web/modules/anchor_link/js/plugins/link/lang/bn.js
index 2e81bc31c043fc6e5f082aafc8dc275485862ef1..e581c552ed88513d1111d7adc7926ff81fa29ca2 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/bn.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/bn.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'bn', {
 	acccessKey: 'প্রবেশ কী',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'bn', {
 	noAnchors: '(No anchors available in the document)', // MISSING
 	noEmail: 'অনুগ্রহ করে ইমেইল এড্রেস টাইপ করুন',
 	noUrl: 'অনুগ্রহ করে URL লিংক টাইপ করুন',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<other>', // MISSING
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'ডিপেন্ডেন্ট (Netscape)',
 	popupFeatures: 'পপআপ উইন্ডো ফীচার সমূহ',
 	popupFullScreen: 'পূর্ণ পর্দা জুড়ে (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'bn', {
 	toAnchor: 'এই পেজে নোঙর কর',
 	toEmail: 'ইমেইল',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'লিংক যুক্ত কর',
 	type: 'লিংক প্রকার',
 	unlink: 'লিংক সরাও',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/bs.js b/web/modules/anchor_link/js/plugins/link/lang/bs.js
index 70b8e4e972d8644a7552cf64459a6b026dd53c7e..d2889fee7659a74e9fc81347fa4ef6c6cd294d30 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/bs.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/bs.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'bs', {
 	acccessKey: 'Pristupna tipka',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'bs', {
 	noAnchors: '(Nema dostupnih sidra na stranici)',
 	noEmail: 'Molimo ukucajte e-mail adresu',
 	noUrl: 'Molimo ukucajte URL link',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<other>', // MISSING
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Ovisno (Netscape)',
 	popupFeatures: 'Moguænosti popup prozora',
 	popupFullScreen: 'Cijeli ekran (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'bs', {
 	toAnchor: 'Sidro na ovoj stranici',
 	toEmail: 'E-Mail',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Ubaci/Izmjeni link',
 	type: 'Tip linka',
 	unlink: 'Izbriši link',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/ca.js b/web/modules/anchor_link/js/plugins/link/lang/ca.js
index 120ca4b61b038e8f8e89ac6a1dad2b63582bde26..e68b79b1fed1cac68a2b6e7122092e9afa573542 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/ca.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/ca.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'ca', {
 	acccessKey: 'Clau d\'accés',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'ca', {
 	noAnchors: '(No hi ha àncores disponibles en aquest document)',
 	noEmail: 'Si us plau, escrigui l\'adreça correu electrònic',
 	noUrl: 'Si us plau, escrigui l\'enllaç URL',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<altre>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Depenent (Netscape)',
 	popupFeatures: 'Característiques finestra popup',
 	popupFullScreen: 'Pantalla completa (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'ca', {
 	toAnchor: 'Àncora en aquesta pàgina',
 	toEmail: 'Correu electrònic',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Insereix/Edita enllaç',
 	type: 'Tipus d\'enllaç',
 	unlink: 'Elimina l\'enllaç',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/cs.js b/web/modules/anchor_link/js/plugins/link/lang/cs.js
index db0b5d4f4cc9da49adc8a1e6c841bb604a0bc8c0..8bf5cb9de4e4a8540ac38b20e7bdac0397021c0b 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/cs.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/cs.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'cs', {
 	acccessKey: 'Přístupový klíč',
@@ -19,7 +19,7 @@ CKEDITOR.plugins.setLang( 'link', 'cs', {
 	anchorName: 'Podle jména kotvy',
 	charset: 'Přiřazená znaková sada',
 	cssClasses: 'Třída stylu',
-	download: 'Force Download', // MISSING
+	download: 'Vynutit stažení',
 	displayText: 'Zobrazit text',
 	emailAddress: 'E-mailová adresa',
 	emailBody: 'Tělo zprávy',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'cs', {
 	noAnchors: '(Ve stránce není definována žádná kotva!)',
 	noEmail: 'Zadejte prosím e-mailovou adresu',
 	noUrl: 'Zadejte prosím URL odkazu',
+	noTel: 'Vyplňte prosím telefonní číslo',
 	other: '<jiný>',
+	phoneNumber: 'Telefonní číslo',
 	popupDependent: 'Závislost (Netscape)',
 	popupFeatures: 'Vlastnosti vyskakovacího okna',
 	popupFullScreen: 'Celá obrazovka (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'cs', {
 	toAnchor: 'Kotva v této stránce',
 	toEmail: 'E-mail',
 	toUrl: 'URL',
+	toPhone: 'Telefon',
 	toolbar: 'Odkaz',
 	type: 'Typ odkazu',
 	unlink: 'Odstranit odkaz',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/cy.js b/web/modules/anchor_link/js/plugins/link/lang/cy.js
index f47c54e5ae61d1021734bff72dbff3257f0d4fca..369b75f2814477a2edd41410ca2d9b592304fe9b 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/cy.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/cy.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'cy', {
 	acccessKey: 'Allwedd Mynediad',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'cy', {
 	noAnchors: '(Dim angorau ar gael yn y ddogfen)',
 	noEmail: 'Teipiwch gyfeiriad yr e-bost',
 	noUrl: 'Teipiwch URL y ddolen',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<eraill>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Dibynnol (Netscape)',
 	popupFeatures: 'Nodweddion Ffenestr Bop',
 	popupFullScreen: 'Sgrin Llawn (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'cy', {
 	toAnchor: 'Dolen at angor yn y testun',
 	toEmail: 'E-bost',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Dolen',
 	type: 'Math y Ddolen',
 	unlink: 'Datgysylltu',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/da.js b/web/modules/anchor_link/js/plugins/link/lang/da.js
index 5350263c040e70632a1cb371b48daf66e4c68ba0..7adaedeae5b08f01f915c0ae48b355a5006147ca 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/da.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/da.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'da', {
 	acccessKey: 'Genvejstast',
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'da', {
 	anchorName: 'Efter ankernavn',
 	charset: 'Tegnsæt',
 	cssClasses: 'Typografiark',
-	download: 'Force Download', // MISSING
-	displayText: 'Display Text', // MISSING
+	download: 'Tving Download',
+	displayText: 'Vis tekst',
 	emailAddress: 'E-mailadresse',
 	emailBody: 'Besked',
 	emailSubject: 'Emne',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'da', {
 	noAnchors: '(Ingen bogmærker i dokumentet)',
 	noEmail: 'Indtast e-mailadresse!',
 	noUrl: 'Indtast hyperlink-URL!',
+	noTel: 'Indtast venligst et telefonnummer',
 	other: '<anden>',
+	phoneNumber: 'Telefonnummer',
 	popupDependent: 'Koblet/dependent (Netscape)',
 	popupFeatures: 'Egenskaber for popup',
 	popupFullScreen: 'Fuld skærm (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'da', {
 	toAnchor: 'Bogmærke på denne side',
 	toEmail: 'E-mail',
 	toUrl: 'URL',
+	toPhone: 'Telefon',
 	toolbar: 'Indsæt/redigér hyperlink',
 	type: 'Type',
 	unlink: 'Fjern hyperlink',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/de-ch.js b/web/modules/anchor_link/js/plugins/link/lang/de-ch.js
index 1575303f766afa8d89f548816e85f7198dbd75ef..2821f6d6d3ce21b356d5e70ebc50766dcac7a9e2 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/de-ch.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/de-ch.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'de-ch', {
 	acccessKey: 'Zugriffstaste',
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'de-ch', {
 	anchorName: 'Nach Ankername',
 	charset: 'Verknüpfter Ressourcenzeichensatz',
 	cssClasses: 'Formatvorlagenklasse',
-	download: 'Force Download', // MISSING
-	displayText: 'Display Text', // MISSING
+	download: 'Herunterladen erzwingen',
+	displayText: 'Anzeigetext',
 	emailAddress: 'E-Mail-Adresse',
 	emailBody: 'Nachrichtentext',
 	emailSubject: 'Betreffzeile',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'de-ch', {
 	noAnchors: '(Keine Anker im Dokument vorhanden)',
 	noEmail: 'Bitte geben Sie E-Mail-Adresse an',
 	noUrl: 'Bitte geben Sie die Link-URL an',
+	noTel: 'Bitte geben Sie die Telefonnummer ein',
 	other: '<andere>',
+	phoneNumber: 'Telefonnummer',
 	popupDependent: 'Abhängig (Netscape)',
 	popupFeatures: 'Pop-up Fenstereigenschaften',
 	popupFullScreen: 'Vollbild (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'de-ch', {
 	toAnchor: 'Anker in dieser Seite',
 	toEmail: 'E-Mail',
 	toUrl: 'URL',
+	toPhone: 'Telefon',
 	toolbar: 'Link einfügen/editieren',
 	type: 'Link-Typ',
 	unlink: 'Link entfernen',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/de.js b/web/modules/anchor_link/js/plugins/link/lang/de.js
index 4a48db0e355d78b802434bb91f049cfe321adafc..f558240b4dd7a8b4b4616af94b88d1fb11805585 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/de.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/de.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'de', {
 	acccessKey: 'Zugriffstaste',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'de', {
 	noAnchors: '(Keine Anker im Dokument vorhanden)',
 	noEmail: 'Bitte geben Sie E-Mail-Adresse an',
 	noUrl: 'Bitte geben Sie die Link-URL an',
+	noTel: 'Bitte geben Sie die Telefonnummer ein',
 	other: '<andere>',
+	phoneNumber: 'Telefonnummer',
 	popupDependent: 'Abhängig (Netscape)',
 	popupFeatures: 'Pop-up Fenstereigenschaften',
 	popupFullScreen: 'Vollbild (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'de', {
 	toAnchor: 'Anker in dieser Seite',
 	toEmail: 'E-Mail',
 	toUrl: 'URL',
+	toPhone: 'Telefon',
 	toolbar: 'Link einfügen/editieren',
 	type: 'Link-Typ',
 	unlink: 'Link entfernen',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/el.js b/web/modules/anchor_link/js/plugins/link/lang/el.js
index 30fa7feee963574a829a846aefc2256c32a3fbb3..9e90d21b5ee64c3312b3b4ec520b47889bc4ac7d 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/el.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/el.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'el', {
 	acccessKey: 'Συντόμευση',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'el', {
 	noAnchors: '(Δεν υπάρχουν άγκυρες στο κείμενο)',
 	noEmail: 'Εισάγετε τη διεύθυνση ηλεκτρονικού ταχυδρομείου',
 	noUrl: 'Εισάγετε την τοποθεσία (URL) του συνδέσμου',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<άλλο>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Εξαρτημένο (Netscape)',
 	popupFeatures: 'Επιλογές Αναδυόμενου Παραθύρου',
 	popupFullScreen: 'Πλήρης Οθόνη (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'el', {
 	toAnchor: 'Άγκυρα σε αυτήν τη σελίδα',
 	toEmail: 'E-Mail',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Σύνδεσμος',
 	type: 'Τύπος Συνδέσμου',
 	unlink: 'Αφαίρεση Συνδέσμου',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/en-au.js b/web/modules/anchor_link/js/plugins/link/lang/en-au.js
index 508a1ec284635e3c978ef3cd2ddbea9107c49415..3c0e21f62d7d030b46733aa16e2f81991d5bdff5 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/en-au.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/en-au.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'en-au', {
 	acccessKey: 'Access Key',
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'en-au', {
 	anchorName: 'By Anchor Name',
 	charset: 'Linked Resource Charset',
 	cssClasses: 'Stylesheet Classes',
-	download: 'Force Download', // MISSING
-	displayText: 'Display Text', // MISSING
+	download: 'Force Download',
+	displayText: 'Display Text',
 	emailAddress: 'E-Mail Address',
 	emailBody: 'Message Body',
 	emailSubject: 'Message Subject',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'en-au', {
 	noAnchors: '(No anchors available in the document)',
 	noEmail: 'Please type the e-mail address',
 	noUrl: 'Please type the link URL',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<other>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Dependent (Netscape)',
 	popupFeatures: 'Popup Window Features',
 	popupFullScreen: 'Full Screen (IE)',
@@ -47,7 +49,7 @@ CKEDITOR.plugins.setLang( 'link', 'en-au', {
 	popupStatusBar: 'Status Bar',
 	popupToolbar: 'Toolbar',
 	popupTop: 'Top Position',
-	rel: 'Relationship', // MISSING
+	rel: 'Relationship',
 	selectAnchor: 'Select an Anchor',
 	styles: 'Style',
 	tabIndex: 'Tab Index',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'en-au', {
 	toAnchor: 'Link to anchor in the text',
 	toEmail: 'E-mail',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Link',
 	type: 'Link Type',
 	unlink: 'Unlink',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/en-ca.js b/web/modules/anchor_link/js/plugins/link/lang/en-ca.js
index e281ab0996dbeed11dcf7890f4e91005ec749153..f47b17ef2de2bb6238c56a360bef063f75c9663a 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/en-ca.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/en-ca.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'en-ca', {
 	acccessKey: 'Access Key',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'en-ca', {
 	noAnchors: '(No anchors available in the document)',
 	noEmail: 'Please type the e-mail address',
 	noUrl: 'Please type the link URL',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<other>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Dependent (Netscape)',
 	popupFeatures: 'Popup Window Features',
 	popupFullScreen: 'Full Screen (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'en-ca', {
 	toAnchor: 'Link to anchor in the text',
 	toEmail: 'E-mail',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Link',
 	type: 'Link Type',
 	unlink: 'Unlink',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/en-gb.js b/web/modules/anchor_link/js/plugins/link/lang/en-gb.js
index cdf0290f21418da60bf2998388f2816f4cb5cbe7..e7595d4969692997b083fb74b829234d92927457 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/en-gb.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/en-gb.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'en-gb', {
 	acccessKey: 'Access Key',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'en-gb', {
 	noAnchors: '(No anchors available in the document)',
 	noEmail: 'Please type the e-mail address',
 	noUrl: 'Please type the link URL',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<other>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Dependent (Netscape)',
 	popupFeatures: 'Popup Window Features',
 	popupFullScreen: 'Full Screen (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'en-gb', {
 	toAnchor: 'Link to anchor in the text',
 	toEmail: 'E-mail',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Link',
 	type: 'Link Type',
 	unlink: 'Unlink',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/en.js b/web/modules/anchor_link/js/plugins/link/lang/en.js
index 555f3624cd5eb22bcae728fa3c430563d572913e..191851e7b438f5f0c6b6b6649da7beaa3a8590f6 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/en.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/en.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'en', {
 	acccessKey: 'Access Key',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'en', {
 	noAnchors: '(No anchors available in the document)',
 	noEmail: 'Please type the e-mail address',
 	noUrl: 'Please type the link URL',
+	noTel: 'Please type the phone number',
 	other: '<other>',
+	phoneNumber: 'Phone number',
 	popupDependent: 'Dependent (Netscape)',
 	popupFeatures: 'Popup Window Features',
 	popupFullScreen: 'Full Screen (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'en', {
 	toAnchor: 'Link to anchor in the text',
 	toEmail: 'E-mail',
 	toUrl: 'URL',
+	toPhone: 'Phone',
 	toolbar: 'Link',
 	type: 'Link Type',
 	unlink: 'Unlink',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/eo.js b/web/modules/anchor_link/js/plugins/link/lang/eo.js
index 6bcd8395d6e6554a76431a118d4800e7a003217d..cc5bd27f54020c13d4f23abb3d43404180029d99 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/eo.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/eo.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'eo', {
 	acccessKey: 'Fulmoklavo',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'eo', {
 	noAnchors: '<Ne disponeblas ankroj en la dokumento>',
 	noEmail: 'Bonvolu entajpi la retpoŝtadreson',
 	noUrl: 'Bonvolu entajpi la URL-on',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<alia>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Dependa (Netscape)',
 	popupFeatures: 'Atributoj de la Ŝprucfenestro',
 	popupFullScreen: 'Tutekrane (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'eo', {
 	toAnchor: 'Ankri en tiu ĉi paĝo',
 	toEmail: 'Retpoŝto',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Enmeti/Ŝanĝi Ligilon',
 	type: 'Tipo de Ligilo',
 	unlink: 'Forigi Ligilon',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/es-mx.js b/web/modules/anchor_link/js/plugins/link/lang/es-mx.js
index f378cbf031763ca4253520f224041eca728fe278..bbd9488135594886b51644b6d2d6485a27d8ebc8 100644
--- a/web/modules/anchor_link/js/plugins/link/lang/es-mx.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/es-mx.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'es-mx', {
 	acccessKey: 'Llave de acceso',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'es-mx', {
 	noAnchors: '(No hay anclas disponibles en el documento)',
 	noEmail: 'Escriba la dirección de correo electrónico',
 	noUrl: 'Escriba la URL del enlace',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<other>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Dependiente (Netscape)',
 	popupFeatures: 'Ventana emergente',
 	popupFullScreen: 'Pantalla completa (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'es-mx', {
 	toAnchor: 'Enlace al ancla en el texto',
 	toEmail: 'Correo electrónico',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Enlace',
 	type: 'Tipo de enlace',
 	unlink: 'Desconectar',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/es.js b/web/modules/anchor_link/js/plugins/link/lang/es.js
index d151c7d79cc7cb7bb46f65461e95cf0317a6c2e4..c442ea81b05ae45910e8a1a0a578d2e1414c4b57 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/es.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/es.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'es', {
 	acccessKey: 'Tecla de Acceso',
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'es', {
 	anchorName: 'Por Nombre de Referencia',
 	charset: 'Fuente de caracteres vinculado',
 	cssClasses: 'Clases de hojas de estilo',
-	download: 'Force Download', // MISSING
-	displayText: 'Display Text', // MISSING
+	download: 'Forzar la descarga',
+	displayText: 'Mostrar texto',
 	emailAddress: 'Dirección de E-Mail',
 	emailBody: 'Cuerpo del Mensaje',
 	emailSubject: 'Título del Mensaje',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'es', {
 	noAnchors: '(No hay referencias disponibles en el documento)',
 	noEmail: 'Por favor escriba la dirección de e-mail',
 	noUrl: 'Por favor escriba el vínculo URL',
+	noTel: 'Por favor ingrese el numero de telefono',
 	other: '<otro>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Dependiente (Netscape)',
 	popupFeatures: 'Características de Ventana Emergente',
 	popupFullScreen: 'Pantalla Completa (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'es', {
 	toAnchor: 'Referencia en esta página',
 	toEmail: 'E-Mail',
 	toUrl: 'URL',
+	toPhone: 'Teléfono',
 	toolbar: 'Insertar/Editar Vínculo',
 	type: 'Tipo de vínculo',
 	unlink: 'Eliminar Vínculo',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/et.js b/web/modules/anchor_link/js/plugins/link/lang/et.js
index 94353ead9b5d6090efe753f945cc7447b560bf94..d888acf44fba5ab53182439d261256c16fcf920d 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/et.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/et.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'et', {
 	acccessKey: 'Juurdepääsu võti',
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'et', {
 	anchorName: 'Ankru nime järgi',
 	charset: 'Lingitud ressursi märgistik',
 	cssClasses: 'Stiilistiku klassid',
-	download: 'Force Download', // MISSING
-	displayText: 'Display Text', // MISSING
+	download: 'Sunni allalaadimine',
+	displayText: 'Näidatav tekst',
 	emailAddress: 'E-posti aadress',
 	emailBody: 'Sõnumi tekst',
 	emailSubject: 'Sõnumi teema',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'et', {
 	noAnchors: '(Selles dokumendis pole ankruid)',
 	noEmail: 'Palun kirjuta e-posti aadress',
 	noUrl: 'Palun kirjuta lingi URL',
+	noTel: 'Palun sisesta telefoninumber',
 	other: '<muu>',
+	phoneNumber: 'Telefoninumber',
 	popupDependent: 'Sõltuv (Netscape)',
 	popupFeatures: 'Hüpikakna omadused',
 	popupFullScreen: 'Täisekraan (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'et', {
 	toAnchor: 'Ankur sellel lehel',
 	toEmail: 'E-post',
 	toUrl: 'URL',
+	toPhone: 'Telefon',
 	toolbar: 'Lingi lisamine/muutmine',
 	type: 'Lingi liik',
 	unlink: 'Lingi eemaldamine',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/eu.js b/web/modules/anchor_link/js/plugins/link/lang/eu.js
index 345241ea48bfe5dee1ce5378bd5f9d482895284e..5a1300d3e4e70ad2e8c3fb473847d3e2ea388194 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/eu.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/eu.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'eu', {
 	acccessKey: 'Sarbide-tekla',
@@ -19,7 +19,7 @@ CKEDITOR.plugins.setLang( 'link', 'eu', {
 	anchorName: 'Aingura-izenaren arabera',
 	charset: 'Estekatutako baliabide karaktere-jokoa',
 	cssClasses: 'Estilo-orriko klaseak',
-	download: 'Force Download', // MISSING
+	download: 'Behartu deskarga',
 	displayText: 'Bistaratu testua',
 	emailAddress: 'E-posta helbidea',
 	emailBody: 'Mezuaren gorputza',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'eu', {
 	noAnchors: '(Ez dago aingurarik erabilgarri dokumentuan)',
 	noEmail: 'Mesedez idatzi e-posta helbidea',
 	noUrl: 'Mesedez idatzi estekaren URLa',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<bestelakoa>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Menpekoa (Netscape)',
 	popupFeatures: 'Laster-leihoaren ezaugarriak',
 	popupFullScreen: 'Pantaila osoa (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'eu', {
 	toAnchor: 'Estekatu testuko aingurara',
 	toEmail: 'E-posta',
 	toUrl: 'URLa',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Esteka',
 	type: 'Esteka-mota',
 	unlink: 'Kendu esteka',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/fa.js b/web/modules/anchor_link/js/plugins/link/lang/fa.js
index 4722d084da3ab4b0cfc4a107e1f23b11561bbb7b..fa4e4936d937dfdb64d6a2640263c137c8ecc108 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/fa.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/fa.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'fa', {
 	acccessKey: 'کلید دستیابی',
@@ -8,36 +8,38 @@ CKEDITOR.plugins.setLang( 'link', 'fa', {
 	advisoryContentType: 'نوع محتوای کمکی',
 	advisoryTitle: 'عنوان کمکی',
 	anchor: {
-		toolbar: 'گنجاندن/ویرایش لنگر',
-		menu: 'ویژگی​های لنگر',
-		title: 'ویژگی​های لنگر',
-		name: 'نام لنگر',
+		toolbar: 'گنجاندن/ویرایش لینک',
+		menu: 'ویرایش لینک',
+		title: 'ویژگی​های لینک',
+		name: 'نام لینک',
 		errorName: 'لطفا نام لنگر را بنویسید',
-		remove: 'حذف لنگر'
+		remove: 'حذف لینک'
 	},
 	anchorId: 'با شناسهٴ المان',
-	anchorName: 'با نام لنگر',
+	anchorName: 'با نام لینک ',
 	charset: 'نویسه​گان منبع پیوند شده',
-	cssClasses: 'کلاس​های شیوه​نامه(Stylesheet)',
-	download: 'Force Download', // MISSING
-	displayText: 'Display Text', // MISSING
+	cssClasses: 'کلاس​های شیوه​نامه (Style sheet)',
+	download: 'بارگیری اجباری',
+	displayText: 'نمایش متن',
 	emailAddress: 'نشانی پست الکترونیکی',
 	emailBody: 'متن پیام',
 	emailSubject: 'موضوع پیام',
 	id: 'شناسه',
 	info: 'اطلاعات پیوند',
-	langCode: 'جهت​نمای زبان',
+	langCode: 'کد زبان',
 	langDir: 'جهت​نمای زبان',
 	langDirLTR: 'چپ به راست (LTR)',
 	langDirRTL: 'راست به چپ (RTL)',
 	menu: 'ویرایش پیوند',
 	name: 'نام',
-	noAnchors: '(در این سند لنگری دردسترس نیست)',
+	noAnchors: '(در این سند لینکی دردسترس نیست)',
 	noEmail: 'لطفا نشانی پست الکترونیکی را بنویسید',
-	noUrl: 'لطفا URL پیوند را بنویسید',
+	noUrl: 'لطفا آدرس پیوند را بنویسید',
+	noTel: 'لطفا شماره تلفن را وارد کنید',
 	other: '<سایر>',
+	phoneNumber: 'شماره تلفن',
 	popupDependent: 'وابسته (Netscape)',
-	popupFeatures: 'ویژگی​های پنجرهٴ پاپاپ',
+	popupFeatures: 'ویژگی​های پنجره ی پاپاپ',
 	popupFullScreen: 'تمام صفحه (IE)',
 	popupLeft: 'موقعیت چپ',
 	popupLocationBar: 'نوار موقعیت',
@@ -48,18 +50,19 @@ CKEDITOR.plugins.setLang( 'link', 'fa', {
 	popupToolbar: 'نوار ابزار',
 	popupTop: 'موقعیت بالا',
 	rel: 'وابستگی',
-	selectAnchor: 'یک لنگر برگزینید',
+	selectAnchor: 'یک لینک برگزینید',
 	styles: 'شیوه (style)',
 	tabIndex: 'نمایهٴ دسترسی با برگه',
 	target: 'مقصد',
-	targetFrame: '<فریم>',
-	targetFrameName: 'نام فریم مقصد',
+	targetFrame: '<قاب>',
+	targetFrameName: 'نام قاب مقصد',
 	targetPopup: '<پنجرهٴ پاپاپ>',
-	targetPopupName: 'نام پنجرهٴ پاپاپ',
+	targetPopupName: 'نام پنجره ی پاپاپ',
 	title: 'پیوند',
 	toAnchor: 'لنگر در همین صفحه',
 	toEmail: 'پست الکترونیکی',
-	toUrl: 'URL',
+	toUrl: 'آدرس',
+	toPhone: 'تلفن',
 	toolbar: 'گنجاندن/ویرایش پیوند',
 	type: 'نوع پیوند',
 	unlink: 'برداشتن پیوند',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/fi.js b/web/modules/anchor_link/js/plugins/link/lang/fi.js
index 2c53c3c093a051ff1fff33fa180a055e0be27bc7..0022e37239370eff891d57dbeef8cac5c2ae218d 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/fi.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/fi.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'fi', {
 	acccessKey: 'Pikanäppäin',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'fi', {
 	noAnchors: '(Ei ankkureita tässä dokumentissa)',
 	noEmail: 'Kirjoita sähköpostiosoite',
 	noUrl: 'Linkille on kirjoitettava URL',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<muu>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Riippuva (Netscape)',
 	popupFeatures: 'Popup ikkunan ominaisuudet',
 	popupFullScreen: 'Täysi ikkuna (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'fi', {
 	toAnchor: 'Ankkuri tässä sivussa',
 	toEmail: 'Sähköposti',
 	toUrl: 'Osoite',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Lisää linkki/muokkaa linkkiä',
 	type: 'Linkkityyppi',
 	unlink: 'Poista linkki',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/fo.js b/web/modules/anchor_link/js/plugins/link/lang/fo.js
index c4584590273b13b29ac79504860af2e2ee42581c..998d840a27fbcdded85550ef4b0101e165996d6a 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/fo.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/fo.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'fo', {
 	acccessKey: 'Snarvegisknöttur',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'fo', {
 	noAnchors: '(Eingir marknasteinar eru í hesum dokumentið)',
 	noEmail: 'Vinarliga skriva teldupost-adressu',
 	noUrl: 'Vinarliga skriva tilknýti (URL)',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<annað>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Bundið (Netscape)',
 	popupFeatures: 'Popup vindeygans víðkaðu eginleikar',
 	popupFullScreen: 'Fullur skermur (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'fo', {
 	toAnchor: 'Tilknýti til marknastein í tekstinum',
 	toEmail: 'Teldupostur',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Ger/broyt tilknýti',
 	type: 'Tilknýtisslag',
 	unlink: 'Strika tilknýti',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/fr-ca.js b/web/modules/anchor_link/js/plugins/link/lang/fr-ca.js
index 70f5c2b46099d82a2f025384447d1595117c3ae0..90bbae9f0f55c86c2fb04c4ecfc7d5c6937d0264 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/fr-ca.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/fr-ca.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'fr-ca', {
 	acccessKey: 'Touche d\'accessibilité',
@@ -20,7 +20,7 @@ CKEDITOR.plugins.setLang( 'link', 'fr-ca', {
 	charset: 'Encodage de la cible',
 	cssClasses: 'Classes CSS',
 	download: 'Force Download', // MISSING
-	displayText: 'Display Text', // MISSING
+	displayText: 'Afficher le texte',
 	emailAddress: 'Courriel',
 	emailBody: 'Corps du message',
 	emailSubject: 'Objet du message',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'fr-ca', {
 	noAnchors: '(Pas d\'ancre disponible dans le document)',
 	noEmail: 'Veuillez saisir le courriel',
 	noUrl: 'Veuillez saisir l\'URL',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<autre>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Dépendante (Netscape)',
 	popupFeatures: 'Caractéristiques de la fenêtre popup',
 	popupFullScreen: 'Plein écran (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'fr-ca', {
 	toAnchor: 'Ancre dans cette page',
 	toEmail: 'Courriel',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Lien',
 	type: 'Type de lien',
 	unlink: 'Supprimer le lien',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/fr.js b/web/modules/anchor_link/js/plugins/link/lang/fr.js
index b6a6c36b840d9ca45e96d6547947d92903cd2b77..9f9556933a590f100f94df93054464cd9a13a03d 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/fr.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/fr.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'fr', {
 	acccessKey: 'Touche d\'accessibilité',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'fr', {
 	noAnchors: '(Aucune ancre disponible dans ce document)',
 	noEmail: 'Veuillez entrer l\'adresse électronique',
 	noUrl: 'Veuillez entrer l\'URL du lien',
+	noTel: 'Veuillez entrer le numéro de téléphone',
 	other: '<autre>',
+	phoneNumber: 'Numéro de téléphone',
 	popupDependent: 'Dépendante (Netscape)',
 	popupFeatures: 'Caractéristiques de la fenêtre surgissante',
 	popupFullScreen: 'Plein écran (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'fr', {
 	toAnchor: 'Ancre',
 	toEmail: 'Courriel',
 	toUrl: 'URL',
+	toPhone: 'Téléphone',
 	toolbar: 'Lien',
 	type: 'Type de lien',
 	unlink: 'Supprimer le lien',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/gl.js b/web/modules/anchor_link/js/plugins/link/lang/gl.js
index 1d8062b97d427894c4ac38c3173f9f9685e0fd90..176652786c1ced7e7cc4152a756a9c610e35df65 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/gl.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/gl.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'gl', {
 	acccessKey: 'Chave de acceso',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'gl', {
 	noAnchors: '(Non hai ancoraxes dispoñíbeis no documento)',
 	noEmail: 'Escriba o enderezo de correo',
 	noUrl: 'Escriba a ligazón URL',
-	other: '<outro>',
+	noTel: 'Escriba o número de teléfono',
+	other: '<other>',
+	phoneNumber: 'Número de teléfono',
 	popupDependent: 'Dependente (Netscape)',
 	popupFeatures: 'Características da xanela emerxente',
 	popupFullScreen: 'Pantalla completa (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'gl', {
 	toAnchor: 'Ligar coa ancoraxe no testo',
 	toEmail: 'Correo',
 	toUrl: 'URL',
+	toPhone: 'Teléfono',
 	toolbar: 'Ligazón',
 	type: 'Tipo de ligazón',
 	unlink: 'Eliminar a ligazón',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/gu.js b/web/modules/anchor_link/js/plugins/link/lang/gu.js
index f42672b1d9896d1fd912b45961ea55ca01a6fe20..17a51e068d7dbad070581f81f79e6de7bde4e132 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/gu.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/gu.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'gu', {
 	acccessKey: 'ઍક્સેસ કી',
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'gu', {
 	anchorName: 'ઍંકર નામથી પસંદ કરો',
 	charset: 'લિંક રિસૉર્સ કૅરિક્ટર સેટ',
 	cssClasses: 'સ્ટાઇલ-શીટ ક્લાસ',
-	download: 'Force Download', // MISSING
-	displayText: 'Display Text', // MISSING
+	download: 'ડાઉનલોડ કરો',
+	displayText: 'લખાણ દેખાડો',
 	emailAddress: 'ઈ-મેલ સરનામું',
 	emailBody: 'સંદેશ',
 	emailSubject: 'ઈ-મેલ વિષય',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'gu', {
 	noAnchors: '(ડૉક્યુમન્ટમાં ઍંકરની સંખ્યા)',
 	noEmail: 'ઈ-મેલ સરનામું ટાઇપ કરો',
 	noUrl: 'લિંક  URL ટાઇપ કરો',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<other> <અન્ય>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'ડિપેન્ડન્ટ (Netscape)',
 	popupFeatures: 'પૉપ-અપ વિન્ડો ફીચરસૅ',
 	popupFullScreen: 'ફુલ સ્ક્રીન (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'gu', {
 	toAnchor: 'આ પેજનો ઍંકર',
 	toEmail: 'ઈ-મેલ',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'લિંક ઇન્સર્ટ/દાખલ કરવી',
 	type: 'લિંક પ્રકાર',
 	unlink: 'લિંક કાઢવી',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/he.js b/web/modules/anchor_link/js/plugins/link/lang/he.js
index f98bd48a18794b037cbd065bd11f311f86279d09..35790e25fa3058df94b4f5eb491209a24c59818f 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/he.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/he.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'he', {
 	acccessKey: 'מקש גישה',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'he', {
 	noAnchors: '(אין עוגנים זמינים בדף)',
 	noEmail: 'יש להקליד את כתובת הדוא"ל',
 	noUrl: 'יש להקליד את כתובת הקישור (URL)',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<אחר>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'תלוי (Netscape)',
 	popupFeatures: 'תכונות החלון הקופץ',
 	popupFullScreen: 'מסך מלא (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'he', {
 	toAnchor: 'עוגן בעמוד זה',
 	toEmail: 'דוא"ל',
 	toUrl: 'כתובת (URL)',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'הוספת/עריכת קישור',
 	type: 'סוג קישור',
 	unlink: 'הסרת הקישור',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/hi.js b/web/modules/anchor_link/js/plugins/link/lang/hi.js
index 2e1866c059e219bfb619e6f4d954580f64da5cb5..6dc8e3d4c53b2d84c610445ed8058ed6e4853b10 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/hi.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/hi.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'hi', {
 	acccessKey: 'ऍक्सॅस की',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'hi', {
 	noAnchors: '(डॉक्यूमॅन्ट में ऐंकर्स की संख्या)',
 	noEmail: 'ई-मेल पता टाइप करें',
 	noUrl: 'लिंक URL टाइप करें',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<अन्य>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'डिपेन्डॅन्ट (Netscape)',
 	popupFeatures: 'पॉप-अप विन्डो फ़ीचर्स',
 	popupFullScreen: 'फ़ुल स्क्रीन (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'hi', {
 	toAnchor: 'इस पेज का ऐंकर',
 	toEmail: 'ई-मेल',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'लिंक इन्सर्ट/संपादन',
 	type: 'लिंक प्रकार',
 	unlink: 'लिंक हटायें',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/hr.js b/web/modules/anchor_link/js/plugins/link/lang/hr.js
index bf54d0f05c251699a7a51f240cef3549b1a81503..68285bd4a3cb663d3663b5eafcc29e2336350cc1 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/hr.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/hr.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'hr', {
 	acccessKey: 'Pristupna tipka',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'hr', {
 	noAnchors: '(Nema dostupnih sidra)',
 	noEmail: 'Molimo upišite e-mail adresu',
 	noUrl: 'Molimo upišite URL link',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<drugi>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Ovisno (Netscape)',
 	popupFeatures: 'Mogućnosti popup prozora',
 	popupFullScreen: 'Cijeli ekran (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'hr', {
 	toAnchor: 'Sidro na ovoj stranici',
 	toEmail: 'E-Mail',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Ubaci/promijeni vezu',
 	type: 'Vrsta veze',
 	unlink: 'Ukloni vezu',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/hu.js b/web/modules/anchor_link/js/plugins/link/lang/hu.js
index d9b798e66da82ac1e5e651d69b31905bd6b517a8..e512e380373a175b10749fe75d0f0f768a86d59c 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/hu.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/hu.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'hu', {
 	acccessKey: 'Billentyűkombináció',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'hu', {
 	noAnchors: '(Nincs horgony a dokumentumban)',
 	noEmail: 'Adja meg az E-Mail címet',
 	noUrl: 'Adja meg a hivatkozás webcímét',
+	noTel: 'Adja meg a telefonszámot',
 	other: '<más>',
+	phoneNumber: 'Telefonszám',
 	popupDependent: 'Szülőhöz kapcsolt (csak Netscape)',
 	popupFeatures: 'Felugró ablak jellemzői',
 	popupFullScreen: 'Teljes képernyő (csak IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'hu', {
 	toAnchor: 'Horgony az oldalon',
 	toEmail: 'E-Mail',
 	toUrl: 'URL',
+	toPhone: 'Telefon',
 	toolbar: 'Hivatkozás beillesztése/módosítása',
 	type: 'Hivatkozás típusa',
 	unlink: 'Hivatkozás törlése',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/id.js b/web/modules/anchor_link/js/plugins/link/lang/id.js
index a92758ecfffc54addb9b4991098076a56393c53a..0240059312baba4b679afcedd1176fe57f166c4a 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/id.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/id.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'id', {
 	acccessKey: 'Access Key', // MISSING
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'id', {
 	noAnchors: '(No anchors available in the document)', // MISSING
 	noEmail: 'Silahkan ketikkan alamat e-mail',
 	noUrl: 'Silahkan ketik URL tautan',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<lainnya>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Dependent (Netscape)', // MISSING
 	popupFeatures: 'Popup Window Features', // MISSING
 	popupFullScreen: 'Full Screen (IE)', // MISSING
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'id', {
 	toAnchor: 'Link to anchor in the text', // MISSING
 	toEmail: 'E-mail', // MISSING
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Tautan',
 	type: 'Link Type', // MISSING
 	unlink: 'Unlink', // MISSING
diff --git a/web/modules/anchor_link/js/plugins/link/lang/is.js b/web/modules/anchor_link/js/plugins/link/lang/is.js
index ee9f3af43123d41af7e40eaef13a487af9683cb3..04412508c842be933b9ae7522da4903e16f9f348 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/is.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/is.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'is', {
 	acccessKey: 'Skammvalshnappur',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'is', {
 	noAnchors: '<Engin bókamerki á skrá>',
 	noEmail: 'Sláðu inn netfang!',
 	noUrl: 'Sláðu inn veffang stiklunnar!',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<annar>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Háð venslum (Netscape)',
 	popupFeatures: 'Eigindi sprettiglugga',
 	popupFullScreen: 'Heilskjár (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'is', {
 	toAnchor: 'Bókamerki á þessari síðu',
 	toEmail: 'Netfang',
 	toUrl: 'Vefslóð',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Stofna/breyta stiklu',
 	type: 'Stikluflokkur',
 	unlink: 'Fjarlægja stiklu',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/it.js b/web/modules/anchor_link/js/plugins/link/lang/it.js
index 582e3caaf7a89329ea81cbe18a174de0abc36d5b..516c50b745804818ba855a16cca46a684884b582 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/it.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/it.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'it', {
 	acccessKey: 'Scorciatoia da tastiera',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'it', {
 	noAnchors: '(Nessuna ancora disponibile nel documento)',
 	noEmail: 'Devi inserire un\'indirizzo e-mail',
 	noUrl: 'Devi inserire l\'URL del collegamento',
+	noTel: 'Inserire il numero di telefono',
 	other: '<altro>',
+	phoneNumber: 'Numero di telefono',
 	popupDependent: 'Dipendente (Netscape)',
 	popupFeatures: 'Caratteristiche finestra popup',
 	popupFullScreen: 'A tutto schermo (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'it', {
 	toAnchor: 'Ancora nel testo',
 	toEmail: 'E-Mail',
 	toUrl: 'URL',
+	toPhone: 'Telefono',
 	toolbar: 'Collegamento',
 	type: 'Tipo di Collegamento',
 	unlink: 'Elimina collegamento',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/ja.js b/web/modules/anchor_link/js/plugins/link/lang/ja.js
index 3e573cc0222c3ac1dce18f9ed76a1309560b1255..e85d70f68761460809c9aef22701acd2e569e766 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/ja.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/ja.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'ja', {
 	acccessKey: 'アクセスキー',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'ja', {
 	noAnchors: '(このドキュメント内にアンカーはありません)',
 	noEmail: 'メールアドレスを入力してください。',
 	noUrl: 'リンクURLを入力してください。',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<その他の>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: '開いたウィンドウに連動して閉じる (Netscape)',
 	popupFeatures: 'ポップアップウィンドウ特徴',
 	popupFullScreen: '全画面モード(IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'ja', {
 	toAnchor: 'ページ内のアンカー',
 	toEmail: 'E-Mail',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'リンク挿入/編集',
 	type: 'リンクタイプ',
 	unlink: 'リンクを削除',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/ka.js b/web/modules/anchor_link/js/plugins/link/lang/ka.js
index 4daf90d12fd0d3f7c160b4c36b3608dc2f2a00a6..f70041807a667e63b4e7a22f3055348ee68c017e 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/ka.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/ka.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'ka', {
 	acccessKey: 'წვდომის ღილაკი',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'ka', {
 	noAnchors: '(ამ დოკუმენტში ღუზა არაა)',
 	noEmail: 'აკრიფეთ ელფოსტის მისამართი',
 	noUrl: 'აკრიფეთ ბმულის URL',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<სხვა>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'დამოკიდებული (Netscape)',
 	popupFeatures: 'Popup ფანჯრის პარამეტრები',
 	popupFullScreen: 'მთელი ეკრანი (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'ka', {
 	toAnchor: 'ბმული ტექსტში ღუზაზე',
 	toEmail: 'ელფოსტა',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'ბმული',
 	type: 'ბმულის ტიპი',
 	unlink: 'ბმულის მოხსნა',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/km.js b/web/modules/anchor_link/js/plugins/link/lang/km.js
index 5db758b81f6bc472ca225fd5009d9a4abf86b252..1dd14417754099899b461c74c76b293488cc3234 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/km.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/km.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'km', {
 	acccessKey: 'សោរ​ចូល',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'km', {
 	noAnchors: '(មិន​មាន​យុថ្កា​នៅ​ក្នុង​ឯកសារ​អត្ថថបទ​ទេ)',
 	noEmail: 'សូម​បញ្ចូល​អាសយដ្ឋាន​អ៊ីមែល',
 	noUrl: 'សូម​បញ្ចូល​តំណ URL',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<ផ្សេង​ទៀត>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Dependent (Netscape)',
 	popupFeatures: 'មុខ​ងារ​ផុស​ផ្ទាំង​វីនដូ​ឡើង',
 	popupFullScreen: 'ពេញ​អេក្រង់ (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'km', {
 	toAnchor: 'ត​ភ្ជាប់​ទៅ​យុថ្កា​ក្នុង​អត្ថបទ',
 	toEmail: 'អ៊ីមែល',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'តំណ',
 	type: 'ប្រភេទ​តំណ',
 	unlink: 'ផ្ដាច់​តំណ',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/ko.js b/web/modules/anchor_link/js/plugins/link/lang/ko.js
index e0641f6df367c377f92502ad4acd842881b3e994..d6d6260e52c4479ddb0a57f877abe7d19794f114 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/ko.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/ko.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'ko', {
 	acccessKey: '액세스 키',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'ko', {
 	noAnchors: '(문서에 책갈피가 없습니다.)',
 	noEmail: '이메일 주소를 입력하십시오',
 	noUrl: '링크 주소(URL)를 입력하십시오',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<기타>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Dependent (Netscape)',
 	popupFeatures: '팝업창 속성',
 	popupFullScreen: '전체화면 (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'ko', {
 	toAnchor: '책갈피',
 	toEmail: '이메일',
 	toUrl: '주소(URL)',
+	toPhone: 'Phone', // MISSING
 	toolbar: '링크 삽입/변경',
 	type: '링크 종류',
 	unlink: '링크 지우기',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/ku.js b/web/modules/anchor_link/js/plugins/link/lang/ku.js
index 1ac6a07bd56b2d4b7aee1d3d4979591aa8108aa9..64b31577866ce335eccf92fd460c100d1c2cbadd 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/ku.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/ku.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'ku', {
 	acccessKey: 'کلیلی دەستپێگەیشتن',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'ku', {
 	noAnchors: '(هیچ جۆرێکی لەنگەر ئامادە نیە لەم پەڕەیه)',
 	noEmail: 'تکایە ناونیشانی ئیمەیل بنووسە',
 	noUrl: 'تکایە ناونیشانی بەستەر بنووسە',
+	noTel: 'تکایە ژمارەی تەلەفۆن دابنێ',
 	other: '<هیتر>',
+	phoneNumber: 'ژمارەی تەلەفۆن',
 	popupDependent: 'پێوەبەستراو (Netscape)',
 	popupFeatures: 'خاسیەتی پەنجەرەی سەرهەڵدەر',
 	popupFullScreen: 'پڕ بەپڕی شاشە (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'ku', {
 	toAnchor: 'بەستەر بۆ لەنگەر له دەق',
 	toEmail: 'ئیمەیل',
 	toUrl: 'ناونیشانی بەستەر',
+	toPhone: 'تەلەفۆن',
 	toolbar: 'دانان/ڕێکخستنی بەستەر',
 	type: 'جۆری بەستەر',
 	unlink: 'لابردنی بەستەر',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/lt.js b/web/modules/anchor_link/js/plugins/link/lang/lt.js
index 6dbddc48a956a0e1d81f78df65d8f2acb2d0b91d..2f4568ae5a5cea4578f8aef0d78d0576c48b70a5 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/lt.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/lt.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'lt', {
 	acccessKey: 'Prieigos raktas',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'lt', {
 	noAnchors: '(Šiame dokumente žymių nėra)',
 	noEmail: 'Prašome įvesti el.pašto adresą',
 	noUrl: 'Prašome įvesti nuorodos URL',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<kitas>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Priklausomas (Netscape)',
 	popupFeatures: 'Išskleidžiamo lango savybės',
 	popupFullScreen: 'Visas ekranas (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'lt', {
 	toAnchor: 'Žymė šiame puslapyje',
 	toEmail: 'El.paštas',
 	toUrl: 'Nuoroda',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Įterpti/taisyti nuorodą',
 	type: 'Nuorodos tipas',
 	unlink: 'Panaikinti nuorodą',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/lv.js b/web/modules/anchor_link/js/plugins/link/lang/lv.js
index c33e014a3432b6ea304f7a89304fd1f6ea814895..f90d2981ed7f57cc85ca2dbf693072393b7392d9 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/lv.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/lv.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'lv', {
 	acccessKey: 'Pieejas taustiņš',
@@ -19,23 +19,25 @@ CKEDITOR.plugins.setLang( 'link', 'lv', {
 	anchorName: 'Pēc iezīmes nosaukuma',
 	charset: 'Pievienotā resursa kodējums',
 	cssClasses: 'Stilu saraksta klases',
-	download: 'Force Download', // MISSING
-	displayText: 'Display Text', // MISSING
+	download: 'Piespiedu ielāde',
+	displayText: 'Attēlot tekstu',
 	emailAddress: 'E-pasta adrese',
-	emailBody: 'Ziņas saturs',
-	emailSubject: 'Ziņas tēma',
+	emailBody: 'Ziņojuma pamatteksts',
+	emailSubject: 'Ziņojuma tēma',
 	id: 'ID',
-	info: 'Hipersaites informācija',
+	info: 'Saites informācija',
 	langCode: 'Valodas kods',
 	langDir: 'Valodas lasīšanas virziens',
 	langDirLTR: 'No kreisās uz labo (LTR)',
 	langDirRTL: 'No labās uz kreiso (RTL)',
-	menu: 'Labot hipersaiti',
+	menu: 'Rediģēt saiti',
 	name: 'Nosaukums',
 	noAnchors: '(Šajā dokumentā nav iezīmju)',
-	noEmail: 'Lūdzu norādi e-pasta adresi',
-	noUrl: 'Lūdzu norādi hipersaiti',
+	noEmail: 'Lūdzu, ievadiet e-pasta adresi',
+	noUrl: 'Lūdzu, ievadiet saites URL',
+	noTel: 'Lūdzu, ievadiet tālruņa numuru',
 	other: '<cits>',
+	phoneNumber: 'Tālruņa numurs',
 	popupDependent: 'Atkarīgs (Netscape)',
 	popupFeatures: 'Uznirstošā loga nosaukums īpašības',
 	popupFullScreen: 'Pilnā ekrānā (IE)',
@@ -56,12 +58,13 @@ CKEDITOR.plugins.setLang( 'link', 'lv', {
 	targetFrameName: 'Mērķa ietvara nosaukums',
 	targetPopup: '<uznirstošā logā>',
 	targetPopupName: 'Uznirstošā loga nosaukums',
-	title: 'Hipersaite',
+	title: 'Saite',
 	toAnchor: 'Iezīme šajā lapā',
 	toEmail: 'E-pasts',
 	toUrl: 'Adrese',
-	toolbar: 'Ievietot/Labot hipersaiti',
-	type: 'Hipersaites tips',
-	unlink: 'Noņemt hipersaiti',
+	toPhone: 'Tālrunis',
+	toolbar: 'Saite',
+	type: 'Saites tips',
+	unlink: 'Atsaistīt',
 	upload: 'Augšupielādēt'
 } );
diff --git a/web/modules/anchor_link/js/plugins/link/lang/mk.js b/web/modules/anchor_link/js/plugins/link/lang/mk.js
index 1667e254d49a15eab2a31ac31b65e55b7d02c540..84f96af60aa4f475eeac979d09d1f61967b470e9 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/mk.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/mk.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'mk', {
 	acccessKey: 'Access Key', // MISSING
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'mk', {
 	noAnchors: '(No anchors available in the document)', // MISSING
 	noEmail: 'Please type the e-mail address', // MISSING
 	noUrl: 'Please type the link URL', // MISSING
+	noTel: 'Please type the phone number', // MISSING
 	other: '<other>', // MISSING
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Dependent (Netscape)', // MISSING
 	popupFeatures: 'Popup Window Features', // MISSING
 	popupFullScreen: 'Full Screen (IE)', // MISSING
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'mk', {
 	toAnchor: 'Link to anchor in the text', // MISSING
 	toEmail: 'E-mail', // MISSING
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Врска',
 	type: 'Link Type', // MISSING
 	unlink: 'Unlink', // MISSING
diff --git a/web/modules/anchor_link/js/plugins/link/lang/mn.js b/web/modules/anchor_link/js/plugins/link/lang/mn.js
index a5c0324b1e62b5630db24f63477c62485db4b60c..df53ce65237cc59015d7c9daa668e55d055fee24 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/mn.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/mn.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'mn', {
 	acccessKey: 'Холбох түлхүүр',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'mn', {
 	noAnchors: '(Баримт бичиг зангуугүй байна)',
 	noEmail: 'Э-шуудангий хаягаа шивнэ үү',
 	noUrl: 'Холбоосны URL хаягийг шивнэ үү',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<other>', // MISSING
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Хамаатай (Netscape)',
 	popupFeatures: 'Popup цонхны онцлог',
 	popupFullScreen: 'Цонх дүүргэх (Internet Explorer)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'mn', {
 	toAnchor: 'Энэ бичвэр дэх зангуу руу очих холбоос',
 	toEmail: 'Э-захиа',
 	toUrl: 'цахим хуудасны хаяг (URL)',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Холбоос',
 	type: 'Линкийн төрөл',
 	unlink: 'Холбоос авч хаях',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/ms.js b/web/modules/anchor_link/js/plugins/link/lang/ms.js
index 1cebe16d83f88f1d651a649e345c97b4642a7845..6a967b364e15a4407b46bdd2463ad550232095c1 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/ms.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/ms.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'ms', {
 	acccessKey: 'Kunci Akses',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'ms', {
 	noAnchors: '(Tiada pautan terdapat dalam dokumen ini)',
 	noEmail: 'Sila taip alamat e-mail',
 	noUrl: 'Sila taip sambungan URL',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<lain>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Bergantungan (Netscape)',
 	popupFeatures: 'Ciri Tetingkap Popup',
 	popupFullScreen: 'Skrin Penuh (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'ms', {
 	toAnchor: 'Pautan dalam muka surat ini',
 	toEmail: 'E-Mail',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Masukkan/Sunting Sambungan',
 	type: 'Jenis Sambungan',
 	unlink: 'Buang Sambungan',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/nb.js b/web/modules/anchor_link/js/plugins/link/lang/nb.js
index c829d2aec9e20078f47fd53753a250488eda46dc..e0509146e4a01bd2b766585db486f64f55604b2d 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/nb.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/nb.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'nb', {
 	acccessKey: 'Aksessknapp',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'nb', {
 	noAnchors: '(Ingen anker i dokumentet)',
 	noEmail: 'Vennligst skriv inn e-postadressen',
 	noUrl: 'Vennligst skriv inn lenkens URL',
+	noTel: 'Vennligst skriv inn telefonnummeret',
 	other: '<annen>',
+	phoneNumber: 'Telefonnummer',
 	popupDependent: 'Avhenging (Netscape)',
 	popupFeatures: 'Egenskaper for popup-vindu',
 	popupFullScreen: 'Fullskjerm (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'nb', {
 	toAnchor: 'Lenke til anker i teksten',
 	toEmail: 'E-post',
 	toUrl: 'URL',
+	toPhone: 'Telefon',
 	toolbar: 'Lenke',
 	type: 'Lenketype',
 	unlink: 'Fjern lenke',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/nl.js b/web/modules/anchor_link/js/plugins/link/lang/nl.js
index 9c6f3656d4076507d4fe4c03cb067fdf07abc8e8..f0b6de0ead3f75cde3edcf668b6228f858ace5f4 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/nl.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/nl.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'nl', {
 	acccessKey: 'Toegangstoets',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'nl', {
 	noAnchors: '(Geen interne links in document gevonden)',
 	noEmail: 'Geef een e-mailadres',
 	noUrl: 'Geef de link van de URL',
+	noTel: 'Geef een telefoonnummer',
 	other: '<ander>',
+	phoneNumber: 'Telefoonnummer',
 	popupDependent: 'Afhankelijk (Netscape)',
 	popupFeatures: 'Instellingen popupvenster',
 	popupFullScreen: 'Volledig scherm (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'nl', {
 	toAnchor: 'Interne link in pagina',
 	toEmail: 'E-mail',
 	toUrl: 'URL',
+	toPhone: 'Telefoon',
 	toolbar: 'Link invoegen/wijzigen',
 	type: 'Linktype',
 	unlink: 'Link verwijderen',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/no.js b/web/modules/anchor_link/js/plugins/link/lang/no.js
index c7fd06301b822f2de4182b504c6c2fce4a0bb7fd..0e4981b5a5114109ca204e9073ed1e2cf08d8697 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/no.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/no.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'no', {
 	acccessKey: 'Aksessknapp',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'no', {
 	noAnchors: '(Ingen anker i dokumentet)',
 	noEmail: 'Vennligst skriv inn e-postadressen',
 	noUrl: 'Vennligst skriv inn lenkens URL',
+	noTel: 'Skriv inn telefonnummer',
 	other: '<annen>',
+	phoneNumber: 'Telefonnummer',
 	popupDependent: 'Avhenging (Netscape)',
 	popupFeatures: 'Egenskaper for popup-vindu',
 	popupFullScreen: 'Fullskjerm (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'no', {
 	toAnchor: 'Lenke til anker i teksten',
 	toEmail: 'E-post',
 	toUrl: 'URL',
+	toPhone: 'Telefon',
 	toolbar: 'Sett inn/Rediger lenke',
 	type: 'Lenketype',
 	unlink: 'Fjern lenke',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/oc.js b/web/modules/anchor_link/js/plugins/link/lang/oc.js
index 2995878adaede28faa7577e49e11f14f6b48edb5..0f219359681e23fcdf53d089f9c1da3611fdd99f 100644
--- a/web/modules/anchor_link/js/plugins/link/lang/oc.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/oc.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'oc', {
 	acccessKey: 'Tòca d\'accessibilitat',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'oc', {
 	noAnchors: '(Cap d\'ancòra pas disponibla dins aqueste document)',
 	noEmail: 'Entratz l\'adreça electronica',
 	noUrl: 'Entratz l\'URL del ligam',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<autre>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Dependenta (Netscape)',
 	popupFeatures: 'Caracteristicas de la fenèstra sorgissenta',
 	popupFullScreen: 'Ecran complet (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'oc', {
 	toAnchor: 'Ancòra',
 	toEmail: 'Corrièl',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Ligam',
 	type: 'Tipe de ligam',
 	unlink: 'Suprimir lo ligam',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/pl.js b/web/modules/anchor_link/js/plugins/link/lang/pl.js
index 2527b3ef3a5d2be0e9c34ec5bfa73f51eb2f4922..3d27329dbc7d1b9e55fcc5b37a56820c6b362dc8 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/pl.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/pl.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'pl', {
 	acccessKey: 'Klawisz dostępu',
@@ -12,7 +12,7 @@ CKEDITOR.plugins.setLang( 'link', 'pl', {
 		menu: 'Właściwości kotwicy',
 		title: 'Właściwości kotwicy',
 		name: 'Nazwa kotwicy',
-		errorName: 'Wpisz nazwę kotwicy',
+		errorName: 'Podaj nazwę kotwicy.',
 		remove: 'Usuń kotwicę'
 	},
 	anchorId: 'Wg identyfikatora',
@@ -33,9 +33,11 @@ CKEDITOR.plugins.setLang( 'link', 'pl', {
 	menu: 'Edytuj odnośnik',
 	name: 'Nazwa',
 	noAnchors: '(W dokumencie nie zdefiniowano żadnych kotwic)',
-	noEmail: 'Podaj adres e-mail',
-	noUrl: 'Podaj adres URL',
+	noEmail: 'Podaj adres e-mail.',
+	noUrl: 'Podaj adres URL.',
+	noTel: 'Podaj numer telefonu.',
 	other: '<inny>',
+	phoneNumber: 'Numer telefonu',
 	popupDependent: 'Okno zależne (Netscape)',
 	popupFeatures: 'Właściwości wyskakującego okna',
 	popupFullScreen: 'Pełny ekran (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'pl', {
 	toAnchor: 'Odnośnik wewnątrz strony (kotwica)',
 	toEmail: 'Adres e-mail',
 	toUrl: 'Adres URL',
+	toPhone: 'Telefon',
 	toolbar: 'Wstaw/edytuj odnośnik',
 	type: 'Typ odnośnika',
 	unlink: 'Usuń odnośnik',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/pt-br.js b/web/modules/anchor_link/js/plugins/link/lang/pt-br.js
index c693d5d32c506484cb0b560b10118dc3f3758a34..b66be5736f91038d33f53933145655f7cc3ec2b3 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/pt-br.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/pt-br.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'pt-br', {
 	acccessKey: 'Chave de Acesso',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'pt-br', {
 	noAnchors: '(Não há âncoras no documento)',
 	noEmail: 'Por favor, digite o endereço de e-mail',
 	noUrl: 'Por favor, digite o endereço do Link',
+	noTel: 'Por favor, informe o número do telefone',
 	other: '<outro>',
+	phoneNumber: 'Número de telefone',
 	popupDependent: 'Dependente (Netscape)',
 	popupFeatures: 'Propriedades da Janela Pop-up',
 	popupFullScreen: 'Modo Tela Cheia (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'pt-br', {
 	toAnchor: 'Âncora nesta página',
 	toEmail: 'E-Mail',
 	toUrl: 'URL',
+	toPhone: 'Telefone',
 	toolbar: 'Inserir/Editar Link',
 	type: 'Tipo de hiperlink',
 	unlink: 'Remover Link',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/pt.js b/web/modules/anchor_link/js/plugins/link/lang/pt.js
index 8002099dc2277f67bea4fb088340824f0bfc97c4..de3f3f49b7d92210d5e4e808091ef49dc926b411 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/pt.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/pt.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'pt', {
 	acccessKey: 'Chave de acesso',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'pt', {
 	noAnchors: '(Não existem âncoras no documento)',
 	noEmail: 'Por favor, escreva o endereço de email',
 	noUrl: 'Por favor, introduza o endereço URL',
+	noTel: 'Por favor, escreva o número de telefone',
 	other: '<outro>',
+	phoneNumber: 'Número de telefone',
 	popupDependent: 'Dependente (Netscape)',
 	popupFeatures: 'Características de janela flutuante',
 	popupFullScreen: 'Janela completa (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'pt', {
 	toAnchor: 'Ligar a âncora no texto',
 	toEmail: 'Email',
 	toUrl: 'URL',
+	toPhone: 'Telefone',
 	toolbar: 'Hiperligação',
 	type: 'Tipo de hiperligação',
 	unlink: 'Eliminar hiperligação',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/ro.js b/web/modules/anchor_link/js/plugins/link/lang/ro.js
index 396a44e71600f1d11fec7d78c511d51df4b7bb25..0d7bc490ad7ae3dc9e4d3d64208f3bd9e187f646 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/ro.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/ro.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'ro', {
 	acccessKey: 'Tasta de acces',
@@ -19,23 +19,25 @@ CKEDITOR.plugins.setLang( 'link', 'ro', {
 	anchorName: 'după numele ancorei',
 	charset: 'Setul de caractere al resursei legate',
 	cssClasses: 'Clasele cu stilul paginii (CSS)',
-	download: 'Force Download', // MISSING
-	displayText: 'Display Text', // MISSING
+	download: 'descarcă',
+	displayText: 'afișează textul',
 	emailAddress: 'Adresă de e-mail',
-	emailBody: 'Opțiuni Meniu Contextual',
+	emailBody: 'conținut email',
 	emailSubject: 'Subiectul mesajului',
-	id: 'Id',
+	id: 'identitate',
 	info: 'Informaţii despre link (Legătură web)',
 	langCode: 'Direcţia cuvintelor',
 	langDir: 'Direcţia cuvintelor',
-	langDirLTR: 'stânga-dreapta (LTR)',
-	langDirRTL: 'dreapta-stânga (RTL)',
+	langDirLTR: 'de la stânga la dreapta (LTR)',
+	langDirRTL: 'de la dreapta la stânga (RTL)',
 	menu: 'Editează Link',
 	name: 'Nume',
-	noAnchors: '(Nicio ancoră disponibilă în document)',
+	noAnchors: 'Nu există nici o ancoră',
 	noEmail: 'Vă rugăm să scrieţi adresa de e-mail',
 	noUrl: 'Vă rugăm să scrieţi URL-ul',
-	other: '<alt>',
+	noTel: 'Please type the phone number', // MISSING
+	other: 'altceva',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Dependent (Netscape)',
 	popupFeatures: 'Proprietăţile ferestrei popup',
 	popupFullScreen: 'Tot ecranul (Full Screen)(IE)',
@@ -44,22 +46,23 @@ CKEDITOR.plugins.setLang( 'link', 'ro', {
 	popupMenuBar: 'Bara de meniu',
 	popupResizable: 'Redimensionabil',
 	popupScrollBars: 'Bare de derulare',
-	popupStatusBar: 'Bara de status',
+	popupStatusBar: 'Bara de stare',
 	popupToolbar: 'Bara de opţiuni',
 	popupTop: 'Poziţia la dreapta',
-	rel: 'Relație',
+	rel: 'Relaționare',
 	selectAnchor: 'Selectaţi o ancoră',
 	styles: 'Stil',
 	tabIndex: 'Indexul tabului',
 	target: 'Ţintă (Target)',
-	targetFrame: '<frame>',
+	targetFrame: 'frame țintă',
 	targetFrameName: 'Numele frameului ţintă',
-	targetPopup: '<fereastra popup>',
+	targetPopup: 'popup țintă',
 	targetPopupName: 'Numele ferestrei popup',
-	title: 'Link (Legătură web)',
+	title: 'titlu',
 	toAnchor: 'Ancoră în această pagină',
 	toEmail: 'E-Mail',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Inserează/Editează link (legătură web)',
 	type: 'Tipul link-ului (al legăturii web)',
 	unlink: 'Înlătură link (legătură web)',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/ru.js b/web/modules/anchor_link/js/plugins/link/lang/ru.js
index b862b91573bc896226d5566455ba348acb313d5f..262337b90e5336d1bfc25300fabbd972cb07e5cb 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/ru.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/ru.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'ru', {
 	acccessKey: 'Клавиша доступа',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'ru', {
 	noAnchors: '(В документе нет ни одного якоря)',
 	noEmail: 'Пожалуйста, введите email адрес',
 	noUrl: 'Пожалуйста, введите ссылку',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<другой>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Зависимое (Netscape)',
 	popupFeatures: 'Параметры всплывающего окна',
 	popupFullScreen: 'Полноэкранное (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'ru', {
 	toAnchor: 'Ссылка на якорь в тексте',
 	toEmail: 'Email',
 	toUrl: 'Ссылка',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Вставить/Редактировать ссылку',
 	type: 'Тип ссылки',
 	unlink: 'Убрать ссылку',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/si.js b/web/modules/anchor_link/js/plugins/link/lang/si.js
index 948574bdfe48d6700628f11eb763c0960edb7bea..1f4870beb946ff10d6c8fe0faf2d1cc26c80da80 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/si.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/si.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'si', {
 	acccessKey: 'ප්‍රවේශ  යතුර',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'si', {
 	noAnchors: '(No anchors available in the document)', // MISSING
 	noEmail: 'Please type the e-mail address', // MISSING
 	noUrl: 'Please type the link URL', // MISSING
+	noTel: 'Please type the phone number', // MISSING
 	other: '<other>', // MISSING
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Dependent (Netscape)', // MISSING
 	popupFeatures: 'Popup Window Features', // MISSING
 	popupFullScreen: 'Full Screen (IE)', // MISSING
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'si', {
 	toAnchor: 'Link to anchor in the text', // MISSING
 	toEmail: 'E-mail', // MISSING
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'සබැඳිය',
 	type: 'Link Type', // MISSING
 	unlink: 'Unlink', // MISSING
diff --git a/web/modules/anchor_link/js/plugins/link/lang/sk.js b/web/modules/anchor_link/js/plugins/link/lang/sk.js
index c2498f493186d614e7c1301ed0f4922aab5da664..ed27b8d1154bcf3a2caec37643abb0980a9ce8aa 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/sk.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/sk.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'sk', {
 	acccessKey: 'Prístupový kľúč',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'sk', {
 	noAnchors: '(V dokumente nie sú dostupné žiadne kotvy)',
 	noEmail: 'Zadajte prosím e-mailovú adresu',
 	noUrl: 'Zadajte prosím URL odkazu',
+	noTel: 'Zadajte prosím telefónne číslo',
 	other: '<iný>',
+	phoneNumber: 'Telefónne číslo',
 	popupDependent: 'Závislosť (Netscape)',
 	popupFeatures: 'Vlastnosti vyskakovacieho okna',
 	popupFullScreen: 'Celá obrazovka (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'sk', {
 	toAnchor: 'Odkaz na kotvu v texte',
 	toEmail: 'E-mail',
 	toUrl: 'URL',
+	toPhone: 'Telefón',
 	toolbar: 'Odkaz',
 	type: 'Typ odkazu',
 	unlink: 'Odstrániť odkaz',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/sl.js b/web/modules/anchor_link/js/plugins/link/lang/sl.js
index fdacc40d4003e351a327cc8f705258c8c29aa407..b68f4a2de6b2f747bd58a9d8f56242e446296267 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/sl.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/sl.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'sl', {
 	acccessKey: 'Tipka za dostop',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'sl', {
 	noAnchors: '(V tem dokumentu ni sider)',
 	noEmail: 'Vnesite e-poštni naslov',
 	noUrl: 'Vnesite URL povezave',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<drugo>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Podokno (Netscape)',
 	popupFeatures: 'Značilnosti pojavnega okna',
 	popupFullScreen: 'Celozaslonsko (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'sl', {
 	toAnchor: 'Sidro na tej strani',
 	toEmail: 'E-pošta',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Vstavi/uredi povezavo',
 	type: 'Vrsta povezave',
 	unlink: 'Odstrani povezavo',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/sq.js b/web/modules/anchor_link/js/plugins/link/lang/sq.js
index 00bd453794a9eb7c45041d169c8badbd664a1882..f9d054cf1ec91c712c240f3cf0a6be0c6db4551c 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/sq.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/sq.js
@@ -1,56 +1,58 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'sq', {
-	acccessKey: 'Sipas ID-së së Elementit',
+	acccessKey: 'Elementi i qasjes',
 	advanced: 'Të përparuara',
-	advisoryContentType: 'Lloji i Përmbajtjes Këshillimore',
-	advisoryTitle: 'Titull',
+	advisoryContentType: 'Lloji i Përmbajtjes Këshillimorit',
+	advisoryTitle: 'Titulli Këshillimorit',
 	anchor: {
 		toolbar: 'Spirancë',
 		menu: 'Redakto Spirancën',
-		title: 'Anchor Properties', // MISSING
+		title: 'Karakteristikat e Spirancës',
 		name: 'Emri i Spirancës',
 		errorName: 'Ju lutemi shkruani emrin e spirancës',
 		remove: 'Largo Spirancën'
 	},
 	anchorId: 'Sipas ID-së së Elementit',
 	anchorName: 'Sipas Emrit të Spirancës',
-	charset: 'Seti i Karaktereve të Burimeve të Nëdlidhura',
-	cssClasses: 'Klasa stili CSS',
-	download: 'Force Download', // MISSING
-	displayText: 'Display Text', // MISSING
+	charset: 'Seti i Karaktereve të Burimeve të lidhura',
+	cssClasses: 'CSS Klasat',
+	download: 'Nxit Shkarkimin',
+	displayText: 'Shfaq Tekstin',
 	emailAddress: 'Posta Elektronike',
-	emailBody: 'Trupi i Porosisë',
+	emailBody: 'Hapësira e Porosisë',
 	emailSubject: 'Titulli i Porosisë',
 	id: 'Id',
-	info: 'Informacione të Nyjes',
-	langCode: 'Kod gjuhe',
-	langDir: 'Drejtim teksti',
+	info: 'Informacione të Nyjës',
+	langCode: 'Kodi Gjuhës',
+	langDir: 'Drejtimi Gjuhës',
 	langDirLTR: 'Nga e majta në të djathë (LTR)',
 	langDirRTL: 'Nga e djathta në të majtë (RTL)',
 	menu: 'Redakto Nyjen',
-	name: 'Emër',
+	name: 'Emri',
 	noAnchors: '(Nuk ka asnjë spirancë në dokument)',
 	noEmail: 'Ju lutemi shkruani postën elektronike',
-	noUrl: 'Ju lutemi shkruani URL-në e nyjes',
-	other: '<tjetër>',
+	noUrl: 'Ju lutemi shkruani URL-në e nyjës',
+	noTel: 'Please type the phone number', // MISSING
+	other: '<other>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'E Varur (Netscape)',
 	popupFeatures: 'Karakteristikat e Dritares së Dialogut',
-	popupFullScreen: 'Ekran i Plotë  (IE)',
+	popupFullScreen: 'Ekrani Plotë  (IE)',
 	popupLeft: 'Pozita Majtas',
-	popupLocationBar: 'Shiriti i Lokacionit',
-	popupMenuBar: 'Shiriti i Menysë',
+	popupLocationBar: 'Shiriti Vendit',
+	popupMenuBar: 'Shiriti Menysë',
 	popupResizable: 'I ndryshueshëm',
 	popupScrollBars: 'Shiritat zvarritës',
-	popupStatusBar: 'Shiriti i Statutit',
-	popupToolbar: 'Shiriti i Mejteve',
+	popupStatusBar: 'Shiriti Statutit',
+	popupToolbar: 'Shiriti Mjeteve',
 	popupTop: 'Top Pozita',
 	rel: 'Marrëdhëniet',
-	selectAnchor: 'Përzgjidh një Spirancë',
+	selectAnchor: 'Përzgjidh Spirancë',
 	styles: 'Stil',
-	tabIndex: 'Indeksi i fletave',
+	tabIndex: 'Indeksi Fletës',
 	target: 'Objektivi',
 	targetFrame: '<frame>',
 	targetFrameName: 'Emri i Kornizës së Synuar',
@@ -60,8 +62,9 @@ CKEDITOR.plugins.setLang( 'link', 'sq', {
 	toAnchor: 'Lidhu me spirancën në tekst',
 	toEmail: 'Posta Elektronike',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Nyja',
-	type: 'Lloji i Nyjes',
-	unlink: 'Largo Nyjen',
+	type: 'Lloji i Nyjës',
+	unlink: 'Largo Nyjën',
 	upload: 'Ngarko'
 } );
diff --git a/web/modules/anchor_link/js/plugins/link/lang/sr-latn.js b/web/modules/anchor_link/js/plugins/link/lang/sr-latn.js
index e1f3ea6fbda18843b42767791f47954dd196baac..e498cba026ac88d584e3aa35c010f64f358d96bb 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/sr-latn.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/sr-latn.js
@@ -1,67 +1,70 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'sr-latn', {
-	acccessKey: 'Pristupni taster',
-	advanced: 'Napredni tagovi',
-	advisoryContentType: 'Advisory vrsta sadržaja',
-	advisoryTitle: 'Advisory naslov',
+	acccessKey: 'Kombinacija tastera',
+	advanced: 'Dalje mogućnosti',
+	advisoryContentType: 'Tip sadržaja pomoći',
+	advisoryTitle: 'Oznaka za pomoć',
 	anchor: {
 		toolbar: 'Unesi/izmeni sidro',
-		menu: 'Osobine sidra',
-		title: 'Osobine sidra',
+		menu: 'Karakteristike sidra',
+		title: 'Karakteristike sidra',
 		name: 'Naziv sidra',
 		errorName: 'Unesite naziv sidra',
 		remove: 'Ukloni sidro'
 	},
 	anchorId: 'Po Id-u elementa',
 	anchorName: 'Po nazivu sidra',
-	charset: 'Linked Resource Charset',
-	cssClasses: 'Stylesheet klase',
-	download: 'Force Download', // MISSING
-	displayText: 'Display Text', // MISSING
+	charset: 'Kod stranica navedenog sadržaja',
+	cssClasses: 'Stilske oznake',
+	download: 'Obavezno preuzimanje',
+	displayText: 'Prikazani tekst',
 	emailAddress: 'E-Mail adresa',
 	emailBody: 'Sadržaj poruke',
-	emailSubject: 'Naslov',
+	emailSubject: 'Naslov poruke',
 	id: 'Id',
-	info: 'Link Info',
-	langCode: 'Smer jezika',
-	langDir: 'Smer jezika',
+	info: 'Osnovne karakteristike',
+	langCode: 'Smer pisanja',
+	langDir: 'Smer pisanja',
 	langDirLTR: 'S leva na desno (LTR)',
 	langDirRTL: 'S desna na levo (RTL)',
 	menu: 'Izmeni link',
 	name: 'Naziv',
-	noAnchors: '(Nema dostupnih sidra)',
-	noEmail: 'Otkucajte adresu elektronske pote',
+	noAnchors: '(Nema sidra u dokumentu)',
+	noEmail: 'Odredite e-mail adresu',
 	noUrl: 'Unesite URL linka',
-	other: '<остало>',
+	noTel: 'Unesite broj telefona',
+	other: '<оstalo>',
+	phoneNumber: 'Broj telefona',
 	popupDependent: 'Zavisno (Netscape)',
-	popupFeatures: 'Mogućnosti popup prozora',
+	popupFeatures: 'Karakteristike iskačućeg prozora',
 	popupFullScreen: 'Prikaz preko celog ekrana (IE)',
-	popupLeft: 'Od leve ivice ekrana (px)',
+	popupLeft: 'Leva pozicija ',
 	popupLocationBar: 'Lokacija',
 	popupMenuBar: 'Kontekstni meni',
 	popupResizable: 'Promenljive veličine',
-	popupScrollBars: 'Scroll bar',
+	popupScrollBars: 'Klizač',
 	popupStatusBar: 'Statusna linija',
-	popupToolbar: 'Toolbar',
-	popupTop: 'Od vrha ekrana (px)',
-	rel: 'Odnos',
+	popupToolbar: 'Traka sa altakama',
+	popupTop: 'Gornja pozicija',
+	rel: 'Vrsta odnosа',
 	selectAnchor: 'Odaberi sidro',
 	styles: 'Stil',
 	tabIndex: 'Tab indeks',
-	target: 'Meta',
+	target: 'Prikaži sadržaj',
 	targetFrame: '<okvir>',
-	targetFrameName: 'Naziv odredišnog frejma',
-	targetPopup: '<popup prozor>',
-	targetPopupName: 'Naziv popup prozora',
-	title: 'Link',
+	targetFrameName: 'Naziv okvira',
+	targetPopup: ' <iskačuć prozor>',
+	targetPopupName: 'Naziv iskačućeg prozora',
+	title: 'Karaktersitike linka',
 	toAnchor: 'Sidro na ovoj stranici',
 	toEmail: 'E-Mail',
 	toUrl: 'URL',
+	toPhone: 'Telefon',
 	toolbar: 'Unesi/izmeni link',
 	type: 'Vrsta linka',
 	unlink: 'Ukloni link',
-	upload: 'Pošalji'
+	upload: 'Postavi'
 } );
diff --git a/web/modules/anchor_link/js/plugins/link/lang/sr.js b/web/modules/anchor_link/js/plugins/link/lang/sr.js
index 73ad0b13fb59d5bed83d9b728b1d67ec61eaec0f..3180033d344fdabd3d9c190683b2e34b876067fe 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/sr.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/sr.js
@@ -1,67 +1,70 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'sr', {
-	acccessKey: 'Приступни тастер',
-	advanced: 'Напредни тагови',
-	advisoryContentType: 'Advisory врста садржаја',
-	advisoryTitle: 'Advisory наслов',
+	acccessKey: 'Комбинација тастера',
+	advanced: 'Даље поције',
+	advisoryContentType: 'Тип садржаја помоћи',
+	advisoryTitle: 'Ознака за помоћ',
 	anchor: {
 		toolbar: 'Унеси/измени сидро',
-		menu: 'Особине сидра',
-		title: 'Особине сидра',
-		name: 'Име сидра',
-		errorName: 'Молимо Вас да унесете име сидра',
-		remove: 'Remove Anchor'
+		menu: 'Карактеристике сидра',
+		title: 'Карактеристике сидра',
+		name: 'Назив сидра',
+		errorName: 'Унесите назив сидра',
+		remove: 'Уклони сидро'
 	},
-	anchorId: 'Пo Ид-jу елемента',
+	anchorId: 'Пo Ид-у елемента',
 	anchorName: 'По називу сидра',
-	charset: 'Linked Resource Charset',
-	cssClasses: 'Stylesheet класе',
-	download: 'Force Download', // MISSING
-	displayText: 'Display Text', // MISSING
-	emailAddress: 'Адреса електронске поште',
+	charset: 'Код страницанаведеног садржаја',
+	cssClasses: 'Стилске ознаке',
+	download: 'Обавезно преузимање',
+	displayText: 'Приказани текст',
+	emailAddress: 'Е-маил адреса',
 	emailBody: 'Садржај поруке',
-	emailSubject: 'Наслов',
+	emailSubject: 'Наслов пруке',
 	id: 'Ид',
-	info: 'Линк инфо',
-	langCode: 'Смер језика',
-	langDir: 'Смер језика',
+	info: 'Основне карактеристике',
+	langCode: 'Смер писања',
+	langDir: 'Смер писања',
 	langDirLTR: 'С лева на десно (LTR)',
 	langDirRTL: 'С десна на лево (RTL)',
 	menu: 'Промени линк',
 	name: 'Назив',
-	noAnchors: '(Нема доступних сидра)',
-	noEmail: 'Откуцајте адресу електронске поште',
+	noAnchors: '(Нема сидра у документу)',
+	noEmail: 'Одредите е-маил адресу',
 	noUrl: 'Унесите УРЛ линка',
+	noTel: 'Унесите број телефона',
 	other: '<друго>',
+	phoneNumber: 'Број телефона',
 	popupDependent: 'Зависно (Netscape)',
-	popupFeatures: 'Могућности искачућег прозора',
+	popupFeatures: 'Карактеристике искачућег прозора',
 	popupFullScreen: 'Приказ преко целог екрана (ИE)',
-	popupLeft: 'Од леве ивице екрана (пиксела)',
+	popupLeft: 'Лева позиција',
 	popupLocationBar: 'Локација',
 	popupMenuBar: 'Контекстни мени',
-	popupResizable: 'Величина се мења',
-	popupScrollBars: 'Скрол бар',
+	popupResizable: 'Промењиве величине',
+	popupScrollBars: 'Клизач',
 	popupStatusBar: 'Статусна линија',
-	popupToolbar: 'Toolbar',
-	popupTop: 'Од врха екрана (пиксела)',
-	rel: 'Однос',
+	popupToolbar: 'Трака са алаткама',
+	popupTop: 'Горња позиција',
+	rel: 'Врста односа',
 	selectAnchor: 'Одабери сидро',
 	styles: 'Стил',
 	tabIndex: 'Таб индекс',
-	target: 'Meтa',
+	target: 'Прикажи садржај',
 	targetFrame: '<оквир>',
-	targetFrameName: 'Назив одредишног фрејма',
+	targetFrameName: 'Назив оквира',
 	targetPopup: '<искачући прозор>',
 	targetPopupName: 'Назив искачућег прозора',
-	title: 'Линк',
+	title: 'Карактеристике линка',
 	toAnchor: 'Сидро на овој страници',
-	toEmail: 'Eлектронска пошта',
+	toEmail: 'E-маил',
 	toUrl: 'УРЛ',
+	toPhone: 'Телефон',
 	toolbar: 'Унеси/измени линк',
 	type: 'Врста линка',
 	unlink: 'Уклони линк',
-	upload: 'Пошаљи'
+	upload: 'Постави'
 } );
diff --git a/web/modules/anchor_link/js/plugins/link/lang/sv.js b/web/modules/anchor_link/js/plugins/link/lang/sv.js
index 67b7dcfd5095bbef5525aaf5b64bb99ee7b3b56f..4c05b07a281b3ddbf32f5680fabc489d165e8b2a 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/sv.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/sv.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'sv', {
 	acccessKey: 'Behörighetsnyckel',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'sv', {
 	noAnchors: '(Inga ankare kunde hittas)',
 	noEmail: 'Var god ange e-postadress',
 	noUrl: 'Var god ange länkens URL',
+	noTel: 'Var god ange telefonnummer',
 	other: '<annan>',
+	phoneNumber: 'Telefonnummer',
 	popupDependent: 'Beroende (endast Netscape)',
 	popupFeatures: 'Popup-fönstrets egenskaper',
 	popupFullScreen: 'Helskärm (endast IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'sv', {
 	toAnchor: 'Länk till ankare i texten',
 	toEmail: 'E-post',
 	toUrl: 'URL',
+	toPhone: 'Telefon',
 	toolbar: 'Infoga/Redigera länk',
 	type: 'Länktyp',
 	unlink: 'Radera länk',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/th.js b/web/modules/anchor_link/js/plugins/link/lang/th.js
index b27ff84917ac1446f049608eda65c0f73c59a3dd..4eadb330c91e21373e04b94ce5bfe8a98aaac6ec 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/th.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/th.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'th', {
 	acccessKey: 'แอคเซส คีย์',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'th', {
 	noAnchors: '(ยังไม่มีจุดเชื่อมโยงภายในหน้าเอกสารนี้)',
 	noEmail: 'กรุณาระบุอีเมล์ (E-mail)',
 	noUrl: 'กรุณาระบุที่อยู่อ้างอิงออนไลน์ (URL)',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<อื่น ๆ>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'แสดงเต็มหน้าจอ (Netscape)',
 	popupFeatures: 'คุณสมบัติของหน้าจอเล็ก (Pop-up)',
 	popupFullScreen: 'แสดงเต็มหน้าจอ (IE5.5++ เท่านั้น)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'th', {
 	toAnchor: 'จุดเชื่อมโยง (Anchor)',
 	toEmail: 'ส่งอีเมล์ (E-Mail)',
 	toUrl: 'ที่อยู่อ้างอิง URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'แทรก/แก้ไข ลิงค์',
 	type: 'ประเภทของลิงค์',
 	unlink: 'ลบ ลิงค์',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/tr.js b/web/modules/anchor_link/js/plugins/link/lang/tr.js
index 378accaabf07246a19af4d38a7ef729b8261871f..80fbe56477001d65351f43c5da0fc8103af578ab 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/tr.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/tr.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'tr', {
 	acccessKey: 'Erişim Tuşu',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'tr', {
 	noAnchors: '(Bu belgede hiç çapa yok)',
 	noEmail: 'Lütfen E-posta adresini yazın',
 	noUrl: 'Lütfen Link URL\'sini yazın',
+	noTel: 'Lütfen telefon numaranızı yazınız',
 	other: '<diğer>',
+	phoneNumber: 'Telefon numarası',
 	popupDependent: 'Bağımlı (Netscape)',
 	popupFeatures: 'Yeni Açılan Pencere Özellikleri',
 	popupFullScreen: 'Tam Ekran (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'tr', {
 	toAnchor: 'Bu sayfada çapa',
 	toEmail: 'E-Posta',
 	toUrl: 'URL',
+	toPhone: 'Telefon',
 	toolbar: 'Link Ekle/Düzenle',
 	type: 'Link Türü',
 	unlink: 'Köprü Kaldır',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/tt.js b/web/modules/anchor_link/js/plugins/link/lang/tt.js
index 046248359b33874a11269a24a29efa28fa0fe4b6..027f906bd2b6dbbda06631c31caab77447fb2a73 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/tt.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/tt.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'tt', {
 	acccessKey: 'Access Key', // MISSING
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'tt', {
 	noAnchors: '(Әлеге документта якорьләр табылмады)',
 	noEmail: 'Электрон почта адресын языгыз',
 	noUrl: 'Сылталаманы языгыз',
+	noTel: 'Телефон номерыгызны языгыз',
 	other: '<бүтән>',
+	phoneNumber: 'Телефон номеры',
 	popupDependent: 'Бәйле (Netscape)',
 	popupFeatures: 'Popup Window Features', // MISSING
 	popupFullScreen: 'Тулы экран (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'tt', {
 	toAnchor: 'Якорьне текст белән бәйләү',
 	toEmail: 'Электрон почта',
 	toUrl: 'Сылталама',
+	toPhone: 'Телефон',
 	toolbar: 'Сылталама',
 	type: 'Сылталама төре',
 	unlink: 'Сылталаманы бетерү',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/ug.js b/web/modules/anchor_link/js/plugins/link/lang/ug.js
index e7487876099be1271c370bda5192b66fd548c9ac..353201ef717012ac0a1842371165cb3bb2b8ce46 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/ug.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/ug.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'ug', {
 	acccessKey: 'زىيارەت كۇنۇپكا',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'ug', {
 	noAnchors: '(بۇ پۈتۈكتە ئىشلەتكىلى بولىدىغان لەڭگەرلىك نۇقتا يوق)',
 	noEmail: 'ئېلخەت ئادرېسىنى كىرگۈزۈڭ',
 	noUrl: 'ئۇلانما ئادرېسىنى كىرگۈزۈڭ',
+	noTel: 'Please type the phone number', // MISSING
 	other: '‹باشقا›',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'تەۋە (NS)',
 	popupFeatures: 'قاڭقىش كۆزنەك خاسلىقى',
 	popupFullScreen: 'پۈتۈن ئېكران (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'ug', {
 	toAnchor: 'بەت ئىچىدىكى لەڭگەرلىك نۇقتا ئۇلانمىسى',
 	toEmail: 'ئېلخەت',
 	toUrl: 'ئادرېس',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'ئۇلانما قىستۇر/تەھرىرلە',
 	type: 'ئۇلانما تىپى',
 	unlink: 'ئۇلانما بىكار قىل',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/uk.js b/web/modules/anchor_link/js/plugins/link/lang/uk.js
index 189957d5f76e971ece63cd2e2e3be7d7a8b1a863..366abe82430192255463734d2c0694715b552009 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/uk.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/uk.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'uk', {
 	acccessKey: 'Гаряча клавіша',
@@ -19,8 +19,8 @@ CKEDITOR.plugins.setLang( 'link', 'uk', {
 	anchorName: 'За ім\'ям елементу',
 	charset: 'Кодування',
 	cssClasses: 'Клас CSS',
-	download: 'Force Download', // MISSING
-	displayText: 'Display Text', // MISSING
+	download: 'Завантажити як файл',
+	displayText: 'Відображуваний текст',
 	emailAddress: 'Адреса ел. пошти',
 	emailBody: 'Тіло повідомлення',
 	emailSubject: 'Тема листа',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'uk', {
 	noAnchors: '(В цьому документі немає якорів)',
 	noEmail: 'Будь ласка, вкажіть адрес ел. пошти',
 	noUrl: 'Будь ласка, вкажіть URL посилання',
+	noTel: 'Будь ласка, введіть номер телефону',
 	other: '<інший>',
+	phoneNumber: 'Номер телефону',
 	popupDependent: 'Залежний (Netscape)',
 	popupFeatures: 'Властивості випливаючого вікна',
 	popupFullScreen: 'Повний екран (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'uk', {
 	toAnchor: 'Якір на цю сторінку',
 	toEmail: 'Ел. пошта',
 	toUrl: 'URL',
+	toPhone: 'Телефон',
 	toolbar: 'Вставити/Редагувати посилання',
 	type: 'Тип посилання',
 	unlink: 'Видалити посилання',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/vi.js b/web/modules/anchor_link/js/plugins/link/lang/vi.js
index a079e3a170d864b89b7c1713cb067b9a9d14e90b..6a00ae57df09ec13dfd319226b503fe02ac04227 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/vi.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/vi.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'vi', {
 	acccessKey: 'Phím hỗ trợ truy cập',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'vi', {
 	noAnchors: '(Không có điểm neo nào trong tài liệu)',
 	noEmail: 'Hãy đưa vào địa chỉ thư điện tử',
 	noUrl: 'Hãy đưa vào đường dẫn liên kết (URL)',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<khác>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: 'Phụ thuộc (Netscape)',
 	popupFeatures: 'Đặc điểm của cửa sổ Popup',
 	popupFullScreen: 'Toàn màn hình (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'vi', {
 	toAnchor: 'Neo trong trang này',
 	toEmail: 'Thư điện tử',
 	toUrl: 'URL',
+	toPhone: 'Phone', // MISSING
 	toolbar: 'Chèn/Sửa liên kết',
 	type: 'Kiểu liên kết',
 	unlink: 'Xoá liên kết',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/zh-cn.js b/web/modules/anchor_link/js/plugins/link/lang/zh-cn.js
index 9b706d6988c8f87ac44c00b9ad1a2ceddd72c613..1f67fe437fd9420491e62979006ba30b83dbe782 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/zh-cn.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/zh-cn.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'zh-cn', {
 	acccessKey: '访问键',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'zh-cn', {
 	noAnchors: '(此文档没有可用的锚点)',
 	noEmail: '请输入电子邮件地址',
 	noUrl: '请输入超链接地址',
+	noTel: '请输入电话号码',
 	other: '<其他>',
+	phoneNumber: '电话号码',
 	popupDependent: '依附 (NS)',
 	popupFeatures: '弹出窗口属性',
 	popupFullScreen: '全屏 (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'zh-cn', {
 	toAnchor: '页内锚点链接',
 	toEmail: '电子邮件',
 	toUrl: '地址',
+	toPhone: '电话',
 	toolbar: '插入/编辑超链接',
 	type: '超链接类型',
 	unlink: '取消超链接',
diff --git a/web/modules/anchor_link/js/plugins/link/lang/zh.js b/web/modules/anchor_link/js/plugins/link/lang/zh.js
index 3b8c407c0a7b5d2af6e3051b28177a3bd8980b53..edf76f44a84a71c618ba902a6601ba264bf9e1ee 100755
--- a/web/modules/anchor_link/js/plugins/link/lang/zh.js
+++ b/web/modules/anchor_link/js/plugins/link/lang/zh.js
@@ -1,6 +1,6 @@
 /*
-Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
-For licensing, see LICENSE.md or http://ckeditor.com/license
+Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
 CKEDITOR.plugins.setLang( 'link', 'zh', {
 	acccessKey: '便捷鍵',
@@ -35,7 +35,9 @@ CKEDITOR.plugins.setLang( 'link', 'zh', {
 	noAnchors: '(本文件中無可用之錨點)',
 	noEmail: '請輸入電子郵件',
 	noUrl: '請輸入連結 URL',
+	noTel: 'Please type the phone number', // MISSING
 	other: '<其他>',
+	phoneNumber: 'Phone number', // MISSING
 	popupDependent: '獨立 (Netscape)',
 	popupFeatures: '快顯視窗功能',
 	popupFullScreen: '全螢幕 (IE)',
@@ -60,6 +62,7 @@ CKEDITOR.plugins.setLang( 'link', 'zh', {
 	toAnchor: '文字中的錨點連結',
 	toEmail: '電子郵件',
 	toUrl: '網址',
+	toPhone: 'Phone', // MISSING
 	toolbar: '連結',
 	type: '連結類型',
 	unlink: '取消連結',
diff --git a/web/modules/anchor_link/js/plugins/link/plugin.js b/web/modules/anchor_link/js/plugins/link/plugin.js
index fce564c41d18b968eb75ebfb42030d259b5bf73f..6faa525237f86c701dff78316ab169a6a51c185b 100755
--- a/web/modules/anchor_link/js/plugins/link/plugin.js
+++ b/web/modules/anchor_link/js/plugins/link/plugin.js
@@ -1,6 +1,6 @@
-/**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md or http://ckeditor.com/license
+/**
+ * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  */
 
 'use strict';
@@ -51,10 +51,12 @@
 			var allowed = 'a[!href]',
 				required = 'a[href]';
 
-			if ( CKEDITOR.dialog.isTabEnabled( editor, 'link', 'advanced' ) )
+			if ( CKEDITOR.dialog.isTabEnabled( editor, 'link', 'advanced' ) ) {
 				allowed = allowed.replace( ']', ',accesskey,charset,dir,id,lang,name,rel,tabindex,title,type,download]{*}(*)' );
-			if ( CKEDITOR.dialog.isTabEnabled( editor, 'link', 'target' ) )
+			}
+			if ( CKEDITOR.dialog.isTabEnabled( editor, 'link', 'target' ) ) {
 				allowed = allowed.replace( ']', ',target,onclick]' );
+			}
 
 			// Add the link and unlink buttons.
 			editor.addCommand( 'link', new CKEDITOR.dialogCommand( 'link', {
@@ -70,6 +72,9 @@
 
 			editor.setKeystroke( CKEDITOR.CTRL + 76 /*L*/, 'link' );
 
+			// (#2478)
+			editor.setKeystroke( CKEDITOR.CTRL + 75 /*K*/, 'link' );
+
 			if ( editor.ui.addButton ) {
 				editor.ui.addButton( 'Link', {
 					label: editor.lang.link.toolbar,
@@ -114,18 +119,21 @@
 			// If the "contextmenu" plugin is loaded, register the listeners.
 			if ( editor.contextMenu ) {
 				editor.contextMenu.addListener( function( element ) {
-					if ( !element || element.isReadOnly() )
+					if ( !element || element.isReadOnly() ) {
 						return null;
+					}
 
 					var anchor = CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, element );
 
-					if ( !anchor && !( anchor = CKEDITOR.plugins.link.getSelectedLink( editor ) ) )
+					if ( !anchor && !( anchor = CKEDITOR.plugins.link.getSelectedLink( editor ) ) ) {
 						return null;
+					}
 
 					var menu = {};
 
-					if ( anchor && anchor.hasAttribute( 'name' ) )
+					if ( anchor && anchor.hasAttribute( 'name' ) ) {
 						menu.anchor = menu.removeAnchor = CKEDITOR.TRISTATE_OFF;
+					}
 
 					return menu;
 				} );
@@ -139,11 +147,13 @@
 			editor.dataProcessor.dataFilter.addRules( {
 				elements: {
 					a: function( element ) {
-						if ( !element.attributes.name )
+						if ( !element.attributes.name ) {
 							return null;
+						}
 
-						if ( !element.children.length )
+						if ( !element.children.length ) {
 							return editor.createFakeParserElement( element, 'cke_anchor', 'anchor' );
+						}
 
 						return null;
 					}
@@ -154,8 +164,9 @@
 			if ( pathFilters ) {
 				pathFilters.push( function( element, name ) {
 					if ( name == 'a' ) {
-						if ( CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, element ) || ( element.getAttribute( 'name' ) && ( !element.getAttribute( 'href' ) || !element.getChildCount() ) ) )
+						if ( CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, element ) || ( element.getAttribute( 'name' ) && ( !element.getAttribute( 'href' ) || !element.getChildCount() ) ) ) {
 							return 'anchor';
+						}
 					}
 				} );
 			}
@@ -164,7 +175,7 @@
 
 	// Loads the parameters in a selected link to the link dialog fields.
 	var javascriptProtocolRegex = /^javascript:/,
-		emailRegex = /^mailto:([^?]+)(?:\?(.+))?$/,
+		emailRegex = /^(?:mailto)(?:(?!\?(subject|body)=).)+/i,
 		emailSubjectRegex = /subject=([^;?:@&=$,\/]*)/i,
 		emailBodyRegex = /body=([^;?:@&=$,\/]*)/i,
 		anchorRegex = /^#(.*)$/,
@@ -173,7 +184,8 @@
 		encodedEmailLinkRegex = /^javascript:void\(location\.href='mailto:'\+String\.fromCharCode\(([^)]+)\)(?:\+'(.*)')?\)$/,
 		functionCallProtectedEmailLinkRegex = /^javascript:([^(]+)\(([^)]+)\)$/,
 		popupRegex = /\s*window.open\(\s*this\.href\s*,\s*(?:'([^']*)'|null)\s*,\s*'([^']*)'\s*\)\s*;\s*return\s*false;*\s*/,
-		popupFeaturesRegex = /(?:^|,)([^=]+)=(\d+|yes|no)/gi;
+		popupFeaturesRegex = /(?:^|,)([^=]+)=(\d+|yes|no)/gi,
+		telRegex = /^tel:(.*)$/;
 
 	var advAttrNames = {
 		id: 'advId',
@@ -200,9 +212,9 @@
 	}
 
 	function protectEmailAddressAsEncodedString( address ) {
-		var charCode,
-			length = address.length,
-			encodedChars = [];
+		var length = address.length,
+			encodedChars = [],
+			charCode;
 
 		for ( var i = 0; i < length; i++ ) {
 			charCode = address.charCodeAt( i );
@@ -216,9 +228,10 @@
 		var plugin = editor.plugins.link,
 			name = plugin.compiledProtectionFunction.name,
 			params = plugin.compiledProtectionFunction.params,
-			paramName, paramValue, retval;
+			retval = [ name, '(' ],
+			paramName,
+			paramValue;
 
-		retval = [ name, '(' ];
 		for ( var i = 0; i < params.length; i++ ) {
 			paramName = params[ i ].toLowerCase();
 			paramValue = email[ paramName ];
@@ -283,18 +296,18 @@
 				ranges = selection.getRanges(),
 				links = [],
 				link,
-				range,
-				i;
+				range;
 
 			if ( !returnMultiple && selectedElement && selectedElement.is( 'a' ) ) {
 				return selectedElement;
 			}
 
-			for ( i = 0; i < ranges.length; i++ ) {
+			for ( var i = 0; i < ranges.length; i++ ) {
 				range = selection.getRanges()[ i ];
 
 				// Skip bogus to cover cases of multiple selection inside tables (#tp2245).
-				range.shrink( CKEDITOR.SHRINK_TEXT, false, { skipBogus: true } );
+				// Shrink to element to prevent losing anchor (#859).
+				range.shrink( CKEDITOR.SHRINK_ELEMENT, true, { skipBogus: true } );
 				link = editor.elementPath( range.getCommonAncestor() ).contains( 'a', 1 );
 
 				if ( link && returnMultiple ) {
@@ -320,17 +333,17 @@
 			var editable = editor.editable(),
 
 				// The scope of search for anchors is the entire document for inline editors
-				// and editor's editable for classic editor/divarea (http://dev.ckeditor.com/ticket/11359).
+				// and editor's editable for classic editor/divarea (https://dev.ckeditor.com/ticket/11359).
 				scope = ( editable.isInline() && !editor.plugins.divarea ) ? editor.document : editable,
 
 				links = scope.getElementsByTag( 'a' ),
 				imgs = scope.getElementsByTag( 'img' ),
 				anchors = [],
-				i = 0,
+				iterator = 0,
 				item;
 
 			// Retrieve all anchors within the scope.
-			while ( ( item = links.getItem( i++ ) ) ) {
+			while ( ( item = links.getItem( iterator++ ) ) ) {
 				if ( item.data( 'cke-saved-name' ) || item.hasAttribute( 'name' ) ) {
 					anchors.push( {
 						name: item.data( 'cke-saved-name' ) || item.getAttribute( 'name' ),
@@ -339,9 +352,9 @@
 				}
 			}
 			// Retrieve all "fake anchors" within the scope.
-			i = 0;
+			iterator = 0;
 
-			while ( ( item = imgs.getItem( i++ ) ) ) {
+			while ( ( item = imgs.getItem( iterator++ ) ) ) {
 				if ( ( item = this.tryRestoreFakeAnchor( editor, item ) ) ) {
 					anchors.push( {
 						name: item.getAttribute( 'name' ),
@@ -364,7 +377,7 @@
 		fakeAnchor: true,
 
 		/**
-		 * For browsers that do not support CSS3 `a[name]:empty()`. Note that IE9 is included because of http://dev.ckeditor.com/ticket/7783.
+		 * For browsers that do not support CSS3 `a[name]:empty()`. Note that IE9 is included because of https://dev.ckeditor.com/ticket/7783.
 		 *
 		 * @readonly
 		 * @deprecated 4.3.3 It is set to `false` in every browser.
@@ -390,8 +403,9 @@
 		tryRestoreFakeAnchor: function( editor, element ) {
 			if ( element && element.data( 'cke-real-element-type' ) && element.data( 'cke-real-element-type' ) == 'anchor' ) {
 				var link = editor.restoreRealElement( element );
-				if ( link.data( 'cke-saved-name' ) )
+				if ( link.data( 'cke-saved-name' ) ) {
 					return link;
+				}
 			}
 		},
 
@@ -403,7 +417,7 @@
 		 * **Note:** Data model format produced by the parser must be compatible with the Link
 		 * plugin dialog because it is passed directly to {@link CKEDITOR.dialog#setupContent}.
 		 *
-		 * @since 4.4
+		 * @since 4.4.0
 		 * @param {CKEDITOR.editor} editor
 		 * @param {CKEDITOR.dom.element} element
 		 * @returns {Object} An object of link data.
@@ -412,13 +426,17 @@
 			var href = ( element && ( element.data( 'cke-saved-href' ) || element.getAttribute( 'href' ) ) ) || '',
 				compiledProtectionFunction = editor.plugins.link.compiledProtectionFunction,
 				emailProtection = editor.config.emailProtection,
-				javascriptMatch, emailMatch, anchorMatch, urlMatch,
-				retval = {};
-
-			if ( ( javascriptMatch = href.match( javascriptProtocolRegex ) ) ) {
+				retval = {},
+				javascriptMatch = href.match( javascriptProtocolRegex ),
+				emailMatch,
+				anchorMatch,
+				urlMatch,
+				telMatch;
+
+			if ( javascriptMatch ) {
 				if ( emailProtection == 'encode' ) {
 					href = href.replace( encodedEmailLinkRegex, function( match, protectedAddress, rest ) {
-						// Without it 'undefined' is appended to e-mails without subject and body (http://dev.ckeditor.com/ticket/9192).
+						// Without it 'undefined' is appended to e-mails without subject and body (https://dev.ckeditor.com/ticket/9192).
 						rest = rest || '';
 
 						return 'mailto:' +
@@ -431,13 +449,14 @@
 					href.replace( functionCallProtectedEmailLinkRegex, function( match, funcName, funcArgs ) {
 						if ( funcName == compiledProtectionFunction.name ) {
 							retval.type = 'email';
-							var email = retval.email = {};
 
-							var paramRegex = /[^,\s]+/g,
+							var email = retval.email = {},
+								paramRegex = /[^,\s]+/g,
 								paramQuoteRegex = /(^')|('$)/g,
 								paramsMatch = funcArgs.match( paramRegex ),
 								paramsMatchLength = paramsMatch.length,
-								paramName, paramVal;
+								paramName,
+								paramVal;
 
 							for ( var i = 0; i < paramsMatchLength; i++ ) {
 								paramVal = decodeURIComponent( unescapeSingleQuote( paramsMatch[ i ].replace( paramQuoteRegex, '' ) ) );
@@ -455,15 +474,18 @@
 					retval.type = 'anchor';
 					retval.anchor = {};
 					retval.anchor.name = retval.anchor.id = anchorMatch[ 1 ];
+				} else if ( ( telMatch = href.match( telRegex ) ) ) {
+					retval.type = 'tel';
+					retval.tel = telMatch[ 1 ];
 				}
 				// Protected email link as encoded string.
 				else if ( ( emailMatch = href.match( emailRegex ) ) ) {
 					var subjectMatch = href.match( emailSubjectRegex ),
-						bodyMatch = href.match( emailBodyRegex );
+						bodyMatch = href.match( emailBodyRegex ),
+						email = ( retval.email = {} );
 
 					retval.type = 'email';
-					var email = ( retval.email = {} );
-					email.address = emailMatch[ 1 ];
+					email.address = emailMatch[ 0 ].replace( 'mailto:', '' );
 					subjectMatch && ( email.subject = decodeURIComponent( subjectMatch[ 1 ] ) );
 					bodyMatch && ( email.body = decodeURIComponent( bodyMatch[ 1 ] ) );
 				}
@@ -493,11 +515,12 @@
 
 						var featureMatch;
 						while ( ( featureMatch = popupFeaturesRegex.exec( onclickMatch[ 2 ] ) ) ) {
-							// Some values should remain numbers (http://dev.ckeditor.com/ticket/7300)
-							if ( ( featureMatch[ 2 ] == 'yes' || featureMatch[ 2 ] == '1' ) && !( featureMatch[ 1 ] in { height: 1, width: 1, top: 1, left: 1 } ) )
+							// Some values should remain numbers (https://dev.ckeditor.com/ticket/7300)
+							if ( ( featureMatch[ 2 ] == 'yes' || featureMatch[ 2 ] == '1' ) && !( featureMatch[ 1 ] in { height: 1, width: 1, top: 1, left: 1 } ) ) {
 								retval.target[ featureMatch[ 1 ] ] = true;
-							else if ( isFinite( featureMatch[ 2 ] ) )
+							} else if ( isFinite( featureMatch[ 2 ] ) ) {
 								retval.target[ featureMatch[ 1 ] ] = featureMatch[ 2 ];
+							}
 						}
 					}
 				} else {
@@ -513,21 +536,22 @@
 				}
 
 				var advanced = {};
-
 				for ( var a in advAttrNames ) {
 					var val = element.getAttribute( a );
 
-					if ( val )
+					if ( val ) {
 						advanced[ advAttrNames[ a ] ] = val;
+					}
 				}
 
 				var advName = element.data( 'cke-saved-name' ) || advanced.advName;
-
-				if ( advName )
+				if ( advName ) {
 					advanced.advName = advName;
+				}
 
-				if ( !CKEDITOR.tools.isEmpty( advanced ) )
+				if ( !CKEDITOR.tools.isEmpty( advanced ) ) {
 					retval.advanced = advanced;
+				}
 			}
 
 			return retval;
@@ -538,7 +562,7 @@
 		 * of attributes to be set (with their values) and an array of attributes to be removed.
 		 * This method can be used to compose or to update any link element with the given data.
 		 *
-		 * @since 4.4
+		 * @since 4.4.0
 		 * @param {CKEDITOR.editor} editor
 		 * @param {Object} data Data in {@link #parseLinkAttributes} format.
 		 * @returns {Object} An object consisting of two keys, i.e.:
@@ -567,15 +591,15 @@
 						url = ( data.url && CKEDITOR.tools.trim( data.url.url ) ) || '';
 
 					set[ 'data-cke-saved-href' ] = ( url.indexOf( '/' ) === 0 ) ? url : protocol + url;
-
 					break;
+
 				case 'anchor':
 					var name = ( data.anchor && data.anchor.name ),
 						id = ( data.anchor && data.anchor.id );
 
 					set[ 'data-cke-saved-href' ] = '#' + ( name || id || '' );
-
 					break;
+
 				case 'email':
 					var email = data.email,
 						address = email.address,
@@ -605,8 +629,8 @@
 							} else {
 								linkHref = [ 'mailto:', address, argList ];
 							}
-
 							break;
+
 						default:
 							// Separating name and domain.
 							var nameAndDomain = address.split( '@', 2 );
@@ -615,9 +639,12 @@
 
 							linkHref = [ 'javascript:', protectEmailLinkAsFunction( editor, email ) ]; // jshint ignore:line
 					}
-
 					set[ 'data-cke-saved-href' ] = linkHref.join( '' );
 					break;
+
+				case 'tel':
+					set[ 'data-cke-saved-href' ] = 'tel:' + data.tel;
+					break;
 			}
 
 			// Popups and target.
@@ -631,12 +658,14 @@
 						],
 						featureLength = featureList.length,
 						addFeature = function( featureName ) {
-							if ( data.target[ featureName ] )
+							if ( data.target[ featureName ] ) {
 								featureList.push( featureName + '=' + data.target[ featureName ] );
+							}
 						};
 
-					for ( var i = 0; i < featureLength; i++ )
+					for ( var i = 0; i < featureLength; i++ ) {
 						featureList[ i ] = featureList[ i ] + ( data.target[ featureList[ i ] ] ? '=yes' : '=no' );
+					}
 
 					addFeature( 'width' );
 					addFeature( 'left' );
@@ -661,17 +690,20 @@
 				for ( var a in advAttrNames ) {
 					var val = data.advanced[ advAttrNames[ a ] ];
 
-					if ( val )
+					if ( val ) {
 						set[ a ] = val;
+					}
 				}
 
-				if ( set.name )
+				if ( set.name ) {
 					set[ 'data-cke-saved-name' ] = set.name;
+				}
 			}
 
-			// Browser need the "href" fro copy/paste link to work. (http://dev.ckeditor.com/ticket/6641)
-			if ( set[ 'data-cke-saved-href' ] )
+			// Browser need the "href" fro copy/paste link to work. (https://dev.ckeditor.com/ticket/6641)
+			if ( set[ 'data-cke-saved-href' ] ) {
 				set.href = set[ 'data-cke-saved-href' ];
+			}
 
 			var removed = {
 				target: 1,
@@ -681,16 +713,18 @@
 				'download': 1
 			};
 
-			if ( data.advanced )
+			if ( data.advanced ) {
 				CKEDITOR.tools.extend( removed, advAttrNames );
+			}
 
 			// Remove all attributes which are not currently set.
-			for ( var s in set )
+			for ( var s in set ) {
 				delete removed[ s ];
+			}
 
 			return {
 				set: set,
-				removed: CKEDITOR.tools.objectKeys( removed )
+				removed: CKEDITOR.tools.object.keys( removed )
 			};
 		},
 
@@ -737,11 +771,11 @@
 		exec: function( editor ) {
 			// IE/Edge removes link from selection while executing "unlink" command when cursor
 			// is right before/after link's text. Therefore whole link must be selected and the
-			// position of cursor must be restored to its initial state after unlinking. (http://dev.ckeditor.com/ticket/13062)
+			// position of cursor must be restored to its initial state after unlinking. (https://dev.ckeditor.com/ticket/13062)
 			if ( CKEDITOR.env.ie ) {
 				var range = editor.getSelection().getRanges()[ 0 ],
 					link = ( range.getPreviousEditableNode() && range.getPreviousEditableNode().getAscendant( 'a', true ) ) ||
-							( range.getNextEditableNode() && range.getNextEditableNode().getAscendant( 'a', true ) ),
+						( range.getNextEditableNode() && range.getNextEditableNode().getAscendant( 'a', true ) ),
 					bookmark;
 
 				if ( range.collapsed && link ) {
@@ -766,10 +800,11 @@
 
 			var element = path.lastElement && path.lastElement.getAscendant( 'a', true );
 
-			if ( element && element.getName() == 'a' && element.getAttribute( 'href' ) && element.getChildCount() )
+			if ( element && element.getName() == 'a' && element.getAttribute( 'href' ) && element.getChildCount() ) {
 				this.setState( CKEDITOR.TRISTATE_OFF );
-			else
+			} else {
 				this.setState( CKEDITOR.TRISTATE_DISABLED );
+			}
 		},
 
 		contextSensitive: 1,
@@ -784,9 +819,10 @@
 			var sel = editor.getSelection(),
 				bms = sel.createBookmarks(),
 				anchor;
-			if ( sel && ( anchor = sel.getSelectedElement() ) && ( !anchor.getChildCount() ? CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, anchor ) : anchor.is( 'a' ) ) )
+
+			if ( sel && ( anchor = sel.getSelectedElement() ) && ( !anchor.getChildCount() ? CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, anchor ) : anchor.is( 'a' ) ) ) {
 				anchor.remove( 1 );
-			else {
+			} else {
 				if ( ( anchor = CKEDITOR.plugins.link.getSelectedLink( editor ) ) ) {
 					if ( anchor.hasAttribute( 'href' ) ) {
 						anchor.removeAttributes( { name: 1, 'data-cke-saved-name': 1 } );
@@ -816,13 +852,36 @@
 		 * @cfg {Boolean} [linkShowTargetTab=true]
 		 * @member CKEDITOR.config
 		 */
-		linkShowTargetTab: true
+		linkShowTargetTab: true,
+
+		/**
+		 * Default URL protocol used for the Link dialog.
+		 *
+		 * Available values are:
+		 *
+		 * * `'http://'`
+		 * * `'https://'`
+		 * * `'ftp://'`
+		 * * `'news://'`
+		 * * `''` &mdash; An empty string for the `<other>` option.
+		 *
+		 * ```js
+		 * config.linkDefaultProtocol = 'https://';
+		 * ```
+		 *
+		 * @cfg {String}
+		 * @member CKEDITOR.config
+		 * @since 4.13.0
+		 */
+		linkDefaultProtocol: 'http://'
 
 		/**
 		 * Whether JavaScript code is allowed as a `href` attribute in an anchor tag.
 		 * With this option enabled it is possible to create links like:
 		 *
-		 *		<a href="javascript:alert('Hello world!')">hello world</a>
+		 * ```html
+		 * <a href="javascript:alert('Hello world!')">hello world</a>
+		 * ```
 		 *
 		 * By default JavaScript links are not allowed and will not pass
 		 * the Link dialog window validation.
@@ -831,5 +890,29 @@
 		 * @cfg {Boolean} [linkJavaScriptLinksAllowed=false]
 		 * @member CKEDITOR.config
 		 */
+
+		/**
+		 * Optional JavaScript regular expression used whenever phone numbers in the Link dialog should be validated.
+		 *
+		 * ```js
+		 * config.linkPhoneRegExp = /^[0-9]{9}$/;
+		 * ```
+		 *
+		 * @since 4.11.0
+		 * @cfg {RegExp} [linkPhoneRegExp]
+		 * @member CKEDITOR.config
+		 */
+
+		/**
+		 * Optional message for the alert popup used when the phone number in the Link dialog does not pass the validation.
+		 *
+		 * ```js
+		 * config.linkPhoneMsg = "Invalid number";
+		 * ```
+		 *
+		 * @since 4.11.0
+		 * @cfg {String} [linkPhoneMsg]
+		 * @member CKEDITOR.config
+		 */
 	} );
 } )();
diff --git a/web/modules/anchor_link/src/Plugin/CKEditorPlugin/AnchorLink.php b/web/modules/anchor_link/src/Plugin/CKEditorPlugin/AnchorLink.php
index 16d5744b012d0af5086f83b3875a720248d754fb..fe41d982f81c9f4ac6663f9f16436d8fb46568bb 100755
--- a/web/modules/anchor_link/src/Plugin/CKEditorPlugin/AnchorLink.php
+++ b/web/modules/anchor_link/src/Plugin/CKEditorPlugin/AnchorLink.php
@@ -51,12 +51,12 @@ public function isInternal() {
    */
   public function getButtons() {
     return [
-      'Link' => [
-        'label' => $this->t('Link'),
+      'LinkToAnchor' => [
+        'label' => $this->t('Link to anchor'),
         'image' => drupal_get_path('module', 'anchor_link') . '/js/plugins/link/icons/link.png',
       ],
-      'Unlink' => [
-        'label' => $this->t('Unlink'),
+      'UnlinkAnchor' => [
+        'label' => $this->t('Unlink Anchor'),
         'image' => drupal_get_path('module', 'anchor_link') . '/js/plugins/link/icons/unlink.png',
       ],
       'Anchor' => [
diff --git a/web/modules/anchor_link/src/Plugin/Linkit/Matcher/CKEditorAnchorLinkMatcher.php b/web/modules/anchor_link/src/Plugin/Linkit/Matcher/CKEditorAnchorLinkMatcher.php
new file mode 100644
index 0000000000000000000000000000000000000000..f3a6079814490d275bfb9cb77ba6fd0919465090
--- /dev/null
+++ b/web/modules/anchor_link/src/Plugin/Linkit/Matcher/CKEditorAnchorLinkMatcher.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace Drupal\anchor_link\Plugin\Linkit\Matcher;
+
+use Drupal\Component\Utility\Html;
+use Drupal\linkit\MatcherBase;
+use Drupal\linkit\Suggestion\DescriptionSuggestion;
+use Drupal\linkit\Suggestion\SuggestionCollection;
+
+/**
+ * Provides specific linkit matchers for Anchor links.
+ *
+ * @Matcher(
+ *   id = "ckeditor_anchor_link",
+ *   label = @Translation("CKEditor Anchor link"),
+ * )
+ */
+class CKEditorAnchorLinkMatcher extends MatcherBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute($string) {
+    $suggestions = new SuggestionCollection();
+
+    $string = ltrim($string, '#');
+
+    $suggestion = new DescriptionSuggestion();
+    $suggestion->setLabel($this->t('#@anchor_link', ['@anchor_link' => $string]))
+      ->setPath('#' . $string)
+      ->setGroup($this->t('Anchor links (within the same page)'));
+
+    $suggestions->addSuggestion($suggestion);
+
+    return $suggestions;
+  }
+
+}
diff --git a/web/modules/better_exposed_filters/better_exposed_filters.info.yml b/web/modules/better_exposed_filters/better_exposed_filters.info.yml
index 618d14e5c5d8af00ad260fd0954ef7d228cbb895..5ee4c8020ec19711bd1f7ede5df138e542a8b3ad 100644
--- a/web/modules/better_exposed_filters/better_exposed_filters.info.yml
+++ b/web/modules/better_exposed_filters/better_exposed_filters.info.yml
@@ -10,7 +10,7 @@ dependencies:
   - jquery_ui_touch_punch:jquery_ui_touch_punch
   - jquery_ui_datepicker:jquery_ui_datepicker
 
-# Information added by Drupal.org packaging script on 2021-07-07
-version: '8.x-5.0-beta3'
+# Information added by Drupal.org packaging script on 2021-10-20
+version: '8.x-5.0'
 project: 'better_exposed_filters'
-datestamp: 1625665749
+datestamp: 1634748725
diff --git a/web/modules/better_exposed_filters/src/Plugin/better_exposed_filters/filter/DatePickers.php b/web/modules/better_exposed_filters/src/Plugin/better_exposed_filters/filter/DatePickers.php
index ccd8f41f651ba1030860409e3f485f63ce10ba7b..4f9c29e1b0b60c6de13e5d9390614f86917021f0 100644
--- a/web/modules/better_exposed_filters/src/Plugin/better_exposed_filters/filter/DatePickers.php
+++ b/web/modules/better_exposed_filters/src/Plugin/better_exposed_filters/filter/DatePickers.php
@@ -34,41 +34,47 @@ public static function isApplicable($filter = NULL, array $filter_options = [])
   public function exposedFormAlter(array &$form, FormStateInterface $form_state) {
     $field_id = $this->getExposedFilterFieldId();
 
+    // Handle wrapper element added to exposed filters
+    // in https://www.drupal.org/project/drupal/issues/2625136.
+    $wrapper_id = $field_id . '_wrapper';
+    if (!isset($form[$field_id]) && isset($form[$wrapper_id])) {
+      $element = &$form[$wrapper_id][$field_id];
+    }
+    else {
+      $element = &$form[$field_id];
+    }
+
     parent::exposedFormAlter($form, $form_state);
 
     // Attach the JS (@see /js/datepickers.js)
     $form['#attached']['library'][] = 'better_exposed_filters/datepickers';
 
     // Date picker settings.
-    $form[$field_id]['#attached']['drupalSettings']['better_exposed_filters']['datepicker'] = TRUE;
-    $form[$field_id]['#attached']['drupalSettings']['better_exposed_filters']['datepicker_options'] = [];
-    $drupal_settings = &$form[$field_id]['#attached']['drupalSettings']['better_exposed_filters']['datepicker_options'];
+    $element['#attached']['drupalSettings']['better_exposed_filters']['datepicker'] = TRUE;
+    $element['#attached']['drupalSettings']['better_exposed_filters']['datepicker_options'] = [];
+    $drupal_settings = &$element['#attached']['drupalSettings']['better_exposed_filters']['datepicker_options'];
 
     // Single Date API-based input element.
-    $is_single_date = isset($form[$field_id]['value']['#type'])
-    && 'date_text' == $form[$field_id]['value']['#type'];
+    $is_single_date = isset($element['value']['#type'])
+      && 'date_text' == $element['value']['#type'];
     // Double Date-API-based input elements such as "in-between".
-    $is_double_date = isset($form[$field_id]['min']) && isset($form[$field_id]['max'])
-      && 'date_text' == $form[$field_id]['min']['#type']
-      && 'date_text' == $form[$field_id]['max']['#type'];
+    $is_double_date = isset($element['min']) && isset($element['max'])
+      && 'date_text' == $element['min']['#type']
+      && 'date_text' == $element['max']['#type'];
 
-    // @todo lots of repetition of code. Let's re-organize and clean up.
     if ($is_single_date || $is_double_date) {
-      if (isset($form[$field_id]['value'])) {
-        $format = $form[$field_id]['value']['#date_format'];
-        $form[$field_id]['value']['#attributes']['class'][] = 'bef-datepicker';
-        $form[$field_id]['value']['#attributes']['type'] = 'date';
-        $form[$field_id]['value']['#attributes']['autocomplete'] = 'off';
+      if (isset($element['value'])) {
+        $format = $element['value']['#date_format'];
+        $element['value']['#attributes']['class'][] = 'bef-datepicker';
+        $element['value']['#attributes']['autocomplete'] = 'off';
       }
       else {
         // Both min and max share the same format.
-        $format = $form[$field_id]['min']['#date_format'];
-        $form[$field_id]['min']['#attributes']['class'][] = 'bef-datepicker';
-        $form[$field_id]['max']['#attributes']['class'][] = 'bef-datepicker';
-        $form[$field_id]['min']['#attributes']['type'] = 'date';
-        $form[$field_id]['max']['#attributes']['type'] = 'date';
-        $form[$field_id]['min']['#attributes']['autocomplete'] = 'off';
-        $form[$field_id]['max']['#attributes']['autocomplete'] = 'off';
+        $format = $element['min']['#date_format'];
+        $element['min']['#attributes']['class'][] = 'bef-datepicker';
+        $element['max']['#attributes']['class'][] = 'bef-datepicker';
+        $element['min']['#attributes']['autocomplete'] = 'off';
+        $element['max']['#attributes']['autocomplete'] = 'off';
       }
 
       // Convert Date API format to jQuery UI date format.
@@ -78,25 +84,22 @@ public function exposedFormAlter(array &$form, FormStateInterface $form_state) {
     else {
       /*
        * Standard Drupal date field.  Depending on the settings, the field
-       * can be at $form[$field_id] (single field) or
-       * $form[$field_id][subfield] for two-value date fields or filters
+       * can be at $element (single field) or
+       * $element[subfield] for two-value date fields or filters
        * with exposed operators.
        */
       $fields = ['min', 'max', 'value'];
-      if (count(array_intersect($fields, array_keys($form[$field_id])))) {
-        $form[$field_id]['#type'] = 'container';
+      if (count(array_intersect($fields, array_keys($element)))) {
         foreach ($fields as $field) {
-          if (isset($form[$field_id][$field])) {
-            $form[$field_id][$field]['#attributes']['class'][] = 'bef-datepicker';
-            $form[$field_id][$field]['#attributes']['type'] = 'date';
-            $form[$field_id][$field]['#attributes']['autocomplete'] = 'off';
+          if (isset($element[$field])) {
+            $element[$field]['#attributes']['class'][] = 'bef-datepicker';
+            $element[$field]['#attributes']['autocomplete'] = 'off';
           }
         }
       }
       else {
-        $form[$field_id]['#attributes']['class'][] = 'bef-datepicker';
-        $form[$field_id]['#attributes']['type'] = 'date';
-        $form[$field_id]['#attributes']['autocomplete'] = 'off';
+        $element['#attributes']['class'][] = 'bef-datepicker';
+        $element['#attributes']['autocomplete'] = 'off';
       }
     }
   }
@@ -104,7 +107,7 @@ public function exposedFormAlter(array &$form, FormStateInterface $form_state) {
   /**
    * Convert Date API formatting to jQuery formatDate formatting.
    *
-   * @todo To be honest, I'm not sure this is needed.  Can you set a
+   * @todo: To be honest, I'm not sure this is needed.  Can you set a
    * Date API field to accept anything other than Y-m-d? Well, better
    * safe than sorry...
    *
diff --git a/web/modules/better_exposed_filters/src/Plugin/better_exposed_filters/filter/FilterWidgetBase.php b/web/modules/better_exposed_filters/src/Plugin/better_exposed_filters/filter/FilterWidgetBase.php
index 6f21a9a0b2473cb9abba77707000a2206a444648..4ba5a32a5c5e8836ddf1bc27511d034adc5f9c9b 100644
--- a/web/modules/better_exposed_filters/src/Plugin/better_exposed_filters/filter/FilterWidgetBase.php
+++ b/web/modules/better_exposed_filters/src/Plugin/better_exposed_filters/filter/FilterWidgetBase.php
@@ -215,6 +215,9 @@ public function exposedFormAlter(array &$form, FormStateInterface $form_state) {
         '#type' => 'details',
         '#title' => $exposed_label,
         '#description' => $exposed_description,
+        '#attributes' => [
+          'class' => ['form-item'],
+        ],
       ];
 
       if ($is_secondary) {
diff --git a/web/modules/better_exposed_filters/tests/modules/bef_test/bef_test.info.yml b/web/modules/better_exposed_filters/tests/modules/bef_test/bef_test.info.yml
index 6cd859141c648cb3b0b87e794d48e0d03d144343..3256312ffafd86f8c452c226efd748a4eca0e194 100644
--- a/web/modules/better_exposed_filters/tests/modules/bef_test/bef_test.info.yml
+++ b/web/modules/better_exposed_filters/tests/modules/bef_test/bef_test.info.yml
@@ -10,7 +10,7 @@ dependencies:
   - drupal:options
   - drupal:user
 
-# Information added by Drupal.org packaging script on 2021-07-07
-version: '8.x-5.0-beta3'
+# Information added by Drupal.org packaging script on 2021-10-20
+version: '8.x-5.0'
 project: 'better_exposed_filters'
-datestamp: 1625665749
+datestamp: 1634748725
diff --git a/web/modules/captcha/README.md b/web/modules/captcha/README.md
index 61f7cf830174705025069131be0fe5ab6961143e..771e737a4b92f7c5e317ac476e5ed4d1e5186932 100755
--- a/web/modules/captcha/README.md
+++ b/web/modules/captcha/README.md
@@ -83,3 +83,9 @@ MAINTAINERS
 Supporting organizations:
 
  * Chuva Inc. - https://www.drupal.org/chuva-inc
+
+DEVELOPMENT
+-------------
+  You can disable captcha in your local or test environment by adding the
+  following line to settings.php:
+  $settings['disable_captcha'] = TRUE;
diff --git a/web/modules/captcha/captcha.inc b/web/modules/captcha/captcha.inc
index b1fa2379aad8288d498ec8a65883c680ca591729..f390faadd1af805de8514e5d28a0b32de919b8e8 100755
--- a/web/modules/captcha/captcha.inc
+++ b/web/modules/captcha/captcha.inc
@@ -178,6 +178,20 @@ function _captcha_get_description() {
   return Xss::filter($description);
 }
 
+/**
+ * Gets the error message for when a user enters an incorrect CAPTCHA answer.
+ *
+ * @return string
+ *   Error message.
+ */
+function _captcha_get_error_message() {
+  $error_message = \Drupal::config('captcha.settings')->get('wrong_captcha_response_message');
+  if ($error_message) {
+    return Xss::filter($error_message);
+  }
+  return t('The answer you entered for the CAPTCHA was not correct.');
+}
+
 /**
  * Parse or interpret the given captcha_type.
  *
diff --git a/web/modules/captcha/captcha.info.yml b/web/modules/captcha/captcha.info.yml
index 5fd7cf593af9f3c6cd7e31c6b7c8ca8f6fe5d734..d197d084a64552cd5d288c61caf3ca753c375b6d 100644
--- a/web/modules/captcha/captcha.info.yml
+++ b/web/modules/captcha/captcha.info.yml
@@ -8,7 +8,7 @@ configure: captcha_settings
 dependencies:
   - drupal:node
 
-# Information added by Drupal.org packaging script on 2020-06-03
-version: '8.x-1.1'
+# Information added by Drupal.org packaging script on 2021-04-29
+version: '8.x-1.2'
 project: 'captcha'
-datestamp: 1591160979
+datestamp: 1619673377
diff --git a/web/modules/captcha/captcha.module b/web/modules/captcha/captcha.module
index 8174a923629860057980e5bb5d06dd11f6ab2c1a..0b298252c83874696a926187effae4bb26dabb03 100755
--- a/web/modules/captcha/captcha.module
+++ b/web/modules/captcha/captcha.module
@@ -19,6 +19,7 @@
 use Drupal\Core\Render\Markup;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Url;
+use Drupal\Core\Site\Settings;
 
 /**
  * Constants for CAPTCHA persistence.
@@ -288,6 +289,22 @@ function captcha_form_alter(array &$form, FormStateInterface $form_state, $form_
       '#markup' => '<div class="messages messages--warning">' . t('Most CAPTCHA methods will disable the caching of pages that contain a CAPTCHA element. Check the different implementations to know more about how it affects caching.') . '</div>',
     ];
   }
+
+  // Disable captcha if override is set.
+  if (Settings::get('disable_captcha', FALSE) === TRUE) {
+    $override_notice = [
+      '#type' => 'html_tag',
+      '#tag' => 'strong',
+      '#value' => t('Captcha is currently disabled via settings.php.'),
+    ];
+    if (isset($form['elements']['captcha'])) {
+      $form['elements']['captcha'] = $override_notice;
+    }
+    if (isset($form['captcha'])) {
+      $form['captcha'] = $override_notice;
+    }
+  }
+
 }
 
 /**
@@ -465,71 +482,34 @@ function captcha_validate($element, FormStateInterface &$form_state) {
   // TODO: is this correct in all cases: see comments in previous revisions?
   $csid = $captcha_info['captcha_sid'];
 
-  $solution = \Drupal::database()
-    ->select('captcha_sessions', 'cs')
-    ->fields('cs', ['solution'])
-    ->condition('csid', $csid)
-    ->execute()
-    ->fetchField();
-
   // Bypass captcha validation if access attribute value is false.
   if (empty($captcha_info['access'])) {
     return FALSE;
   }
 
-  // @todo: what is the result when there is no entry for
-  // the captcha_session? in D6 it was FALSE, what in D7?
-  if ($solution === FALSE) {
-    // Unknown challenge_id.
-    // TODO: this probably never happens anymore now that there is detection
-    // for CAPTCHA session reuse attacks in _captcha_get_posted_captcha_info().
-    $form_state->setErrorByName('captcha', t('CAPTCHA validation error: unknown CAPTCHA session ID. Contact the site administrator if this problem persists.'));
-    \Drupal::logger('CAPTCHA')->error(
-      'CAPTCHA validation error: unknown CAPTCHA session ID (%csid).',
-      ['%csid' => var_export($csid, TRUE)]);
-  }
-  else {
-    // Get CAPTCHA validate function or fall back on strict equality.
+  // If the form is cacheable where all solution validation is handed off or if
+  // we found a session with a solution then continue with validation.
+  $is_cacheable = (bool) $form_state->getValue('captcha_cacheable', FALSE);
+
+  if ($is_cacheable) {
+    // Completely ignore the captcha_sessions table,
+    // since the captcha_sid can get reused by the cache.
+    $solution = FALSE;
     $captcha_validate = $element['#captcha_validate'];
     if (!function_exists($captcha_validate)) {
-      $captcha_validate = 'captcha_validate_strict_equality';
+      // Cacheable CAPTCHAs must provide their own validation function.
+      $form_state->setErrorByName('captcha', t('CAPTCHA configuration error: Contact the site administrator.'));
+      \Drupal::logger('CAPTCHA')->error(
+        'CAPTCHA configuration error: cacheable CAPTCHA type %challenge did not provide a validation function.',
+        ['%challenge' => $captcha_info['captcha_type']]);
     }
     // Check the response with the CAPTCHA validation function.
     // Apart from the traditional expected $solution and received $response,
     // we also provide the CAPTCHA $element and $form_state
     // arrays for more advanced use cases.
-    if ($captcha_validate($solution, $captcha_response, $element, $form_state)) {
-
-      // Get the CAPTCHA persistence setting.
-      $captcha_persistence = \Drupal::config('captcha.settings')
-        ->get('persistence');
-
-      if (in_array($captcha_persistence,
-        [
-          CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL,
-          CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_TYPE,
-        ])) {
-        // Only save the success in $_SESSION if it is actually needed for
-        // further validation in _captcha_required_for_user(). Setting
-        // this kills the page cache so let's not be cavalier about it.
-        $_SESSION['captcha_success_form_ids'][$form_id] = $form_id;
-      }
-
-      // Record success.
-      \Drupal::database()->update('captcha_sessions')
-        ->condition('csid', $csid)
-        ->fields(['status' => CAPTCHA_STATUS_SOLVED])
-        ->expression('attempts', 'attempts + 1')
-        ->execute();
-    }
-    else {
+    if (!$captcha_validate($solution, $captcha_response, $element, $form_state)) {
       // Wrong answer.
-      \Drupal::database()->update('captcha_sessions')
-        ->condition('csid', $csid)
-        ->expression('attempts', 'attempts + 1')
-        ->execute();
-
-      $form_state->setErrorByName('captcha_response', t('The answer you entered for the CAPTCHA was not correct.'));
+      $form_state->setErrorByName('captcha_response', _captcha_get_error_message());
       // Update wrong response counter.
       if (\Drupal::config('captcha.settings')->get('enable_stats', FALSE)) {
         Drupal::state()->set('captcha.wrong_response_counter', Drupal::state()
@@ -540,17 +520,97 @@ function captcha_validate($element, FormStateInterface &$form_state) {
         ->get('log_wrong_responses', FALSE)
       ) {
         \Drupal::logger('CAPTCHA')->notice(
-          '%form_id post blocked by CAPTCHA module: challenge %challenge (by module %module), user answered "@response", but the solution was "@solution".',
+          '%form_id post blocked by CAPTCHA module: challenge %challenge (by module %module).',
           [
             '%form_id' => $form_id,
-            '@response' => $captcha_response,
-            '@solution' => $solution,
             '%challenge' => $captcha_info['captcha_type'],
             '%module' => $captcha_info['module'],
           ]);
       }
     }
   }
+  else {
+    $solution = \Drupal::database()
+      ->select('captcha_sessions', 'cs')
+      ->fields('cs', ['solution'])
+      ->condition('csid', $csid)
+      ->execute()
+      ->fetchField();
+
+    if ($solution !== FALSE) {
+      // Get CAPTCHA validate function or fall back on strict equality.
+      $captcha_validate = $element['#captcha_validate'];
+      if (!function_exists($captcha_validate)) {
+        $captcha_validate = 'captcha_validate_strict_equality';
+      }
+      // Check the response with the CAPTCHA validation function.
+      // Apart from the traditional expected $solution and received $response,
+      // we also provide the CAPTCHA $element and $form_state
+      // arrays for more advanced use cases.
+      if ($captcha_validate($solution, $captcha_response, $element, $form_state)) {
+
+        // Get the CAPTCHA persistence setting.
+        $captcha_persistence = \Drupal::config('captcha.settings')
+          ->get('persistence');
+
+        if (in_array($captcha_persistence,
+          [
+            CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL,
+            CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_TYPE,
+          ])) {
+          // Only save the success in $_SESSION if it is actually needed for
+          // further validation in _captcha_required_for_user(). Setting
+          // this kills the page cache so let's not be cavalier about it.
+          $_SESSION['captcha_success_form_ids'][$form_id] = $form_id;
+        }
+
+        // Record success.
+        \Drupal::database()->update('captcha_sessions')
+          ->condition('csid', $csid)
+          ->fields(['status' => CAPTCHA_STATUS_SOLVED])
+          ->expression('attempts', 'attempts + 1')
+          ->execute();
+      }
+      else {
+        // Wrong answer.
+        \Drupal::database()->update('captcha_sessions')
+          ->condition('csid', $csid)
+          ->expression('attempts', 'attempts + 1')
+          ->execute();
+
+        $form_state->setErrorByName('captcha_response', _captcha_get_error_message());
+        // Update wrong response counter.
+        if (\Drupal::config('captcha.settings')->get('enable_stats', FALSE)) {
+          Drupal::state()->set('captcha.wrong_response_counter', Drupal::state()
+            ->get('captcha.wrong_response_counter', 0) + 1);
+        }
+
+        if (\Drupal::config('captcha.settings')
+          ->get('log_wrong_responses', FALSE)
+        ) {
+          \Drupal::logger('CAPTCHA')->notice(
+            '%form_id post blocked by CAPTCHA module: challenge %challenge (by module %module), user answered "@response", but the solution was "@solution".',
+            [
+              '%form_id' => $form_id,
+              '@response' => $captcha_response,
+              '@solution' => $solution,
+              '%challenge' => $captcha_info['captcha_type'],
+              '%module' => $captcha_info['module'],
+            ]);
+        }
+      }
+    }
+    else {
+      // If the session is gone and we can't confirm a solution error.
+      // Note: _captcha_get_posted_captcha_info() validates and triggers session
+      // rebuilds for re-use attacks during element processing so this should be
+      // rare if it ever happens.
+      $form_state->setErrorByName('captcha', t('CAPTCHA validation error: unknown CAPTCHA session ID. Contact the site administrator if this problem persists.'));
+      \Drupal::logger('CAPTCHA')->error(
+        'CAPTCHA validation error: unknown CAPTCHA session ID (%csid).',
+        ['%csid' => var_export($csid, TRUE)]);
+    }
+  }
 }
 
 /**
diff --git a/web/modules/captcha/config/schema/captcha.settings.yml b/web/modules/captcha/config/schema/captcha.settings.yml
index b91cb03a54ba2d7a8074849e81102c8aa316359a..483148a24f63145ae4c9e1f52ee0435e9d8eef3c 100755
--- a/web/modules/captcha/config/schema/captcha.settings.yml
+++ b/web/modules/captcha/config/schema/captcha.settings.yml
@@ -23,6 +23,9 @@ captcha.settings:
     add_captcha_description:
       type: boolean
       label: 'Add a description to the CAPTCHA'
+    wrong_captcha_response_message:
+      type: label
+      label: 'The error message when a user has entered an incorrect CAPTCHA answer.'
     default_validation:
       type: integer
       label: 'Default CAPTCHA validation'
diff --git a/web/modules/captcha/image_captcha/image_captcha.info.yml b/web/modules/captcha/image_captcha/image_captcha.info.yml
index a1d5195a7f19c2c396c9f90f968d4d0dce9d73bb..859edd894245c9c566b86b1e616524b4fa5c3f80 100644
--- a/web/modules/captcha/image_captcha/image_captcha.info.yml
+++ b/web/modules/captcha/image_captcha/image_captcha.info.yml
@@ -4,10 +4,10 @@ description: Provides an image based CAPTCHA.
 package: Spam control
 core_version_requirement: ^8.8 || ^9
 dependencies:
-  - captcha
+  - captcha:captcha
 configure: admin/config/people/captcha/image_captcha
 
-# Information added by Drupal.org packaging script on 2020-06-03
-version: '8.x-1.1'
+# Information added by Drupal.org packaging script on 2021-04-29
+version: '8.x-1.2'
 project: 'captcha'
-datestamp: 1591160979
+datestamp: 1619673377
diff --git a/web/modules/captcha/image_captcha/image_captcha.install b/web/modules/captcha/image_captcha/image_captcha.install
index 003f2246971d6055abe63895756d9ce018c6ef11..913fbef32935b2ee95bcc74487071cad50d30e42 100755
--- a/web/modules/captcha/image_captcha/image_captcha.install
+++ b/web/modules/captcha/image_captcha/image_captcha.install
@@ -38,7 +38,7 @@ function image_captcha_install() {
   $config = \Drupal::configFactory()->getEditable('image_captcha.settings');
 
   $config->set('image_captcha_fonts', [
-    drupal_get_path('module', 'image_captcha') . '/fonts/Tesox/tesox.ttf',
-    drupal_get_path('module', 'image_captcha') . '/fonts/Tuffy/Tuffy.ttf',
+    hash('sha256', drupal_get_path('module', 'image_captcha') . '/fonts/Tesox/tesox.ttf'),
+    hash('sha256', drupal_get_path('module', 'image_captcha') . '/fonts/Tuffy/Tuffy.ttf'),
   ])->save(TRUE);
 }
diff --git a/web/modules/captcha/image_captcha/image_captcha.libraries.yml b/web/modules/captcha/image_captcha/image_captcha.libraries.yml
index 4f37b86f0d43b3a44ee5db62227bdffcae855704..b9b8de2bc8533349889efc9f60a42837198bce47 100755
--- a/web/modules/captcha/image_captcha/image_captcha.libraries.yml
+++ b/web/modules/captcha/image_captcha/image_captcha.libraries.yml
@@ -15,3 +15,6 @@ image-captcha-refresh:
   version: 1.0
   js:
     js/image_captcha_refresh.js: {}
+  css:
+    theme:
+      image_captcha_refresh.css: {}
diff --git a/web/modules/captcha/image_captcha/image_captcha.links.menu.yml b/web/modules/captcha/image_captcha/image_captcha.links.menu.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b2f3731dcc8b3d935e22d693e4fd334a8121e4dc
--- /dev/null
+++ b/web/modules/captcha/image_captcha/image_captcha.links.menu.yml
@@ -0,0 +1,6 @@
+image_captcha.settings:
+  title: 'Image Captcha'
+  route_name: image_captcha.settings
+  description: 'Configure Image Captcha Settings.'
+  parent: captcha.settings
+  weight: -1
diff --git a/web/modules/captcha/image_captcha/image_captcha.links.task.yml b/web/modules/captcha/image_captcha/image_captcha.links.task.yml
new file mode 100644
index 0000000000000000000000000000000000000000..0e18abcbf4b2d619f406f7ac11d3e8bf8fbaf957
--- /dev/null
+++ b/web/modules/captcha/image_captcha/image_captcha.links.task.yml
@@ -0,0 +1,5 @@
+image_captcha.settings:
+  title: 'Image Captcha'
+  route_name: image_captcha.settings
+  base_route: captcha_settings
+  weight: -1
diff --git a/web/modules/captcha/image_captcha/image_captcha.module b/web/modules/captcha/image_captcha/image_captcha.module
index 8832ac80b6a656e9c3afa0edcf4db692e7e7adac..7ad3c1ad26322f60ef5696a929f242a0982debad 100755
--- a/web/modules/captcha/image_captcha/image_captcha.module
+++ b/web/modules/captcha/image_captcha/image_captcha.module
@@ -8,6 +8,7 @@
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Url;
 use Drupal\Core\Link;
+use Drupal\Core\DrupalKernel;
 
 define('IMAGE_CAPTCHA_ALLOWED_CHARACTERS', 'aAbBCdEeFfGHhijKLMmNPQRrSTtWXYZ23456789');
 
@@ -47,6 +48,61 @@ function _image_captcha_get_enabled_fonts() {
   }
 }
 
+/**
+ * Helper function to get font(s).
+ *
+ * @return string|array
+ *   URI of file hash or List of font paths.
+ */
+function _image_captcha_get_font_uri($token = NULL) {
+  $fonts = [
+    'BUILTIN' => 'BUILTIN',
+  ];
+  $available_fonts = _image_captcha_get_available_fonts_from_directories();
+  foreach ($available_fonts as $file_token => $font_info) {
+    $fonts[$file_token] = $font_info['uri'];
+  }
+  return ((!empty($token) && !empty($fonts[$token])) ? $fonts[$token] : $fonts);
+}
+
+/**
+ * Helper function to get fonts from the given directories.
+ *
+ * @param array|null $directories
+ *   (Optional) an array of directories
+ *   to recursively search through, if not given, the default
+ *   directories will be used.
+ *
+ * @return array
+ *   Fonts file objects (with fields 'name',
+ *   'basename' and 'filename'), keyed on the sha256 hash of the font
+ *   path (to have an easy token that can be used in an url
+ *   without en/decoding issues).
+ */
+function _image_captcha_get_available_fonts_from_directories($directories = NULL) {
+  // If no fonts directories are given: use the default.
+  if ($directories === NULL) {
+    $request = \Drupal::service('request_stack')->getCurrentRequest();
+    $directories = [
+      drupal_get_path('module', 'image_captcha') . '/fonts',
+      'sites/all/libraries/fonts',
+      DrupalKernel::findSitePath($request) . '/libraries/fonts',
+    ];
+  }
+  // Collect the font information.
+  $fonts = [];
+  foreach ($directories as $directory) {
+    if (\Drupal::service('file_system')->prepareDirectory($directory)) {
+      $files = \Drupal::service('file_system')->scanDirectory($directory, '/\.[tT][tT][fF]$/');
+      foreach ($files as $filename => $font) {
+        $fonts[hash('sha256', $filename)] = (array) $font;
+      }
+    }
+  }
+
+  return $fonts;
+}
+
 /**
  * Helper function for checking if the specified fonts are available.
  *
diff --git a/web/modules/captcha/image_captcha/image_captcha.routing.yml b/web/modules/captcha/image_captcha/image_captcha.routing.yml
index bd6c3ad8666663b6c586729e592c2abf79e5375f..e3d92a502eea1b192d88ac1ca5d7a7f7bc28f494 100755
--- a/web/modules/captcha/image_captcha/image_captcha.routing.yml
+++ b/web/modules/captcha/image_captcha/image_captcha.routing.yml
@@ -8,7 +8,7 @@ image_captcha.settings:
 image_captcha.font_preview:
   path: '/admin/config/people/captcha/image_captcha/font_preview/{token}'
   defaults:
-    _controller: '\Drupal\image_captcha\Controller\CaptchaFontPreview::content'
+    _controller: '\Drupal\image_captcha\Controller\CaptchaFontPreviewController::getFont'
   requirements:
     _permission: 'administer CAPTCHA settings'
 
diff --git a/web/modules/captcha/image_captcha/image_captcha_refresh.css b/web/modules/captcha/image_captcha/image_captcha_refresh.css
new file mode 100644
index 0000000000000000000000000000000000000000..325b1f3f7970e02400fb8e697be3e2df5d87cc3a
--- /dev/null
+++ b/web/modules/captcha/image_captcha/image_captcha_refresh.css
@@ -0,0 +1,38 @@
+.image_captcha_refresh_loader {
+  border: 5px solid #f3f3f3;
+  border-radius: 50%;
+  border-top: 5px solid #000;
+  width: 30px;
+  height: 30px;
+  -webkit-animation: image_captcha_refresh_spin 1s linear infinite;
+  animation: image_captcha_refresh_spin 1s linear infinite;
+  position: absolute;
+  left: 0;
+  right: 0;
+  margin: auto;
+  top: 0;
+  bottom: 0;
+}
+
+/* Safari */
+@-webkit-keyframes image_captcha_refresh_spin {
+  0% {
+    -webkit-transform: rotate(0deg);
+}
+  100% {
+    -webkit-transform: rotate(360deg);
+}
+}
+
+@keyframes image_captcha_refresh_spin {
+  0% {
+    transform: rotate(0deg);
+}
+  100% {
+    transform: rotate(360deg);
+}
+}
+
+.captcha {
+  position: relative;
+}
diff --git a/web/modules/captcha/image_captcha/js/image_captcha_refresh.js b/web/modules/captcha/image_captcha/js/image_captcha_refresh.js
index 457c58e7d1e1fba101c28e53b08bb43c53d0b616..807fa510ccf5269c982ebee83a9f92a9c3f4ae9a 100644
--- a/web/modules/captcha/image_captcha/js/image_captcha_refresh.js
+++ b/web/modules/captcha/image_captcha/js/image_captcha_refresh.js
@@ -24,6 +24,8 @@
         var date = new Date();
         var baseUrl = document.location.origin;
         var url = baseUrl + '/' + $(this).attr('href') + '?' + date.getTime();
+        // Adding loader.
+        $('.captcha').append('<div class="image_captcha_refresh_loader"></div>');
         $.get(
           url,
           {},
@@ -32,6 +34,7 @@
               $('.captcha', $form).find('img').attr('src', response.data.url);
               $('input[name=captcha_sid]', $form).val(response.data.sid);
               $('input[name=captcha_token]', $form).val(response.data.token);
+              $('.captcha .image_captcha_refresh_loader').remove();
             }
             else {
               alert(response.message);
diff --git a/web/modules/captcha/image_captcha/src/Controller/CaptchaFontPreviewController.php b/web/modules/captcha/image_captcha/src/Controller/CaptchaFontPreviewController.php
new file mode 100644
index 0000000000000000000000000000000000000000..ed405fcff968a4be2efec7ae3bf9c298b6e66ab7
--- /dev/null
+++ b/web/modules/captcha/image_captcha/src/Controller/CaptchaFontPreviewController.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace Drupal\image_captcha\Controller;
+
+use Drupal\Core\Config\ImmutableConfig;
+use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\image_captcha\StreamedResponse\CaptchaFontPreviewStreamedResponse;
+use Drupal\Core\PageCache\ResponsePolicy\KillSwitch;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Controller which generates the image from defined settings.
+ */
+class CaptchaFontPreviewController implements ContainerInjectionInterface {
+
+  /**
+   * Image Captcha config storage.
+   *
+   * @var \Drupal\Core\Config\ImmutableConfig
+   */
+  protected $config;
+
+  /**
+   * Kill Switch for page caching.
+   *
+   * @var \Drupal\Core\PageCache\ResponsePolicy\KillSwitch
+   */
+  protected $killSwitch;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(ImmutableConfig $config, KillSwitch $kill_switch) {
+    $this->config = $config;
+    $this->killSwitch = $kill_switch;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('config.factory')->get('image_captcha.settings'),
+      $container->get('page_cache_kill_switch')
+    );
+  }
+
+  /**
+   * Main method that throw ImageResponse object to generate image.
+   *
+   * @return \Drupal\image_captcha\StreamedResponse\CaptchaFontPreviewStreamedResponse
+   *   Make a CaptchaImageResponse with the correct configuration and return it.
+   */
+  public function getFont($token) {
+    $this->killSwitch->trigger();
+    return new CaptchaFontPreviewStreamedResponse($this->config, $token);
+  }
+
+}
diff --git a/web/modules/captcha/image_captcha/src/Controller/CaptchaImageGeneratorController.php b/web/modules/captcha/image_captcha/src/Controller/CaptchaImageGeneratorController.php
index 49bef40e6094ada5a9b72b026b3adbc168c37a2f..241f2f444245b95811f5a86bd535dd02c55c45c5 100644
--- a/web/modules/captcha/image_captcha/src/Controller/CaptchaImageGeneratorController.php
+++ b/web/modules/captcha/image_captcha/src/Controller/CaptchaImageGeneratorController.php
@@ -3,6 +3,8 @@
 namespace Drupal\image_captcha\Controller;
 
 use Drupal\Core\Config\Config;
+use Drupal\Core\Database\Connection;
+use Drupal\Core\File\FileSystemInterface;
 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
 use Psr\Log\LoggerInterface;
 use Drupal\Core\PageCache\ResponsePolicy\KillSwitch;
@@ -14,6 +16,13 @@
  */
 class CaptchaImageGeneratorController implements ContainerInjectionInterface {
 
+  /**
+   * Connection container.
+   *
+   * @var \Drupal\Core\Database\Connection
+   */
+  protected $connection;
+
   /**
    * Image Captcha config storage.
    *
@@ -21,6 +30,13 @@ class CaptchaImageGeneratorController implements ContainerInjectionInterface {
    */
   protected $config;
 
+  /**
+   * File System Service.
+   *
+   * @var \Drupal\Core\File\FileSystemInterface
+   */
+  protected $fileSystem;
+
   /**
    * Watchdog logger channel for captcha.
    *
@@ -38,10 +54,12 @@ class CaptchaImageGeneratorController implements ContainerInjectionInterface {
   /**
    * {@inheritdoc}
    */
-  public function __construct(Config $config, LoggerInterface $logger, KillSwitch $kill_switch) {
+  public function __construct(Config $config, LoggerInterface $logger, KillSwitch $kill_switch, Connection $connection, FileSystemInterface $file_system) {
     $this->config = $config;
     $this->logger = $logger;
     $this->killSwitch = $kill_switch;
+    $this->connection = $connection;
+    $this->fileSystem = $file_system;
   }
 
   /**
@@ -51,7 +69,9 @@ public static function create(ContainerInterface $container) {
     return new static(
       $container->get('config.factory')->get('image_captcha.settings'),
       $container->get('logger.factory')->get('captcha'),
-      $container->get('page_cache_kill_switch')
+      $container->get('page_cache_kill_switch'),
+      $container->get('database'),
+      $container->get('file_system')
     );
   }
 
@@ -63,7 +83,7 @@ public static function create(ContainerInterface $container) {
    */
   public function image() {
     $this->killSwitch->trigger();
-    return new CaptchaImageResponse($this->config, $this->logger);
+    return new CaptchaImageResponse($this->config, $this->logger, $this->connection, $this->fileSystem);
   }
 
 }
diff --git a/web/modules/captcha/image_captcha/src/Form/ImageCaptchaSettingsForm.php b/web/modules/captcha/image_captcha/src/Form/ImageCaptchaSettingsForm.php
index 130ecf2aea6044174282459f8515afbda678a0a6..d56f0ce7cc66360f3fde0fcbc9d7e3ea2d0801ce 100755
--- a/web/modules/captcha/image_captcha/src/Form/ImageCaptchaSettingsForm.php
+++ b/web/modules/captcha/image_captcha/src/Form/ImageCaptchaSettingsForm.php
@@ -79,7 +79,7 @@ protected function getEditableConfigNames() {
   public function buildForm(array $form, FormStateInterface $form_state) {
     $config = $this->config('image_captcha.settings');
     // Add CSS and JS for theming and added usability on admin form.
-    $form['#attached']['library'][] = 'captcha_image/base';
+    $form['#attached']['library'][] = 'image_captcha/base';
 
     // First some error checking.
     $setup_status = _image_captcha_check_setup(FALSE);
@@ -274,6 +274,10 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
       }
 
       $readable_fonts = [];
+      $available_fonts = _image_captcha_get_font_uri();
+      foreach ($fonts as $token) {
+        $fonts[$token] = $available_fonts[$token];
+      }
       list($readable_fonts, $problem_fonts) = _image_captcha_check_fonts($fonts);
       if (count($problem_fonts) > 0) {
         $form_state->setErrorByName('image_captcha_fonts', $this->t('The following fonts are not readable: %fonts.', ['%fonts' => implode(', ', $problem_fonts)]));
@@ -295,13 +299,21 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
    * {@inheritdoc}
    */
   public function submitForm(array &$form, FormStateInterface $form_state) {
+    $imageSettings = $form_state->cleanValues()->getValues();
     if (!isset($form['image_captcha_font_settings']['no_ttf_support'])) {
       // Filter the image_captcha fonts array to pick out the selected ones.
-      $fonts = array_filter($form_state->getValue('image_captcha_fonts'));
-      $this->config('image_captcha.settings')
-        ->set('image_captcha_fonts', $fonts)
-        ->save();
+      $image_captcha_fonts = $form_state->getValue('image_captcha_fonts');
+      $imageSettings['image_captcha_fonts'] = array_filter($imageSettings['image_captcha_fonts']);
+    }
+    $config = $this->config('image_captcha.settings');
+    // Exclude few fields from config.
+    $exclude = ['image', 'captcha_sid', 'captcha_token', 'captcha_response'];
+    foreach ($imageSettings as $configName => $configValue) {
+      if (!in_array($configName, $exclude)) {
+        $config->set($configName, $configValue);
+      }
     }
+    $config->save();
 
     parent::SubmitForm($form, $form_state);
   }
@@ -339,7 +351,7 @@ protected function settingsDotSection() {
       $available_fonts = [];
 
       // List of folders to search through for TrueType fonts.
-      $fonts = $this->getAvailableFontsFromDirectories();
+      $fonts = _image_captcha_get_available_fonts_from_directories();
       // Cache the list of previewable fonts. All the previews are done
       // in separate requests, and we don't want to rescan the filesystem
       // every time, so we cache the result.
@@ -358,20 +370,16 @@ protected function settingsDotSection() {
           'title' => $title,
           'alt' => $title,
         ];
-        $available_fonts[$font['uri']] = '<img' . new Attribute($attributes) . ' />';
+        $available_fonts[$token] = '<img' . new Attribute($attributes) . ' />';
       }
 
       // Append the PHP built-in font at the end.
       $title = $this->t('Preview of built-in font');
-      $attributes = [
-        'src' => Url::fromRoute('image_captcha.font_preview', ['token' => 'BUILTIN'])
+      $available_fonts['BUILTIN'] = $this->t('PHP built-in font: <img src="@font_preview_url" alt="@title" title="@title"', [
+        '@font_preview_url' => Url::fromRoute('image_captcha.font_preview', ['token' => 'BUILTIN'])
           ->toString(),
-        'alt' => $title,
-        'title' => $title,
-      ];
-      $available_fonts['BUILTIN'] = (string) $this->t('PHP built-in font: font_preview', [
-        'font_preview' => '<img' . new Attribute($attributes) . ' />',
-      ]);
+        '@title' => $title,
+      ])->__toString();
 
       $default_fonts = _image_captcha_get_enabled_fonts();
       $conf_path = DrupalKernel::findSitePath($this->getRequest());
@@ -426,38 +434,4 @@ protected function settingsDotSection() {
     return $form;
   }
 
-  /**
-   * Helper function to get fonts from the given directories.
-   *
-   * @param array|null $directories
-   *   (Optional) an array of directories
-   *   to recursively search through, if not given, the default
-   *   directories will be used.
-   *
-   * @return array
-   *   Fonts file objects (with fields 'name',
-   *   'basename' and 'filename'), keyed on the sha256 hash of the font
-   *   path (to have an easy token that can be used in an url
-   *   without en/decoding issues).
-   */
-  protected function getAvailableFontsFromDirectories($directories = NULL) {
-    // If no fonts directories are given: use the default.
-    if ($directories === NULL) {
-      $directories = [
-        drupal_get_path('module', 'image_captcha') . '/fonts',
-        'sites/all/libraries/fonts',
-        DrupalKernel::findSitePath($this->getRequest()) . '/libraries/fonts',
-      ];
-    }
-    // Collect the font information.
-    $fonts = [];
-    foreach ($directories as $directory) {
-      foreach ($this->fileSystem->scanDirectory($directory, '/\.[tT][tT][fF]$/') as $filename => $font) {
-        $fonts[hash('sha256', $filename)] = $font;
-      }
-    }
-
-    return $fonts;
-  }
-
 }
diff --git a/web/modules/captcha/image_captcha/src/Response/CaptchaImageResponse.php b/web/modules/captcha/image_captcha/src/Response/CaptchaImageResponse.php
index 6f441069822ac293b7476ec03d786c6fb2320e2a..8668954dc06a679e68f8594749326ea1473864ce 100755
--- a/web/modules/captcha/image_captcha/src/Response/CaptchaImageResponse.php
+++ b/web/modules/captcha/image_captcha/src/Response/CaptchaImageResponse.php
@@ -3,6 +3,8 @@
 namespace Drupal\image_captcha\Response;
 
 use Drupal\Core\Config\Config;
+use Drupal\Core\Database\Connection;
+use Drupal\Core\File\FileSystemInterface;
 use Psr\Log\LoggerInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
@@ -16,6 +18,13 @@ class CaptchaImageResponse extends Response {
 
   const LOG_LEVEL = 'ERROR';
 
+  /**
+   * Database connection configuration container.
+   *
+   * @var \Drupal\Core\Database\Connection
+   */
+  protected $connection;
+
   /**
    * Image Captcha config storage.
    *
@@ -23,6 +32,13 @@ class CaptchaImageResponse extends Response {
    */
   protected $config;
 
+  /**
+   * File System container.
+   *
+   * @var \Drupal\Core\File\FileSystemInterface
+   */
+  protected $fileSystem;
+
   /**
    * Watchdog logger channel for captcha.
    *
@@ -40,11 +56,13 @@ class CaptchaImageResponse extends Response {
   /**
    * {@inheritdoc}
    */
-  public function __construct(Config $config, LoggerInterface $logger, $callback = NULL, $status = 200, $headers = []) {
+  public function __construct(Config $config, LoggerInterface $logger, Connection $connection, FileSystemInterface $fileSystem, $callback = NULL, $status = 200, $headers = []) {
     parent::__construct(NULL, $status, $headers);
 
     $this->config = $config;
     $this->logger = $logger;
+    $this->connection = $connection;
+    $this->fileSystem = $fileSystem;
   }
 
   /**
@@ -53,7 +71,7 @@ public function __construct(Config $config, LoggerInterface $logger, $callback =
   public function prepare(Request $request) {
     $session_id = $request->get('session_id');
 
-    $code = \Drupal::database()
+    $code = $this->connection
       ->select('captcha_sessions', 'cs')
       ->fields('cs', ['solution'])
       ->condition('csid', $session_id)
@@ -371,11 +389,12 @@ protected function printString(&$image, $width, $height, array $fonts, $font_siz
 
       // Pick a random font from the list.
       $font = $fonts[array_rand($fonts)];
+      $font = _image_captcha_get_font_uri($font);
 
       // Get character dimensions for TrueType fonts.
       if ($font != 'BUILTIN') {
         putenv('GDFONTPATH=' . realpath('.'));
-        $bbox = imagettfbbox($font_size, 0, \Drupal::service('file_system')->realpath($font), $character);
+        $bbox = imagettfbbox($font_size, 0, $this->fileSystem->realpath($font), $character);
         // In very rare cases with some versions of the GD library, the x-value
         // of the left side of the bounding box as returned by the first call of
         // imagettfbbox is corrupt (value -2147483648 = 0x80000000).
@@ -383,7 +402,7 @@ protected function printString(&$image, $width, $height, array $fonts, $font_siz
         // can be used as workaround.
         // This issue is discussed at http://drupal.org/node/349218.
         if ($bbox[2] < 0) {
-          $bbox = imagettfbbox($font_size, 0, \Drupal::service('file_system')->realpath($font), $character);
+          $bbox = imagettfbbox($font_size, 0, $this->fileSystem->realpath($font), $character);
         }
       }
       else {
@@ -402,7 +421,7 @@ protected function printString(&$image, $width, $height, array $fonts, $font_siz
       }
 
       // Random (but small) rotation of the character.
-      // TODO: add a setting for this?
+      // @todo add a setting for this?
       $angle = mt_rand(-10, 10);
 
       // Determine print position: at what coordinate should the character be
@@ -439,7 +458,7 @@ protected function printString(&$image, $width, $height, array $fonts, $font_siz
         imagestring($image, 5, $pos_x, $pos_y, $character, $color);
       }
       else {
-        imagettftext($image, $font_size, $angle, $pos_x, $pos_y, $color, \Drupal::service('file_system')->realpath($font), $character);
+        imagettftext($image, $font_size, $angle, $pos_x, $pos_y, $color, $this->fileSystem->realpath($font), $character);
       }
     }
 
diff --git a/web/modules/captcha/image_captcha/src/Controller/CaptchaFontPreview.php b/web/modules/captcha/image_captcha/src/StreamedResponse/CaptchaFontPreviewStreamedResponse.php
similarity index 60%
rename from web/modules/captcha/image_captcha/src/Controller/CaptchaFontPreview.php
rename to web/modules/captcha/image_captcha/src/StreamedResponse/CaptchaFontPreviewStreamedResponse.php
index c843153f3173f6901ba17dd85efbea7d28c712db..a5dbac3bdd41d2ef7c9e2af6427f6799d3a1adcf 100755
--- a/web/modules/captcha/image_captcha/src/Controller/CaptchaFontPreview.php
+++ b/web/modules/captcha/image_captcha/src/StreamedResponse/CaptchaFontPreviewStreamedResponse.php
@@ -1,38 +1,58 @@
 <?php
 
-namespace Drupal\image_captcha\Controller;
+namespace Drupal\image_captcha\StreamedResponse;
 
-use Symfony\Component\HttpFoundation\Request;
+use Drupal\Core\Config\ImmutableConfig;
 use Symfony\Component\HttpFoundation\StreamedResponse;
 
 /**
  * A Controller to preview the captcha font on the settings page.
  */
-class CaptchaFontPreview extends StreamedResponse {
+class CaptchaFontPreviewStreamedResponse extends StreamedResponse {
+
+  /**
+   * Config service.
+   *
+   * @var \Drupal\Core\Config\ImmutableConfig
+   */
+  protected $config;
+
+  /**
+   * Token font selector.
+   *
+   * @string
+   */
+  protected $token;
 
   /**
    * {@inheritdoc}
    */
-  public function content(Request $request) {
-    $token = $request->get('token');
+  public function __construct(ImmutableConfig $config, $token, $callback = NULL, $status = 200, $headers = []) {
+    parent::__construct(NULL, $status, $headers);
+
+    $this->config = $config;
+    $this->token = $token;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function sendContent() {
     // Get the font from the given font token.
-    if ($token == 'BUILTIN') {
+    if ($this->token == 'BUILTIN') {
       $font = 'BUILTIN';
     }
     else {
       // Get the mapping of font tokens to font file objects.
-      $fonts = \Drupal::config('image_captcha.settings')
-        ->get('image_captcha_fonts_preview_map_cache');
-      if (!isset($fonts[$token])) {
-        echo 'bad token';
-        exit();
+      $fonts = $this->config->get('image_captcha_fonts_preview_map_cache');
+      if (!isset($fonts[$this->token])) {
+        return 'bad token';
       }
       // Get the font path.
-      $font = $fonts[$token]['uri'];
+      $font = $fonts[$this->token]['uri'];
       // Some sanity checks if the given font is valid.
       if (!is_file($font) || !is_readable($font)) {
-        echo 'bad font';
-        exit();
+        return 'bad font';
       }
     }
 
@@ -45,7 +65,7 @@ public function content(Request $request) {
     // Allocate image resource.
     $image = imagecreatetruecolor($width, $height);
     if (!$image) {
-      exit();
+      return NULL;
     }
     // White background and black foreground.
     $background_color = imagecolorallocate($image, 255, 255, 255);
@@ -65,9 +85,6 @@ public function content(Request $request) {
     imagepng($image);
     // Release image memory.
     imagedestroy($image);
-
-    // Close connection.
-    exit();
   }
 
 }
diff --git a/web/modules/captcha/migrations/d7_captcha_points.yml b/web/modules/captcha/migrations/d7_captcha_points.yml
new file mode 100644
index 0000000000000000000000000000000000000000..74d1cffdcbce1e9dd790805d5d158c97ea2c0a41
--- /dev/null
+++ b/web/modules/captcha/migrations/d7_captcha_points.yml
@@ -0,0 +1,18 @@
+id: d7_captcha_points
+label: 'Captcha Points Table'
+migration_tags:
+  - Drupal 7
+  - Configuration
+source:
+  plugin: d7_captcha_points
+process:
+  formId: form_id
+  label: form_id
+  captchaType:
+    plugin: captcha_type_formatter
+    source: captcha_type
+  status:
+    plugin: default_value
+    default_value: TRUE
+destination:
+  plugin: entity:captcha_point
\ No newline at end of file
diff --git a/web/modules/captcha/migrations/d7_captcha_settings.yml b/web/modules/captcha/migrations/d7_captcha_settings.yml
new file mode 100644
index 0000000000000000000000000000000000000000..5e37885928ba87a8b3acaf0d819b9f2acad42c5d
--- /dev/null
+++ b/web/modules/captcha/migrations/d7_captcha_settings.yml
@@ -0,0 +1,36 @@
+id: d7_captcha_settings
+label: 'Captcha Settings'
+migration_tags:
+  - Drupal 7
+  - Configuration
+source:
+  plugin: variable
+  variables:
+    - captcha_add_captcha_description
+    - captcha_administration_mode
+    - captcha_allow_on_admin_pages
+    - captcha_default_challenge
+    - captcha_default_challenge_on_nonlisted_forms
+    - captcha_default_validation
+    - captcha_description
+    - captcha_enable_stats
+    - captcha_error_message
+    - captcha_log_wrong_responses
+    - captcha_persistence
+    - captcha_placement_map_cache
+  source_module:
+    - captcha
+process:
+  enabled_default: captcha_default_challenge_on_nonlisted_forms
+  default_challenge: captcha_default_challenge
+  description: captcha_description
+  administration_mode: captcha_administration_mode
+  allow_on_admin_pages: captcha_allow_on_admin_pages
+  add_captcha_description: captcha_add_captcha_description
+  default_validation: captcha_default_validation
+  persistence: captcha_persistence
+  enable_stats: captcha_enable_stats
+  log_wrong_responses: captcha_log_wrong_responses
+destination:
+  plugin: config
+  config_name: captcha.settings
diff --git a/web/modules/captcha/modules/captcha_long_form_id_test/captcha_long_form_id_test.info.yml b/web/modules/captcha/modules/captcha_long_form_id_test/captcha_long_form_id_test.info.yml
index cf5b8d5668b934bca4dd3f5a139feb6e48acde6f..6d6bce9f86c82cb9f17ab4b39a02a73c9a6224e6 100644
--- a/web/modules/captcha/modules/captcha_long_form_id_test/captcha_long_form_id_test.info.yml
+++ b/web/modules/captcha/modules/captcha_long_form_id_test/captcha_long_form_id_test.info.yml
@@ -5,7 +5,7 @@ package: Testing
 core_version_requirement: ^8.8 || ^9
 hidden: true
 
-# Information added by Drupal.org packaging script on 2020-06-03
-version: '8.x-1.1'
+# Information added by Drupal.org packaging script on 2021-04-29
+version: '8.x-1.2'
 project: 'captcha'
-datestamp: 1591160979
+datestamp: 1619673377
diff --git a/web/modules/captcha/modules/captcha_test/captcha_test.info.yml b/web/modules/captcha/modules/captcha_test/captcha_test.info.yml
new file mode 100644
index 0000000000000000000000000000000000000000..df735cfe5e41889bc6ae7b578b2244fc1808d0f4
--- /dev/null
+++ b/web/modules/captcha/modules/captcha_test/captcha_test.info.yml
@@ -0,0 +1,11 @@
+name: 'Captcha Test'
+type: module
+description: 'Provides captcha types for tests.'
+package: Testing
+core_version_requirement: ^8.8 || ^9
+hidden: true
+
+# Information added by Drupal.org packaging script on 2021-04-29
+version: '8.x-1.2'
+project: 'captcha'
+datestamp: 1619673377
diff --git a/web/modules/captcha/modules/captcha_test/captcha_test.module b/web/modules/captcha/modules/captcha_test/captcha_test.module
new file mode 100644
index 0000000000000000000000000000000000000000..97d976847ec15b3a67afca1d4921b2d113779233
--- /dev/null
+++ b/web/modules/captcha/modules/captcha_test/captcha_test.module
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * @file
+ * Contains hook implementations for the Captcha Test module.
+ */
+
+/**
+ * Implements hook_captcha().
+ */
+function captcha_test_captcha($op, $captcha_type = '') {
+  switch ($op) {
+    case 'list':
+      return [];
+
+    case 'generate':
+      if ($captcha_type === 'TestCacheable') {
+        // A cacheable Captcha type.
+        $result = [
+          'cacheable' => TRUE,
+          // Cacheable captcha types need to provide a custom validation
+          // callback that doesn't care about the solution, because a form can
+          // be shown containing a cached CSID that has since been deleted
+          // from the {captcha_sessions} table.
+          'captcha_validate' => 'captcha_test_captcha_captcha_validation',
+          'solution' => 'Test 123',
+          'form' => [],
+        ];
+        $result['form']['captcha_response'] = [
+          '#type' => 'textfield',
+          '#title' => t('Test one two three'),
+          '#required' => TRUE,
+        ];
+
+        return $result;
+      }
+  }
+}
+
+/**
+ * Validation callback.
+ */
+function captcha_test_captcha_captcha_validation() {
+  return TRUE;
+}
diff --git a/web/modules/captcha/src/Element/Captcha.php b/web/modules/captcha/src/Element/Captcha.php
index 51c5dcd7690ce6c8808f5a47b62646ebfe6c6cd1..9fd2c04b01db40ba75b57755ba2a8bdbc97a410b 100644
--- a/web/modules/captcha/src/Element/Captcha.php
+++ b/web/modules/captcha/src/Element/Captcha.php
@@ -101,7 +101,7 @@ public static function processCaptchaElement(&$element, FormStateInterface $form
     // Get the form ID of the form we are currently processing (which is not
     // necessary the same form that is submitted (if any).
     $this_form_id = isset($complete_form['form_id']['#value']) ?
-      preg_replace("/[^a-z0-9_]/", "", (string) $complete_form['form_id']['#value'])
+      preg_replace("/[^a-z0-9_-]/", "", (string) $complete_form['form_id']['#value'])
       : NULL;
 
     // Get the CAPTCHA session ID.
diff --git a/web/modules/captcha/src/Form/CaptchaSettingsForm.php b/web/modules/captcha/src/Form/CaptchaSettingsForm.php
index 36072f148e8f1b1008bf241e931aca034aee758f..32db4377a0d4794810f5fb1811cda73295251941 100755
--- a/web/modules/captcha/src/Form/CaptchaSettingsForm.php
+++ b/web/modules/captcha/src/Form/CaptchaSettingsForm.php
@@ -164,6 +164,16 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       ],
     ];
 
+    // Field for the wrong captcha response error message.
+    $form['wrong_captcha_response_message'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Wrong CAPTCHA response error message'),
+      '#description' => $this->t('Configurable error message that the user gets when it enters an incorrect CAPTCHA answer.'),
+      '#default_value' => _captcha_get_error_message(),
+      '#maxlength' => 256,
+      '#required' => TRUE,
+    ];
+
     // Option for case sensitive/insensitive validation of the responses.
     $form['default_validation'] = [
       '#type' => 'radios',
@@ -241,6 +251,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
     // Save (or reset) the CAPTCHA descriptions.
     $config->set('description', $form_state->getValue('description'));
 
+    $config->set('wrong_captcha_response_message', $form_state->getValue('wrong_captcha_response_message'));
     $config->set('default_validation', $form_state->getValue('default_validation'));
     $config->set('persistence', $form_state->getValue('persistence'));
     $config->set('enable_stats', $form_state->getValue('enable_stats'));
@@ -256,7 +267,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
    *
    * @param array $form
    *   Form structured array.
-   * @param Drupal\Core\Form\FormStateInterface $form_state
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
    *   Form state structured array.
    */
   public function clearCaptchaPlacementCacheSubmit(array $form, FormStateInterface $form_state) {
diff --git a/web/modules/captcha/src/Plugin/migrate/process/CaptchaTypeFormatter.php b/web/modules/captcha/src/Plugin/migrate/process/CaptchaTypeFormatter.php
new file mode 100644
index 0000000000000000000000000000000000000000..d83eb5c811e7bc69733dae3ef1775417d0505878
--- /dev/null
+++ b/web/modules/captcha/src/Plugin/migrate/process/CaptchaTypeFormatter.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Drupal\captcha\Plugin\migrate\process;
+
+use Drupal\migrate\MigrateExecutableInterface;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Perform captcha type transformation.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "captcha_type_formatter"
+ * )
+ *
+ * To do custom value transformations use the following:
+ *
+ * @code
+ * field_text:
+ *   plugin: captcha_type_formatter
+ *   source: text
+ * @endcode
+ */
+class CaptchaTypeFormatter extends ProcessPluginBase {
+
+  /**
+   * Transforms the d7 separate captcha type and module into one row.
+   */
+  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
+    $module = $row->getSourceProperty('module') ?? 'captcha';
+    $type = $row->getSourceProperty('captcha_type');
+    return $module . '/' . $type;
+  }
+
+}
diff --git a/web/modules/captcha/src/Plugin/migrate/source/CaptchaPoints.php b/web/modules/captcha/src/Plugin/migrate/source/CaptchaPoints.php
new file mode 100644
index 0000000000000000000000000000000000000000..18df2195fbcb43172e81c0b9f3dc0c4c5faec354
--- /dev/null
+++ b/web/modules/captcha/src/Plugin/migrate/source/CaptchaPoints.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace Drupal\captcha\Plugin\migrate\source;
+
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\State\StateInterface;
+use Drupal\migrate\Plugin\MigrationInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Drupal 7 captcha point source from database.
+ *
+ * @MigrateSource(
+ *   id = "d7_captcha_points",
+ *   source_module = "captcha"
+ * )
+ */
+class CaptchaPoints extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state, EntityTypeManagerInterface $entity_type_manager) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state, $entity_type_manager);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $migration,
+      $container->get('state'),
+      $container->get('entity_type.manager'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    return $this->select('captcha_points', 'c')->fields('c');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return [
+      'form_id' => $this->t('The name of the form'),
+      'module' => $this->t('The captcha point providing module.'),
+      'captcha_type' => $this->t('The captcha type.'),
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['form_id']['type'] = 'string';
+    return $ids;
+  }
+
+}
diff --git a/web/modules/captcha/tests/fixtures/drupal7.php b/web/modules/captcha/tests/fixtures/drupal7.php
new file mode 100644
index 0000000000000000000000000000000000000000..8a78dcf1c554e0cdc6d2781e4e0cf6f4cfa43edc
--- /dev/null
+++ b/web/modules/captcha/tests/fixtures/drupal7.php
@@ -0,0 +1,256 @@
+<?php
+
+/**
+ * @file
+ * A database agnostic dump for testing purposes.
+ */
+
+use Drupal\Core\Database\Database;
+
+$connection = Database::getConnection();
+
+$connection->insert('variable')
+  ->fields([
+    'name',
+    'value',
+  ])
+  ->values([
+    'name' => 'captcha_add_captcha_description',
+    'value' => 'i:1;',
+  ])
+  ->values([
+    'name' => 'captcha_administration_mode',
+    'value' => 'i:1;',
+  ])
+  ->values([
+    'name' => 'captcha_allow_on_admin_pages',
+    'value' => 'i:0;',
+  ])
+  ->values([
+    'name' => 'captcha_default_challenge',
+    'value' => 's:12:"captcha/Math";',
+  ])
+  ->values([
+    'name' => 'captcha_default_challenge_on_nonlisted_forms',
+    'value' => 'i:1;',
+  ])
+  ->values([
+    'name' => 'captcha_default_validation',
+    'value' => 's:1:"1";',
+  ])
+  ->values([
+    'name' => 'captcha_description',
+    'value' => 's:110:"This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.";',
+  ])
+  ->values([
+    'name' => 'captcha_enable_stats',
+    'value' => 'i:1;',
+  ])
+  ->values([
+    'name' => 'captcha_error_message',
+    'value' => 's:55:"The answer you entered for the CAPTCHA was not correct.";',
+  ])
+  ->values([
+    'name' => 'captcha_log_wrong_responses',
+    'value' => 'i:1;',
+  ])
+  ->values([
+    'name' => 'captcha_persistence',
+    'value' => 's:1:"1";',
+  ])
+  ->execute();
+
+$connection->insert('system')
+  ->fields([
+    'filename',
+    'name',
+    'type',
+    'owner',
+    'status',
+    'bootstrap',
+    'schema_version',
+    'weight',
+    'info',
+  ])
+  ->values([
+    'filename' => 'sites/all/modules/captcha/captcha.module',
+    'name' => 'captcha',
+    'type' => 'module',
+    'owner' => '',
+    'status' => '1',
+    'bootstrap' => '0',
+    'schema_version' => '7001',
+    'weight' => '0',
+    'info' => 'a:13:{s:4:\"name\";s:7:\"CAPTCHA\";s:11:\"description\";s:61:\"Base CAPTCHA module for adding challenges to arbitrary forms.\";s:7:\"package\";s:12:\"Spam control\";s:4:\"core\";s:3:\"7.x\";s:9:\"configure\";s:27:\"admin/config/people/captcha\";s:5:\"files\";a:5:{i:0;s:14:\"captcha.module\";i:1;s:11:\"captcha.inc\";i:2;s:17:\"captcha.admin.inc\";i:3;s:15:\"captcha.install\";i:4;s:12:\"captcha.test\";}s:7:\"version\";s:7:\"7.x-1.7\";s:7:\"project\";s:7:\"captcha\";s:9:\"datestamp\";s:10:\"1582293280\";s:5:\"mtime\";i:1582293280;s:12:\"dependencies\";a:0:{}s:3:\"php\";s:5:\"5.2.4\";s:9:\"bootstrap\";i:0;}',
+  ])
+  ->execute();
+
+// Create the Captcha Points D7 Table.
+$connection->schema()->createTable('captcha_points', [
+  'fields' => [
+    'form_id' => [
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => 128,
+      'default' => '',
+    ],
+    'module' => [
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => 64,
+      'default' => '',
+    ],
+    'captcha_type' => [
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => 64,
+      'default' => '',
+    ],
+  ],
+  'primary key' => [
+    'form_id',
+  ],
+  'mysql_character_set' => 'utf8',
+]);
+
+$connection->insert('captcha_points')
+  ->fields([
+    'form_id',
+    'module',
+    'captcha_type',
+  ])
+  ->values([
+    'form_id' => 'comment_node_article_form',
+    'module' => 'captcha',
+    'captcha_type' => 'Math',
+  ])
+  ->values([
+    'form_id' => 'user_pass',
+    'module' => 'captcha',
+    'captcha_type' => 'Math',
+  ])
+  ->execute();
+
+// Create the Captcha Points D7 Table.
+$connection->schema()->createTable('captcha_sessions', [
+  'fields' => [
+    'csid' => [
+      'type' => 'serial',
+      'not null' => TRUE,
+      'size' => 'normal',
+    ],
+    'token' => [
+      'type' => 'varchar',
+      'not null' => FALSE,
+      'length' => 64,
+    ],
+    'uid' => [
+      'type' => 'int',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'default' => 0,
+    ],
+    'sid' => [
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => 128,
+      'default' => '',
+    ],
+    'ip_address' => [
+      'type' => 'varchar',
+      'not null' => FALSE,
+      'length' => 128,
+    ],
+    'timestamp' => [
+      'type' => 'int',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'default' => 0,
+    ],
+    'form_id' => [
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => 128,
+      'default' => '',
+    ],
+    'solution' => [
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => 128,
+      'default' => '',
+    ],
+    'status' => [
+      'type' => 'int',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'default' => 0,
+    ],
+    'attempts' => [
+      'type' => 'int',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'default' => 0,
+    ],
+  ],
+  'primary key' => [
+    'csid',
+  ],
+  'indexes' => [
+    'csid_ip' => [
+      'csid',
+      'ip_address',
+    ],
+  ],
+  'mysql_character_set' => 'utf8',
+]);
+
+$connection->insert('captcha_sessions')
+  ->fields([
+    'csid',
+    'token',
+    'uid',
+    'sid',
+    'ip_address',
+    'timestamp',
+    'form_id',
+    'solution',
+    'status',
+    'attempts',
+  ])
+  ->values([
+    'csid' => 1,
+    'token' => '69e2767a2c651a887764bb60ea04cd0a',
+    'uid' => 0,
+    'sid' => 'svBxnT_AK4YFTbiUdCN3g9lCEqhC66NEbxasNNvGRug',
+    'ip_address' => '172.18.0.1',
+    'timestamp' => 1617948210,
+    'form_id' => 'user_login_block',
+    'solution' => '11',
+    'status' => 0,
+    'attempts' => 0,
+  ])
+  ->values([
+    'csid' => 2,
+    'token' => '69e2767a2c651a887764bb60ea04cd0b',
+    'uid' => 0,
+    'sid' => 'avBxnT_AK4YFTbiUdCN3g9lCEqhC66NEbxasNNvGRug',
+    'ip_address' => '172.18.0.1',
+    'timestamp' => 1617948230,
+    'form_id' => 'user_login_block',
+    'solution' => '20',
+    'status' => 0,
+    'attempts' => 0,
+  ])
+  ->values([
+    'csid' => 3,
+    'token' => '69e2767a2c651a887764bb60ea04cd0c',
+    'uid' => 0,
+    'sid' => 'bvBxnT_AK4YFTbiUdCN3g9lCEqhC66NEbxasNNvGRug',
+    'ip_address' => '172.18.0.1',
+    'timestamp' => 1617948240,
+    'form_id' => 'user_login_block',
+    'solution' => '25',
+    'status' => 0,
+    'attempts' => 0,
+  ])
+  ->execute();
diff --git a/web/modules/captcha/tests/src/Functional/CaptchaAdminTest.php b/web/modules/captcha/tests/src/Functional/CaptchaAdminTest.php
index 8f519d2ff57c24dc9ddb839ff0c7861caf40d0aa..3d9afe9ee5fd143ca012aed4a6e345ca1b137dbc 100755
--- a/web/modules/captcha/tests/src/Functional/CaptchaAdminTest.php
+++ b/web/modules/captcha/tests/src/Functional/CaptchaAdminTest.php
@@ -4,6 +4,7 @@
 
 use Drupal\captcha\Entity\CaptchaPoint;
 use Drupal\Core\Url;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
 
 /**
  * Tests CAPTCHA admin settings.
@@ -12,17 +13,19 @@
  */
 class CaptchaAdminTest extends CaptchaWebTestBase {
 
+  use StringTranslationTrait;
+
   /**
    * Test access to the admin pages.
    */
   public function testAdminAccess() {
     $this->drupalLogin($this->normalUser);
     $this->drupalGet(self::CAPTCHA_ADMIN_PATH);
-    $this->assertText(t('Access denied'), 'Normal users should not be able to access the CAPTCHA admin pages', 'CAPTCHA');
+    $this->assertSession()->pageTextContains($this->t('Access denied'), 'Normal users should not be able to access the CAPTCHA admin pages', 'CAPTCHA');
 
     $this->drupalLogin($this->adminUser);
     $this->drupalGet(self::CAPTCHA_ADMIN_PATH);
-    $this->assertNoText(t('Access denied'), 'Admin users should be able to access the CAPTCHA admin pages', 'CAPTCHA');
+    $this->assertSession()->pageTextNotContains($this->t('Access denied'), 'Admin users should be able to access the CAPTCHA admin pages', 'CAPTCHA');
   }
 
   /**
@@ -34,10 +37,10 @@ public function testCaptchaPointSettingGetterAndSetter() {
     /* @var CaptchaPoint $result */
     $result = captcha_get_form_id_setting($comment_form_id);
     $this->assertNotNull($result, 'CAPTCHA exists', 'CAPTCHA');
-    $this->assertEqual($result->getCaptchaType(), 'test', 'CAPTCHA type: default', 'CAPTCHA');
+    $this->assertEquals($result->getCaptchaType(), 'test', 'CAPTCHA type: default');
     $result = captcha_get_form_id_setting($comment_form_id, TRUE);
     $this->assertNotNull($result, 'CAPTCHA exists', 'CAPTCHA');
-    $this->assertEqual($result, 'test', 'Setting and symbolic getting CAPTCHA point: "test"', 'CAPTCHA');
+    $this->assertEquals($result, 'test', 'Setting and symbolic getting CAPTCHA point: "test"');
 
     // Set to 'default'.
     captcha_set_form_id_setting($comment_form_id, 'default');
@@ -46,24 +49,24 @@ public function testCaptchaPointSettingGetterAndSetter() {
       ->save();
     $result = captcha_get_form_id_setting($comment_form_id);
     $this->assertNotNull($result, 'CAPTCHA exists', 'CAPTCHA');
-    $this->assertEqual($result->getCaptchaType(), 'foo/bar', 'Setting and getting CAPTCHA point: default', 'CAPTCHA');
+    $this->assertEquals($result->getCaptchaType(), 'foo/bar', 'Setting and getting CAPTCHA point: default');
     $result = captcha_get_form_id_setting($comment_form_id, TRUE);
-    $this->assertNotNull($result, 'Setting and symbolic getting CAPTCHA point: "default"', 'CAPTCHA');
-    $this->assertEqual($result, 'foo/bar', 'Setting and symbolic getting CAPTCHA point: default', 'CAPTCHA');
+    $this->assertNotNull($result, 'Setting and symbolic getting CAPTCHA point: "default"');
+    $this->assertEquals($result, 'foo/bar', 'Setting and symbolic getting CAPTCHA point: default');
 
     // Set to 'baz/boo'.
     captcha_set_form_id_setting($comment_form_id, 'baz/boo');
     $result = captcha_get_form_id_setting($comment_form_id);
     $this->assertNotNull($result, 'CAPTCHA exists', 'CAPTCHA');
-    $this->assertEqual($result->getCaptchaType(), 'baz/boo', 'Setting and getting CAPTCHA point: baz/boo', 'CAPTCHA');
+    $this->assertEquals($result->getCaptchaType(), 'baz/boo', 'Setting and getting CAPTCHA point: baz/boo');
     $result = captcha_get_form_id_setting($comment_form_id, TRUE);
-    $this->assertEqual($result, 'baz/boo', 'Setting and symbolic getting CAPTCHA point: "baz/boo"', 'CAPTCHA');
+    $this->assertEquals($result, 'baz/boo', 'Setting and symbolic getting CAPTCHA point: "baz/boo"');
 
     // Set to NULL (which should delete the CAPTCHA point setting entry).
     captcha_set_form_id_setting($comment_form_id, NULL);
     $result = captcha_get_form_id_setting($comment_form_id);
     $this->assertNotNull($result, 'CAPTCHA exists', 'CAPTCHA');
-    $this->assertEqual($result->getCaptchaType(), 'foo/bar', 'Setting and getting CAPTCHA point: NULL', 'CAPTCHA');
+    $this->assertEquals($result->getCaptchaType(), 'foo/bar', 'Setting and getting CAPTCHA point: NULL');
     $result = captcha_get_form_id_setting($comment_form_id, TRUE);
     $this->assertNotNull($result, 'CAPTCHA exists', 'CAPTCHA');
 
@@ -75,9 +78,9 @@ public function testCaptchaPointSettingGetterAndSetter() {
     $this->assertNotNull($result, 'Setting and getting CAPTCHA point: baba/fofo', 'CAPTCHA');
     // $this->assertEqual($result->module, 'baba', 'Setting and getting
     // CAPTCHA point: baba/fofo', 'CAPTCHA');.
-    $this->assertEqual($result->getCaptchaType(), 'baba/fofo', 'Setting and getting CAPTCHA point: baba/fofo', 'CAPTCHA');
+    $this->assertEquals($result->getCaptchaType(), 'baba/fofo', 'Setting and getting CAPTCHA point: baba/fofo');
     $result = captcha_get_form_id_setting($comment_form_id, TRUE);
-    $this->assertEqual($result, 'baba/fofo', 'Setting and symbolic getting CAPTCHA point: "baba/fofo"', 'CAPTCHA');
+    $this->assertEquals($result, 'baba/fofo', 'Setting and symbolic getting CAPTCHA point: "baba/fofo"');
   }
 
   /**
@@ -91,13 +94,12 @@ public function testCaptchaPointSettingGetterAndSetter() {
    */
   protected function assertCaptchaSetting($form_id, $challenge_type) {
     $result = captcha_get_form_id_setting(self::COMMENT_FORM_ID, TRUE);
-    $this->assertEqual($result, $challenge_type,
-      t('Check CAPTCHA setting for form: expected: @expected, received: @received.',
+    $this->assertEquals($result, $challenge_type,
+      $this->t('Check CAPTCHA setting for form: expected: @expected, received: @received.',
         [
           '@expected' => var_export($challenge_type, TRUE),
           '@received' => var_export($result, TRUE),
-        ]),
-      'CAPTCHA');
+        ]));
   }
 
   /**
@@ -110,8 +112,9 @@ public function testCaptchaAdminLinks() {
     $edit = [
       'administration_mode' => TRUE,
     ];
-
-    $this->drupalPostForm(self::CAPTCHA_ADMIN_PATH, $edit, t('Save configuration'));
+    
+    $this->drupalGet(self::CAPTCHA_ADMIN_PATH);
+    $this->submitForm($edit, $this->t('Save configuration'));
 
     // Create a node with comments enabled.
     $node = $this->drupalCreateNode();
@@ -120,7 +123,7 @@ public function testCaptchaAdminLinks() {
     $this->drupalGet('node/' . $node->id());
 
     // Click the add new comment link.
-    $this->clickLink(t('Add new comment'));
+    $this->clickLink($this->t('Add new comment'));
     $add_comment_url = $this->getUrl();
 
     // Remove fragment part from comment URL to avoid
@@ -128,56 +131,59 @@ public function testCaptchaAdminLinks() {
     $add_comment_url = strtok($add_comment_url, "#");
 
     // Click the CAPTCHA admin link to enable a challenge.
-    $this->clickLink(t('Place a CAPTCHA here for untrusted users.'));
+    $this->clickLink($this->t('Place a CAPTCHA here for untrusted users.'));
 
     // Enable Math CAPTCHA.
     $edit = ['captchaType' => 'captcha/Math'];
-    $this->drupalPostForm($this->getUrl(), $edit, t('Save'));
+    $this->drupalGet($this->getUrl());
+    $this->submitForm($edit, $this->t('Save'));
+
     // Check if returned to original comment form.
-    $this->assertUrl($add_comment_url, [],
+    $this->assertSession()->addressEquals($add_comment_url, [],
       'After setting CAPTCHA with CAPTCHA admin links: should return to original form.', 'CAPTCHA');
 
     // Check if CAPTCHA was successfully enabled
     // (on CAPTCHA admin links fieldset).
-    $this->assertText(t('CAPTCHA: challenge "@type" enabled', ['@type' => $edit['captchaType']]),
+    $this->assertSession()->pageTextContains($this->t('CAPTCHA: challenge "@type" enabled', ['@type' => $edit['captchaType']]),
       'Enable a challenge through the CAPTCHA admin links', 'CAPTCHA');
 
     // Check if CAPTCHA was successfully enabled (through API).
     $this->assertCaptchaSetting(self::COMMENT_FORM_ID, 'captcha/Math');
 
     // Edit challenge type through CAPTCHA admin links.
-    $this->clickLink(t('change'));
+    $this->clickLink($this->t('change'));
 
     // Enable Math CAPTCHA.
     $edit = ['captchaType' => 'default'];
-    $this->drupalPostForm($this->getUrl(), $edit, t('Save'));
+    $this->drupalGet($this->getUrl());
+    $this->submitForm($edit, 'Save');
 
     // Check if returned to original comment form.
-    $this->assertEqual($add_comment_url, $this->getUrl(),
-      'After editing challenge type CAPTCHA admin links: should return to original form.', 'CAPTCHA');
+    $this->assertEquals($add_comment_url, $this->getUrl(),
+      'After editing challenge type CAPTCHA admin links: should return to original form.');
 
     // Check if CAPTCHA was successfully changed
     // (on CAPTCHA admin links fieldset).
     // This is actually the same as the previous setting because
     // the captcha/Math is the default for the default challenge.
     // TODO Make sure the edit is a real change.
-    $this->assertText(t('CAPTCHA: challenge "@type" enabled', ['@type' => $edit['captchaType']]),
+    $this->assertSession()->pageTextContains($this->t('CAPTCHA: challenge "@type" enabled', ['@type' => $edit['captchaType']]),
       'Enable a challenge through the CAPTCHA admin links', 'CAPTCHA');
     // Check if CAPTCHA was successfully edited (through API).
     $this->assertCaptchaSetting(self::COMMENT_FORM_ID, 'default');
 
     // Disable challenge through CAPTCHA admin links.
     $this->drupalGet(Url::fromRoute('entity.captcha_point.disable', ['captcha_point' => self::COMMENT_FORM_ID]));
-    $this->drupalPostForm(NULL, [], t('Disable'));
+    $this->submitForm([], $this->t('Disable'));
 
     // Check if returned to captcha point list.
     global $base_url;
-    $this->assertEqual($base_url . '/admin/config/people/captcha/captcha-points', $this->getUrl(),
-      'After disabling challenge in CAPTCHA admin: should return to captcha point list.', 'CAPTCHA');
+    $this->assertEquals($base_url . '/admin/config/people/captcha/captcha-points', $this->getUrl(),
+      'After disabling challenge in CAPTCHA admin: should return to captcha point list.');
 
     // Check if CAPTCHA was successfully disabled
     // (on CAPTCHA admin links fieldset).
-    $this->assertRaw(t('Captcha point %form_id has been disabled.', ['%form_id' => self::COMMENT_FORM_ID]),
+    $this->assertSession()->responseContains($this->t('Captcha point %form_id has been disabled.', ['%form_id' => self::COMMENT_FORM_ID]),
       'Disable challenge through the CAPTCHA admin links', 'CAPTCHA');
   }
 
@@ -196,7 +202,7 @@ public function testUntrustedUserPosting() {
 
     // Go to node page and click the "add comment" link.
     $this->drupalGet('node/' . $node->id());
-    $this->clickLink(t('Add new comment'));
+    $this->clickLink($this->t('Add new comment'));
     $add_comment_url = $this->getUrl();
 
     // Check if CAPTCHA is visible on form.
@@ -204,8 +210,9 @@ public function testUntrustedUserPosting() {
     // Try to post a comment with wrong answer.
     $edit = $this->getCommentFormValues();
     $edit['captcha_response'] = 'xx';
-    $this->drupalPostForm($add_comment_url, $edit, t('Preview'));
-    $this->assertText(self::CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE,
+    $this->drupalGet($add_comment_url);
+    $this->submitForm($edit, $this->t('Preview'));
+    $this->assertSession()->pageTextContains(self::CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE,
       'wrong CAPTCHA should block form submission.', 'CAPTCHA');
   }
 
@@ -220,12 +227,13 @@ public function testXssOnCaptchaDescription() {
     $this->drupalLogin($this->adminUser);
     $xss = '<script type="text/javascript">alert("xss")</script>';
     $edit = ['description' => $xss];
-    $this->drupalPostForm(self::CAPTCHA_ADMIN_PATH, $edit, 'Save configuration');
+    $this->drupalGet(self::CAPTCHA_ADMIN_PATH);
+    $this->submitForm($edit, $this->t('Save configuration'));
 
     // Visit user register form and check if JavaScript snippet is there.
     $this->drupalLogout();
     $this->drupalGet('user/register');
-    $this->assertNoRaw($xss, 'JavaScript should not be allowed in CAPTCHA description.', 'CAPTCHA');
+    $this->assertSession()->responseNotContains($xss, 'JavaScript should not be allowed in CAPTCHA description.', 'CAPTCHA');
   }
 
   /**
@@ -242,7 +250,9 @@ public function testCaptchaPlacementCacheClearing() {
     $this->assertNotNull($placement_map, 'CAPTCHA placement cache should be set.');
     // Clear the cache.
     $this->drupalLogin($this->adminUser);
-    $this->drupalPostForm(self::CAPTCHA_ADMIN_PATH, [], t('Clear the CAPTCHA placement cache'));
+    $this->drupalGet(self::CAPTCHA_ADMIN_PATH);
+    $this->submitForm([], $this->t('Clear the CAPTCHA placement cache'));
+
     // Check that the placement cache is unset.
     $placement_map = $this->container->get('cache.default')
       ->get('captcha_placement_map_cache');
@@ -286,23 +296,26 @@ public function testCaptchaPointAdministration() {
       'formId' => $captcha_point_form_id,
       'captchaType' => $captcha_point_module . '/' . $captcha_point_type,
     ];
-    $this->drupalPostForm(self::CAPTCHA_ADMIN_PATH . '/captcha-points/add', $form_values, t('Save'));
-    $this->assertText(t('Form ID field is required.'));
+    $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha-points/add');
+    $this->submitForm($form_values, 'Save');
+    $this->assertSession()->pageTextContains($this->t('Form ID field is required.'));
 
     // Set CAPTCHA point through admin/user/captcha/captcha/captcha_point.
     $form_values['label'] = $label;
-    $this->drupalPostForm(self::CAPTCHA_ADMIN_PATH . '/captcha-points/add', $form_values, t('Save'));
-    $this->assertRaw(t('Captcha Point for %label form was created.', ['%label' => $captcha_point_form_id]));
+    $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha-points/add');
+    $this->submitForm($form_values, $this->t('Save'));
+    $this->assertSession()->responseContains($this->t('Captcha Point for %label form was created.', ['%label' => $captcha_point_form_id]));
 
     // Check in database.
     /* @var CaptchaPoint result */
     $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
-    $this->assertEqual($result->captchaType, $captcha_point_module . '/' . $captcha_point_type,
+    $this->assertEquals($result->captchaType, $captcha_point_module . '/' . $captcha_point_type,
       'Enabled CAPTCHA point should have module and type set');
 
     // Disable CAPTCHA point again.
-    $this->drupalPostForm(self::CAPTCHA_ADMIN_PATH . '/captcha-points/' . $captcha_point_form_id . '/disable', [], t('Disable'));
-    $this->assertRaw(t('Captcha point %label has been disabled.', ['%label' => $label]), 'Disabling of CAPTCHA point');
+    $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha-points/' . $captcha_point_form_id . '/disable');
+    $this->submitForm([], $this->t('Disable'));
+    $this->assertSession()->responseContains($this->t('Captcha point %label has been disabled.', ['%label' => $label]), 'Disabling of CAPTCHA point');
 
     // Check in database.
     $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
@@ -313,17 +326,19 @@ public function testCaptchaPointAdministration() {
     $form_values = [
       'captchaType' => $captcha_point_module . '/' . $captcha_point_type,
     ];
-    $this->drupalPostForm(self::CAPTCHA_ADMIN_PATH . '/captcha-points/' . $captcha_point_form_id, $form_values, t('Save'));
-    $this->assertRaw(t('Captcha Point for %form_id form was updated.', ['%form_id' => $captcha_point_form_id]), 'Saving of CAPTCHA point settings');
+    $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha-points/' . $captcha_point_form_id);
+    $this->submitForm($form_values, $this->t('Save'));
+    $this->assertSession()->responseContains($this->t('Captcha Point for %form_id form was updated.', ['%form_id' => $captcha_point_form_id]), 'Saving of CAPTCHA point settings');
 
     // Check in database.
     $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
-    $this->assertEqual($result->captchaType, $captcha_point_module . '/' . $captcha_point_type,
+    $this->assertEquals($result->captchaType, $captcha_point_module . '/' . $captcha_point_type,
       'Enabled CAPTCHA point should have module and type set');
 
     // Delete CAPTCHA point.
-    $this->drupalPostForm(self::CAPTCHA_ADMIN_PATH . '/captcha-points/' . $captcha_point_form_id . '/delete', [], t('Delete'));
-    $this->assertRaw(t('Captcha point %label has been deleted.', ['%label' => $label]),
+    $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha-points/' . $captcha_point_form_id . '/delete');
+    $this->submitForm([], $this->t('Delete'));
+    $this->assertSession()->responseContains($this->t('Captcha point %label has been deleted.', ['%label' => $label]),
       'Deleting of CAPTCHA point');
 
     $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
@@ -347,8 +362,9 @@ public function testCaptchaPointAdministrationByNonAdmin() {
       'formId' => $captcha_point_form_id,
       'captchaType' => $captcha_point_module . '/' . $captcha_point_type,
     ];
-    $this->drupalPostForm(self::CAPTCHA_ADMIN_PATH . '/captcha-points/add', $form_values, 'Save');
-    $this->assertRaw(t('Captcha Point for %form_id form was created.', ['%form_id' => $captcha_point_form_id]));
+    $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha-points/add');
+    $this->submitForm($form_values, $this->t('Save'));
+    $this->assertSession()->responseContains($this->t('Captcha Point for %form_id form was created.', ['%form_id' => $captcha_point_form_id]));
 
     // Switch from admin to non-admin.
     $this->drupalLogin($this->normalUser);
@@ -356,17 +372,17 @@ public function testCaptchaPointAdministrationByNonAdmin() {
     // Try to set CAPTCHA point
     // through admin/user/captcha/captcha/captcha_point.
     $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha-points');
-    $this->assertText(t('You are not authorized to access this page.'),
+    $this->assertSession()->pageTextContains($this->t('You are not authorized to access this page.'),
       'Non admin should not be able to set a CAPTCHA point');
 
     // Try to disable the CAPTCHA point.
     $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha-points/' . $captcha_point_form_id . '/disable');
-    $this->assertText(t('You are not authorized to access this page.'),
+    $this->assertSession()->pageTextContains($this->t('You are not authorized to access this page.'),
       'Non admin should not be able to disable a CAPTCHA point');
 
     // Try to delete the CAPTCHA point.
     $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha-points/' . $captcha_point_form_id . '/delete');
-    $this->assertText(t('You are not authorized to access this page.'),
+    $this->assertSession()->pageTextContains($this->t('You are not authorized to access this page.'),
       'Non admin should not be able to delete a CAPTCHA point');
 
     // Switch from nonadmin to admin again.
@@ -374,11 +390,12 @@ public function testCaptchaPointAdministrationByNonAdmin() {
 
     // Check if original CAPTCHA point still exists in database.
     $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
-    $this->assertEqual($result->captchaType, $captcha_point_module . '/' . $captcha_point_type, 'Enabled CAPTCHA point should have module and type set');
+    $this->assertEquals($result->captchaType, $captcha_point_module . '/' . $captcha_point_type, 'Enabled CAPTCHA point should have module and type set');
 
     // Delete captcha point.
-    $this->drupalPostForm(self::CAPTCHA_ADMIN_PATH . '/captcha-points/' . $captcha_point_form_id . '/delete', [], 'Delete');
-    $this->assertRaw(t('Captcha point %label has been deleted.', ['%label' => $label]), 'Disabling of CAPTCHA point');
+    $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha-points/' . $captcha_point_form_id . '/delete');
+    $this->submitForm([], 'Delete');
+    $this->assertSession()->responseContains($this->t('Captcha point %label has been deleted.', ['%label' => $label]), 'Disabling of CAPTCHA point');
   }
 
 }
diff --git a/web/modules/captcha/tests/src/Functional/CaptchaCacheTest.php b/web/modules/captcha/tests/src/Functional/CaptchaCacheTest.php
index 391856aac798707b20ed71de40c01ba65bb351e0..5e4639807422ad76094f8aaf797a30c2b6756d65 100644
--- a/web/modules/captcha/tests/src/Functional/CaptchaCacheTest.php
+++ b/web/modules/captcha/tests/src/Functional/CaptchaCacheTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\captcha\Functional;
 
+use Drupal\Core\Database\Database;
+
 /**
  * Tests CAPTCHA caching on various pages.
  *
@@ -14,12 +16,16 @@ class CaptchaCacheTest extends CaptchaWebTestBase {
    *
    * @var array
    */
-  public static $modules = ['block', 'image_captcha'];
+  protected static $modules = [
+    'block',
+    'image_captcha',
+    'captcha_test',
+  ];
 
   /**
    * {@inheritdoc}
    */
-  public function setUp() {
+  public function setUp(): void {
     parent::setUp();
 
     $this->drupalPlaceBlock('user_login_block', ['id' => 'login']);
@@ -32,41 +38,85 @@ public function testCacheTags() {
     global $base_path;
     // Check caching without captcha as anonymous user.
     $this->drupalGet('');
-    $this->assertEqual($this->drupalGetHeader('x-drupal-cache'), 'MISS');
+    $this->assertEquals($this->getSession()->getResponseHeader('x-drupal-cache'), 'MISS');
     $this->drupalGet('');
-    $this->assertEqual($this->drupalGetHeader('x-drupal-cache'), 'HIT');
+    $this->assertEquals($this->getSession()->getResponseHeader('x-drupal-cache'), 'HIT');
 
     // Enable captcha on login block and test caching.
     captcha_set_form_id_setting('user_login_form', 'captcha/Math');
     $this->drupalGet('');
     $sid = $this->getCaptchaSidFromForm();
-    $this->assertNull($this->drupalGetHeader('x-drupal-cache'), 'Cache is disabled');
+    $this->assertNull($this->getSession()->getResponseHeader('x-drupal-cache'), 'Cache is disabled');
     $this->drupalGet('');
-    $this->assertNotEqual($sid, $this->getCaptchaSidFromForm());
+    $this->assertNotEquals($sid, $this->getCaptchaSidFromForm());
 
     // Switch challenge to captcha/Test, check the captcha isn't cached.
     captcha_set_form_id_setting('user_login_form', 'captcha/Test');
     $this->drupalGet('');
     $sid = $this->getCaptchaSidFromForm();
-    $this->assertNull($this->drupalGetHeader('x-drupal-cache'), 'Cache is disabled');
+    $this->assertNull($this->getSession()->getResponseHeader('x-drupal-cache'), 'Cache is disabled');
     $this->drupalGet('');
-    $this->assertNotEqual($sid, $this->getCaptchaSidFromForm());
+    $this->assertNotEquals($sid, $this->getCaptchaSidFromForm());
 
     // Switch challenge to image_captcha/Image, check the captcha isn't cached.
     captcha_set_form_id_setting('user_login_form', 'image_captcha/Image');
     $this->drupalGet('');
     $image_path = $this->getSession()->getPage()->find('css', '.captcha img')->getAttribute('src');
-    $this->assertNull($this->drupalGetHeader('x-drupal-cache'), 'Cache disabled');
+    $this->assertNull($this->getSession()->getResponseHeader('x-drupal-cache'), 'Cache disabled');
     // Check that we get a new image when vising the page again.
     $this->drupalGet('');
-    $this->assertNotEqual($image_path, $this->getSession()->getPage()->find('css', '.captcha img')->getAttribute('src'));
+    $this->assertNotEquals($image_path, $this->getSession()->getPage()->find('css', '.captcha img')->getAttribute('src'));
     // Check image caching, remove the base path since drupalGet() expects the
     // internal path.
     $this->drupalGet(substr($image_path, strlen($base_path)));
-    $this->assertResponse(200);
+    $this->assertSession()->statusCodeEquals(200);
     // Request image twice to make sure no errors happen (due to page caching).
     $this->drupalGet(substr($image_path, strlen($base_path)));
-    $this->assertResponse(200);
+    $this->assertSession()->statusCodeEquals(200);
+  }
+
+  /**
+   * Tests a cacheable captcha type.
+   */
+  public function testCacheableCaptcha() {
+    $web_assert = $this->assertSession();
+
+    // Enable captcha on login block with a cacheable captcha.
+    captcha_set_form_id_setting('user_login_form', 'captcha_test/TestCacheable');
+
+    // Warm up the caches.
+    $this->drupalGet('');
+
+    // Let's check if the page is cached.
+    $this->drupalGet('');
+    static::assertSame('HIT', $this->drupalGetHeader('X-Drupal-Cache'), 'Cache enabled');
+
+    $edit = [
+      'name' => $this->normalUser->getDisplayName(),
+      'pass' => $this->normalUser->pass_raw,
+      'captcha_response' => 'Test 123',
+    ];
+    $this->submitForm($edit, 'Log in');
+    $web_assert->addressEquals('user/' . $this->normalUser->id());
+
+    // Simulate a cron run that deletes the {captcha_session} data.
+    $connection = Database::getConnection();
+    $connection->delete('captcha_sessions')->execute();
+
+    // Log out and reload the form. Because the captcha is cacheable, the form
+    // is retrieved from the render cache, and contains the same CSID as
+    // previously.
+    $this->drupalLogout();
+    $this->drupalGet('');
+    static::assertSame('HIT', $this->drupalGetHeader('X-Drupal-Cache'), 'Cache enabled');
+
+    $edit = [
+      'name' => $this->normalUser->getDisplayName(),
+      'pass' => $this->normalUser->pass_raw,
+      'captcha_response' => 'Test 123',
+    ];
+    $this->submitForm($edit, 'Log in');
+    $web_assert->addressEquals('user/' . $this->normalUser->id());
   }
 
 }
diff --git a/web/modules/captcha/tests/src/Functional/CaptchaCronTest.php b/web/modules/captcha/tests/src/Functional/CaptchaCronTest.php
index f908e2378d0905bf8282eba44477db630ded25a7..44f58ccd35d9e416f36a5c013622cc9727c3c242 100644
--- a/web/modules/captcha/tests/src/Functional/CaptchaCronTest.php
+++ b/web/modules/captcha/tests/src/Functional/CaptchaCronTest.php
@@ -17,7 +17,7 @@ class CaptchaCronTest extends BrowserTestBase {
    *
    * @var array
    */
-  public static $modules = ['captcha'];
+  protected static $modules = ['captcha'];
 
   /**
    * {@inheritdoc}
diff --git a/web/modules/captcha/tests/src/Functional/CaptchaPersistenceTest.php b/web/modules/captcha/tests/src/Functional/CaptchaPersistenceTest.php
index 9755da90019e9c35444059541dfb5bc69026a9dc..725795f88f70c465563153959c23db675ac192a2 100755
--- a/web/modules/captcha/tests/src/Functional/CaptchaPersistenceTest.php
+++ b/web/modules/captcha/tests/src/Functional/CaptchaPersistenceTest.php
@@ -23,7 +23,8 @@ private function setUpPersistence($persistence) {
     $this->drupalLogin($this->adminUser);
     // Set persistence.
     $edit = ['persistence' => $persistence];
-    $this->drupalPostForm(self::CAPTCHA_ADMIN_PATH, $edit, 'Save configuration');
+    $this->drupalGet(self::CAPTCHA_ADMIN_PATH);
+    $this->submitForm($edit, 'Save configuration');
     // Log admin out.
     $this->drupalLogout();
 
@@ -48,7 +49,7 @@ private function setUpPersistence($persistence) {
    */
   protected function assertPreservedCsid($captcha_sid_initial) {
     $captcha_sid = $this->getCaptchaSidFromForm();
-    $this->assertEqual($captcha_sid_initial, $captcha_sid,
+    $this->assertEquals($captcha_sid_initial, $captcha_sid,
       "CAPTCHA session ID should be preserved (expected: $captcha_sid_initial, found: $captcha_sid).");
   }
 
@@ -60,7 +61,7 @@ protected function assertPreservedCsid($captcha_sid_initial) {
    */
   protected function assertDifferentCsid($captcha_sid_initial) {
     $captcha_sid = $this->getCaptchaSidFromForm();
-    $this->assertNotEqual($captcha_sid_initial, $captcha_sid, "CAPTCHA session ID should be different.");
+    $this->assertNotEquals($captcha_sid_initial, $captcha_sid, "CAPTCHA session ID should be different.");
   }
 
   /**
@@ -82,7 +83,7 @@ public function testPersistenceAlways() {
       'pass' => 'bazlaz',
       'captcha_response' => 'Test 123',
     ];
-    $this->drupalPostForm(NULL, $edit, $this->t('Log in'), [], self::LOGIN_HTML_FORM_ID);
+    $this->submitForm($edit, $this->t('Log in'), self::LOGIN_HTML_FORM_ID);
     // Check that there was no error message for the CAPTCHA.
     $this->assertCaptchaResponseAccepted();
 
@@ -92,7 +93,7 @@ public function testPersistenceAlways() {
     $this->assertPreservedCsid($captcha_sid_initial);
 
     // Post from again.
-    $this->drupalPostForm(NULL, $edit, $this->t('Log in'), [], self::LOGIN_HTML_FORM_ID);
+    $this->submitForm($edit, $this->t('Log in'), self::LOGIN_HTML_FORM_ID);
     // Check that there was no error message for the CAPTCHA.
     $this->assertCaptchaResponseAccepted();
     $this->assertPreservedCsid($captcha_sid_initial);
@@ -116,7 +117,7 @@ public function testPersistencePerFormInstance() {
       'pass' => 'bazlaz',
       'captcha_response' => 'Test 123',
     ];
-    $this->drupalPostForm(NULL, $edit, $this->t('Log in'), [], self::LOGIN_HTML_FORM_ID);
+    $this->submitForm($edit, $this->t('Log in'), self::LOGIN_HTML_FORM_ID);
     // Check that there was no error message for the CAPTCHA.
     $this->assertCaptchaResponseAccepted();
     // There shouldn't be a CAPTCHA on the new form.
@@ -153,7 +154,7 @@ public function testPersistencePerFormType() {
       'pass' => 'bazlaz',
       'captcha_response' => 'Test 123',
     ];
-    $this->drupalPostForm(NULL, $edit, $this->t('Log in'), [], self::LOGIN_HTML_FORM_ID);
+    $this->submitForm($edit, $this->t('Log in'), self::LOGIN_HTML_FORM_ID);
     // Check that there was no error message for the CAPTCHA.
     $this->assertCaptchaResponseAccepted();
     // There shouldn't be a CAPTCHA on the new form.
@@ -195,7 +196,7 @@ public function testPersistenceOnlyOnce() {
       'pass' => 'bazlaz',
       'captcha_response' => 'Test 123',
     ];
-    $this->drupalPostForm(NULL, $edit, $this->t('Log in'), [], self::LOGIN_HTML_FORM_ID);
+    $this->submitForm($edit, $this->t('Log in'), self::LOGIN_HTML_FORM_ID);
     // Check that there was no error message for the CAPTCHA.
     $this->assertCaptchaResponseAccepted();
     // There shouldn't be a CAPTCHA on the new form.
diff --git a/web/modules/captcha/tests/src/Functional/CaptchaSessionReuseAttackTestCase.php b/web/modules/captcha/tests/src/Functional/CaptchaSessionReuseAttackTestCase.php
index b165f386f0f276d92b948a0cda2e91bce73a2ee2..83c7d4ffe062078c86ddb47425c6e98be486778f 100755
--- a/web/modules/captcha/tests/src/Functional/CaptchaSessionReuseAttackTestCase.php
+++ b/web/modules/captcha/tests/src/Functional/CaptchaSessionReuseAttackTestCase.php
@@ -14,7 +14,7 @@ class CaptchaSessionReuseAttackTestCase extends CaptchaWebTestBase {
    */
   protected function assertCaptchaSessionIdReuseAttackDetection() {
     // There should be an error message about wrong response.
-    $this->assertText(self::CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE,
+    $this->assertSession()->pageTextContains(self::CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE,
       'CAPTCHA response should flagged as wrong.',
       'CAPTCHA'
     );
@@ -47,7 +47,7 @@ public function testCaptchaSessionReuseAttackDetectionOnCommentPreview() {
     // Post the form with the solution.
     $edit = $this->getCommentFormValues();
     $edit['captcha_response'] = $solution;
-    $this->drupalPostForm(NULL, $edit, t('Preview'));
+    $this->submitForm($edit, 'Preview');
     // Answer should be accepted and further CAPTCHA omitted.
     $this->assertCaptchaResponseAccepted();
     $this->assertCaptchaPresence(FALSE);
@@ -57,10 +57,10 @@ public function testCaptchaSessionReuseAttackDetectionOnCommentPreview() {
 
     // Post a new comment, reusing the previous CAPTCHA session.
     $edit = $this->getCommentFormValues();
-    $this->assertSession()->hiddenFieldExists("captcha_sid")->setValue((string) $captcha_sid);
-    $this->assertSession()->hiddenFieldExists("captcha_token")->setValue((string) $captcha_token);
+    $this->assertSession()->hiddenFieldExists("captcha_sid")->setValue((string)$captcha_sid);
+    $this->assertSession()->hiddenFieldExists("captcha_token")->setValue((string)$captcha_token);
     $edit['captcha_response'] = $solution;
-    $this->drupalPostForm(NULL, $edit, t('Preview'));
+    $this->submitForm($edit, 'Preview');
     // CAPTCHA session reuse attack should be detected.
     $this->assertCaptchaSessionIdReuseAttackDetection();
     // There should be a CAPTCHA.
@@ -93,7 +93,7 @@ public function testCaptchaSessionReuseAttackDetectionOnNodeForm() {
     $edit = $this->getNodeFormValues();
     $edit['captcha_response'] = $solution;
     // Preview the node.
-    $this->drupalPostForm(NULL, $edit, t('Preview'));
+    $this->submitForm($edit, 'Preview');
     // Answer should be accepted.
     $this->assertCaptchaResponseAccepted();
     // Check that there is no CAPTCHA after preview.
@@ -105,10 +105,10 @@ public function testCaptchaSessionReuseAttackDetectionOnNodeForm() {
 
     // Post a new node, reusing the previous CAPTCHA session.
     $edit = $this->getNodeFormValues();
-    $this->assertSession()->hiddenFieldExists("captcha_sid")->setValue((string) $captcha_sid);
-    $this->assertSession()->hiddenFieldExists("captcha_token")->setValue((string) $captcha_token);
+    $this->assertSession()->hiddenFieldExists("captcha_sid")->setValue((string)$captcha_sid);
+    $this->assertSession()->hiddenFieldExists("captcha_token")->setValue((string)$captcha_token);
     $edit['captcha_response'] = $solution;
-    $this->drupalPostForm(NULL, $edit, t('Preview'));
+    $this->submitForm($edit, 'Preview');
     // CAPTCHA session reuse attack should be detected.
     $this->assertCaptchaSessionIdReuseAttackDetection();
     // There should be a CAPTCHA.
@@ -140,12 +140,12 @@ public function testCaptchaSessionReuseAttackDetectionOnLoginForm() {
       'pass' => $this->normalUser->pass_raw,
       'captcha_response' => $solution,
     ];
-    $this->drupalPostForm(NULL, $edit, t('Log in'), [], self::LOGIN_HTML_FORM_ID);
+    $this->submitForm($edit, 'Log in', self::LOGIN_HTML_FORM_ID);
     $this->assertCaptchaResponseAccepted();
     $this->assertCaptchaPresence(FALSE);
     // If a "log out" link appears on the page, it is almost certainly because
     // the login was successful.
-    $this->assertText($this->normalUser->getDisplayName());
+    $this->assertSession()->pageTextContains($this->normalUser->getDisplayName());
 
     // Log out again.
     $this->drupalLogout();
@@ -154,10 +154,10 @@ public function testCaptchaSessionReuseAttackDetectionOnLoginForm() {
     $this->drupalGet('<front>');
 
     // Try to log in again, reusing the previous CAPTCHA session.
-    $this->assertSession()->hiddenFieldExists("captcha_sid")->setValue((string) $captcha_sid);
-    $this->assertSession()->hiddenFieldExists("captcha_token")->setValue((string) $captcha_token);
-    $this->assert('pass', json_encode($edit));
-    $this->drupalPostForm(NULL, $edit, t('Log in'));
+    $this->assertSession()->hiddenFieldExists("captcha_sid")->setValue((string)$captcha_sid);
+    $this->assertSession()->hiddenFieldExists("captcha_token")->setValue((string)$captcha_token);
+    $this->assertNotEmpty(json_encode($edit));
+    $this->submitForm($edit, 'Log in');
     // CAPTCHA session reuse attack should be detected.
     $this->assertCaptchaSessionIdReuseAttackDetection();
     // There should be a CAPTCHA.
@@ -182,11 +182,12 @@ public function testMultipleCaptchaProtectedFormsOnOnePage() {
     $edit = $this->getCommentFormValues();
     $comment_subject = $edit['subject[0][value]'];
     $edit['captcha_response'] = 'Test 123';
-    $this->drupalPostForm('comment/reply/node/' . $node->id() . '/comment', $edit, t('Preview'));
+    $this->drupalGet('comment/reply/node/' . $node->id() . '/comment');
+    $this->submitForm($edit, 'Preview');
     // Post should be accepted: no warnings,
     // no CAPTCHA reuse detection (which could be used by user log in block).
     $this->assertCaptchaResponseAccepted();
-    $this->assertText($comment_subject);
+    $this->assertSession()->pageTextContains($comment_subject);
   }
 
 }
diff --git a/web/modules/captcha/tests/src/Functional/CaptchaTest.php b/web/modules/captcha/tests/src/Functional/CaptchaTest.php
index d28c54431dd491ed00ba5b73d5f4c24c01b8aa1a..54639986646a76577050809b0ca6b4707821de6c 100755
--- a/web/modules/captcha/tests/src/Functional/CaptchaTest.php
+++ b/web/modules/captcha/tests/src/Functional/CaptchaTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\captcha\Functional;
 
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+
 /**
  * Tests CAPTCHA main test case sensitivity.
  *
@@ -9,12 +11,14 @@
  */
 class CaptchaTest extends CaptchaWebTestBase {
 
+  use StringTranslationTrait;
+
   /**
    * Modules to enable.
    *
    * @var array
    */
-  public static $modules = ['block', 'captcha_long_form_id_test'];
+  protected static $modules = ['block', 'captcha_long_form_id_test'];
 
   /**
    * Testing the protection of the user log in form.
@@ -44,15 +48,50 @@ public function testCaptchaOnLoginForm() {
       'pass' => $user->pass_raw,
       'captcha_response' => '?',
     ];
-    $this->drupalPostForm(NULL, $edit, t('Log in'), [], self::LOGIN_HTML_FORM_ID);
+    $this->submitForm($edit, $this->t('Log in'), self::LOGIN_HTML_FORM_ID);
     // Check for error message.
-    $this->assertText(self::CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE, 'CAPTCHA should block user login form', 'CAPTCHA');
+    $this->assertSession()->pageTextContains(self::CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE, 'CAPTCHA should block user login form', 'CAPTCHA');
 
     // And make sure that user is not logged in:
     // check for name and password fields on ?q=user.
     $this->drupalGet('user');
-    $this->assertField('name', t('Username field found.'), 'CAPTCHA');
-    $this->assertField('pass', t('Password field found.'), 'CAPTCHA');
+    $this->assertSession()->fieldExists('name');
+    $this->assertSession()->fieldExists('pass');
+  }
+
+  /**
+   * Testing the response error menssage.
+   */
+  public function testCaptchaResponseErrorMenssage() {
+    // Customize the response error message.
+    $this->drupalLogin($this->adminUser);
+    $customized_menssage = 'The answer you entered is wrong.';
+    $edit = [
+      'wrong_captcha_response_message' => $customized_menssage,
+    ];
+    $this->drupalGet("admin/config/people/captcha");
+    $this->submitForm($edit, $this->t('Save configuration'));
+
+    // Set a CAPTCHA on login form.
+    /* @var \Drupal\captcha\Entity\CaptchaPoint $captcha_point */
+    $captcha_point = \Drupal::entityTypeManager()
+      ->getStorage('captcha_point')
+      ->load('user_login_form');
+    $captcha_point->setCaptchaType('captcha/Math');
+    $captcha_point->enable()->save();
+
+    // Check if the menssage is default.
+    $this->drupalLogout();
+    $this->drupalGet('user');
+    // Try to log in, which should fail.
+    $edit = [
+      'name' => $this->adminUser->getDisplayName(),
+      'pass' => $this->adminUser->pass_raw,
+      'captcha_response' => '?',
+    ];
+    $this->submitForm($edit, $this->t('Log in'), self::LOGIN_HTML_FORM_ID);
+    $this->assertSession()->pageTextContains($customized_menssage, 'CAPTCHA should block user login form', 'CAPTCHA');
+
   }
 
   /**
@@ -83,23 +122,24 @@ protected function assertCommentPosting($captcha_response, $should_pass, $messag
     $comment_subject = $edit['subject[0][value]'];
     $comment_body = $edit['comment_body[0][value]'];
     $edit['captcha_response'] = $captcha_response;
-    $this->drupalPostForm('comment/reply/node/' . $node->id() . '/comment', $edit, t('Save'), [], 'comment-form');
+    $this->drupalGet('comment/reply/node/' . $node->id() . '/comment');
+    $this->submitForm($edit, $this->t('Save'), 'comment-form');
 
     if ($should_pass) {
       // There should be no error message.
       $this->assertCaptchaResponseAccepted();
       // Get node page and check that comment shows up.
       $this->drupalGet('node/' . $node->id());
-      $this->assertText($comment_subject, $message . ' Comment should show up on node page.', 'CAPTCHA');
-      $this->assertText($comment_body, $message . ' Comment should show up on node page.', 'CAPTCHA');
+      $this->assertSession()->pageTextContains($comment_subject, $message . ' Comment should show up on node page.', 'CAPTCHA');
+      $this->assertSession()->pageTextContains($comment_body, $message . ' Comment should show up on node page.', 'CAPTCHA');
     }
     else {
       // Check for error message.
-      $this->assertText(self::CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE, $message . ' Comment submission should be blocked.', 'CAPTCHA');
+      $this->assertSession()->pageTextContains(self::CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE, $message . ' Comment submission should be blocked.', 'CAPTCHA');
       // Get node page and check that comment is not present.
       $this->drupalGet('node/' . $node->id());
-      $this->assertNoText($comment_subject, $message . ' Comment should not show up on node page.', 'CAPTCHA');
-      $this->assertNoText($comment_body, $message . ' Comment should not show up on node page.', 'CAPTCHA');
+      $this->assertSession()->pageTextNotContains($comment_subject, $message . ' Comment should not show up on node page.', 'CAPTCHA');
+      $this->assertSession()->pageTextNotContains($comment_body, $message . ' Comment should not show up on node page.', 'CAPTCHA');
     }
   }
 
@@ -153,7 +193,8 @@ public function testCaptchaDescriptionAfterCommentPreview() {
     // Preview comment with correct CAPTCHA answer.
     $edit = $this->getCommentFormValues();
     $edit['captcha_response'] = 'Test 123';
-    $this->drupalPostForm('comment/reply/node/' . $node->id() . '/comment', $edit, t('Preview'));
+    $this->drupalGet('comment/reply/node/' . $node->id() . '/comment');
+    $this->submitForm($edit, $this->t('Preview'));
 
     // Check that there is no CAPTCHA after preview.
     $this->assertCaptchaPresence(FALSE);
@@ -180,7 +221,7 @@ public function testCaptchaSessionReuseOnNodeForms() {
     $edit = $this->getNodeFormValues();
     $edit['captcha_response'] = 'Test 123';
     $this->drupalGet('node/add/page');
-    $this->drupalPostForm(NULL, $edit, t('Preview'));
+    $this->submitForm($edit, $this->t('Preview'));
 
     $this->assertCaptchaPresence(FALSE);
   }
@@ -229,8 +270,9 @@ public function testLongFormId() {
     ];
 
     // Create intentionally long id Captcha Point.
-    $this->drupalPostForm(self::CAPTCHA_ADMIN_PATH . '/captcha-points/add', $form_values, t('Save'));
-    $this->assertRaw(t('Captcha Point for %label form was created.', ['%label' => $formId]));
+    $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha-points/add');
+    $this->submitForm($form_values, $this->t('Save'));
+    $this->assertSession()->responseContains($this->t('Captcha Point for %label form was created.', ['%label' => $formId]));
 
     // We need to log out to test the captcha.
     $this->drupalLogout();
diff --git a/web/modules/captcha/tests/src/Functional/CaptchaWebTestBase.php b/web/modules/captcha/tests/src/Functional/CaptchaWebTestBase.php
index 705684fd73c9bd9f9e11f93ac78bcc0af0a4f691..f4598ef8e01093f015c74484c43a35332d50c7c3 100755
--- a/web/modules/captcha/tests/src/Functional/CaptchaWebTestBase.php
+++ b/web/modules/captcha/tests/src/Functional/CaptchaWebTestBase.php
@@ -44,7 +44,7 @@ abstract class CaptchaWebTestBase extends BrowserTestBase {
    *
    * @var array
    */
-  public static $modules = ['captcha', 'comment'];
+  protected static $modules = ['captcha', 'comment'];
 
   /**
    * {@inheritdoc}
@@ -120,12 +120,12 @@ public function setUp() {
    */
   protected function assertCaptchaResponseAccepted() {
     // There should be no error message about unknown CAPTCHA session ID.
-    $this->assertNoText(self::CAPTCHA_UNKNOWN_CSID_ERROR_MESSAGE,
+    $this->assertSession()->pageTextNotContains(self::CAPTCHA_UNKNOWN_CSID_ERROR_MESSAGE,
       'CAPTCHA response should be accepted (known CSID).',
       'CAPTCHA'
     );
     // There should be no error message about wrong response.
-    $this->assertNoText(self::CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE,
+    $this->assertSession()->pageTextNotContains(self::CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE,
       'CAPTCHA response should be accepted (correct response).',
       'CAPTCHA'
     );
@@ -139,12 +139,12 @@ protected function assertCaptchaResponseAccepted() {
    */
   protected function assertCaptchaPresence($presence) {
     if ($presence) {
-      $this->assertText(_captcha_get_description(),
+      $this->assertSession()->pageTextContains(_captcha_get_description(),
         'There should be a CAPTCHA on the form.', 'CAPTCHA'
       );
     }
     else {
-      $this->assertNoText(_captcha_get_description(),
+      $this->assertSession()->pageTextNotContains(_captcha_get_description(),
         'There should be no CAPTCHA on the form.', 'CAPTCHA'
       );
     }
@@ -236,9 +236,9 @@ protected function getMathCaptchaSolutionFromForm($form_html_id = NULL) {
     else {
       $elements = $this->xpath('//form[@id="' . $form_html_id . '"]//div[contains(@class, "form-item-captcha-response")]/span[@class="field-prefix"]');
     }
-    $this->assert('pass', json_encode($elements));
+    $this->assertTrue('pass', json_encode($elements));
     $challenge = (string) $elements[0];
-    $this->assert('pass', $challenge);
+    $this->assertTrue('pass', $challenge);
     // Extract terms and operator from challenge.
     $matches = [];
     preg_match('/\\s*(\\d+)\\s*(-|\\+)\\s*(\\d+)\\s*=\\s*/', $challenge, $matches);
diff --git a/web/modules/captcha/tests/src/Kernel/Migrate/d7/MigrateCaptchaPointsTest.php b/web/modules/captcha/tests/src/Kernel/Migrate/d7/MigrateCaptchaPointsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b2148e4179e4a71f306c1f060cd772ebd5906839
--- /dev/null
+++ b/web/modules/captcha/tests/src/Kernel/Migrate/d7/MigrateCaptchaPointsTest.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace Drupal\Tests\captcha\Kernel\Migrate\d7;
+
+use Drupal\captcha\CaptchaPointInterface;
+use Drupal\captcha\Entity\CaptchaPoint;
+use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
+
+/**
+ * Migrates various configuration objects owned by the captcha module.
+ *
+ * @group captcha
+ */
+class MigrateCaptchaPointsTest extends MigrateDrupal7TestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['captcha'];
+
+  /**
+   * The expected captcha points from the Captcha fixture.
+   *
+   * @var array[]
+   */
+  protected $captchaPoints = [
+    [
+      'form_id' => 'comment_node_article_form',
+      'captcha_type' => 'captcha/Math',
+      'status' => TRUE,
+    ],
+    [
+      'form_id' => 'user_pass',
+      'captcha_type' => 'captcha/Math',
+      'status' => TRUE,
+    ],
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    $this->loadFixture(implode(DIRECTORY_SEPARATOR, [
+      DRUPAL_ROOT,
+      drupal_get_path('module', 'captcha'),
+      'tests',
+      'fixtures',
+      'drupal7.php',
+    ]));
+
+    $this->installEntitySchema('captcha_point');
+    $this->installSchema('captcha', ['captcha_sessions']);
+    $this->installConfig('captcha');
+
+    $migrations = [
+      'd7_captcha_points',
+    ];
+    $this->executeMigrations($migrations);
+
+    $this->captchaStorage = $this->container->get('entity_type.manager')
+      ->getStorage('captcha_point');
+  }
+
+  /**
+   * Tests a single captcha point type.
+   *
+   * @param string $form_id
+   *   The captcha point form id.
+   * @param string $captcha_type
+   *   The expected captcha type for the config.
+   * @param bool $status
+   *   The expected status for a captcha type.
+   */
+  protected function assertEntity(string $form_id, string $captcha_type, $status) {
+    /** @var \Drupal\captcha\CaptchaPointInterface $entity */
+    $entity = CaptchaPoint::load($form_id);
+    $this->assertInstanceOf(CaptchaPointInterface::class, $entity);
+    $this->assertSame($form_id, $entity->getFormId());
+    $this->assertSame($captcha_type, $entity->getCaptchaType());
+    $this->assertSame($status, $entity->status());
+  }
+
+  /**
+   * Tests that all expected configuration gets migrated.
+   */
+  public function testCaptchaPointsMigration() {
+    // Test captcha points.
+    foreach ($this->captchaPoints as $captcha_point) {
+      $this->assertEntity($captcha_point['form_id'], $captcha_point['captcha_type'], $captcha_point['status']);
+    }
+  }
+
+}
diff --git a/web/modules/captcha/tests/src/Kernel/Migrate/d7/MigrateCaptchaSimpleConfigurationTest.php b/web/modules/captcha/tests/src/Kernel/Migrate/d7/MigrateCaptchaSimpleConfigurationTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..82fa0447e038d2fa294bf44a21686222d9d67514
--- /dev/null
+++ b/web/modules/captcha/tests/src/Kernel/Migrate/d7/MigrateCaptchaSimpleConfigurationTest.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace Drupal\Tests\captcha\Kernel\Migrate\d7;
+
+use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
+
+/**
+ * Migrates various configuration objects owned by the captcha module.
+ *
+ * @group captcha
+ */
+class MigrateCaptchaSimpleConfigurationTest extends MigrateDrupal7TestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['captcha'];
+
+  /**
+   * The expected configuration from the Captcha fixture.
+   *
+   * @var array[]
+   */
+  protected $expectedConfig = [
+    'captcha.settings' => [
+      'enabled_default' => 1,
+      'default_challenge' => 'captcha/Math',
+      'description' => 'This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.',
+      'administration_mode' => TRUE,
+      'allow_on_admin_pages' => FALSE,
+      'add_captcha_description' => TRUE,
+      'default_validation' => 1,
+      'persistence' => 1,
+      'enable_stats' => TRUE,
+      'log_wrong_responses' => TRUE,
+    ],
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    $this->loadFixture(implode(DIRECTORY_SEPARATOR, [
+      DRUPAL_ROOT,
+      drupal_get_path('module', 'captcha'),
+      'tests',
+      'fixtures',
+      'drupal7.php',
+    ]));
+
+    $migrations = [
+      'd7_captcha_settings',
+    ];
+    $this->executeMigrations($migrations);
+  }
+
+  /**
+   * Tests that all expected configuration gets migrated.
+   */
+  public function testConfigurationMigration() {
+    // Test Config.
+    foreach ($this->expectedConfig as $config_id => $values) {
+      $actual = \Drupal::config($config_id)->get();
+      $this->assertSame($values, $actual);
+    }
+  }
+
+}