tmgmt_locale.ui.inc 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. <?php
  2. /**
  3. * @file
  4. * Provides the I18nString source controller.
  5. */
  6. /**
  7. * Class TMGMTI18nStringDefaultSourceUIController
  8. *
  9. * UI Controller fo i18n strings translation jobs.
  10. */
  11. class TMGMTLocaleSourceUIController extends TMGMTDefaultSourceUIController {
  12. /**
  13. * Gets locale strings.
  14. *
  15. * @param string $textgroup
  16. * The locale textgroup.
  17. * @param string $search_label
  18. * Label to search for.
  19. * @param string $missing_target_language
  20. * Missing translation language.
  21. *
  22. * @return array
  23. * List of i18n strings data.
  24. */
  25. function getStrings($textgroup, $search_label = NULL, $missing_target_language = NULL) {
  26. $languages = drupal_map_assoc(array_keys(language_list()));
  27. $select = db_select('locales_source', 'ls')
  28. ->fields('ls', array('lid', 'source'));
  29. $select->addTag('tmgmt_sources_search');
  30. $select->addMetaData('plugin', 'locale');
  31. $select->addMetaData('type', $textgroup);
  32. $select->condition('ls.textgroup', $textgroup);
  33. if (!empty($search_label)) {
  34. $select->condition('ls.source', "%$search_label%", 'LIKE');
  35. }
  36. if (!empty($missing_target_language) && in_array($missing_target_language, $languages)) {
  37. $select->isNull("lt_$missing_target_language.language");
  38. }
  39. // Join locale targets for each language.
  40. // We want all joined fields to be named as langcodes, but langcodes could
  41. // contain hyphens in their names, which is not allowed by the most database
  42. // engines. So we create a langcode-to-filed_alias map, and rename fields
  43. // later.
  44. $langcode_to_filed_alias_map = array();
  45. foreach ($languages as $langcode) {
  46. $table_alias = $select->leftJoin('locales_target', db_escape_field("lt_$langcode"), "ls.lid = %alias.lid AND %alias.language = '$langcode'");
  47. $langcode_to_filed_alias_map[$langcode] = $select->addField($table_alias, 'language');
  48. }
  49. $select = $select->extend('PagerDefault')->limit(variable_get('tmgmt_source_list_limit', 20));
  50. $rows = $select->execute()->fetchAll();
  51. foreach ($rows as $row) {
  52. foreach ($langcode_to_filed_alias_map as $langcode => $field_alias) {
  53. $row->{$langcode} = $row->{$field_alias};
  54. unset($row->{$field_alias});
  55. }
  56. }
  57. return $rows;
  58. }
  59. /**
  60. * Gets overview form header.
  61. *
  62. * @return array
  63. * Header array definition as expected by theme_tablesort().
  64. */
  65. public function overviewFormHeader() {
  66. $languages = array();
  67. foreach (language_list() as $langcode => $language) {
  68. $languages['langcode-' . $langcode] = array(
  69. 'data' => check_plain($language->name),
  70. );
  71. }
  72. $header = array(
  73. 'source' => array('data' => t('Source text')),
  74. ) + $languages;
  75. return $header;
  76. }
  77. /**
  78. * Implements TMGMTSourceUIControllerInterface::overviewForm().
  79. */
  80. public function overviewForm($form, &$form_state, $type) {
  81. $form += $this->overviewSearchFormPart($form, $form_state, $type);
  82. $form['items'] = array(
  83. '#type' => 'tableselect',
  84. '#header' => $this->overviewFormHeader($type),
  85. '#empty' => t('No strings matching given criteria have been found.')
  86. );
  87. $search_data = $this->getSearchFormSubmittedParams();
  88. $strings = $this->getStrings($type, $search_data['label'], $search_data['missing_target_language']);
  89. foreach ($this->getTranslationData($strings, $type) as $id => $data) {
  90. $form['items']['#options'][$id] = $this->overviewRow($type, $data);
  91. }
  92. $form['pager'] = array('#markup' => theme('pager', array('tags' => NULL)));
  93. return $form;
  94. }
  95. /**
  96. * Helper function to create translation data list for the sources page list.
  97. *
  98. * @param array $strings
  99. * Result of the search query returned by tmgmt_i18n_string_get_strings().
  100. * @param string $type
  101. * I18n object type.
  102. *
  103. * @return array
  104. * Structured array with translation data.
  105. */
  106. protected function getTranslationData($strings, $type) {
  107. $objects = array();
  108. // Source language of locale strings is always english.
  109. $source_language = 'en';
  110. foreach ($strings as $string) {
  111. $id = $string->lid;
  112. // Get existing translations and current job items for the entity
  113. // to determine translation statuses
  114. $current_job_items = tmgmt_job_item_load_latest('locale', $type, $id, $source_language);
  115. $objects[$id] = array(
  116. 'id' => $id,
  117. 'object' => $string
  118. );
  119. // Load entity translation specific data.
  120. foreach (language_list() as $langcode => $language) {
  121. $translation_status = 'current';
  122. if ($langcode == $source_language) {
  123. $translation_status = 'original';
  124. }
  125. elseif ($string->{$langcode} === NULL) {
  126. $translation_status = 'missing';
  127. }
  128. $objects[$id]['current_job_items'][$langcode] = isset($current_job_items[$langcode]) ? $current_job_items[$langcode] : NULL;
  129. $objects[$id]['translation_statuses'][$langcode] = $translation_status;
  130. }
  131. }
  132. return $objects;
  133. }
  134. /**
  135. * Builds search form for entity sources overview.
  136. *
  137. * @param array $form
  138. * Drupal form array.
  139. * @param $form_state
  140. * Drupal form_state array.
  141. * @param $type
  142. * Entity type.
  143. *
  144. * @return array
  145. * Drupal form array.
  146. */
  147. public function overviewSearchFormPart($form, &$form_state, $type) {
  148. $options = array();
  149. foreach (language_list() as $langcode => $language) {
  150. $options[$langcode] = $language->name;
  151. }
  152. $default_values = $this->getSearchFormSubmittedParams();
  153. $form['search_wrapper'] = array(
  154. '#prefix' => '<div class="tmgmt-sources-wrapper tmgmt-i18n_string-sources-wrapper">',
  155. '#suffix' => '</div>',
  156. '#weight' => -15,
  157. );
  158. $form['search_wrapper']['search'] = array(
  159. '#tree' => TRUE,
  160. );
  161. $form['search_wrapper']['search']['label'] = array(
  162. '#type' => 'textfield',
  163. '#title' => t('Source text'),
  164. '#default_value' => isset($default_values['label']) ? $default_values['label'] : NULL,
  165. );
  166. // Unset English as it is the source language for all locale strings.
  167. unset($options['en']);
  168. $form['search_wrapper']['search']['missing_target_language'] = array(
  169. '#type' => 'select',
  170. '#title' => t('Not translated to'),
  171. '#options' => $options,
  172. '#empty_option' => '--',
  173. '#default_value' => isset($default_values['missing_target_language']) ? $default_values['missing_target_language'] : NULL,
  174. );
  175. $form['search_wrapper']['search_submit'] = array(
  176. '#type' => 'submit',
  177. '#value' => t('Search'),
  178. );
  179. return $form;
  180. }
  181. /**
  182. * Gets submitted search params.
  183. *
  184. * @return array
  185. */
  186. public function getSearchFormSubmittedParams() {
  187. $params = array(
  188. 'label' => NULL,
  189. 'missing_target_language' => NULL,
  190. );
  191. if (isset($_GET['label'])) {
  192. $params['label'] = $_GET['label'];
  193. }
  194. if (isset($_GET['missing_target_language'])) {
  195. $params['missing_target_language'] = $_GET['missing_target_language'];
  196. }
  197. return $params;
  198. }
  199. /**
  200. * Builds a table row for overview form.
  201. *
  202. * @param string $type
  203. * i18n type.
  204. * @param array $data
  205. * Data needed to build the list row.
  206. *
  207. * @return array
  208. */
  209. public function overviewRow($type, $data) {
  210. // Set the default item key, assume it's the first.
  211. $source = $data['object'];
  212. $row = array(
  213. 'id' => $data['id'],
  214. 'source' => check_plain($source->source),
  215. );
  216. foreach (language_list() as $langcode => $language) {
  217. $row['langcode-' . $langcode] = theme('tmgmt_ui_translation_language_status_single', array(
  218. 'translation_status' => $data['translation_statuses'][$langcode],
  219. 'job_item' => isset($data['current_job_items'][$langcode]) ? $data['current_job_items'][$langcode] : NULL,
  220. ));
  221. }
  222. return $row;
  223. }
  224. /**
  225. * Implements TMGMTSourceUIControllerInterface::overviewFormSubmit().
  226. */
  227. public function overviewFormSubmit($form, &$form_state, $type) {
  228. // Handle search redirect.
  229. $this->overviewSearchFormRedirect($form, $form_state, $type);
  230. $items = array_filter($form_state['values']['items']);
  231. $type = $form_state['item_type'];
  232. $source_lang = 'en';
  233. // Create only single job for all items as the source language is just
  234. // the same for all.
  235. $job = tmgmt_job_create($source_lang, NULL, $GLOBALS['user']->uid);
  236. // Loop through entities and create individual jobs for each source language.
  237. foreach ($items as $item) {
  238. $job->addItem('locale', $type, $item);
  239. }
  240. $form_state['redirect'] = array('admin/tmgmt/jobs/' . $job->tjid,
  241. array('query' => array('destination' => current_path())));
  242. drupal_set_message(t('One job needs to be checked out.'));
  243. }
  244. /**
  245. * Performs redirect with search params appended to the uri.
  246. *
  247. * In case of triggering element is edit-search-submit it redirects to
  248. * current location with added query string containing submitted search form
  249. * values.
  250. *
  251. * @param array $form
  252. * Drupal form array.
  253. * @param $form_state
  254. * Drupal form_state array.
  255. * @param $type
  256. * Entity type.
  257. */
  258. public function overviewSearchFormRedirect($form, &$form_state, $type) {
  259. if ($form_state['triggering_element']['#id'] == 'edit-search-submit') {
  260. $query = array();
  261. foreach ($form_state['values']['search'] as $key => $value) {
  262. $query[$key] = $value;
  263. }
  264. drupal_goto($_GET['q'], array('query' => $query));
  265. }
  266. }
  267. }