locale.install

Install, update, and uninstall functions for the Locale module.

File

drupal/core/modules/locale/locale.install
View source
<?php

/**
 * @file
 * Install, update, and uninstall functions for the Locale module.
 */
use Drupal\Core\Language\Language;

/**
 * Implements hook_install().
 */
function locale_install() {

  // Create the interface translations directory and ensure it's writable.
  if (!($directory = config('locale.settings')
    ->get('translation.path'))) {
    $directory = conf_path() . '/files/translations';
    config('locale.settings')
      ->set('translation.path', $directory)
      ->save();
  }
  file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
}

/**
 * Implements hook_uninstall().
 */
function locale_uninstall() {
  $config = config('locale.settings');

  // Delete all JavaScript translation files.
  $locale_js_directory = 'public://' . $config
    ->get('javascript.directory');
  if (is_dir($locale_js_directory)) {
    $locale_javascripts = Drupal::state()
      ->get('locale.translation.javascript') ?: array();
    foreach ($locale_javascripts as $langcode => $file_suffix) {
      if (!empty($file_suffix)) {
        file_unmanaged_delete($locale_js_directory . '/' . $langcode . '_' . $file_suffix . '.js');
      }
    }

    // Delete the JavaScript translations directory if empty.
    if (!file_scan_directory($locale_js_directory, '/.*/')) {
      drupal_rmdir($locale_js_directory);
    }
  }

  // Clear variables.
  Drupal::state()
    ->delete('system.javascript_parsed');
  Drupal::state()
    ->delete('locale.translation.plurals');
  Drupal::state()
    ->delete('locale.translation.javascript');

  // Remove all node type language variables. Node module might have been
  // enabled, but may be disabled, so use a wildcard delete.
  db_delete('variable')
    ->condition('name', db_like('language_content_type_') . '%', 'LIKE')
    ->execute();
}

/**
 * Implements hook_schema().
 */
