diff --git a/config/global.ini.php b/config/global.ini.php
index 0461f629fb307e4b5b12b022c7bb10ec5bd0ca2c..2793ca1b52fac51337fb078be8f9dade87284dbd 100644
--- a/config/global.ini.php
+++ b/config/global.ini.php
@@ -772,6 +772,7 @@ Plugins[] = TestRunner
 Plugins[] = BulkTracking
 Plugins[] = Resolution
 Plugins[] = DevicePlugins
+Plugins[] = Intl
 
 [PluginsInstalled]
 PluginsInstalled[] = Diagnostics
@@ -781,6 +782,7 @@ PluginsInstalled[] = UsersManager
 PluginsInstalled[] = SitesManager
 PluginsInstalled[] = Installation
 PluginsInstalled[] = Monolog
+PluginsInstalled[] = Intl
 
 [APISettings]
 ; Any key/value pair can be added in this section, they will be available via the REST call
diff --git a/core/Plugin/Manager.php b/core/Plugin/Manager.php
index ce491935ef6f47b95b38d4ea11f80f99181fa8f4..cf7cc09baed435ff65dbe21c37f85789a812dfdc 100644
--- a/core/Plugin/Manager.php
+++ b/core/Plugin/Manager.php
@@ -73,6 +73,7 @@ class Manager
         'Installation',
         'SitesManager',
         'UsersManager',
+        'Intl',
         'API',
         'Proxy',
         'LanguagesManager',
