class TranslationStatusForm

Same name in other branches
  1. 8.9.x core/modules/locale/src/Form/TranslationStatusForm.php \Drupal\locale\Form\TranslationStatusForm
  2. 10 core/modules/locale/src/Form/TranslationStatusForm.php \Drupal\locale\Form\TranslationStatusForm
  3. 11.x core/modules/locale/src/Form/TranslationStatusForm.php \Drupal\locale\Form\TranslationStatusForm

Provides a translation status form.

@internal

Hierarchy

Expanded class hierarchy of TranslationStatusForm

1 string reference to 'TranslationStatusForm'
locale.routing.yml in core/modules/locale/locale.routing.yml
core/modules/locale/locale.routing.yml

File

core/modules/locale/src/Form/TranslationStatusForm.php, line 17

Namespace

Drupal\locale\Form
View source
class TranslationStatusForm extends FormBase {
    
    /**
     * The module handler service.
     *
     * @var \Drupal\Core\Extension\ModuleHandlerInterface
     */
    protected $moduleHandler;
    
    /**
     * The Drupal state storage service.
     *
     * @var \Drupal\Core\State\StateInterface
     */
    protected $state;
    
    /**
     * {@inheritdoc}
     */
    public static function create(ContainerInterface $container) {
        return new static($container->get('module_handler'), $container->get('state'));
    }
    
    /**
     * Constructs a TranslationStatusForm object.
     *
     * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
     *   A module handler.
     * @param \Drupal\Core\State\StateInterface $state
     *   The state service.
     */
    public function __construct(ModuleHandlerInterface $module_handler, StateInterface $state) {
        $this->moduleHandler = $module_handler;
        $this->state = $state;
    }
    
    /**
     * {@inheritdoc}
     */
    public function getFormId() {
        return 'locale_translation_status_form';
    }
    
    /**
     * Form builder for displaying the current translation status.
     *
     * @ingroup forms
     */
    public function buildForm(array $form, FormStateInterface $form_state) {
        $languages = locale_translatable_language_list();
        $status = locale_translation_get_status();
        $options = [];
        $languages_update = [];
        $languages_not_found = [];
        $projects_update = [];
        // Prepare information about projects which have available translation
        // updates.
        if ($languages && $status) {
            $updates = $this->prepareUpdateData($status);
            // Build data options for the select table.
            foreach ($updates as $langcode => $update) {
                $title = $languages[$langcode]->getName();
                $locale_translation_update_info = [
                    '#theme' => 'locale_translation_update_info',
                ];
                foreach ([
                    'updates',
                    'not_found',
                ] as $update_status) {
                    if (isset($update[$update_status])) {
                        $locale_translation_update_info['#' . $update_status] = $update[$update_status];
                    }
                }
                $options[$langcode] = [
                    'title' => [
                        'data' => [
                            '#title' => $title,
                            '#plain_text' => $title,
                        ],
                    ],
                    'status' => [
                        'class' => [
                            'description',
                            'priority-low',
                        ],
                        'data' => $locale_translation_update_info,
                    ],
                ];
                if (!empty($update['not_found'])) {
                    $languages_not_found[$langcode] = $langcode;
                }
                if (!empty($update['updates'])) {
                    $languages_update[$langcode] = $langcode;
                }
            }
            // Sort the table data on language name.
            uasort($options, function ($a, $b) {
                return strcasecmp($a['title']['data']['#title'], $b['title']['data']['#title']);
            });
            $languages_not_found = array_diff($languages_not_found, $languages_update);
        }
        $last_checked = $this->state
            ->get('locale.translation_last_checked');
        $form['last_checked'] = [
            '#theme' => 'locale_translation_last_check',
            '#last' => $last_checked,
        ];
        $header = [
            'title' => [
                'data' => $this->t('Language'),
                'class' => [
                    'title',
                ],
            ],
            'status' => [
                'data' => $this->t('Status'),
                'class' => [
                    'status',
                    'priority-low',
                ],
            ],
        ];
        if (!$languages) {
            $empty = $this->t('No translatable languages available. <a href=":add_language">Add a language</a> first.', [
                ':add_language' => Url::fromRoute('entity.configurable_language.collection')->toString(),
            ]);
        }
        elseif ($status) {
            $empty = $this->t('All translations up to date.');
        }
        else {
            $empty = $this->t('No translation status available. <a href=":check">Check manually</a>.', [
                ':check' => Url::fromRoute('locale.check_translation')->toString(),
            ]);
        }
        // The projects which require an update. Used by the _submit callback.
        $form['projects_update'] = [
            '#type' => 'value',
            '#value' => $projects_update,
        ];
        $form['langcodes'] = [
            '#type' => 'tableselect',
            '#header' => $header,
            '#options' => $options,
            '#default_value' => $languages_update,
            '#empty' => $empty,
            '#js_select' => TRUE,
            '#multiple' => TRUE,
            '#required' => TRUE,
            '#not_found' => $languages_not_found,
            '#after_build' => [
                'locale_translation_language_table',
            ],
        ];
        $form['#attached']['library'][] = 'locale/drupal.locale.admin';
        $form['actions'] = [
            '#type' => 'actions',
        ];
        if ($languages_update) {
            $form['actions']['submit'] = [
                '#type' => 'submit',
                '#value' => $this->t('Update translations'),
            ];
        }
        return $form;
    }
    