function locale_schema() {
  $schema['locales_source'] = array(
    'description' => 'List of English source strings.',
    'fields' => array(
      'lid' => array(
        'type' => 'serial',
        'not null' => TRUE,
        'description' => 'Unique identifier of this string.',
      ),
      'source' => array(
        'type' => 'text',
        'mysql_type' => 'blob',
        'not null' => TRUE,
        'description' => 'The original string in English.',
      ),
      'context' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
        'description' => 'The context this string applies to.',
      ),
      'version' => array(
        'type' => 'varchar',
        'length' => 20,
        'not null' => TRUE,
        'default' => 'none',
        'description' => 'Version of Drupal where the string was last used (for locales optimization).',
      ),
    ),
    'primary key' => array(
      'lid',
    ),
    'indexes' => array(
      'source_context' => array(
        array(
          'source',
          30,
        ),
        'context',
      ),
    ),
  );
  $schema['locales_target'] = array(
    'description' => 'Stores translated versions of strings.',
    'fields' => array(
      'lid' => array(
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
        'description' => 'Source string ID. References {locales_source}.lid.',
      ),
      'translation' => array(
        'type' => 'text',
        'mysql_type' => 'blob',
        'not null' => TRUE,
        'description' => 'Translation string value in this language.',
      ),
      'language' => array(
        'type' => 'varchar',
        'length' => 12,
        'not null' => TRUE,
        'default' => '',
        'description' => 'Language code. References {language}.langcode.',
      ),
      'customized' => array(
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
        // LOCALE_NOT_CUSTOMIZED
        'description' => 'Boolean indicating whether the translation is custom to this site.',
      ),
    ),
    'primary key' => array(
      'language',
      'lid',
    ),
    'foreign keys' => array(
      'locales_source' => array(
        'table' => 'locales_source',
        'columns' => array(
          'lid' => 'lid',
        ),
      ),
    ),
    'indexes' => array(
      'lid' => array(
        'lid',
      ),
    ),
  );
  $schema['locales_location'] = array(
    'description' => 'Location information for source strings.',
    'fields' => array(
      'lid' => array(
        'type' => 'serial',
        'not null' => TRUE,
        'description' => 'Unique identifier of this location.',
      ),
      'sid' => array(
        'type' => 'int',
        'not null' => TRUE,
        'description' => 'Unique identifier of this string.',
      ),
      'type' => array(
        'type' => 'varchar',
        'length' => 50,
        'not null' => TRUE,
        'default' => '',
        'description' => 'The location type (file, config, path, etc).',
      ),
      'name' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
        'description' => 'Type dependent location information (file name, path, etc).',
      ),
      'version' => array(
        'type' => 'varchar',
        'length' => 20,
        'not null' => TRUE,
        'default' => 'none',
        'description' => 'Version of Drupal where the location was found.',
      ),
    ),
    'primary key' => array(
      'lid',
    ),
    'foreign keys' => array(
      'locales_source' => array(
        'table' => 'locales_source',
        'columns' => array(
          'sid' => 'lid',
        ),
      ),
    ),
    'indexes' => array(
      'string_id' => array(
        'sid',
      ),
      'string_type' => array(
        'sid',
        'type',
      ),
    ),
  );
  $schema['locale_file'] = array(
    'description' => 'File import status information for interface translation files.',
    'fields' => array(
      'project' => array(
        'type' => 'varchar',
        'length' => '255',
        'not null' => TRUE,
        'default' => '',
        'description' => 'A unique short name to identify the project the file belongs to.',
      ),
      'langcode' => array(
        'type' => 'varchar',
        'length' => '12',
        'not null' => TRUE,
        'default' => '',
        'description' => 'Language code of this translation. References {language}.langcode.',
      ),
      'filename' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
        'description' => 'Filename of the imported file.',
      ),
      'version' => array(
        'type' => 'varchar',
        'length' => '128',
        'not null' => TRUE,
        'default' => '',
        'description' => 'Version tag of the imported file.',
      ),
      'uri' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
        'description' => 'URI of the remote file, the resulting local file or the locally imported file.',
      ),
      'timestamp' => array(
        'type' => 'int',
        'not null' => FALSE,
        'default' => 0,
        'description' => 'Unix timestamp of the imported file.',
      ),
      'last_checked' => array(
        'type' => 'int',
        'not null' => FALSE,
        'default' => 0,
        'description' => 'Unix timestamp of the last time this translation was confirmed to be the most recent release available.',
      ),
    ),
    'primary key' => array(
      'project',
      'langcode',
    ),
  );
  $schema['locale_project'] = array(
    'description' => 'Translation status information for projects and server data.',
    'fields' => array(
      'name' => array(
        'description' => 'A unique short name to identify the project.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
      ),
      'project_type' => array(
        'description' => 'Project type: core, module, or theme.',
        'type' => 'varchar',
        'length' => 15,
        'not null' => TRUE,
      ),
      'core' => array(
        // http://drupal.org/node/542202#core has an example.
        'description' => 'Core compatibility string for this project, for example: 8.x',
        'type' => 'varchar',
        'length' => 4,
        'not null' => TRUE,
        'default' => '',
      ),
      'version' => array(
        // http://drupal.org/node/467026 has examples.
        'description' => 'The version release of the project, for example: 8.x-2.1 or 8.x-1.0-dev',
        'type' => 'varchar',
        'length' => 128,
        'not null' => TRUE,
        'default' => '',
      ),
      'server_pattern' => array(
        'description' => 'Pattern of path and name of the gettext file at the translation server.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'status' => array(
        // locale.compare.inc gives possible values for status.
        'description' => 'The status of the project. Possible values are: 1 = enabled, 0 = disabled.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 1,
      ),
    ),
    'primary key' => array(
      'name',
    ),
  );
  return $schema;
}

/**
 * Implements hook_requirements().
 */
