function LocaleJs::rebuild

Same name and namespace in other branches
  1. main core/modules/locale/src/LocaleJs.php \Drupal\locale\LocaleJs::rebuild()

Creates or recreates the JavaScript translation file for a language.

@internal

Parameters

string|null $langcode: (optional) The language that the translation file should be (re)created for, or NULL for the current language. Defaults to NULL.

Return value

bool TRUE if translation file exists, FALSE otherwise.

1 call to LocaleJs::rebuild()
LocaleJs::jsTranslate in core/modules/locale/src/LocaleJs.php
Returns a list of translation files given a list of JavaScript files.

File

core/modules/locale/src/LocaleJs.php, line 305

Class

LocaleJs
Provides the locale javascript related methods.

Namespace

Drupal\locale

Code

public function rebuild(?string $langcode = NULL) : bool {
  if (!isset($langcode)) {
    $language = $this->languageManager
      ->getCurrentLanguage();
  }
  else {
    // Get information about the locale.
    $languages = $this->languageManager
      ->getLanguages();
    $language = $languages[$langcode];
  }
  // Construct the array for JavaScript translations.
  // Only add strings with a translation to the translations array.
  $conditions = [
    'type' => 'javascript',
    'language' => $language->getId(),
    'translated' => TRUE,
  ];
  $translations = [];
  foreach ($this->localeStorage
    ->getTranslations($conditions) as $data) {
    $translations[$data->context][$data->source] = $data->translation;
  }
  // Include custom string overrides.
  $customStrings = Settings::get('locale_custom_strings_' . $language->getId(), []);
  foreach ($customStrings as $context => $strings) {
    foreach ($strings as $source => $translation) {
      $translations[$context][$source] = $translation;
    }
  }
  // Construct the JavaScript file, if there are translations.
  $dataHash = NULL;
  $data = $status = '';
  if (!empty($translations)) {
    $data = [
      'strings' => $translations,
    ];
    $localePlurals = $this->pluralFormula
      ->getFormula($language->getId());
    if ($localePlurals) {
      $data['pluralFormula'] = $localePlurals;
    }
    $data = 'window.drupalTranslations = ' . Json::encode($data) . ';';
    $dataHash = Crypt::hashBase64($data);
  }
  // Construct the filepath where JS translation files are stored.
  // There is (on purpose) no front end to edit that variable.
  $dir = 'assets://' . $this->configFactory
    ->get('locale.settings')
    ->get('javascript.directory');
  // Delete old file, if we have no translations anymore, or a different file
  // to be saved.
  $localeJavascripts = $this->state
    ->get('locale.translation.javascript', []);
  $changedHash = !isset($localeJavascripts[$language->getId()]) || $localeJavascripts[$language->getId()] != $dataHash;
  if (!empty($localeJavascripts[$language->getId()]) && (!$data || $changedHash)) {
    try {
      $this->fileSystem
        ->delete($dir . '/' . $language->getId() . '_' . $localeJavascripts[$language->getId()] . '.js');
    } catch (FileException) {
      // Ignore.
    }
    $localeJavascripts[$language->getId()] = '';
    $status = 'deleted';
  }
  // Only create a new file if the content has changed or the original file
  // got lost.
  $dest = $dir . '/' . $language->getId() . '_' . $dataHash . '.js';
  if ($data && ($changedHash || !file_exists($dest))) {
    // Ensure that the directory exists and is writable, if possible.
    $this->fileSystem
      ->prepareDirectory($dir, FileSystemInterface::CREATE_DIRECTORY);
    // Save the file.
    try {
      if ($this->fileSystem
        ->saveData($data, $dest)) {
        $localeJavascripts[$language->getId()] = $dataHash;
        // If we deleted a previous version of the file and we replace it
        // with a new one we have an update.
        if ($status == 'deleted') {
          $status = 'updated';
        }
        elseif ($changedHash) {
          $status = 'created';
        }
        else {
          $status = 'rebuilt';
        }
      }
      else {
        $localeJavascripts[$language->getId()] = '';
        $status = 'error';
      }
    } catch (FileException) {
      // Do nothing.
    }
  }
  // Save the new JavaScript hash (or an empty value if the file just got
  // deleted). Act only if some operation was executed that changed the hash
  // code.
  if ($status && $changedHash) {
    $this->state
      ->set('locale.translation.javascript', $localeJavascripts);
  }
  switch ($status) {
    case 'updated':
      ($this->logger)()
        ->notice('Updated JavaScript translation file for the language %language.', [
        '%language' => $language->getName(),
      ]);
      return TRUE;
    case 'rebuilt':
      ($this->logger)()
        ->warning('JavaScript translation file %file.js was lost.', [
        '%file' => $localeJavascripts[$language->getId()],
      ]);
    // Proceed to the 'created' case as the JavaScript translation file has
    // been created again.
    case 'created':
      ($this->logger)()
        ->notice('Created JavaScript translation file for the language %language.', [
        '%language' => $language->getName(),
      ]);
      return TRUE;
    case 'deleted':
      ($this->logger)()
        ->notice('Removed JavaScript translation file for the language %language because no translations currently exist for that language.', [
        '%language' => $language->getName(),
      ]);
      return TRUE;
    case 'error':
      ($this->logger)()
        ->error('An error occurred during creation of the JavaScript translation file for the language %language.', [
        '%language' => $language->getName(),
      ]);
      return FALSE;
    default:
      // No operation needed.
      return TRUE;
  }
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.