function 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.

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.