function locale_requirements($phase) {
  $requirements = array();
  if ($phase == 'runtime') {
    $available_updates = array();
    $updates_not_found = array();
    $languages = locale_translatable_language_list();
    if ($languages) {

      // Determine the status of the translation updates per lanuage.
      $status = Drupal::state()
        ->get('locale.translation_status');
      if ($status) {
        foreach ($status as $project_id => $project) {
          foreach ($project as $langcode => $project_info) {
            if (!isset($project_info->type)) {
              $updates_not_found[$langcode] = $languages[$langcode]->name;
            }
            elseif ($project_info->type == LOCALE_TRANSLATION_LOCAL || $project_info->type == LOCALE_TRANSLATION_REMOTE) {
              $available_updates[$langcode] = $languages[$langcode]->name;
            }
          }
        }
        if ($available_updates || $updates_not_found) {
          if ($available_updates) {
            $requirements['locale_translation'] = array(
              'title' => 'Translation update status',
              'value' => l(t('Updates available'), 'admin/reports/translations'),
              'severity' => REQUIREMENT_WARNING,
              'description' => t('Updates available for: @languages. See the <a href="@updates">Available translation updates</a> page for more information.', array(
                '@languages' => implode(', ', $available_updates),
                '@updates' => url('admin/reports/translations'),
              )),
            );
          }
          else {
            $requirements['locale_translation'] = array(
              'title' => 'Translation update status',
              'value' => t('Missing translations'),
              'severity' => REQUIREMENT_INFO,
              'description' => t('Missing translations for: @languages. See the <a href="@updates">Available translation updates</a> page for more information.', array(
                '@languages' => implode(', ', $updates_not_found),
                '@updates' => url('admin/reports/translations'),
              )),
            );
          }
        }
        else {
          $requirements['locale_translation'] = array(
            'title' => 'Translation update status',
            'value' => t('Up to date'),
            'severity' => REQUIREMENT_OK,
          );
        }
      }
      else {
        $requirements['locale_translation'] = array(
          'title' => 'Translation update status',
          'value' => l(t('Can not determine status'), 'admin/reports/translations'),
          'severity' => REQUIREMENT_WARNING,
          'description' => t('No translation status is available. See the <a href="@updates">Available translation updates</a> page for more information.', array(
            '@updates' => url('admin/reports/translations'),
          )),
        );
      }
    }
  }
  return $requirements;
}

/**
 * @addtogroup updates-7.x-to-8.x
 * @{
 */

/**
 * Drops textgroup support.
 *
 * Update assumes i18n migrated this data before the update happened. Core never
 * used textgroups for anything, so it is not our job to find a place for the
 * data elsewhere.
 */
function locale_update_8000() {
  $subquery = db_select('locales_source', 'ls')
    ->fields('ls', array(
    'lid',
  ))
    ->condition('ls.textgroup', 'default', '<>');
  db_delete('locales_target')
    ->condition('lid', $subquery, 'IN')
    ->execute();
  db_delete('locales_source')
    ->condition('textgroup', 'default', '<>')
    ->execute();
  db_drop_field('locales_source', 'textgroup');
}

/**
 * Language type 'language' renamed to 'language_interface'.
 *
 * @ingroup config_upgrade
 */
function locale_update_8001() {

  // Only change language_types if we had this setting saved. Keep order
  // of types because that is significant for value dependency.
  $types = update_variable_get('language_types', NULL);
  if (!empty($types) && isset($types['language'])) {
    $new_types = array();
    foreach ($types as $key => $type) {
      $new_types[$key == 'language' ? 'language_interface' : $key] = $type;
    }
    update_variable_set('language_types', $new_types);
  }

  // Rename language_negotiation_language setting if exists.
  $setting = update_variable_get('language_negotiation_language', NULL);
  if ($setting !== NULL) {
    update_variable_set('language_negotiation_language_interface', $setting);
    update_variable_del('language_negotiation_language');
  }

  // Rename locale_language_providers_weight_language setting if exists.
  $weight = update_variable_get('locale_language_providers_weight_language', NULL);
  if ($weight !== NULL) {
    update_variable_set('locale_language_providers_weight_language_interface', $weight);
    update_variable_del('locale_language_providers_weight_language');
  }

  // Update block data in all core block related tables. Contributed modules
  // storing data for blocks will need to update for themselves.
  $block_tables = array(
    'block',
    'block_node_type',
    'block_role',
  );
  foreach ($block_tables as $table) {

    // Perform the update only if the language switcher block data is available.
    $block_data = db_query_range('SELECT 1 FROM {' . $table . '} WHERE delta = :delta AND module = :module', 0, 1, array(
      ':delta' => 'language',
      ':module' => 'locale',
    ))
      ->fetchField();
    if ($block_data) {

      // If block information is rebuilt before performing the update, we might
      // already have data for the new delta. In this case we need to remove it
      // to avoid integrity constraint violation errors.
      db_delete($table)
        ->condition('delta', 'language_interface')
        ->condition('module', 'locale')
        ->execute();
      db_update($table)
        ->fields(array(
        'delta' => 'language_interface',
      ))
        ->condition('delta', 'language')
        ->condition('module', 'locale')
        ->execute();
    }
  }
}