    /**
     * Prepare information about projects with available translation updates.
     *
     * @param array $status
     *   Translation update status as an array keyed by Project ID and langcode.
     *
     * @return array
     *   Translation update status as an array keyed by language code and
     *   translation update status.
     */
    protected function prepareUpdateData(array $status) {
        $updates = [];
        // @todo Calling locale_translation_build_projects() is an expensive way to
        //   get a module name. In follow-up issue
        //   https://www.drupal.org/node/1842362 the project name will be stored to
        //   display use, like here.
        $this->moduleHandler
            ->loadInclude('locale', 'compare.inc');
        $project_data = locale_translation_build_projects();
        foreach ($status as $project) {
            foreach ($project as $langcode => $project_info) {
                // No translation file found for this project-language combination.
                if (empty($project_info->type)) {
                    $updates[$langcode]['not_found'][] = [
                        'name' => $project_info->name == 'drupal' ? $this->t('Drupal core') : $project_data[$project_info->name]->info['name'],
                        'version' => $project_info->version,
                        'info' => $this->createInfoString($project_info),
                    ];
                }
                elseif ($project_info->type == LOCALE_TRANSLATION_LOCAL || $project_info->type == LOCALE_TRANSLATION_REMOTE) {
                    $local = $project_info->files[LOCALE_TRANSLATION_LOCAL] ?? NULL;
                    $remote = $project_info->files[LOCALE_TRANSLATION_REMOTE] ?? NULL;
                    $recent = _locale_translation_source_compare($local, $remote) == LOCALE_TRANSLATION_SOURCE_COMPARE_LT ? $remote : $local;
                    $updates[$langcode]['updates'][] = [
                        'name' => $project_info->name == 'drupal' ? $this->t('Drupal core') : $project_data[$project_info->name]->info['name'],
                        'version' => $project_info->version,
                        'timestamp' => $recent->timestamp,
                    ];
                }
            }
        }
        return $updates;
    }
    
    /**
     * Provides debug info for projects in case translation files are not found.
     *
     * Translations files are being fetched either from Drupal translation server
     * and local files or only from the local filesystem depending on the
     * "Translation source" setting at admin/config/regional/translate/settings.
     * This method will produce debug information including the respective path(s)
     * based on this setting.
     *
     * @param array $project_info
     *   An array which is the project information of the source.
     *
     * @return string
     *   The string which contains debug information.
     */
    protected function createInfoString($project_info) {
        $remote_path = $project_info->files['remote']->uri ?? FALSE;
        $local_path = $project_info->files['local']->uri ?? FALSE;
        if (locale_translation_use_remote_source() && $remote_path && $local_path) {
            return $this->t('File not found at %remote_path nor at %local_path', [
                '%remote_path' => $remote_path,
                '%local_path' => $local_path,
            ]);
        }
        elseif ($local_path) {
            return $this->t('File not found at %local_path', [
                '%local_path' => $local_path,
            ]);
        }
        return $this->t('Translation file location could not be determined.');
    }
    
