Commit b3c0d09b authored by catch's avatar catch
Browse files

task: #3590050 Deprecate and replace locale_status related functions

By: nicxvan
By: berdir
By: penyaskito
By: gábor hojtsy
By: catch
(cherry picked from commit f240c62e)
parent fc1df9b8
Loading
Loading
Loading
Loading
Loading
+3 −99
Original line number Diff line number Diff line
@@ -40,11 +40,8 @@
use Drupal\Core\Routing\RouteObjectInterface;
use Drupal\locale\LocaleDefaultOptions;
use Drupal\locale\LocaleFetch;
use Drupal\locale\File\LocaleFileManager;
use Drupal\locale\LocaleConfigBatch;
use Drupal\locale\LocaleProjectChecker;
use Drupal\locale\LocaleProjectRepository;
use Drupal\locale\LocaleTranslatableProject;
use Psr\Http\Client\ClientExceptionInterface;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpFoundation\Request;
@@ -1702,11 +1699,8 @@ function install_install_profile(&$install_state): void {
 *
 * @param array $install_state
 *   An array of information about the current installation state.
 *
 * @return array
 *   The batch definition, if there are language files to download.
 */
function install_download_additional_translations_operations(&$install_state): array {
function install_download_additional_translations_operations(&$install_state): void {
  \Drupal::moduleHandler()->loadInclude('locale', 'bulk.inc');

  $langcode = $install_state['parameters']['langcode'];
@@ -1738,21 +1732,6 @@ function install_download_additional_translations_operations(&$install_state): a
    }
  }

  // If there is more than one language or the single one is not English, we
  // should download/import translations.
  $languages = \Drupal::languageManager()->getLanguages();
  $operations = [];
  foreach ($languages as $langcode => $language) {
    // The installer language was already downloaded. Available translations are
    // stored in $install_state. Check downloads for the other languages if any.
    // Ignore any download errors here, since we are in the middle of an install
    // process and there is no way back. We will not import what we cannot
    // download.
    if (!isset($install_state['translations'][$langcode])) {
      $operations[] = ['install_check_translations', [$langcode, $install_state['server_pattern']]];
    }
  }
  return $operations;
}

/**
@@ -1765,87 +1744,12 @@ function install_download_additional_translations_operations(&$install_state): a
 *   The batch definition, if there are language files to import.
 */
function install_import_translations(&$install_state) {
  install_download_additional_translations_operations($install_state);
  // If there is more than one language or the single one is not English, we
  // should import translations.
  $batch_builder = (new BatchBuilder())
    ->setFile(\Drupal::service('extension.path.resolver')->getPath('module', 'locale') . '/locale.batch.inc');
  foreach (install_download_additional_translations_operations($install_state) as $operation) {
    $batch_builder->addOperation($operation[0], $operation[1]);
  }
  $languages = \Drupal::languageManager()->getLanguages();
  if (count($languages) > 1 || !isset($languages['en'])) {
    $batch_builder->addOperation(
      '_install_prepare_import',
      [array_keys($languages), $install_state['server_pattern']],
    );

    // Set up a batch to import translations for drupal core. Translation import
    // for contrib modules happens in install_import_translations_remaining.
    foreach ($languages as $language) {
      if (locale_translation_use_remote_source()) {
        $batch_builder->addOperation(
          LocaleFetch::class . ':batchDownload',
          ['drupal', $language->getId()],
        );
      }
      $batch_builder->addOperation(
        LocaleFetch::class . ':batchImport',
        ['drupal', $language->getId(), []],
      );
    }

    $batch_builder
      ->setTitle(t('Updating translations.'))
      ->setProgressMessage('')
      ->setErrorMessage(t('Error importing translation files'))
      ->setFinishCallback(LocaleFetch::class . ':batchFinished');
    return $batch_builder->toArray();
  }
}

/**
 * Tells the translation import process that Drupal core is installed.
 *
 * @param array $langcodes
 *   Language codes used for the translations.
 * @param string $server_pattern
 *   Server access pattern (to replace language code, version number, etc. in).
 */