/**
 * Removes duplicates in {locales_source}.
 *
 * Aggressively removes duplicates that has not already been removed by
 * locale_update_7004() in Drupal 7.x.
 */
function locale_update_8002() {

  // Look up all duplicates.
  $results = db_query("SELECT source, context FROM {locales_source} GROUP BY source, context HAVING COUNT(*) > 1");

  // For each set of duplicates, select one row that should survive, preferably
  // one that has been translated, and delete the rest.
  foreach ($results as $row) {
    $lid = db_query("SELECT s.lid FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid WHERE s.source = :source AND s.context = :context ORDER BY translation IS NULL", array(
      ':source' => $row->source,
      ':context' => $row->context,
    ))
      ->fetchField();
    db_delete('locales_source')
      ->condition('source', $row->source)
      ->condition('context', $row->context)
      ->condition('lid', $lid, '<>')
      ->execute();
  }

  // Finally remove any rows from {locales_target} that refer to non-existing
  // lids.
  $subquery = db_select('locales_source', 't')
    ->fields('t', array(
    'lid',
  ));
  db_delete('locales_target')
    ->condition('lid', $subquery, 'NOT IN')
    ->execute();
}

/**
 * Converts language domains to new format.
 *
 * @ingroup config_upgrade
 */
function locale_update_8003() {
  $message = '';
  $config = config('language.negotiation');
  $domains = $config
    ->get('url.domains') ?: array();

  // $used_domains keeps track of the domain names in use.
  $used_domains = array();
  foreach ($domains as $langcode => $domain) {

    // Domain names can not contain protocol and/or ports.
    if (!empty($domain)) {
      $host = 'http://' . str_replace(array(
        'http://',
        'https://',
      ), '', $domain);
      if (parse_url($host, PHP_URL_HOST) != $domain) {
        $domains[$langcode] = parse_url($host, PHP_URL_HOST);
      }
      if (array_key_exists($domain, $used_domains)) {
        if (empty($message)) {
          $message = 'Some languages are using the same domain name, you should change these domain names at ' . l('URL language detection configuration', 'admin/config/regional/language/configure/url' . '.');
        }
      }
      else {
        $used_domains[$domain] = $domain;
      }
    }
  }
  $config
    ->set('url.domains', $domains)
    ->save();
  if (!empty($message)) {
    return $message;
  }
}

/**
 * Rename language providers to language negotiation methods.
 *
 * @ingroup config_upgrade
 */
function locale_update_8004() {
  $types = update_variable_get('language_types', NULL);
  if (!empty($types)) {
    foreach ($types as $type => $configurable) {

      // Rename the negotiation and language switch callback keys.
      $negotiation = update_variable_get('language_negotiation_' . $type, NULL);
      if (!empty($negotiation)) {
        foreach ($negotiation as $method_id => &$method) {
          if (isset($method['callbacks']['language'])) {
            $method['callbacks']['negotiation'] = $method['callbacks']['language'];
            unset($method['callbacks']['language']);
          }
          if (isset($method['callbacks']['switcher'])) {
            $method['callbacks']['language_switch'] = $method['callbacks']['switcher'];
            unset($method['callbacks']['switcher']);
          }
        }
        update_variable_set('language_negotiation_' . $type, $negotiation);
      }

      // Rename the language negotiation methods weight variable.
      $weight = update_variable_get('locale_language_providers_weight_' . $type, NULL);
      if ($weight !== NULL) {
        update_variable_set('language_negotiation_methods_weight_' . $type, $weight);
        update_variable_del('locale_language_providers_weight_' . $type);
      }
    }
  }
}