diff --git a/plugins/Intl/Commands/GenerateIntl.php b/plugins/Intl/Commands/GenerateIntl.php
new file mode 100644
index 0000000000000000000000000000000000000000..c0a524b28859e4923b2139eee6933b7610f66eda
--- /dev/null
+++ b/plugins/Intl/Commands/GenerateIntl.php
@@ -0,0 +1,260 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+
+namespace Piwik\Plugins\Intl\Commands;
+
+use Piwik\Container\StaticContainer;
+use Piwik\Development;
+use Piwik\Filesystem;
+use Piwik\Http;
+use Piwik\Plugin\ConsoleCommand;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * Console Command to generate Intl-data files for Piwik
+ *
+ * This script uses the master data of unicode-cldr/cldr-localenames-full repository to fetch available translations
+ */
+class GenerateIntl extends ConsoleCommand
+{
+    public function isEnabled()
+    {
+        return Development::isEnabled();
+    }
+
+    protected function configure()
+    {
+        $this->setName('translations:generate-intl-data')
+            ->setDescription('Generates Intl-data for Piwik');
+    }
+
+    protected function transformLangCode($langCode)
+    {
+        if (substr_count($langCode, '-') == 1) {
+            $langCodeParts = explode('-', $langCode, 2);
+            return sprintf('%s-%s', $langCodeParts[0], strtoupper($langCodeParts[1]));
+        }
+        return $langCode;
+    }
+
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        $piwikLanguages = \Piwik\Plugins\LanguagesManager\API::getInstance()->getAvailableLanguages();
+
+        $aliasesUrl = 'https://raw.githubusercontent.com/unicode-cldr/cldr-core/master/supplemental/aliases.json';
+        $aliasesData = Http::fetchRemoteFile($aliasesUrl);
+        $aliasesData = json_decode($aliasesData, true);
+        $aliasesData = $aliasesData['supplemental']['metadata']['alias']['languageAlias'];
+
+        $writePath = Filesystem::getPathToPiwikRoot() . '/plugins/Intl/lang/%s.json';
+
+        foreach ($piwikLanguages AS $langCode) {
+
+            if ($langCode == 'dev') {
+                continue;
+            }
+
+            $requestLangCode = $transformedLangCode = $this->transformLangCode($langCode);
+
+            if (array_key_exists($requestLangCode, $aliasesData)) {
+                $requestLangCode = $aliasesData[$requestLangCode]['_replacement'];
+            }
+
+            // fix some locales
+            $localFixes = array(
+                'pt' => 'pt-PT',
+                'pt-br' => 'pt',
+                'zh-cn' => 'zh-Hans',
+                'zh-tw' => 'zh-Hant'
+            );
+
+            if (array_key_exists($langCode, $localFixes)) {
+                $requestLangCode = $localFixes[$langCode];
+            }
+
+            $translations = (array)@json_decode(file_get_contents(sprintf($writePath, $langCode)), true);
+
+            $this->fetchLanguageData($output, $transformedLangCode, $requestLangCode, $translations);
+            $this->fetchTerritoryData($output, $transformedLangCode, $requestLangCode, $translations);
+            $this->fetchCalendarData($output, $transformedLangCode, $requestLangCode, $translations);
+
+            ksort($translations['Intl']);
+
+            file_put_contents(sprintf($writePath, $langCode), json_encode($translations, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
+        }
+    }
+
+    protected function getEnglishLanguageName($code)
+    {
+        $languageDataUrl = 'https://raw.githubusercontent.com/unicode-cldr/cldr-localenames-full/master/main/%s/languages.json';
+
+        static $languageData = array();
+
+        try {
+            if (empty($languageData)) {
+                $languageData = Http::fetchRemoteFile(sprintf($languageDataUrl, 'en'));
+                $languageData = json_decode($languageData, true);
+                $languageData = $languageData['main']['en']['localeDisplayNames']['languages'];
+            }
+
+            return (array_key_exists($code, $languageData) && $languageData[$code] != $code) ? $languageData[$code] : '';
+        } catch (\Exception $e) {
+        }
+
+        return '';
+    }
+
+    protected function fetchLanguageData(OutputInterface $output, $langCode, $requestLangCode, &$translations)
+    {
+        $languageCodes = array_keys(StaticContainer::get('Piwik\Intl\Data\Provider\LanguageDataProvider')->getLanguageList());
+
+        $languageDataUrl = 'https://raw.githubusercontent.com/unicode-cldr/cldr-localenames-full/master/main/%s/languages.json';
+
+        try {
+            $languageData = Http::fetchRemoteFile(sprintf($languageDataUrl, $requestLangCode));
+            $languageData = json_decode($languageData, true);
+            $languageData = $languageData['main'][$requestLangCode]['localeDisplayNames']['languages'];
+
+            if (empty($languageData)) {
+                throw new \Exception();
+            }
+
+            foreach ($languageCodes AS $code) {
+                if (!empty($languageData[$code]) && $languageData[$code] != $code) {
+                    $translations['Intl']['Language_' . $code] = $languageData[$code];
+                }
+            }
+
+            if (array_key_exists($langCode, $languageData) && $languageData[$langCode] != $langCode) {
+                $translations['Intl']['OriginalLanguageName'] = $languageData[$langCode];
+            } else if (array_key_exists($requestLangCode, $languageData) && $languageData[$requestLangCode] != $requestLangCode) {
+                $translations['Intl']['OriginalLanguageName'] = $languageData[$requestLangCode];
+            }
+            $translations['Intl']['EnglishLanguageName'] = $this->getEnglishLanguageName($langCode) ? $this->getEnglishLanguageName($langCode) : $this->getEnglishLanguageName($requestLangCode);
+
+            $output->writeln('Saved language data for ' . $langCode);
+        } catch (\Exception $e) {
+            $output->writeln('Unable to import language data for ' . $langCode);
+        }
+    }
+
+    protected function fetchTerritoryData(OutputInterface $output, $langCode, $requestLangCode, &$translations)
+    {
+        $territoryDataUrl = 'https://raw.githubusercontent.com/unicode-cldr/cldr-localenames-full/master/main/%s/territories.json';
+
+        $countryCodes = array_keys(StaticContainer::get('Piwik\Intl\Data\Provider\RegionDataProvider')->getCountryList());
+        $countryCodes = array_map('strtoupper', $countryCodes);
+
+        $continentMapping = array(
+            "afr" => "002",
+            "amc" => "013",
+            "amn" => "003",
+            "ams" => "005",
+            "ant" => "AQ",
+            "asi" => "142",
+            "eur" => "150",
+            "oce" => "009"
+        );
+
+        try {
+            $territoryData = Http::fetchRemoteFile(sprintf($territoryDataUrl, $requestLangCode));
+            $territoryData = json_decode($territoryData, true);
+            $territoryData = $territoryData['main'][$requestLangCode]['localeDisplayNames']['territories'];
+
+            foreach ($countryCodes AS $code) {
+                if (!empty($territoryData[$code]) && $territoryData[$code] != $code) {
+                    $translations['Intl']['Country_' . $code] = $territoryData[$code];
+                }
+            }
+
+            foreach ($continentMapping as $shortCode => $code) {
+                if (!empty($territoryData[$code]) && $territoryData[$code] != $code) {
+                    $translations['Intl']['Continent_' . $shortCode] = $territoryData[$code];
+                }
+            }
+
+            $output->writeln('Saved territory data for ' . $langCode);
+        } catch (\Exception $e) {
+            $output->writeln('Unable to import territory data for ' . $langCode);
+        }
+    }
+
+    protected function fetchCalendarData(OutputInterface $output, $langCode, $requestLangCode, &$translations)
+    {
+        $calendarDataUrl = 'https://raw.githubusercontent.com/unicode-cldr/cldr-dates-full/master/main/%s/ca-gregorian.json';
+
+        try {
+            $calendarData = Http::fetchRemoteFile(sprintf($calendarDataUrl, $requestLangCode));
+            $calendarData = json_decode($calendarData, true);
+            $calendarData = $calendarData['main'][$requestLangCode]['dates']['calendars']['gregorian'];
+
+            for ($i = 1; $i <= 12; $i++) {
+                $translations['Intl']['ShortMonth_' . $i] = $calendarData['months']['format']['abbreviated'][$i];
+                $translations['Intl']['LongMonth_' . $i] = $calendarData['months']['format']['wide'][$i];
+            }
+
+            $days = array(
+                1 => 'mon',
+                2 => 'tue',
+                3 => 'wed',
+                4 => 'thu',
+                5 => 'fri',
+                6 => 'sat',
+                7 => 'sun'
+            );
+
+            foreach ($days AS $nr => $day) {
+                $translations['Intl']['ShortDay_' . $nr] = $calendarData['days']['format']['abbreviated'][$day];
+                $translations['Intl']['LongDay_' . $nr] = $calendarData['days']['format']['wide'][$day];
+            }
+
+            $days = array(
+                'Mo' => 'mon',
+                'Tu' => 'tue',
+                'We' => 'wed',
+                'Th' => 'thu',
+                'Fr' => 'fri',
+                'Sa' => 'sat',
+                'Su' => 'sun'
+            );
+
+            foreach ($days AS $nr => $day) {
+                $translations['Intl']['Day' . $nr] = $calendarData['days']['format']['short'][$day];
+            }
+
+
+            $output->writeln('Saved calendar data for ' . $langCode);
+        } catch (\Exception $e) {
+            $output->writeln('Unable to import calendar data for ' . $langCode);
+        }
+
+        $dateFieldsUrl = 'https://raw.githubusercontent.com/unicode-cldr/cldr-dates-full/master/main/%s/dateFields.json';
+
+        try {
+            $dateFieldData = Http::fetchRemoteFile(sprintf($dateFieldsUrl, $requestLangCode));
+            $dateFieldData = json_decode($dateFieldData, true);
+            $dateFieldData = $dateFieldData['main'][$requestLangCode]['dates']['fields'];
+
+            #$translations['Intl']['Period_Week'] = $dateFieldData['week']['displayName'];
+            #$translations['Intl']['Period_Year'] = $dateFieldData['year']['displayName'];
+            #$translations['Intl']['Period_Day'] = $dateFieldData['day']['displayName'];
+            #$translations['Intl']['Period_Month'] = $dateFieldData['month']['displayName'];
+            $translations['Intl']['YearShort'] = $dateFieldData['year-narrow']['displayName'];
+            $translations['Intl']['Today'] = $dateFieldData['day']['relative-type-0'];
+            $translations['Intl']['Yesterday'] = $dateFieldData['day']['relative-type--1'];
+
+            $output->writeln('Saved date fields for ' . $langCode);
+        } catch (\Exception $e) {
+            $output->writeln('Unable to import date fields for ' . $langCode);
+        }
+    }
+
+
+}
diff --git a/plugins/Intl/Intl.php b/plugins/Intl/Intl.php
new file mode 100644
index 0000000000000000000000000000000000000000..29099884378d08dba80f90ea9e9d57a13c87e07e
--- /dev/null
+++ b/plugins/Intl/Intl.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Intl;
+
+class Intl extends \Piwik\Plugin
+{
+
+}
diff --git a/plugins/LanguagesManager/Commands/GenerateIntl.php b/plugins/LanguagesManager/Commands/GenerateIntl.php
deleted file mode 100644
index 5b8af855bda2cd588451dcf7fd86950e9b661d84..0000000000000000000000000000000000000000
--- a/plugins/LanguagesManager/Commands/GenerateIntl.php
+++ /dev/null
@@ -1,115 +0,0 @@
-<?php
-/**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
-
-namespace Piwik\Plugins\LanguagesManager\Commands;
-
-use Aws\CloudFront\Exception\Exception;
-use Piwik\Container\StaticContainer;
-use Piwik\Filesystem;
-use Piwik\Http;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
-
-/**
- * Console Command to generate Intl-data files for Piwik
- *
- * This script uses the master data of unicode-cldr/cldr-localenames-full repository to fetch available translations
- */
-class GenerateIntl extends TranslationBase
-{
-    protected function configure()
-    {
-        $this->setName('translations:generate-intl-data')
-             ->setDescription('Generates Intl-data for Piwik');
-    }
-
-    protected function execute(InputInterface $input, OutputInterface $output)
-    {
-        $piwikLanguages = \Piwik\Plugins\LanguagesManager\API::getInstance()->getAvailableLanguages();
-        $languageCodes = array_keys(StaticContainer::get('Piwik\Intl\Data\Provider\LanguageDataProvider')->getLanguageList());
-        $countryCodes = array_keys(StaticContainer::get('Piwik\Intl\Data\Provider\RegionDataProvider')->getCountryList());
-        $countryCodes = array_map('strtoupper', $countryCodes);
-
-        $languageDataUrl = 'https://raw.githubusercontent.com/unicode-cldr/cldr-localenames-full/master/main/%s/languages.json';
-        $languageWritePath = Filesystem::getPathToPiwikRoot() . '/core/Intl/Data/Resources/languages/%s.json';
-
-        $countryDataUrl = 'https://raw.githubusercontent.com/unicode-cldr/cldr-localenames-full/master/main/%s/territories.json';
-        $countryWritePath = Filesystem::getPathToPiwikRoot() . '/core/Intl/Data/Resources/countries/%s.json';
-
-
-        foreach ($piwikLanguages AS $langCode) {
-
-            if ($langCode == 'dev') {
-                continue;
-            }
-
-            $requestLangCode = $langCode;
-
-            if (substr_count($langCode, '-') == 1) {
-                $langCodeParts = explode('-', $langCode, 2);
-                $requestLangCode = sprintf('%s-%s', $langCodeParts[0], strtoupper($langCodeParts[1]));
-            }
-
-            if ($langCode == 'zh-cn') {
-                $requestLangCode = 'zh-Hans';
-            }
-
-            if ($langCode == 'zh-tw') {
-                $requestLangCode = 'zh-Hant';
-            }
-
-            try {
-                $languageData = Http::fetchRemoteFile(sprintf($languageDataUrl, $requestLangCode));
-                $languageData = json_decode($languageData, true);
-                $languageData = $languageData['main'][$requestLangCode]['localeDisplayNames']['languages'];
-
-                $translations = (array) @json_decode(file_get_contents(sprintf($languageWritePath, $langCode)));
-
-                if (empty($translations)) {
-                    $translations = array_fill_keys($languageCodes, '');
-                }
-
-                foreach ($languageCodes AS $code) {
-                    if (!empty($languageData[$code]) && $languageData[$code] != $code) {
-                        $translations[$code] = $languageData[$code];
-                    }
-                }
-
-                file_put_contents(sprintf($languageWritePath, $langCode), json_encode($translations, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE));
-                $output->writeln('Saved language data for '.$langCode);
-            } catch (Exception $e) {
-                $output->writeln('Unable to import language data for '.$langCode);
-            }
-
-            try {
-                $countryData = Http::fetchRemoteFile(sprintf($countryDataUrl, $requestLangCode));
-                $countryData = json_decode($countryData, true);
-                $countryData = $countryData['main'][$requestLangCode]['localeDisplayNames']['territories'];
-
-                $translations = (array) @json_decode(file_get_contents(sprintf($countryWritePath, $langCode)));
-
-                if (empty($translations)) {
-                    $translations = array_fill_keys($countryCodes, '');
-                }
-
-                foreach ($countryCodes AS $code) {
-                    if (!empty($countryData[$code]) && $countryData[$code] != $code) {
-                        $translations[$code] = $countryData[$code];
-                    }
-                }
-
-                file_put_contents(sprintf($countryWritePath, $langCode), json_encode($translations, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE));
-                $output->writeln('Saved country data for '.$langCode);
-            } catch (Exception $e) {
-                $output->writeln('Unable to import country data for '.$langCode);
-            }
-
-        }
-    }
-}