function _install_prepare_import($langcodes, $server_pattern): void {
  $module_handler = \Drupal::moduleHandler();
  $module_handler->loadInclude('locale', 'inc', 'locale.bulk');
  $matches = [];

  foreach ($langcodes as $langcode) {
    // Get the translation files located in the translations directory.
    $files = \Drupal::service(LocaleFileManager::class)->getInterfaceTranslationFiles(['drupal'], [$langcode]);
    // Pick the first file which matches the language, if any.
    $file = reset($files);
    if (is_object($file)) {
      $filename = $file->filename;
      preg_match('/drupal-([0-9a-z\.-]+)\.' . $langcode . '\.po/', $filename, $matches);
      // Get the version information. Custom translation files may not have a
      // version number.
      if (isset($matches[1]) && $version = $matches[1]) {
        $info = _install_get_version_info($version);
        // Picking the first file does not necessarily result in the right file.
        // So we check if at least the major version number is available.
        if ($info['major']) {
          $project = new LocaleTranslatableProject(
            name: 'drupal',
            type: 'module',
            core: $info['major'] . '.x',
            version: $version,
            server_pattern: $server_pattern,
            langcode: $langcode,
            status: TRUE,
          );
          \Drupal::service(LocaleProjectRepository::class)->set($project);
          $module_handler->loadInclude('locale', 'inc', 'locale.compare');
          \Drupal::service(LocaleProjectChecker::class)->checkLocalProjects(['drupal'], [$langcode]);
        }
      }
    }
    return \Drupal::service(LocaleFetch::class)->buildUpdateBatch();
  }
}