/**
 * Update plural interface translations to new format.
 *
 * See http://drupal.org/node/532512#comment-5679184 for the details of the
 * structures handled in this update.
 */
function locale_update_8005() {

  // Collect all LIDs that are sources to plural variants.
  $results = db_query("SELECT lid, plid FROM {locales_target} WHERE plural <> 0");
  $plural_lids = array();
  foreach ($results as $row) {

    // Need to collect both LID and PLID. The LID for the first (singular)
    // string can only be retrieved from the first plural's PLID given no
    // other indication. The last plural variant is never referenced, so we
    // need to store the LID directly for that. We never know whether we are
    // on the last plural though, so we always remember LID too.
    $plural_lids[] = $row->lid;
    $plural_lids[] = $row->plid;
  }
  $plural_lids = array_unique($plural_lids);
  if (!empty($plural_lids)) {

    // Look up all translations for these source strings. Ordering by language
    // will group the strings by language, the 'plid' order will get the strings
    // in singular/plural order and 'plural' will get them in precise sequential
    // order needed.
    $results = db_query("SELECT s.lid, s.source, t.translation, t.plid, t.plural, t.language FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid WHERE s.lid IN (:lids) ORDER BY t.language, t.plid, t.plural", array(
      ':lids' => $plural_lids,
    ));

    // Collect the strings into an array and combine values as we go.
    $strings = array();
    $parents_to_sources = array();
    $remove_lids = array();
    foreach ($results as $child) {
      $strings[$child->language][$child->lid] = array(
        'source' => array(
          $child->source,
        ),
        'translation' => array(
          $child->translation,
        ),
      );
      if (empty($child->plid)) {

        // Non-children strings point to themselves as parents. This makes it
        // easy to look up the utmost parents for any plurals.
        $parents_to_sources[$child->lid] = $child->lid;
      }
      else {

        // Children strings point to their utmost parents. Because we get data
        // in PLID order, we can ensure that all previous parents have data now,
        // so we can just copy the parent's data about their parent, etc.
        $parents_to_sources[$child->lid] = $parents_to_sources[$child->plid];

        // Append translation to the utmost parent's translation string.
        $utmost_parent =& $strings[$child->language][$parents_to_sources[$child->plid]];

        // Drop the Drupal-specific numbering scheme from the end of plural
        // formulas.
        $utmost_parent['translation'][] = str_replace('@count[' . $child->plural . ']', '@count', $child->translation);
        if (count($utmost_parent['source']) < 2) {

          // Append source to the utmost parent's source string only if it is
          // the plural variant. Further Drupal specific plural variants are not
          // to be retained for source strings.
          $utmost_parent['source'][] = $child->source;
        }

        // All plural variant LIDs are to be removed with their translations.
        // Only the singular LIDs will be kept.
        $remove_lids[] = $child->lid;
      }
    }

    // Do updates for all source strings and all translations.
    $updated_sources = array();
    foreach ($strings as $langcode => $translations) {
      foreach ($translations as $lid => $translation) {
        if (!in_array($lid, $updated_sources)) {

          // Only update source string if not yet updated. We merged these
          // within the translation lookups because plural information was only
          // available with the translation, but we don't need to save it again
          // for every language.
          db_update('locales_source')
            ->fields(array(
            'source' => implode(LOCALE_PLURAL_DELIMITER, $translation['source']),
          ))
            ->condition('lid', $lid)
            ->execute();
          $updated_sources[] = $lid;
        }
        db_update('locales_target')
          ->fields(array(
          'translation' => implode(LOCALE_PLURAL_DELIMITER, $translation['translation']),
        ))
          ->condition('lid', $lid)
          ->condition('language', $langcode)
          ->execute();
      }
    }

    // Remove all plural LIDs from source and target. only keep those which were
    // originally used for the singular strings (now updated to contain the
    // serialized version of plurals).
    $remove_lids = array_unique($remove_lids);
    db_delete('locales_source')
      ->condition('lid', $remove_lids, 'IN')
      ->execute();
    db_delete('locales_target')
      ->condition('lid', $remove_lids, 'IN')
      ->execute();
  }

  // Drop the primary key because it contains 'plural'.
  db_drop_primary_key('locales_target');

  // Remove the 'plid' and 'plural' columns and indexes.
  db_drop_index('locales_target', 'plid');
  db_drop_field('locales_target', 'plid');
  db_drop_index('locales_target', 'plural');
  db_drop_field('locales_target', 'plural');

  // Add back a primary key without 'plural'.
  db_add_primary_key('locales_target', array(
    'language',
    'lid',
  ));
}

