function _locale_rebuild_js

Same name and namespace in other branches
  1. 7.x includes/locale.inc \_locale_rebuild_js()
  2. 9 core/modules/locale/locale.module \_locale_rebuild_js()
  3. 8.9.x core/modules/locale/locale.module \_locale_rebuild_js()
  4. 10 core/modules/locale/locale.module \_locale_rebuild_js()

(Re-)Creates the JavaScript translation file for a language.

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.

2 calls to _locale_rebuild_js()
LocaleTranslationUiTest::testJavaScriptTranslation in core/modules/locale/tests/src/Functional/LocaleTranslationUiTest.php
Tests the rebuilding of JavaScript translation files on deletion.
locale_js_translate in core/modules/locale/locale.module
Returns a list of translation files given a list of JavaScript files.

File

core/modules/locale/locale.module, line 1211

Code

function _locale_rebuild_js($langcode = NULL) {
    $config = \Drupal::config('locale.settings');
    if (!isset($langcode)) {
        $language = \Drupal::languageManager()->getCurrentLanguage();
    }
    else {
        // Get information about the locale.
        $languages = \Drupal::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 (\Drupal::service('locale.storage')->getTranslations($conditions) as $data) {
        $translations[$data->context][$data->source] = $data->translation;
    }
    // Include custom string overrides.
    $custom_strings = Settings::get('locale_custom_strings_' . $language->getId(), []);
    foreach ($custom_strings as $context => $strings) {
        foreach ($strings as $source => $translation) {
            $translations[$context][$source] = $translation;
        }
    }
    // Construct the JavaScript file, if there are translations.
    $data_hash = NULL;
    $data = $status = '';
    if (!empty($translations)) {
        $data = [
            'strings' => $translations,
        ];
        $locale_plurals = \Drupal::service('locale.plural.formula')->getFormula($language->getId());
        if ($locale_plurals) {
            $data['pluralFormula'] = $locale_plurals;
        }
        $data = 'window.drupalTranslations = ' . Json::encode($data) . ';';
        $data_hash = Crypt::hashBase64($data);
    }
    // Construct the filepath where JS translation files are stored.
    // There is (on purpose) no front end to edit that variable.
    $dir = 'public://' . $config->get('javascript.directory');
    // Delete old file, if we have no translations anymore, or a different file to
    // be saved.
    $locale_javascripts = \Drupal::state()->get('locale.translation.javascript', []);
    $changed_hash = !isset($locale_javascripts[$language->getId()]) || $locale_javascripts[$language->getId()] != $data_hash;
    
    /** @var \Drupal\Core\File\FileSystemInterface $file_system */
    $file_system = \Drupal::service('file_system');
    if (!empty($locale_javascripts[$language->getId()]) && (!$data || $changed_hash)) {
        try {
            $file_system->delete($dir . '/' . $language->getId() . '_' . $locale_javascripts[$language->getId()] . '.js');
        } catch (FileException $e) {
            // Ignore.
        }
        $locale_javascripts[$language->getId()] = '';
        $status = 'deleted';
    }
    // Only create a new file if the content has changed or the original file got
    // lost.
    $dest = $dir . '/' . $language->getId() . '_' . $data_hash . '.js';
    if ($data && ($changed_hash || !file_exists($dest))) {
        // Ensure that the directory exists and is writable, if possible.
        $file_system->prepareDirectory($dir, FileSystemInterface::CREATE_DIRECTORY);
        // Save the file.
        try {
            if ($file_system->saveData($data, $dest)) {
                $locale_javascripts[$language->getId()] = $data_hash;
                // 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 ($changed_hash) {
                    $status = 'created';
                }
                else {
                    $status = 'rebuilt';
                }
            }
            else {
                $locale_javascripts[$language->getId()] = '';
                $status = 'error';
            }
        } catch (FileException $e) {
            // 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 && $changed_hash) {
        \Drupal::state()->set('locale.translation.javascript', $locale_javascripts);
    }
    // Log the operation and return success flag.
    $logger = \Drupal::logger('locale');
    switch ($status) {
        case 'updated':
            $logger->notice('Updated JavaScript translation file for the language %language.', [
                '%language' => $language->getName(),
            ]);
            return TRUE;
        case 'rebuilt':
            $logger->warning('JavaScript translation file %file.js was lost.', [
                '%file' => $locale_javascripts[$language->getId()],
            ]);
        // Proceed to the 'created' case as the JavaScript translation file has
        // been created again.
        case 'created':
            $logger->notice('Created JavaScript translation file for the language %language.', [
                '%language' => $language->getName(),
            ]);
            return TRUE;
        case 'deleted':
            $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':
            $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.