public function testOverview() { $this->loginAsTranslator(); $this->drupalGet('admin/tmgmt/sources/locale/default'); $this->assertText('Hello World'); $this->assertText('Example'); $rows = $this->xpath('//tbody/tr'); foreach ($rows as $row) { if ($row->td[1] == 'Hello World') { $this->assertEqual((string) $row->td[3]->img['title'], t('Translation up to date')); $this->assertEqual((string) $row->td[4]->img['title'], t('Not translated')); } } // Filter on the label. $edit = array('search[label]' => 'Hello'); $this->drupalPostForm(NULL, $edit, t('Search')); $this->assertText('Hello World'); $this->assertNoText('Example'); $locale_object = db_query('SELECT * FROM {locales_source} WHERE source = :source LIMIT 1', array(':source' => 'Hello World'))->fetchObject(); // First add source to the cart to test its functionality. $edit = array('items[' . $locale_object->lid . ']' => TRUE); $this->drupalPostForm(NULL, $edit, t('Add to cart')); $this->assertRaw(t('@count content source was added into the <a href=":url">cart</a>.', array('@count' => 1, ':url' => \Drupal::url('tmgmt.cart')))); $edit['target_language[]'] = array('gsw-berne'); $this->drupalPostForm('admin/tmgmt/cart', $edit, t('Request translation')); // Assert that the job item is displayed. $this->assertText('Hello World'); $this->assertText(t('Locale')); $this->assertText('2'); $this->drupalPostForm(NULL, array('target_language' => 'gsw-berne'), t('Submit to provider')); // Test for the translation flag title. $this->drupalGet('admin/tmgmt/sources/locale/default'); $this->assertRaw(t('Active job item: Needs review')); // Review and accept the job item. $job_items = tmgmt_job_item_load_latest('locale', 'default', $locale_object->lid, 'en'); $this->drupalGet('admin/tmgmt/items/' . $job_items['gsw-berne']->id()); $this->assertRaw('gsw-berne: Hello World'); $this->drupalPostForm(NULL, array(), t('Save as completed')); $this->drupalGet('admin/tmgmt/sources/locale/default'); $this->assertNoRaw(t('Active job item: Needs review')); $rows = $this->xpath('//tbody/tr'); foreach ($rows as $row) { if ($row->td[1] == 'Hello World') { $this->assertEqual((string) $row->td[3]->img['title'], t('Translation up to date')); $this->assertEqual((string) $row->td[4]->img['title'], t('Translation up to date')); } } // Test the missing translation filter. $this->drupalGet('admin/tmgmt/sources/locale/default'); // Check that the source language (en) has been removed from the target language // select box. $elements = $this->xpath('//select[@name=:name]//option[@value=:option]', array(':name' => 'search[target_language]', ':option' => 'en')); $this->assertTrue(empty($elements)); // Filter on the "Not translated to". $edit = array('search[missing_target_language]' => 'gsw-berne'); $this->drupalPostForm(NULL, $edit, t('Search')); // Hello world is translated to "gsw-berne" therefore it must not show up // in the list. $this->assertNoText('Hello World'); }
/** * {@inheritdoc} */ function buildForm(array $form, FormStateInterface $form_state, array $build = NULL) { // Store the entity in the form state so we can easily create the job in the // submit handler. $form_state->set('entity', $build['#entity']); $overview = $build['content_translation_overview']; $form['#title'] = $this->t('Translations of @title', array('@title' => $build['#entity']->label())); $form['actions'] = array('#type' => 'details', '#title' => t('Operations'), '#open' => TRUE, '#attributes' => array('class' => array('tmgmt-source-operations-wrapper'))); $form['actions']['request'] = array('#type' => 'submit', '#button_type' => 'primary', '#value' => $this->t('Request translation'), '#submit' => array('::submitForm')); tmgmt_add_cart_form($form['actions'], $form_state, 'content', $form_state->get('entity')->getEntityTypeId(), $form_state->get('entity')->id()); // Inject our additional column into the header. array_splice($overview['#header'], -1, 0, array(t('Pending Translations'))); // Make this a tableselect form. $form['languages'] = array('#type' => 'tableselect', '#header' => $overview['#header'], '#options' => array()); $languages = \Drupal::languageManager()->getLanguages(); // Check if there is a job / job item that references this translation. $entity_langcode = $form_state->get('entity')->language()->getId(); $items = tmgmt_job_item_load_latest('content', $form_state->get('entity')->getEntityTypeId(), $form_state->get('entity')->id(), $entity_langcode); foreach ($languages as $langcode => $language) { if ($langcode == LanguageInterface::LANGCODE_DEFAULT) { // Never show language neutral on the overview. continue; } // Since the keys are numeric and in the same order we can shift one element // after the other from the original non-form rows. $option = array_shift($overview['#rows']); if ($langcode == $entity_langcode) { $additional = array('data' => array('#markup' => '<strong>' . t('Source') . '</strong>')); // This is the source object so we disable the checkbox for this row. $form['languages'][$langcode] = array('#type' => 'checkbox', '#disabled' => TRUE); } elseif (isset($items[$langcode])) { $item = $items[$langcode]; $states = JobItem::getStates(); $path = \Drupal::routeMatch()->getRouteName() ? Url::fromRouteMatch(\Drupal::routeMatch())->getInternalPath() : ''; $destination = array('destination' => $path); $additional = \Drupal::l($states[$item->getState()], $item->urlInfo()->setOption('query', $destination)); // Disable the checkbox for this row since there is already a translation // in progress that has not yet been finished. This way we make sure that // we don't stack multiple active translations for the same item on top // of each other. $form['languages'][$langcode] = array('#type' => 'checkbox', '#disabled' => TRUE); } else { // There is no translation job / job item for this target language. $additional = t('None'); } // Inject the additional column into the array. // The generated form structure has changed, support both an additional // 'data' key (that is not supported by tableselect) and the old version // without. if (isset($option['data'])) { array_splice($option['data'], -1, 0, array($additional)); // Append the current option array to the form. $form['languages']['#options'][$langcode] = $option['data']; } else { array_splice($option, -1, 0, array($additional)); // Append the current option array to the form. $form['languages']['#options'][$langcode] = $option; } } return $form; }
/** * Builds a table row for simple configuration. * * @param array $definition * A definition. * * @return array * A single table row for the overview. */ public function overviewRowSimple(array $definition) { // Get current job items for the entity to determine translation statuses. $config_id = $definition['names'][0]; $source_lang = \Drupal::config($definition['names'][0])->get('langcode') ?: 'en'; $current_job_items = tmgmt_job_item_load_latest('config', ConfigSource::SIMPLE_CONFIG, $definition['id'], $source_lang); $row = array('id' => $definition['id'], 'title' => $definition['title']); // Load entity translation specific data. foreach (\Drupal::languageManager()->getLanguages() as $langcode => $language) { $translation_status = 'current'; if ($langcode == $source_lang) { $translation_status = 'original'; } elseif (!$this->isTranslated($langcode, $config_id)) { $translation_status = 'missing'; } // @todo Find a way to support marking configuration translations as outdated. $build = $this->buildTranslationStatus($translation_status, isset($current_job_items[$langcode]) ? $current_job_items[$langcode] : NULL); $row['langcode-' . $langcode] = ['data' => \Drupal::service('renderer')->render($build), 'class' => array('langstatus-' . $langcode)]; } return $row; }
/** * Helper function to create translation data list for the sources page list. * * @param array $strings * Result of the search query returned by tmgmt_i18n_string_get_strings(). * @param string $type * I18n object type. * * @return array * Structured array with translation data. */ protected function getTranslationData($strings, $type) { $objects = array(); // Source language of locale strings is always english. $source_language = 'en'; foreach ($strings as $string) { $id = $string->lid; // Get existing translations and current job items for the entity // to determine translation statuses $current_job_items = tmgmt_job_item_load_latest('locale', $type, $id, $source_language); $objects[$id] = array('id' => $id, 'object' => $string); // Load entity translation specific data. foreach ($this->getLanguages() as $langcode => $language) { $translation_status = 'current'; if ($langcode == $source_language) { $translation_status = 'original'; } elseif ($string->{$langcode} === NULL) { $translation_status = 'missing'; } $objects[$id]['current_job_items'][$langcode] = isset($current_job_items[$langcode]) ? $current_job_items[$langcode] : NULL; $objects[$id]['translation_statuses'][$langcode] = $translation_status; } } return $objects; }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, array $build = NULL, $plugin_id = NULL) { // Store the entity in the form state so we can easily create the job in the // submit handler. $mapper_definition = \Drupal::service('plugin.manager.config_translation.mapper')->getDefinition($plugin_id); /** @var \Drupal\config_translation\ConfigMapperInterface $mapper */ $mapper = $this->configMapperManager->createInstance($plugin_id); $mapper->populateFromRouteMatch($this->routeMatch); $form_state->set('mapper', $mapper); if (!isset($mapper_definition['entity_type'])) { $form_state->set('item_type', ConfigSource::SIMPLE_CONFIG); $form_state->set('item_id', $mapper_definition['id']); } else { $id = $mapper->getConfigNames()[0]; $form_state->set('id', $id); $form_state->set('item_type', $plugin_id); $form_state->set('item_id', $id); } $form['#title'] = $this->t('Translations of @title', array('@title' => $mapper->getTitle())); $overview = $build['languages']; $form['top_actions'] = array('#type' => 'details', '#title' => t('Operations'), '#open' => TRUE, '#attributes' => array('class' => array('tmgmt-source-operations-wrapper'))); $form['top_actions']['request'] = array('#type' => 'submit', '#button_type' => 'primary', '#value' => $this->t('Request translation'), '#submit' => array('::submitForm')); tmgmt_add_cart_form($form['top_actions'], $form_state, 'config', $form_state->get('item_type'), $form_state->get('item_id')); // Inject our additional column into the header. array_splice($overview['#header'], -1, 0, array(t('Pending Translations'))); // Make this a tableselect form. $form['languages'] = array('#type' => 'tableselect', '#header' => $overview['#header'], '#options' => array()); $languages = \Drupal::languageManager()->getLanguages(); // Check if there is a job / job item that references this translation. $items = tmgmt_job_item_load_latest('config', $form_state->get('item_type'), $form_state->get('item_id'), $mapper->getLangcode()); foreach ($languages as $langcode => $language) { if ($langcode == LanguageInterface::LANGCODE_DEFAULT) { // Never show language neutral on the overview. continue; } // Since the keys are numeric and in the same order we can shift one element // after the other from the original non-form rows. $option = $overview[$langcode]; if ($langcode == $mapper->getLangcode()) { $additional = array('data' => array('#markup' => '<strong>' . t('Source') . '</strong>')); // This is the source object so we disable the checkbox for this row. $form['languages'][$langcode] = array('#type' => 'checkbox', '#disabled' => TRUE); } elseif (isset($items[$langcode])) { $item = $items[$langcode]; $states = JobItem::getStates(); $additional = \Drupal::l($states[$item->getState()], $item->urlInfo()->setOption('query', array('destination' => Url::fromRoute('<current>')->getInternalPath()))); // Disable the checkbox for this row since there is already a translation // in progress that has not yet been finished. This way we make sure that // we don't stack multiple active translations for the same item on top // of each other. $form['languages'][$langcode] = array('#type' => 'checkbox', '#disabled' => TRUE); } else { // There is no translation job / job item for this target language. $additional = t('None'); } // Inject the additional column into the array. // The generated form structure has changed, support both an additional // 'data' key (that is not supported by tableselect) and the old version // without. if (isset($option['data'])) { array_splice($option['data'], -1, 0, array($additional)); // Append the current option array to the form. $form['languages']['#options'][$langcode] = $option['data']; } else { array_splice($option, -1, 0, array($additional)); // Append the current option array to the form. $form['languages']['#options'][$langcode] = array(drupal_render($option['language']), $additional, drupal_render($option['operations'])); } } return $form; }
/** * Builds a table row for overview form. * * @param array ContentEntityInterface $entity * Data needed to build the list row. * @param array $bundles * The array of bundles. * * @return array */ public function overviewRow(ContentEntityInterface $entity, array $bundles) { $label = $entity->label() ?: $this->t('@type: @id', array('@type' => $entity->getEntityTypeId(), '@id' => $entity->id())); // Get existing translations and current job items for the entity // to determine translation statuses $translations = $entity->getTranslationLanguages(); $source_lang = $entity->language()->getId(); $current_job_items = tmgmt_job_item_load_latest('content', $entity->getEntityTypeId(), $entity->id(), $source_lang); $row = array('id' => $entity->id(), 'title' => $entity->hasLinkTemplate('canonical') ? $entity->toLink($label, 'canonical')->toString() : ($entity->label() ?: $entity->id())); if (count($bundles) > 1) { $row['bundle'] = isset($bundles[$entity->bundle()]) ? $bundles[$entity->bundle()] : t('Unknown'); } // Load entity translation specific data. $manager = \Drupal::service('content_translation.manager'); foreach (\Drupal::languageManager()->getLanguages() as $langcode => $language) { $translation_status = 'current'; if ($langcode == $source_lang) { $translation_status = 'original'; } elseif (!isset($translations[$langcode])) { $translation_status = 'missing'; } elseif ($translation = $entity->getTranslation($langcode)) { $metadata = $manager->getTranslationMetadata($translation); if ($metadata->isOutdated()) { $translation_status = 'outofdate'; } } $build = $this->buildTranslationStatus($translation_status, isset($current_job_items[$langcode]) ? $current_job_items[$langcode] : NULL); $row['langcode-' . $langcode] = ['data' => \Drupal::service('renderer')->render($build), 'class' => array('langstatus-' . $langcode)]; } return $row; }