PageRenderTime 51ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/core/modules/locale/src/Form/TranslateEditForm.php

https://gitlab.com/reasonat/test8
PHP | 239 lines | 177 code | 26 blank | 36 comment | 23 complexity | 9d3780254830cd9d8d75d7779a2b7e0d MD5 | raw file
  1. <?php
  2. namespace Drupal\locale\Form;
  3. use Drupal\Core\Form\FormStateInterface;
  4. use Drupal\Core\Render\Element;
  5. use Drupal\locale\SourceString;
  6. /**
  7. * Defines a translation edit form.
  8. */
  9. class TranslateEditForm extends TranslateFormBase {
  10. /**
  11. * {@inheritdoc}
  12. */
  13. public function getFormId() {
  14. return 'locale_translate_edit_form';
  15. }
  16. /**
  17. * {@inheritdoc}
  18. */
  19. public function buildForm(array $form, FormStateInterface $form_state) {
  20. $filter_values = $this->translateFilterValues();
  21. $langcode = $filter_values['langcode'];
  22. $this->languageManager->reset();
  23. $languages = $this->languageManager->getLanguages();
  24. $langname = isset($langcode) ? $languages[$langcode]->getName() : "- None -";
  25. $form['#attached']['library'][] = 'locale/drupal.locale.admin';
  26. $form['langcode'] = array(
  27. '#type' => 'value',
  28. '#value' => $filter_values['langcode'],
  29. );
  30. $form['strings'] = array(
  31. '#type' => 'table',
  32. '#tree' => TRUE,
  33. '#language' => $langname,
  34. '#header' => [
  35. $this->t('Source string'),
  36. $this->t('Translation for @language', ['@language' => $langname]),
  37. ],
  38. '#empty' => $this->t('No strings available.'),
  39. '#attributes' => ['class' => ['locale-translate-edit-table']],
  40. );
  41. if (isset($langcode)) {
  42. $strings = $this->translateFilterLoadStrings();
  43. $plurals = $this->getNumberOfPlurals($langcode);
  44. foreach ($strings as $string) {
  45. // Cast into source string, will do for our purposes.
  46. $source = new SourceString($string);
  47. // Split source to work with plural values.
  48. $source_array = $source->getPlurals();
  49. $translation_array = $string->getPlurals();
  50. if (count($source_array) == 1) {
  51. // Add original string value and mark as non-plural.
  52. $plural = FALSE;
  53. $form['strings'][$string->lid]['original'] = array(
  54. '#type' => 'item',
  55. '#title' => $this->t('Source string (@language)', array('@language' => $this->t('Built-in English'))),
  56. '#title_display' => 'invisible',
  57. '#plain_text' => $source_array[0],
  58. '#preffix' => '<span lang="en">',
  59. '#suffix' => '</span>',
  60. );
  61. }
  62. else {
  63. // Add original string value and mark as plural.
  64. $plural = TRUE;
  65. $original_singular = [
  66. '#type' => 'item',
  67. '#title' => $this->t('Singular form'),
  68. '#plain_text' => $source_array[0],
  69. '#prefix' => '<span class="visually-hidden">' . $this->t('Source string (@language)', array('@language' => $this->t('Built-in English'))) . '</span><span lang="en">',
  70. '#suffix' => '</span>',
  71. ];
  72. $original_plural = [
  73. '#type' => 'item',
  74. '#title' => $this->t('Plural form'),
  75. '#plain_text' => $source_array[1],
  76. '#preffix' => '<span lang="en">',
  77. '#suffix' => '</span>',
  78. ];
  79. $form['strings'][$string->lid]['original'] = [
  80. $original_singular,
  81. ['#markup' => '<br>'],
  82. $original_plural,
  83. ];
  84. }
  85. if (!empty($string->context)) {
  86. $form['strings'][$string->lid]['original'][] = [
  87. '#type' => 'inline_template',
  88. '#template' => '<br><small>{{ context_title }}: <span lang="en">{{ context }}</span></small>',
  89. '#context' => [
  90. 'context_title' => $this->t('In Context'),
  91. 'context' => $string->context,
  92. ],
  93. ];
  94. }
  95. // Approximate the number of rows to use in the default textarea.
  96. $rows = min(ceil(str_word_count($source_array[0]) / 12), 10);
  97. if (!$plural) {
  98. $form['strings'][$string->lid]['translations'][0] = array(
  99. '#type' => 'textarea',
  100. '#title' => $this->t('Translated string (@language)', array('@language' => $langname)),
  101. '#title_display' => 'invisible',
  102. '#rows' => $rows,
  103. '#default_value' => $translation_array[0],
  104. '#attributes' => array('lang' => $langcode),
  105. );
  106. }
  107. else {
  108. // Add a textarea for each plural variant.
  109. for ($i = 0; $i < $plurals; $i++) {
  110. $form['strings'][$string->lid]['translations'][$i] = array(
  111. '#type' => 'textarea',
  112. // @todo Should use better labels https://www.drupal.org/node/2499639
  113. '#title' => ($i == 0 ? $this->t('Singular form') : $this->formatPlural($i, 'First plural form', '@count. plural form')),
  114. '#rows' => $rows,
  115. '#default_value' => isset($translation_array[$i]) ? $translation_array[$i] : '',
  116. '#attributes' => array('lang' => $langcode),
  117. '#prefix' => $i == 0 ? ('<span class="visually-hidden">' . $this->t('Translated string (@language)', array('@language' => $langname)) . '</span>') : '',
  118. );
  119. }
  120. if ($plurals == 2) {
  121. // Simplify interface text for the most common case.
  122. $form['strings'][$string->lid]['translations'][1]['#title'] = $this->t('Plural form');
  123. }
  124. }
  125. }
  126. if (count(Element::children($form['strings']))) {
  127. $form['actions'] = array('#type' => 'actions');
  128. $form['actions']['submit'] = array(
  129. '#type' => 'submit',
  130. '#value' => $this->t('Save translations'),
  131. );
  132. }
  133. }
  134. $form['pager']['#type'] = 'pager';
  135. return $form;
  136. }
  137. /**
  138. * {@inheritdoc}
  139. */
  140. public function validateForm(array &$form, FormStateInterface $form_state) {
  141. $langcode = $form_state->getValue('langcode');
  142. foreach ($form_state->getValue('strings') as $lid => $translations) {
  143. foreach ($translations['translations'] as $key => $value) {
  144. if (!locale_string_is_safe($value)) {
  145. $form_state->setErrorByName("strings][$lid][translations][$key", $this->t('The submitted string contains disallowed HTML: %string', array('%string' => $value)));
  146. $form_state->setErrorByName("translations][$langcode][$key", $this->t('The submitted string contains disallowed HTML: %string', array('%string' => $value)));
  147. $this->logger('locale')->warning('Attempted submission of a translation string with disallowed HTML: %string', array('%string' => $value));
  148. }
  149. }
  150. }
  151. }
  152. /**
  153. * {@inheritdoc}
  154. */
  155. public function submitForm(array &$form, FormStateInterface $form_state) {
  156. $langcode = $form_state->getValue('langcode');
  157. $updated = array();
  158. // Preload all translations for strings in the form.
  159. $lids = array_keys($form_state->getValue('strings'));
  160. $existing_translation_objects = array();
  161. foreach ($this->localeStorage->getTranslations(array('lid' => $lids, 'language' => $langcode, 'translated' => TRUE)) as $existing_translation_object) {
  162. $existing_translation_objects[$existing_translation_object->lid] = $existing_translation_object;
  163. }
  164. foreach ($form_state->getValue('strings') as $lid => $new_translation) {
  165. $existing_translation = isset($existing_translation_objects[$lid]);
  166. // Plural translations are saved in a delimited string. To be able to
  167. // compare the new strings with the existing strings a string in the same
  168. // format is created.
  169. $new_translation_string_delimited = implode(LOCALE_PLURAL_DELIMITER, $new_translation['translations']);
  170. // Generate an imploded string without delimiter, to be able to run
  171. // empty() on it.
  172. $new_translation_string = implode('', $new_translation['translations']);
  173. $is_changed = FALSE;
  174. if ($existing_translation && $existing_translation_objects[$lid]->translation != $new_translation_string_delimited) {
  175. // If there is an existing translation in the DB and the new translation
  176. // is not the same as the existing one.
  177. $is_changed = TRUE;
  178. }
  179. elseif (!$existing_translation && !empty($new_translation_string)) {
  180. // Newly entered translation.
  181. $is_changed = TRUE;
  182. }
  183. if ($is_changed) {
  184. // Only update or insert if we have a value to use.
  185. $target = isset($existing_translation_objects[$lid]) ? $existing_translation_objects[$lid] : $this->localeStorage->createTranslation(array('lid' => $lid, 'language' => $langcode));
  186. $target->setPlurals($new_translation['translations'])
  187. ->setCustomized()
  188. ->save();
  189. $updated[] = $target->getId();
  190. }
  191. if (empty($new_translation_string) && isset($existing_translation_objects[$lid])) {
  192. // Empty new translation entered: remove existing entry from database.
  193. $existing_translation_objects[$lid]->delete();
  194. $updated[] = $lid;
  195. }
  196. }
  197. drupal_set_message($this->t('The strings have been saved.'));
  198. // Keep the user on the current pager page.
  199. $page = $this->getRequest()->query->get('page');
  200. if (isset($page)) {
  201. $form_state->setRedirect(
  202. 'locale.translate_page',
  203. array(),
  204. array('page' => $page)
  205. );
  206. }
  207. if ($updated) {
  208. // Clear cache and force refresh of JavaScript translations.
  209. _locale_refresh_translations(array($langcode), $updated);
  210. _locale_refresh_configuration(array($langcode), $updated);
  211. }
  212. }
  213. }