+1 −1
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ class ConfigTranslationInstallTest extends InstallerTestBase {
  protected function setUpLanguage(): void {
    // Place custom local translations in the translations directory.
    mkdir(DRUPAL_ROOT . '/' . $this->siteDirectory . '/files/translations', 0777, TRUE);
    file_put_contents(DRUPAL_ROOT . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.eo.po', $this->getPo('eo'));
    file_put_contents(DRUPAL_ROOT . '/' . $this->siteDirectory . '/files/translations/drupal-' . \Drupal::VERSION . '.eo.po', $this->getPo('eo'));

    parent::setUpLanguage();

+1 −2
Original line number Diff line number Diff line
@@ -81,8 +81,7 @@ protected function installParameters() {
msgstr "Non-word-german sdfwedrsdf."

PO;
    $version = explode('.', \Drupal::VERSION)[0] . '.0.0';
    file_put_contents($this->publicFilesDirectory . "/translations/drupal-{$version}.de.po", $contents);
    file_put_contents($this->publicFilesDirectory . '/translations/drupal-' . \Drupal::VERSION . '.de.po', $contents);
    return $parameters;
  }

+37 −105
Original line number Diff line number Diff line
@@ -298,7 +298,7 @@ function locale_system_remove($components): void {
      \Drupal::service(LocaleProjectRepository::class)->deleteMultiple($list);

      // Clear the translation status.
      locale_translation_status_delete_projects($list);
      \Drupal::service(LocaleSource::class)->deleteSources($list);
    }

  }
@@ -442,7 +442,7 @@ function locale_is_translatable($langcode) {
function locale_system_file_system_settings_submit(&$form, FormStateInterface $form_state): void {
  @trigger_error(__FUNCTION__ . 'is deprecated in drupal:11.4.0 and is removed from drupal:12.0.0. There is no replacement. See https://www.drupal.org/node/3571594', E_USER_DEPRECATED);
  if ($form['translation_path']['#default_value'] != $form_state->getValue('translation_path')) {
    locale_translation_clear_status();
    \Drupal::service(LocaleSource::class)->clearSources();
  }

  \Drupal::configFactory()->getEditable('locale.settings')
@@ -523,30 +523,14 @@ function locale_translation_file_history_delete($projects = [], $langcodes = [])
/**
 * Gets the current translation status.
 *
 * @todo What is 'translation status'?
 * @deprecated in drupal:11.4.0 and is removed from drupal:13.0.0. Use
 *  \Drupal::service(LocaleSource::class)->loadSources() instead.
 *
 * @see https://www.drupal.org/node/3591660
 */
function locale_translation_get_status($projects = NULL, $langcodes = NULL): array {
  $result = [];
  $status = \Drupal::keyValue('locale.translation_status')->getAll();
  $projects = $projects ?: array_keys(\Drupal::service(LocaleProjectRepository::class)->getAll());
  $langcodes = $langcodes ?: array_keys(locale_translatable_language_list());

  // Get the translation status of each project-language combination. If no
  // status was stored, a new translation source is created.
  foreach ($projects as $project) {
    foreach ($langcodes as $langcode) {
      if (isset($status[$project][$langcode])) {
        $result[$project][$langcode] = $status[$project][$langcode];
      }
      else {
        $sources = \Drupal::service(LocaleSource::class)->buildSources([$project], [$langcode]);
        if (isset($sources[$project][$langcode])) {
          $result[$project][$langcode] = $sources[$project][$langcode];
        }
      }
    }
  }
  return $result;
  @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.4.0 and is removed from drupal:13.0.0. Use \Drupal::service(LocaleSource::class)->loadSources(). See https://www.drupal.org/node/3591660', E_USER_DEPRECATED);
  return \Drupal::service(LocaleSource::class)->loadSources($projects, $langcodes);
}

/**
@@ -560,77 +544,15 @@ function locale_translation_get_status($projects = NULL, $langcodes = NULL): arr
 *   Type of data to be stored.
 * @param object $data
 *   File object also containing timestamp when the translation is last updated.
 *
 * @deprecated in drupal:11.4.0 and is removed from drupal:13.0.0. Use
 *   \Drupal::service(LocaleSource::class)->saveSource() instead.
 *
 * @see https://www.drupal.org/node/3591660
 */
function locale_translation_status_save($project, $langcode, $type, $data): void {
  // Load the translation status or build it if not already available.
  $status = locale_translation_get_status([$project]);
  if (empty($status)) {
    $projects = \Drupal::service(LocaleProjectRepository::class)->getMultiple([$project]);
    if (isset($projects[$project])) {
      $status[$project][$langcode] = \Drupal::service(LocaleSource::class)->sourceBuild($projects[$project], $langcode);
    }
  }

  // Merge the new status data with the existing status.
  if (isset($status[$project][$langcode])) {
    $request_time = \Drupal::time()->getRequestTime();
    switch ($type) {
      case LOCALE_TRANSLATION_REMOTE:
        // Add the source data to the status array.
        $status[$project][$langcode]->files[$type] = $data;

        // Check if this translation is the most recent one. Set timestamp and
        // data type of the most recent translation source.
        if (isset($data->timestamp) && $data->timestamp) {
          if ($data->timestamp > $status[$project][$langcode]->timestamp) {
            $status[$project][$langcode]->timestamp = $data->timestamp;
            $status[$project][$langcode]->last_checked = $request_time;
            $status[$project][$langcode]->type = $type;
          }
        }
        break;

      case LOCALE_TRANSLATION_LOCAL:
        // Add the source data to the status array.
        $status[$project][$langcode]->files[$type] = $data;

        // Determine if the translation source has changed by comparing by
        // content hash (mtime is unreliable).
        $current_hash = $status[$project][$langcode]->hash ?? '';
        if (!empty($current_hash)) {
          if ($data->hash !== $current_hash) {
            $status[$project][$langcode]->timestamp = $data->timestamp;
            $status[$project][$langcode]->last_checked = $request_time;
            $status[$project][$langcode]->type = $type;
            $status[$project][$langcode]->hash = $data->hash;
          }
        }
        // For legacy rows (pre-hash column being added), fall back to timestamp
        // comparison. This may trigger a one-time re-import, after which a hash
        // is stored and used for all future comparisons.
        elseif (isset($data->timestamp) && $data->timestamp) {
          if ($data->timestamp > $status[$project][$langcode]->timestamp) {
            $status[$project][$langcode]->timestamp = $data->timestamp;
            $status[$project][$langcode]->last_checked = $request_time;
            $status[$project][$langcode]->type = $type;
            $status[$project][$langcode]->hash = $data->hash;
          }
        }
        break;

      case LOCALE_TRANSLATION_CURRENT:
        $data->last_checked = $request_time;
        $status[$project][$langcode]->timestamp = $data->timestamp;
        $status[$project][$langcode]->hash = $data->hash ?? '';
        $status[$project][$langcode]->last_checked = $data->last_checked;
        $status[$project][$langcode]->type = $type;
        \Drupal::service(CurrentImportStorage::class)->save(CurrentImport::createFromSource($data));
        break;
    }

    \Drupal::keyValue('locale.translation_status')->set($project, $status[$project]);
    \Drupal::state()->set('locale.translation_last_checked', $request_time);
  }
  @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.4.0 and is removed from drupal:13.0.0. Use \Drupal::service(LocaleSource::class)->saveSource(). See https://www.drupal.org/node/3591660', E_USER_DEPRECATED);
  \Drupal::service(LocaleSource::class)->saveSource($project, $langcode, $type, $data);
}

/**
@@ -638,17 +560,16 @@ function locale_translation_status_save($project, $langcode, $type, $data): void
 *
 * @param array $langcodes
 *   Language code(s) to be deleted from the cache.
 *
 * @deprecated in drupal:11.4.0 and is removed from drupal:13.0.0. Use
 *   \Drupal::service(LocaleSource::class)->deleteSourcesByLanguage() instead.
 *
 * @see https://www.drupal.org/node/3591660
 */
function locale_translation_status_delete_languages($langcodes): void {
  if ($status = locale_translation_get_status()) {
    foreach ($status as $project => $languages) {
      foreach ($languages as $langcode => $source) {
        if (in_array($langcode, $langcodes)) {
          unset($status[$project][$langcode]);
        }
      }
      \Drupal::keyValue('locale.translation_status')->set($project, $status[$project]);
    }
  @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.4.0 and is removed from drupal:13.0.0. Use \Drupal::service(LocaleSource::class)->deleteSourcesByLanguage(). See https://www.drupal.org/node/3591660', E_USER_DEPRECATED);
  foreach ($langcodes as $langcode) {
    \Drupal::service(LocaleSource::class)->deleteSourcesByLanguage($langcode);
  }
}

@@ -657,17 +578,28 @@ function locale_translation_status_delete_languages($langcodes): void {
 *
 * @param array $projects
 *   Project name(s) to be deleted from the cache.
 *
 * @deprecated in drupal:11.4.0 and is removed from drupal:13.0.0. Use
 *    \Drupal::service(LocaleSource::class)->deleteSources() instead.
 *
 * @see https://www.drupal.org/node/3591660
 */
function locale_translation_status_delete_projects($projects): void {
  \Drupal::keyValue('locale.translation_status')->deleteMultiple($projects);
  @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.4.0 and is removed from drupal:13.0.0. Use \Drupal::service(LocaleSource::class)->deleteSources(). See https://www.drupal.org/node/3591660', E_USER_DEPRECATED);
  \Drupal::service(LocaleSource::class)->deleteSources($projects);
}

/**
 * Clear the translation status cache.
 *
 * @deprecated in drupal:11.4.0 and is removed from drupal:13.0.0. Use
 *     \Drupal::service(LocaleSource::class)->clearSources() instead.
 *
 * @see https://www.drupal.org/node/3591660
 */
function locale_translation_clear_status(): void {
  \Drupal::keyValue('locale.translation_status')->deleteAll();
  \Drupal::state()->delete('locale.translation_last_checked');
  @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.4.0 and is removed from drupal:13.0.0. Use \Drupal::service(LocaleSource::class)->clearSources(). See https://www.drupal.org/node/3591660', E_USER_DEPRECATED);
  \Drupal::service(LocaleSource::class)->clearSources();
}

/**
+10 −3
Original line number Diff line number Diff line
@@ -136,16 +136,23 @@ function locale_translation_load_sources(?array $projects = NULL, ?array $langco
 *
 * @deprecated in drupal:11.4.0 and is removed from drupal:13.0.0. Use
 *   \Drupal::service(LocaleSource::class)
 *   ->buildSources($projects, $langcodes) instead.
 *   ->sourceBuild($project, $langcode) instead.
 *
 * @see https://www.drupal.org/node/3569330
 */
function locale_translation_build_sources(array $projects = [], array $langcodes = []): array {
  @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.4.0 and is removed from drupal:13.0.0. Use \Drupal::service(LocaleSource::class)->buildSources($projects, $langcodes) instead. See https://www.drupal.org/node/3569330', E_USER_DEPRECATED);
  @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.4.0 and is removed from drupal:13.0.0. Use \Drupal::service(LocaleSource::class)->sourceBuild($project, $langcode) instead. See https://www.drupal.org/node/3569330', E_USER_DEPRECATED);
  if (empty($projects)) {
    $projects = array_keys(\Drupal::service(LocaleProjectRepository::class)->getAll());
  }
  return \Drupal::service(LocaleSource::class)->buildSources($projects, $langcodes);
  $sources = [];
  $locale_source = \Drupal::service(LocaleSource::class);
  foreach ($projects as $project) {
    foreach ($langcodes as $langcode) {
      $sources[$project][$langcode] = $locale_source->sourceBuild($project, $langcode);
    }
  }
  return $sources;
}

/**
Loading