diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
index a2a754f..7dedbf6 100644
--- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php
+++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
@@ -284,6 +284,9 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
// @see https://www.drupal.org/node/2208429
\Drupal::service('theme_handler')->refreshInfo();
+ // In order to make uninstalling transactional if anything uses routes.
+ \Drupal::service('router.route_provider')->rebuildRoutesIfUsed();
+
// Allow the module to perform install tasks.
$this->moduleHandler->invoke($module, 'install');
@@ -388,6 +391,9 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
// Remove all configuration belonging to the module.
\Drupal::service('config.manager')->uninstall('module', $module);
+ // In order to make uninstalling transactional if anything uses routes.
+ \Drupal::service('router.route_provider')->rebuildRoutesIfUsed();
+
// Notify interested components that this module's entity types are being
// deleted. For example, a SQL-based storage handler can use this as an
// opportunity to drop the corresponding database tables.
diff --git a/core/lib/Drupal/Core/Routing/RouteProvider.php b/core/lib/Drupal/Core/Routing/RouteProvider.php
index be647e1..bba9d71 100644
--- a/core/lib/Drupal/Core/Routing/RouteProvider.php
+++ b/core/lib/Drupal/Core/Routing/RouteProvider.php
@@ -90,6 +90,13 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
protected $pathProcessor;
/**
+ * Something ugly.
+ *
+ * @var bool
+ */
+ protected $rebuildRoutesIfUsed = FALSE;
+
+ /**
* Cache ID prefix used to load routes.
*/
const ROUTE_LOAD_CID_PREFIX = 'route_provider.route_load:';
@@ -210,6 +217,7 @@ public function preLoadRoutes($names) {
$routes = $cache->data;
}
else {
+ $this->checkAndRebuildRoutes();
try {
$result = $this->connection->query('SELECT name, route FROM {' . $this->connection->escapeTable($this->tableName) . '} WHERE name IN ( :names[] )', array(':names[]' => $routes_to_load));
}
@@ -338,6 +346,8 @@ protected function getRoutesByPath($path) {
return $collection;
}
+ $this->checkAndRebuildRoutes();
+
// The >= check on number_parts allows us to match routes with optional
// trailing wildcard parts as long as the pattern matches, since we
// dump the route pattern without those optional parts.
@@ -387,6 +397,7 @@ public function reset() {
$this->routes = array();
$this->serializedRoutes = array();
$this->cacheTagInvalidator->invalidateTags(['routes']);
+ $this->rebuildRoutesIfUsed = FALSE;
}
/**
@@ -401,6 +412,7 @@ static function getSubscribedEvents() {
* {@inheritdoc}
*/
public function getRoutesPaged($offset, $length = NULL) {
+ $this->checkAndRebuildRoutes();
$select = $this->connection->select($this->tableName, 'router')
->fields('router', ['name', 'route']);
@@ -425,4 +437,22 @@ public function getRoutesCount() {
return $this->connection->query("SELECT COUNT(*) FROM {" . $this->connection->escapeTable($this->tableName) . "}")->fetchField();
}
+ /**
+ * Checks if the rebuildRoutesIfUsed is set and rebuilds the routes.
+ */
+ protected function checkAndRebuildRoutes() {
+ if ($this->rebuildRoutesIfUsed) {
+ \Drupal::service('router.builder')->rebuild();
+ }
+ }
+
+ /**
+ * Causes the first use of the route provider to rebuild routes.
+ */
+ public function rebuildRoutesIfUsed() {
+ $this->rebuildRoutesIfUsed = TRUE;
+ // Do not return $this because this method is not supposed to be nice to
+ // use.
+ }
+
}
diff --git a/core/modules/content_translation/content_translation.install b/core/modules/content_translation/content_translation.install
index 8465fe3..0f8a184 100644
--- a/core/modules/content_translation/content_translation.install
+++ b/core/modules/content_translation/content_translation.install
@@ -5,6 +5,8 @@
* Installation functions for Content Translation module.
*/
+use \Drupal\Core\Url;
+
/**
* Implements hook_install().
*/
@@ -12,6 +14,21 @@ function content_translation_install() {
// Assign a fairly low weight to ensure our implementation of
// hook_module_implements_alter() is run among the last ones.
module_set_weight('content_translation', 10);
+
+ // Translation works when at least two languages are added.
+ if (count(\Drupal::languageManager()->getLanguages()) < 2) {
+ $t_args = [
+ ':language_url' => Url::fromRoute('entity.configurable_language.collection')->toString()
+ ];
+ $message = t('This site has only a single language enabled. Add at least one more language in order to translate content.', $t_args);
+ drupal_set_message($message, 'warning');
+ }
+ // Point the user to the content translation settings.
+ $t_args = [
+ ':settings_url' => Url::fromRoute('language.content_settings_page')->toString()
+ ];
+ $message = t('Enable translation for content types, taxonomy vocabularies, accounts, or any other element you wish to translate.', $t_args);
+ drupal_set_message($message, 'warning');
}
/**
diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module
index f70e4ca..083fc4c 100644
--- a/core/modules/content_translation/content_translation.module
+++ b/core/modules/content_translation/content_translation.module
@@ -14,7 +14,6 @@
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
-use Drupal\Core\Url;
/**
* Implements hook_help().
@@ -50,28 +49,6 @@ function content_translation_help($route_name, RouteMatchInterface $route_match)
}
/**
- * Implements hook_modules_installed().
- */
-function content_translation_modules_installed(array $modules) {
- if (in_array('content_translation', $modules)) {
- // Translation works when at least two languages are added.
- if (count(\Drupal::languageManager()->getLanguages()) < 2) {
- $t_args = [
- ':language_url' => Url::fromRoute('entity.configurable_language.collection')->toString()
- ];
- $message = t('This site has only a single language enabled. Add at least one more language in order to translate content.', $t_args);
- drupal_set_message($message, 'warning');
- }
- // Point the user to the content translation settings.
- $t_args = [
- ':settings_url' => Url::fromRoute('language.content_settings_page')->toString()
- ];
- $message = t('Enable translation for content types, taxonomy vocabularies, accounts, or any other element you wish to translate.', $t_args);
- drupal_set_message($message, 'warning');
- }
-}
-
-/**
* Implements hook_module_implements_alter().
*/
function content_translation_module_implements_alter(&$implementations, $hook) {