    /**
     * {@inheritdoc}
     */
    public function validateForm(array &$form, FormStateInterface $form_state) {
        // Check if a language has been selected. 'tableselect' doesn't.
        if (!array_filter($form_state->getValue('langcodes'))) {
            $form_state->setErrorByName('', $this->t('Select a language to update.'));
        }
    }
    
    /**
     * {@inheritdoc}
     */
    public function submitForm(array &$form, FormStateInterface $form_state) {
        $this->moduleHandler
            ->loadInclude('locale', 'fetch.inc');
        $this->moduleHandler
            ->loadInclude('locale', 'bulk.inc');
        $langcodes = array_filter($form_state->getValue('langcodes'));
        $projects = array_filter($form_state->getValue('projects_update'));
        // Set the translation import options. This determines if existing
        // translations will be overwritten by imported strings.
        $options = _locale_translation_default_update_options();
        // If the status was updated recently we can immediately start fetching the
        // translation updates. If the status is expired we clear it and run a batch
        // to update the status and then fetch the translation updates.
        $last_checked = $this->state
            ->get('locale.translation_last_checked');
        if ($last_checked < REQUEST_TIME - LOCALE_TRANSLATION_STATUS_TTL) {
            locale_translation_clear_status();
            $batch = locale_translation_batch_update_build([], $langcodes, $options);
            batch_set($batch);
        }
        else {
            // Set a batch to download and import translations.
            $batch = locale_translation_batch_fetch_build($projects, $langcodes, $options);
            batch_set($batch);
            // Set a batch to update configuration as well.
            if ($batch = locale_config_batch_update_components($options, $langcodes)) {
                batch_set($batch);
            }
        }
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
DependencySerializationTrait::$_entityStorages protected property
DependencySerializationTrait::$_serviceIds protected property
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
FormBase::$configFactory protected property The config factory. 3
FormBase::$requestStack protected property The request stack. 1
FormBase::$routeMatch protected property The route match.
FormBase::config protected function Retrieves a configuration object.
FormBase::configFactory protected function Gets the config factory for this form. 3
FormBase::container private function Returns the service container.
FormBase::currentUser protected function Gets the current user.
FormBase::getRequest protected function Gets the request object.
FormBase::getRouteMatch protected function Gets the route match.
FormBase::logger protected function Gets the logger for a specific channel.
FormBase::redirect protected function Returns a redirect response object for the specified route.
FormBase::resetConfigFactory public function Resets the configuration factory.
FormBase::setConfigFactory public function Sets the config factory for this form.
FormBase::setRequestStack public function Sets the request stack object to use.
LoggerChannelTrait::$loggerFactory protected property The logger channel factory service.
LoggerChannelTrait::getLogger protected function Gets the logger for a specific channel.
LoggerChannelTrait::setLoggerFactory public function Injects the logger channel factory.
MessengerTrait::$messenger protected property The messenger. 17
MessengerTrait::messenger public function Gets the messenger. 17
MessengerTrait::setMessenger public function Sets the messenger.
RedirectDestinationTrait::$redirectDestination protected property The redirect destination service. 1
RedirectDestinationTrait::getDestinationArray protected function Prepares a &#039;destination&#039; URL query parameter for use with \Drupal\Core\Url.
RedirectDestinationTrait::getRedirectDestination protected function Returns the redirect destination service.
RedirectDestinationTrait::setRedirectDestination public function Sets the redirect destination service.
StringTranslationTrait::$stringTranslation protected property The string translation service. 3
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
TranslationStatusForm::$moduleHandler protected property The module handler service.
TranslationStatusForm::$state protected property The Drupal state storage service.
TranslationStatusForm::buildForm public function Form builder for displaying the current translation status. Overrides FormInterface::buildForm
TranslationStatusForm::create public static function Instantiates a new instance of this class. Overrides FormBase::create
TranslationStatusForm::createInfoString protected function Provides debug info for projects in case translation files are not found.
TranslationStatusForm::getFormId public function Returns a unique string identifying the form. Overrides FormInterface::getFormId
TranslationStatusForm::prepareUpdateData protected function Prepare information about projects with available translation updates.
TranslationStatusForm::submitForm public function Form submission handler. Overrides FormInterface::submitForm
TranslationStatusForm::validateForm public function Form validation handler. Overrides FormBase::validateForm
TranslationStatusForm::__construct public function Constructs a TranslationStatusForm object.

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