Commit 89b5fea7 authored by webchick's avatar webchick
Browse files

Issue #1978916 by likin, YesCT, disasm, ayelet_Cr, tim.plunkett, vijaycs85,...

Issue #1978916 by likin, YesCT, disasm, ayelet_Cr, tim.plunkett, vijaycs85, Letharion: Convert locale_translate_page() to a Controller.
parent b8d150cc
<?php
/**
* @file
* Contains \Drupal\language\Form\ContentLanguageSettingsForm.
*/
namespace Drupal\language\Form;
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Config\Context\ContextInterface;
use Drupal\Core\Entity\EntityManager;
use Drupal\system\SystemConfigFormBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Configure the content language settings for this site.
*/
class ContentLanguageSettingsForm extends SystemConfigFormBase {
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManager
*/
protected $entityManager;
/**
* Constructs a ContentLanguageSettingsForm object.
*
* @param \Drupal\Core\Config\ConfigFactory $config_factory
* The config factory.
* @param \Drupal\Core\Config\Context\ContextInterface $context
* The configuration context to use.
* @param \Drupal\Core\Entity\EntityManager $entity_manager
* The entity manager.
*/
public function __construct(ConfigFactory $config_factory, ContextInterface $context, EntityManager $entity_manager) {
parent::__construct($config_factory, $context);
$this->entityManager = $entity_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('config.factory'),
$container->get('config.context.free'),
$container->get('plugin.manager.entity')
);
}
/**
* Return a list of entity types for which language settings are supported.
*
* @return array
* A list of entity types which are translatable.
*/
protected function entitySupported() {
$supported = array();
foreach ($this->entityManager->getDefinitions() as $entity_type => $info) {
if (!empty($info['translatable'])) {
$supported[$entity_type] = $entity_type;
}
}
return $supported;
}
/**
* {@inheritdoc}
*/
public function getFormID() {
return 'language_content_settings_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, array &$form_state) {
$entity_info = $this->entityManager->getDefinitions();
$labels = array();
$default = array();
$bundles = entity_get_bundles();
$language_configuration = array();
foreach ($this->entitySupported() as $entity_type) {
$labels[$entity_type] = isset($entity_info[$entity_type]['label']) ? $entity_info[$entity_type]['label'] : $entity_type;
$default[$entity_type] = FALSE;
// Check whether we have any custom setting.
foreach ($bundles as $bundle => $bundle_info) {
$conf = language_get_default_configuration($entity_type, $bundle);
if (!empty($conf['language_show']) || $conf['langcode'] != 'site_default') {
$default[$entity_type] = $entity_type;
}
$language_configuration[$entity_type][$bundle] = $conf;
}
}
asort($labels);
$form = array(
'#labels' => $labels,
'#attached' => array(
'library' => array(
array('language', 'drupal.language.admin'),
),
),
);
$form['entity_types'] = array(
'#title' => $this->t('Custom language settings'),
'#type' => 'checkboxes',
'#options' => $labels,
'#default_value' => $default,
);
$form['settings'] = array('#tree' => TRUE);
foreach ($labels as $entity_type => $label) {
$info = $entity_info[$entity_type];
$form['settings'][$entity_type] = array(
'#title' => $label,
'#type' => 'container',
'#entity_type' => $entity_type,
'#theme' => 'language_content_settings_table',
'#bundle_label' => isset($info['bundle_label']) ? $info['bundle_label'] : $label,
'#states' => array(
'visible' => array(
':input[name="entity_types[' . $entity_type . ']"]' => array('checked' => TRUE),
),
),
);
foreach ($bundles as $bundle => $bundle_info) {
$form['settings'][$entity_type][$bundle]['settings'] = array(
'#type' => 'item',
'#label' => $bundle_info['label'],
'language' => array(
'#type' => 'language_configuration',
'#entity_information' => array(
'entity_type' => $entity_type,
'bundle' => $bundle,
),
'#default_value' => $language_configuration[$entity_type][$bundle],
),
);
}
}
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => $this->t('Save'),
);
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, array &$form_state) {
$config = $this->configFactory->get('language.settings');
foreach ($form_state['values']['settings'] as $entity_type => $entity_settings) {
foreach ($entity_settings as $bundle => $bundle_settings) {
$config->set(language_get_default_configuration_settings_key($entity_type, $bundle),
array(
'langcode' => $bundle_settings['settings']['language']['langcode'],
'language_show' => $bundle_settings['settings']['langcode']['language_show'],
)
);
}
}
$config->save();
parent::submitForm($form, $form_state);
}
}
......@@ -122,25 +122,25 @@ function testUILanguageNegotiation() {
'string' => $default_string,
'langcode' => $langcode_browser_fallback,
);
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
$this->drupalPost('admin/config/regional/translate', $search, t('Filter'));
$textarea = current($this->xpath('//textarea'));
$lid = (string) $textarea[0]['name'];
$edit = array(
$lid => $language_browser_fallback_string,
);
$this->drupalPost('admin/config/regional/translate/translate', $edit, t('Save translations'));
$this->drupalPost('admin/config/regional/translate', $edit, t('Save translations'));
$search = array(
'string' => $default_string,
'langcode' => $langcode,
);
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
$this->drupalPost('admin/config/regional/translate', $search, t('Filter'));
$textarea = current($this->xpath('//textarea'));
$lid = (string) $textarea[0]['name'];
$edit = array(
$lid => $language_string,
);
$this->drupalPost('admin/config/regional/translate/translate', $edit, t('Save translations'));
$this->drupalPost('admin/config/regional/translate', $edit, t('Save translations'));
// Configure URL language rewrite.
variable_set('language_negotiation_url_type', Language::TYPE_INTERFACE);
......
......@@ -6,43 +6,15 @@
namespace Drupal\locale\Controller;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Routing\UrlGeneratorInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\locale\Form\TranslateEditForm;
use Drupal\locale\Form\TranslateFilterForm;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Return response for manual check translations.
*/
class LocaleController implements ContainerInjectionInterface {
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Constructs a \Drupal\locale\Controller\LocaleController object.
*
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
*/
public function __construct(ModuleHandlerInterface $module_handler, UrlGeneratorInterface $url_generator) {
$this->moduleHandler = $module_handler;
$this->urlGenerator = $url_generator;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('module_handler'),
$container->get('url_generator')
);
}
class LocaleController extends ControllerBase {
/**
* Checks for translation updates and displays the translations status.
......@@ -53,11 +25,11 @@ public static function create(ContainerInterface $container) {
* A redirection to translations reports page.
*/
public function checkTranslation() {
$this->moduleHandler->loadInclude('locale', 'inc', 'locale.compare');
$this->moduleHandler()->loadInclude('locale', 'inc', 'locale.compare');
// Check translation status of all translatable project in all languages.
// First we clear the cached list of projects. Although not strictly
// nescessary, this is helpfull in case the project list is out of sync.
// necessary, this is helpful in case the project list is out of sync.
locale_translation_flush_projects();
locale_translation_check_projects();
......@@ -67,6 +39,21 @@ public function checkTranslation() {
return batch_process('admin/reports/translations');
}
return new RedirectResponse($this->urlGenerator->generateFromPath('admin/reports/translations', array('absolute' => TRUE)));
// @todo Use $this->redirect() after https://drupal.org/node/1978926.
return new RedirectResponse($this->urlGenerator()->generateFromPath('admin/reports/translations', array('absolute' => TRUE)));
}
/**
* Shows the string search screen.
*
* @return array
* The render array for the string search screen.
*/
public function translatePage() {
return array(
'filter' => drupal_get_form(TranslateFilterForm::create($this->container)),
'form' => drupal_get_form(TranslateEditForm::create($this->container)),
);
}
}
<?php
/**
* @file
* Contains \Drupal\locale\Form\TranslateEditForm.
*/
namespace Drupal\locale\Form;
use Drupal\Component\Utility\String;
use Drupal\locale\SourceString;
/**
* Defines a translation edit form.
*/
class TranslateEditForm extends TranslateFormBase {
/**
* {@inheritdoc}
*/
public function getFormID() {
return 'locale_translate_edit_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, array &$form_state) {
$filter_values = $this->translateFilterValues();
$langcode = $filter_values['langcode'];
drupal_static_reset('language_list');
$languages = language_list();
$langname = isset($langcode) ? $languages[$langcode]->name : "- None -";
$path = drupal_get_path('module', 'locale');
$form['#attached']['css'] = array(
$path . '/css/locale.admin.css',
);
$form['#attached']['library'][] = array('locale', 'drupal.locale.admin');
$form['langcode'] = array(
'#type' => 'value',
'#value' => $filter_values['langcode'],
);
$form['strings'] = array(
'#type' => 'item',
'#tree' => TRUE,
'#language' => $langname,
'#theme' => 'locale_translate_edit_form_strings',
);
if (isset($langcode)) {
$strings = $this->translateFilterLoadStrings();
$plural_formulas = $this->state->get('locale.translation.plurals') ?: array();
foreach ($strings as $string) {
// Cast into source string, will do for our purposes.
$source = new SourceString($string);
// Split source to work with plural values.
$source_array = $source->getPlurals();
$translation_array = $string->getPlurals();
if (count($source_array) == 1) {
// Add original string value and mark as non-plural.
$form['strings'][$string->lid]['plural'] = array(
'#type' => 'value',
'#value' => 0,
);
$form['strings'][$string->lid]['original'] = array(
'#type' => 'item',
'#title' => $this->t('Source string (@language)', array('@language' => $this->t('Built-in English'))),
'#title_display' => 'invisible',
'#markup' => '<span lang="en">' . String::checkPlain($source_array[0]) . '</span>',
);
}
else {
// Add original string value and mark as plural.
$form['strings'][$string->lid]['plural'] = array(
'#type' => 'value',
'#value' => 1,
);
$form['strings'][$string->lid]['original_singular'] = array(
'#type' => 'item',
'#title' => $this->t('Singular form'),
'#markup' => '<span lang="en">' . String::checkPlain($source_array[0]) . '</span>',
'#prefix' => '<span class="visually-hidden">' . $this->t('Source string (@language)', array('@language' => $this->t('Built-in English'))) . '</span>'
);
$form['strings'][$string->lid]['original_plural'] = array(
'#type' => 'item',
'#title' => $this->t('Plural form'),
'#markup' => '<span lang="en">' . String::checkPlain($source_array[1]) . '</span>',
);
}
if (!empty($string->context)) {
$form['strings'][$string->lid]['context'] = array(
'#type' => 'value',
'#value' => '<span lang="en">' . String::checkPlain($string->context) . '</span>',
);
}
// Approximate the number of rows to use in the default textarea.
$rows = min(ceil(str_word_count($source_array[0]) / 12), 10);
if (empty($form['strings'][$string->lid]['plural']['#value'])) {
$form['strings'][$string->lid]['translations'][0] = array(
'#type' => 'textarea',
'#title' => $this->t('Translated string (@language)', array('@language' => $langname)),
'#title_display' => 'invisible',
'#rows' => $rows,
'#default_value' => $translation_array[0],
'#attributes' => array('lang' => $langcode),
);
}
else {
// Dealing with plural strings.
if (isset($plural_formulas[$langcode]['plurals']) && $plural_formulas[$langcode]['plurals'] > 2) {
// Add a textarea for each plural variant.
for ($i = 0; $i < $plural_formulas[$langcode]['plurals']; $i++) {
$form['strings'][$string->lid]['translations'][$i] = array(
'#type' => 'textarea',
'#title' => ($i == 0 ? $this->t('Singular form') : format_plural($i, 'First plural form', '@count. plural form')),
'#rows' => $rows,
'#default_value' => isset($translation_array[$i]) ? $translation_array[$i] : '',
'#attributes' => array('lang' => $langcode),
'#prefix' => $i == 0 ? ('<span class="visually-hidden">' . $this->t('Translated string (@language)', array('@language' => $langname)) . '</span>') : '',
);
}
}
else {
// Fallback for unknown number of plurals.
$form['strings'][$string->lid]['translations'][0] = array(
'#type' => 'textarea',
'#title' => $this->t('Singular form'),
'#rows' => $rows,
'#default_value' => $translation_array[0],
'#attributes' => array('lang' => $langcode),
'#prefix' => '<span class="visually-hidden">' . $this->t('Translated string (@language)', array('@language' => $langname)) . '</span>',
);
$form['strings'][$string->lid]['translations'][1] = array(
'#type' => 'textarea',
'#title' => $this->t('Plural form'),
'#rows' => $rows,
'#default_value' => isset($translation_array[1]) ? $translation_array[1] : '',
'#attributes' => array('lang' => $langcode),
);
}
}
}
if (count(element_children($form['strings']))) {
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => $this->t('Save translations'),
);
}
}
return $form;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, array &$form_state) {
$langcode = $form_state['values']['langcode'];
foreach ($form_state['values']['strings'] as $lid => $translations) {
foreach ($translations['translations'] as $key => $value) {
if (!locale_string_is_safe($value)) {
form_set_error("strings][$lid][translations][$key", $this->t('The submitted string contains disallowed HTML: %string', array('%string' => $value)));
form_set_error("translations][$langcode][$key", $this->t('The submitted string contains disallowed HTML: %string', array('%string' => $value)));
watchdog('locale', 'Attempted submission of a translation string with disallowed HTML: %string', array('%string' => $value), WATCHDOG_WARNING);
}
}
}
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, array &$form_state) {
$langcode = $form_state['values']['langcode'];
$updated = array();
// Preload all translations for strings in the form.
$lids = array_keys($form_state['values']['strings']);
$existing_translation_objects = array();
foreach ($this->localeStorage->getTranslations(array('lid' => $lids, 'language' => $langcode, 'translated' => TRUE)) as $existing_translation_object) {
$existing_translation_objects[$existing_translation_object->lid] = $existing_translation_object;
}
foreach ($form_state['values']['strings'] as $lid => $new_translation) {
$existing_translation = isset($existing_translation_objects[$lid]);
// Plural translations are saved in a delimited string. To be able to
// compare the new strings with the existing strings a string in the same format is created.
$new_translation_string_delimited = implode(LOCALE_PLURAL_DELIMITER, $new_translation['translations']);
// Generate an imploded string without delimiter, to be able to run
// empty() on it.
$new_translation_string = implode('', $new_translation['translations']);
$is_changed = FALSE;
if ($existing_translation && $existing_translation_objects[$lid]->translation != $new_translation_string_delimited) {
// If there is an existing translation in the DB and the new translation
// is not the same as the existing one.
$is_changed = TRUE;
}
elseif (!$existing_translation && !empty($new_translation_string)) {
// Newly entered translation.
$is_changed = TRUE;
}
if ($is_changed) {
// Only update or insert if we have a value to use.
$target = isset($existing_translation_objects[$lid]) ? $existing_translation_objects[$lid] : $this->localeStorage->createTranslation(array('lid' => $lid, 'language' => $langcode));
$target->setPlurals($new_translation['translations'])
->setCustomized()
->save();
$updated[] = $target->getId();
}
if (empty($new_translation_string) && isset($existing_translation_objects[$lid])) {
// Empty new translation entered: remove existing entry from database.
$existing_translation_objects[$lid]->delete();
$updated[] = $lid;
}
}
drupal_set_message($this->t('The strings have been saved.'));
// Keep the user on the current pager page.
$page = $this->getRequest()->query->get('page');
if (isset($page)) {
$form_state['redirect'] = array('admin/config/regional/translate', array('query' => array('page' => $page)));
}
if ($updated) {
// Clear cache and force refresh of JavaScript translations.
_locale_refresh_translations(array($langcode), $updated);
_locale_refresh_configuration(array($langcode), $updated);
}
}
}
<?php
/**
* @file
* Contains \Drupal\locale\Form\TranslateFilterForm.
*/
namespace Drupal\locale\Form;
/**
* Provides a filtered translation edit form.
*/
class TranslateFilterForm extends TranslateFormBase {
/**
* {@inheritdoc}
*/
public function getFormID() {
return 'locale_translate_filter_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, array &$form_state) {
$filters = $this->translateFilters();
$filter_values = $this->translateFilterValues();
$form['#attached']['css'] = array(
drupal_get_path('module', 'locale') . '/css/locale.admin.css',
);
$form['filters'] = array(