diff --git a/core/modules/locale/lib/Drupal/locale/Controller/LocaleController.php b/core/modules/locale/lib/Drupal/locale/Controller/LocaleController.php new file mode 100644 index 0000000..1a558ab --- /dev/null +++ b/core/modules/locale/lib/Drupal/locale/Controller/LocaleController.php @@ -0,0 +1,54 @@ +get('keyvalue')->get('state')); + } + + /** + * Constructs a TranslateEditForm object. + */ + public function __construct(KeyValueStoreInterface $state) { + $this->state = $state; + } + + /** + * Page callback: Shows the string search screen. + * + * @see locale_menu() + */ + public function translatePage() { + + return array( + 'filter' => drupal_get_form(new TranslateFilterForm($this->state)), + 'form' => drupal_get_form(new TranslateEditForm($this->state)), + ); + } + +} diff --git a/core/modules/locale/lib/Drupal/locale/Form/TranslateEditForm.php b/core/modules/locale/lib/Drupal/locale/Form/TranslateEditForm.php new file mode 100644 index 0000000..3132a7d --- /dev/null +++ b/core/modules/locale/lib/Drupal/locale/Form/TranslateEditForm.php @@ -0,0 +1,231 @@ +name : "- None -"; + + $path = drupal_get_path('module', 'locale'); + $form['#attached']['css'] = array( + $path . '/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 = locale_translate_filter_load_strings(); + + $plural_formulas = 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' => t('Source string'), + '#title_display' => 'invisible', + '#markup' => check_plain($source_array[0]), + ); + } + 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' => t('Singular form'), + '#markup' => check_plain($source_array[0]), + ); + $form['strings'][$string->lid]['original_plural'] = array( + '#type' => 'item', + '#title' => t('Plural form'), + '#markup' => check_plain($source_array[1]), + ); + } + if (!empty($string->context)) { + $form['strings'][$string->lid]['context'] = array( + '#type' => 'value', + '#value' => check_plain($string->context), + ); + } + // 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' => t('Translated string'), + '#title_display' => 'invisible', + '#rows' => $rows, + '#default_value' => $translation_array[0], + ); + } + 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 ? t('Singular form') : format_plural($i, 'First plural form', '@count. plural form')), + '#rows' => $rows, + '#default_value' => isset($translation_array[$i]) ? $translation_array[$i] : '', + ); + } + } + else { + // Fallback for unknown number of plurals. + $form['strings'][$string->lid]['translations'][0] = array( + '#type' => 'textarea', + '#title' => t('Singular form'), + '#rows' => $rows, + '#default_value' => $translation_array[0], + ); + $form['strings'][$string->lid]['translations'][1] = array( + '#type' => 'textarea', + '#title' => t('Plural form'), + '#rows' => $rows, + '#default_value' => isset($translation_array[1]) ? $translation_array[1] : '', + ); + } + } + } + if (count(element_children($form['strings']))) { + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array('#type' => 'submit', '#value' => 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", t('The submitted string contains disallowed HTML: %string', array('%string' => $value))); + form_set_error("translations][$langcode][$key", 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 (locale_storage()->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] : locale_storage()->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(t('The strings have been saved.')); + + // Keep the user on the current pager page. + if (isset($_GET['page'])) { + $form_state['redirect'] = array('admin/config/regional/translate', array('query' => array('page' => $_GET['page']))); + } + + if ($updated) { + // Clear cache and force refresh of JavaScript translations. + _locale_refresh_translations(array($langcode), $updated); + } + } +} diff --git a/core/modules/locale/lib/Drupal/locale/Form/TranslateFilterForm.php b/core/modules/locale/lib/Drupal/locale/Form/TranslateFilterForm.php new file mode 100644 index 0000000..dfefa1e --- /dev/null +++ b/core/modules/locale/lib/Drupal/locale/Form/TranslateFilterForm.php @@ -0,0 +1,112 @@ + 'details', + '#title' => t('Filter translatable strings'), + '#collapsed' => FALSE, + ); + foreach ($filters as $key => $filter) { + // Special case for 'string' filter. + if ($key == 'string') { + $form['filters']['status']['string'] = array( + '#type' => 'search', + '#title' => $filter['title'], + '#description' => $filter['description'], + '#default_value' => $filter_values[$key], + ); + } + else { + $empty_option = isset($filter['options'][$filter['default']]) ? $filter['options'][$filter['default']] : '- None -'; + $form['filters']['status'][$key] = array( + '#title' => $filter['title'], + '#type' => 'select', + '#empty_value' => $filter['default'], + '#empty_option' => $empty_option, + '#size' => 0, + '#options' => $filter['options'], + '#default_value' => $filter_values[$key], + ); + if (isset($filter['states'])) { + $form['filters']['status'][$key]['#states'] = $filter['states']; + } + } + } + + $form['filters']['actions'] = array( + '#type' => 'actions', + '#attributes' => array('class' => array('container-inline')), + ); + $form['filters']['actions']['submit'] = array( + '#type' => 'submit', + '#value' => t('Filter'), + ); + if (!empty($_SESSION['locale_translate_filter'])) { + $form['filters']['actions']['reset'] = array( + '#type' => 'submit', + '#value' => t('Reset'), + ); + } + + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, array &$form_state) { + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + + $op = $form_state['values']['op']; + $filters = locale_translate_filters(); + switch ($op) { + case t('Filter'): + foreach ($filters as $name => $filter) { + if (isset($form_state['values'][$name])) { + $_SESSION['locale_translate_filter'][$name] = $form_state['values'][$name]; + } + } + break; + + case t('Reset'): + $_SESSION['locale_translate_filter'] = array(); + break; + } + + $form_state['redirect'] = 'admin/config/regional/translate/translate'; + } +} diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index 75e0a22..bc20183 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -187,9 +187,7 @@ function locale_menu() { $items['admin/config/regional/translate'] = array( 'title' => 'User interface translation', 'description' => 'Translate the built-in user interface.', - 'page callback' => 'locale_translate_page', - 'access arguments' => array('translate interface'), - 'file' => 'locale.pages.inc', + 'route_name' => 'locale_translate_page', 'weight' => -5, ); $items['admin/config/regional/translate/translate'] = array( @@ -1355,3 +1353,135 @@ function _locale_rebuild_js($langcode = NULL) { return TRUE; } } + +/** + * Builds a string search query and returns an array of string objects. + * + * @return array + * Array of Drupal\locale\TranslationString objects. + */ +function locale_translate_filter_load_strings() { + $filter_values = locale_translate_filter_values(); + + // Language is sanitized to be one of the possible options in + // locale_translate_filter_values(). + $conditions = array('language' => $filter_values['langcode']); + $options = array('pager limit' => 30, 'translated' => TRUE, 'untranslated' => TRUE); + + // Add translation status conditions and options. + switch ($filter_values['translation']) { + case 'translated': + $conditions['translated'] = TRUE; + if ($filter_values['customized'] != 'all') { + $conditions['customized'] = $filter_values['customized']; + } + break; + + case 'untranslated': + $conditions['translated'] = FALSE; + break; + + } + + if (!empty($filter_values['string'])) { + $options['filters']['source'] = $filter_values['string']; + if ($options['translated']) { + $options['filters']['translation'] = $filter_values['string']; + } + } + + return locale_storage()->getTranslations($conditions, $options); +} + +/** + * Build array out of search criteria specified in request variables. + */ +function locale_translate_filter_values() { + $filter_values = &drupal_static(__FUNCTION__); + if (!isset($filter_values)) { + $filter_values = array(); + $filters = locale_translate_filters(); + foreach ($filters as $key => $filter) { + $filter_values[$key] = $filter['default']; + // Let the filter defaults be overwritten by parameters in the URL. + if (isset($_GET[$key])) { + // Only allow this value if it was among the options, or + // if there were no fixed options to filter for. + if (!isset($filter['options']) || isset($filter['options'][$_GET[$key]])) { + $filter_values[$key] = $_GET[$key]; + } + } + elseif (isset($_SESSION['locale_translate_filter'][$key])) { + // Only allow this value if it was among the options, or + // if there were no fixed options to filter for. + if (!isset($filter['options']) || isset($filter['options'][$_SESSION['locale_translate_filter'][$key]])) { + $filter_values[$key] = $_SESSION['locale_translate_filter'][$key]; + } + } + } + } + return $filter_values; +} + +/** + * List locale translation filters that can be applied. + */ +function locale_translate_filters() { + $filters = array(); + + // Get all languages, except English. + drupal_static_reset('language_list'); + $languages = language_list(); + $language_options = array(); + foreach ($languages as $langcode => $language) { + if ($langcode != 'en' || locale_translate_english()) { + $language_options[$langcode] = $language->name; + } + } + + // Pick the current interface language code for the filter. + $default_langcode = language(LANGUAGE_TYPE_INTERFACE)->langcode; + if (!isset($language_options[$default_langcode])) { + $available_langcodes = array_keys($language_options); + $default_langcode = array_shift($available_langcodes); + } + + $filters['string'] = array( + 'title' => t('String contains'), + 'description' => t('Leave blank to show all strings. The search is case sensitive.'), + 'default' => '', + ); + + $filters['langcode'] = array( + 'title' => t('Translation language'), + 'options' => $language_options, + 'default' => $default_langcode, + ); + + $filters['translation'] = array( + 'title' => t('Search in'), + 'options' => array( + 'all' => t('Both translated and untranslated strings'), + 'translated' => t('Only translated strings'), + 'untranslated' => t('Only untranslated strings'), + ), + 'default' => 'all', + ); + + $filters['customized'] = array( + 'title' => t('Translation type'), + 'options' => array( + 'all' => t('All'), + LOCALE_NOT_CUSTOMIZED => t('Non-customized translation'), + LOCALE_CUSTOMIZED => t('Customized translation'), + ), + 'states' => array( + 'visible' => array( + ':input[name=translation]' => array('value' => 'translated'), + ), + ), + 'default' => 'all', + ); + + return $filters; +} diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc index a109f5f..cb4e9cd 100644 --- a/core/modules/locale/locale.pages.inc +++ b/core/modules/locale/locale.pages.inc @@ -10,456 +10,6 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** - * Page callback: Shows the string search screen. - * - * @see locale_menu() - */ -function locale_translate_page() { - return array( - 'filter' => drupal_get_form('locale_translate_filter_form'), - 'form' => drupal_get_form('locale_translate_edit_form'), - ); -} - -/** - * Builds a string search query and returns an array of string objects. - * - * @return array - * Array of Drupal\locale\TranslationString objects. - */ -function locale_translate_filter_load_strings() { - $filter_values = locale_translate_filter_values(); - - // Language is sanitized to be one of the possible options in - // locale_translate_filter_values(). - $conditions = array('language' => $filter_values['langcode']); - $options = array('pager limit' => 30, 'translated' => TRUE, 'untranslated' => TRUE); - - // Add translation status conditions and options. - switch ($filter_values['translation']) { - case 'translated': - $conditions['translated'] = TRUE; - if ($filter_values['customized'] != 'all') { - $conditions['customized'] = $filter_values['customized']; - } - break; - - case 'untranslated': - $conditions['translated'] = FALSE; - break; - - } - - if (!empty($filter_values['string'])) { - $options['filters']['source'] = $filter_values['string']; - if ($options['translated']) { - $options['filters']['translation'] = $filter_values['string']; - } - } - - return locale_storage()->getTranslations($conditions, $options); -} - -/** - * Build array out of search criteria specified in request variables. - */ -function locale_translate_filter_values() { - $filter_values = &drupal_static(__FUNCTION__); - if (!isset($filter_values)) { - $filter_values = array(); - $filters = locale_translate_filters(); - foreach ($filters as $key => $filter) { - $filter_values[$key] = $filter['default']; - // Let the filter defaults be overwritten by parameters in the URL. - if (isset($_GET[$key])) { - // Only allow this value if it was among the options, or - // if there were no fixed options to filter for. - if (!isset($filter['options']) || isset($filter['options'][$_GET[$key]])) { - $filter_values[$key] = $_GET[$key]; - } - } - elseif (isset($_SESSION['locale_translate_filter'][$key])) { - // Only allow this value if it was among the options, or - // if there were no fixed options to filter for. - if (!isset($filter['options']) || isset($filter['options'][$_SESSION['locale_translate_filter'][$key]])) { - $filter_values[$key] = $_SESSION['locale_translate_filter'][$key]; - } - } - } - } - return $filter_values; -} - -/** - * List locale translation filters that can be applied. - */ -function locale_translate_filters() { - $filters = array(); - - // Get all languages, except English. - drupal_static_reset('language_list'); - $languages = language_list(); - $language_options = array(); - foreach ($languages as $langcode => $language) { - if ($langcode != 'en' || locale_translate_english()) { - $language_options[$langcode] = $language->name; - } - } - - // Pick the current interface language code for the filter. - $default_langcode = language(LANGUAGE_TYPE_INTERFACE)->langcode; - if (!isset($language_options[$default_langcode])) { - $available_langcodes = array_keys($language_options); - $default_langcode = array_shift($available_langcodes); - } - - $filters['string'] = array( - 'title' => t('String contains'), - 'description' => t('Leave blank to show all strings. The search is case sensitive.'), - 'default' => '', - ); - - $filters['langcode'] = array( - 'title' => t('Translation language'), - 'options' => $language_options, - 'default' => $default_langcode, - ); - - $filters['translation'] = array( - 'title' => t('Search in'), - 'options' => array( - 'all' => t('Both translated and untranslated strings'), - 'translated' => t('Only translated strings'), - 'untranslated' => t('Only untranslated strings'), - ), - 'default' => 'all', - ); - - $filters['customized'] = array( - 'title' => t('Translation type'), - 'options' => array( - 'all' => t('All'), - LOCALE_NOT_CUSTOMIZED => t('Non-customized translation'), - LOCALE_CUSTOMIZED => t('Customized translation'), - ), - 'states' => array( - 'visible' => array( - ':input[name=translation]' => array('value' => 'translated'), - ), - ), - 'default' => 'all', - ); - - return $filters; -} - -/** - * Return form for locale translation filters. - * - * @ingroup forms - */ -function locale_translate_filter_form($form, &$form_state) { - $filters = locale_translate_filters(); - $filter_values = locale_translate_filter_values(); - - $form['#attached']['css'] = array( - drupal_get_path('module', 'locale') . '/locale.admin.css', - ); - - $form['filters'] = array( - '#type' => 'details', - '#title' => t('Filter translatable strings'), - '#collapsed' => FALSE, - ); - foreach ($filters as $key => $filter) { - // Special case for 'string' filter. - if ($key == 'string') { - $form['filters']['status']['string'] = array( - '#type' => 'search', - '#title' => $filter['title'], - '#description' => $filter['description'], - '#default_value' => $filter_values[$key], - ); - } - else { - $empty_option = isset($filter['options'][$filter['default']]) ? $filter['options'][$filter['default']] : '- None -'; - $form['filters']['status'][$key] = array( - '#title' => $filter['title'], - '#type' => 'select', - '#empty_value' => $filter['default'], - '#empty_option' => $empty_option, - '#size' => 0, - '#options' => $filter['options'], - '#default_value' => $filter_values[$key], - ); - if (isset($filter['states'])) { - $form['filters']['status'][$key]['#states'] = $filter['states']; - } - } - } - - $form['filters']['actions'] = array( - '#type' => 'actions', - '#attributes' => array('class' => array('container-inline')), - ); - $form['filters']['actions']['submit'] = array( - '#type' => 'submit', - '#value' => t('Filter'), - ); - if (!empty($_SESSION['locale_translate_filter'])) { - $form['filters']['actions']['reset'] = array( - '#type' => 'submit', - '#value' => t('Reset'), - ); - } - - return $form; -} - -/** - * Process result from locale translation filter form. - */ -function locale_translate_filter_form_submit($form, &$form_state) { - $op = $form_state['values']['op']; - $filters = locale_translate_filters(); - switch ($op) { - case t('Filter'): - foreach ($filters as $name => $filter) { - if (isset($form_state['values'][$name])) { - $_SESSION['locale_translate_filter'][$name] = $form_state['values'][$name]; - } - } - break; - - case t('Reset'): - $_SESSION['locale_translate_filter'] = array(); - break; - - } - - $form_state['redirect'] = 'admin/config/regional/translate/translate'; -} - -/** - * Form constructor for the string editing form. - * - * @see locale_menu() - * @see locale_translate_edit_form_validate() - * @see locale_translate_edit_form_submit() - * - * @ingroup forms - */ -function locale_translate_edit_form($form, &$form_state) { - $filter_values = locale_translate_filter_values(); - $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 . '/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 = locale_translate_filter_load_strings(); - - $plural_formulas = 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' => t('Source string'), - '#title_display' => 'invisible', - '#markup' => check_plain($source_array[0]), - ); - } - 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' => t('Singular form'), - '#markup' => check_plain($source_array[0]), - ); - $form['strings'][$string->lid]['original_plural'] = array( - '#type' => 'item', - '#title' => t('Plural form'), - '#markup' => check_plain($source_array[1]), - ); - } - if (!empty($string->context)) { - $form['strings'][$string->lid]['context'] = array( - '#type' => 'value', - '#value' => check_plain($string->context), - ); - } - // 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' => t('Translated string'), - '#title_display' => 'invisible', - '#rows' => $rows, - '#default_value' => $translation_array[0], - ); - } - 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 ? t('Singular form') : format_plural($i, 'First plural form', '@count. plural form')), - '#rows' => $rows, - '#default_value' => isset($translation_array[$i]) ? $translation_array[$i] : '', - ); - } - } - else { - // Fallback for unknown number of plurals. - $form['strings'][$string->lid]['translations'][0] = array( - '#type' => 'textarea', - '#title' => t('Singular form'), - '#rows' => $rows, - '#default_value' => $translation_array[0], - ); - $form['strings'][$string->lid]['translations'][1] = array( - '#type' => 'textarea', - '#title' => t('Plural form'), - '#rows' => $rows, - '#default_value' => isset($translation_array[1]) ? $translation_array[1] : '', - ); - } - } - } - if (count(element_children($form['strings']))) { - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save translations')); - } - } - return $form; -} - -/** - * Form validation handler for locale_translate_edit_form(). - * - * @see locale_translate_edit_form_submit() - */ -function locale_translate_edit_form_validate($form, &$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", t('The submitted string contains disallowed HTML: %string', array('%string' => $value))); - form_set_error("translations][$langcode][$key", 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); - } - } - } -} - -/** - * Form submission handler for locale_translate_edit_form(). - * - * @see locale_translate_edit_form_validate() - */ -function locale_translate_edit_form_submit($form, &$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 (locale_storage()->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] : locale_storage()->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(t('The strings have been saved.')); - - // Keep the user on the current pager page. - if (isset($_GET['page'])) { - $form_state['redirect'] = array('admin/config/regional/translate', array('query' => array('page' => $_GET['page']))); - } - - if ($updated) { - // Clear cache and refresh configuration and JavaScript translations. - _locale_refresh_translations(array($langcode), $updated); - _locale_refresh_configuration(array($langcode), $updated); - } - -} - -/** * Page callback: Checks for translation updates and displays the translations status. * * Manually checks the translation status without the use of cron. diff --git a/core/modules/locale/locale.routing.yml b/core/modules/locale/locale.routing.yml index a2a5820..46fb1f5 100644 --- a/core/modules/locale/locale.routing.yml +++ b/core/modules/locale/locale.routing.yml @@ -4,3 +4,17 @@ locale_settings: _form: 'Drupal\locale\Form\LocaleSettingsForm' requirements: _permission: 'translate interface' + +locale_translate_page: + pattern: '/admin/config/regional/translate' + defaults: + _content: 'Drupal\locale\Controller\LocaleController::translatePage' + requirements: + _permission: 'translate interface' + +locale_translate_page_tab: + pattern: '/admin/config/regional/translate/translate' + defaults: + _content: 'Drupal\locale\Controller\LocaleController::translatePage' + requirements: + _permission: 'translate interface'