/**
 * Convert language_negotiation_* variables to use the new callbacks.
 *
 * @ingroup config_upgrade
 */
function locale_update_8007() {
  $variable_names = array(
    'language_negotiation_language_interface',
    'language_negotiation_language_content',
    'language_negotiation_language_url',
  );

  // Add all language type weight variables. As the function language_types()
  // is not available its functionality is rebuild.
  $language_types = update_variable_get('language_types', array(
    Language::TYPE_INTERFACE => TRUE,
    Language::TYPE_CONTENT => FALSE,
    Language::TYPE_URL => FALSE,
  ));
  foreach ($language_types as $language_type => $configurable) {
    $variable_names[] = 'language_negotiation_methods_weight_' . $language_type;
  }
  $callback_map = array(
    'locale_language_from_url' => 'language_from_url',
    'locale_language_switcher_url' => 'language_switcher_url',
    'locale_language_url_rewrite_url' => 'language_url_rewrite_url',
    'locale_language_from_session' => 'language_from_session',
    'locale_language_switcher_session' => 'language_switcher_session',
    'locale_language_url_rewrite_session' => 'language_url_rewrite_session',
    'locale_language_from_user' => 'language_from_user',
    'locale_language_from_browser' => 'language_from_browser',
    'locale_language_url_fallback' => 'language_url_fallback',
    'locale_language_from_interface' => 'language_from_interface',
  );
  $type_map = array(
    'locale-interface' => 'language-interface',
    'locale-url' => 'language-url',
    'locale-url-fallback' => 'language-url-fallback',
    'locale-browser' => 'language-browser',
    'locale-user' => 'language-user',
    'locale-session' => 'language-session',
  );
  foreach ($variable_names as $variable_name) {
    $value = update_variable_get($variable_name);

    // Skip processing if the variable is not stored in the db.
    if ($value === NULL) {
      continue;
    }
    $new_value = $value;
    foreach ($value as $type => $type_settings) {

      // Convert the file.
      if (isset($type_settings['file']) && strpos($type_settings['file'], 'core/includes/locale.inc') !== FALSE) {
        $new_value[$type]['file'] = 'core/modules/language/language.negotiation.inc';
      }

      // Convert the callbacks.
      if (is_array($type_settings) && isset($type_settings['callbacks'])) {
        foreach ($type_settings['callbacks'] as $key => $callback) {
          if (isset($callback_map[$callback])) {
            $new_value[$type]['callbacks'][$key] = $callback_map[$callback];
          }
        }
      }

      // Convert the type.
      if (isset($type_map[$type])) {
        $new_value[$type_map[$type]] = $new_value[$type];
        unset($new_value[$type]);
      }
    }

    // If necessary maintain the order of the values / keys of the variable.
    if (stristr($variable_name, 'language_negotiation_methods_weight_') !== FALSE) {
      asort($new_value);
    }
    update_variable_set($variable_name, $new_value);
  }
}

/**
 * Update locale variables to config or state systems as appropriate.
 *
 * @ingroup config_upgrade
 */
function locale_update_8008() {
  update_variables_to_config('locale.settings', array(
    'locale_cache_strings' => 'cache_strings',
    'locale_js_directory' => 'javascript.directory',
  ));
  update_variables_to_config('language.negotiation', array(
    'locale_language_negotiation_session_param' => 'session.parameter',
    'locale_language_negotiation_url_part' => 'url.source',
  ));
}

/**
 * Convert locale blocks to language blocks.
 */
function locale_update_8009() {
  $block_tables = array(
    'block',
    'block_node_type',
    'block_role',
  );
  foreach ($block_tables as $table) {
    db_update($table)
      ->fields(array(
      'module' => 'language',
    ))
      ->condition('module', 'locale')
      ->execute();
  }
}

/**
 * Add {locale_file} table.
 */
function locale_update_8010() {
  $table = array(
    'description' => 'File import status information for interface translation files.',
    'fields' => array(
      'langcode' => array(
        'description' => 'Reference to the {languages}.langcode for this translation.',
        'type' => 'varchar',
        'length' => '12',
        'not null' => TRUE,
      ),
      'filename' => array(
        'description' => 'Filename for importing the file.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'uri' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'timestamp' => array(
        'description' => 'Unix timestamp of the file itself from the point when it was last imported.',
        'type' => 'int',
        'not null' => FALSE,
        'default' => 0,
      ),
    ),
    'primary key' => array(
      'uri',
      'langcode',
    ),
  );
  db_create_table('locale_file', $table);
}

/**
 * Add a cache table and locale_project table for the locale module.
 */
function locale_update_8011() {

  // Add locale_project table.
  db_create_table('locale_project', array(
    'description' => 'Translation status information for projects and server data.',
    'fields' => array(
      'name' => array(
        'description' => 'A unique short name to identify the project.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
      ),
      'project_type' => array(
        'description' => 'Project type, may be core, module, theme',
        'type' => 'varchar',
        'length' => 15,
        'not null' => TRUE,
      ),
      'core' => array(
        'description' => 'Core compatibility string for this project.',
        'type' => 'varchar',
        'length' => 4,
        'not null' => TRUE,
        'default' => '',
      ),
      'version' => array(
        'description' => 'The release version of the project.',
        'type' => 'varchar',
        'length' => 128,
        'not null' => TRUE,
        'default' => '',
      ),
      'server_pattern' => array(
        'description' => 'Pattern of path and name of the gettext file at the translation server.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'status' => array(
        'description' => 'The update status of the project.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 1,
      ),
    ),
    'primary key' => array(
      'name',
    ),
  ));
}

/**
 * Renames language_default language negotiation method to language_selected.
 */
function locale_update_8013() {

  // @todo We only need language.inc here because LANGUAGE_NEGOTIATION_SELECTED
  //   is defined there. Remove this line once that has been converted to a class
  //   constant.
  require_once DRUPAL_ROOT . '/core/includes/language.inc';
  $weight = update_variable_get('language_negotiation_methods_weight_language_interface', NULL);
  if ($weight !== NULL) {
    $weight[LANGUAGE_NEGOTIATION_SELECTED] = $weight['language-default'];
    unset($weight['language-default']);
    update_variable_set('language_negotiation_methods_weight_language_interface', $weight);
  }
  $negotiation_interface = update_variable_get('language_negotiation_language_interface', NULL);
  if ($negotiation_interface !== NULL) {
    if (isset($negotiation_interface['language-default'])) {
      $negotiation_interface[LANGUAGE_NEGOTIATION_SELECTED] = $negotiation_interface['language-default'];
      $negotiation_interface[LANGUAGE_NEGOTIATION_SELECTED]['callbacks']['negotiation'] = 'language_from_selected';
      unset($negotiation_interface['language-default']);
      update_variable_set('language_negotiation_language_interface', $negotiation_interface);
    }
  }
}

/**
 * Drop old 'location' field.
 */
function locale_update_8014() {
  db_drop_field('locales_source', 'location');
}

/**
 * Build a new {locale_file} table.
 */
function locale_update_8015() {

  // The existing table has a primary key on uri and langcode. The new key
  // is on project and langcode. There is no project data in the existing table,
  // and it may not be possible to generate this reliably. Therefore we drop
  // the table and build it again.
  db_drop_table('locale_file');
  $table = array(
    'description' => 'File import status information for interface translation files.',
    'fields' => array(
      'project' => array(
        'type' => 'varchar',
        'length' => '255',
        'not null' => TRUE,
        'default' => '',
        'description' => 'A unique short name to identify the project the file belongs to.',
      ),
      'langcode' => array(
        'type' => 'varchar',
        'length' => '12',
        'not null' => TRUE,
        'default' => '',
        'description' => 'Language code of this translation. References {language}.langcode.',
      ),
      'filename' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
        'description' => 'Filename of the imported file.',
      ),
      'version' => array(
        'type' => 'varchar',
        'length' => '128',
        'not null' => TRUE,
        'default' => '',
        'description' => 'Version tag of the imported file.',
      ),
      'uri' => array(
        'description' => 'File system path for importing the file.',
        'type' => 'text',
        'not null' => TRUE,
      ),
      'timestamp' => array(
        'type' => 'int',
        'not null' => FALSE,
        'default' => 0,
        'description' => 'Unix timestamp of the imported file.',
      ),
      'last_checked' => array(
        'type' => 'int',
        'not null' => FALSE,
        'default' => 0,
        'description' => 'Unix timestamp of the last time this translation was confirmed to be the most recent release available.',
      ),
    ),
    'primary key' => array(
      'project',
      'langcode',
    ),
  );
  db_create_table('locale_file', $table);
}

/**
 * Converts localized date formats.
 */
function locale_update_8016() {
  $configs = array();

  // Fetch all date types from {date_format_type}.
  $result = db_query('SELECT * FROM {date_format_locale}');
  foreach ($result as $format) {
    $language = $format->language;

    // Create config objects for the language if not yet done.
    if (!isset($configs[$language])) {
      $configs[$language] = config('locale.config.' . $language . '.system.date');
    }
    $configs[$language]
      ->set('formats.' . $format->type . '.pattern.php', $format->format);
  }

  // Save all instantiated config objects.
  foreach ($configs as $config) {
    $config
      ->save();
  }
}

/**
 * Moves locale translation directory settings from variable to config.
 *
 * @ingroup config_upgrade
 */
function locale_update_8017() {
  update_variables_to_config('locale.settings', array(
    'locale_translate_file_directory' => 'translation.path',
  ));
}

/**
 * @} End of "addtogroup updates-7.x-to-8.x".
 * The next series of updates should start at 9000.
 */

Functions

Namesort descending Description
locale_install Implements hook_install().
locale_requirements Implements hook_requirements().
locale_schema Implements hook_schema().
locale_uninstall Implements hook_uninstall().
locale_update_8000 Drops textgroup support.
locale_update_8001 Language type 'language' renamed to 'language_interface'.
locale_update_8002 Removes duplicates in {locales_source}.
locale_update_8003 Converts language domains to new format.
locale_update_8004 Rename language providers to language negotiation methods.
locale_update_8005 Update plural interface translations to new format.
locale_update_8007 Convert language_negotiation_* variables to use the new callbacks.
locale_update_8008 Update locale variables to config or state systems as appropriate.
locale_update_8009 Convert locale blocks to language blocks.
locale_update_8010 Add {locale_file} table.
locale_update_8011 Add a cache table and locale_project table for the locale module.
locale_update_8013 Renames language_default language negotiation method to language_selected.
locale_update_8014 Drop old 'location' field.
locale_update_8015 Build a new {locale_file} table.
locale_update_8016 Converts localized date formats.
locale_update_8017 Moves locale translation directory settings from variable to config.